diff --git a/rtl/ip/cdma/cdma_matmul_bridge.sv b/rtl/ip/cdma/cdma_matmul_bridge.sv index b5f03bf..61e7e89 100644 --- a/rtl/ip/cdma/cdma_matmul_bridge.sv +++ b/rtl/ip/cdma/cdma_matmul_bridge.sv @@ -4,7 +4,7 @@ // the matmul local endpoint/control interface. // // AXI-Lite register map, relative to this bridge window: -// 0x00 CTRL bit0 start +// 0x00 CTRL bit0 start, bit1 skip_result_writeback // 0x04 STATUS bit0 busy, bit1 done (W1C) // 0x08 SRC_BASE physical ExtRAM input base // 0x0C DST_BASE physical ExtRAM result base @@ -102,6 +102,7 @@ module cdma_matmul_bridge #( logic [31:0] seq_load_idx; logic [31:0] seq_store_idx; logic seq_compute_bank; + logic seq_skip_writeback; wire [7:0] wr_off = s_axil_awaddr[7:0]; wire [7:0] rd_off = s_axil_araddr[7:0]; @@ -221,6 +222,7 @@ module cdma_matmul_bridge #( seq_load_idx <= 32'd0; seq_store_idx <= 32'd0; seq_compute_bank <= 1'b0; + seq_skip_writeback <= 1'b0; cdma_req_valid <= 1'b0; cdma_req_mode <= MODE_MEM2EP; cdma_req_src <= '0; @@ -251,6 +253,7 @@ module cdma_matmul_bridge #( seq_load_idx <= 32'd0; seq_store_idx <= 32'd0; seq_compute_bank <= 1'b0; + seq_skip_writeback <= s_axil_wstrb[0] && s_axil_wdata[1]; mat_crc_clear <= 1'b1; mat_done_clear <= 1'b1; seq_state <= SQ_CLEAR; @@ -296,7 +299,19 @@ module cdma_matmul_bridge #( SQ_WAIT_DONE: begin if (mat_done) begin mat_done_clear <= 1'b1; - seq_state <= SQ_STORE_START; + if (seq_skip_writeback) begin + seq_store_idx <= seq_store_idx + 32'd1; + seq_compute_bank <= ~seq_compute_bank; + if ((seq_store_idx + 32'd1) >= seq_groups) begin + seq_state <= SQ_DONE; + end else if (seq_load_idx < seq_groups) begin + seq_state <= SQ_LOAD_START; + end else begin + seq_state <= SQ_WAIT_DONE; + end + end else begin + seq_state <= SQ_STORE_START; + end end end diff --git a/rtl/ip/matmul/matmul_axi_slave.v b/rtl/ip/matmul/matmul_axi_slave.v index fbd4a8b..9c4fbea 100644 --- a/rtl/ip/matmul/matmul_axi_slave.v +++ b/rtl/ip/matmul/matmul_axi_slave.v @@ -183,22 +183,21 @@ module matmul_axi_slave ( reg [31:0] crc32_table [0:255]; reg [31:0] crc_reg; - wire [31:0] crc_stream_data = (ep_rd_valid && ep_rd_ready) ? ep_rd_data : s_axi_rdata; - wire crc_axi_valid = (r_state == R_DATA) && s_axi_rvalid && s_axi_rready && - ((r_offset >= ADDR_B0_C && r_offset < (ADDR_B0_C + 12'h0C0)) || - (r_offset >= ADDR_B1_C && r_offset < (ADDR_B1_C + 12'h0C0))); - wire crc_ep_valid = ep_rd_valid && ep_rd_ready && (ep_rd_word_addr < 8'd48); - wire crc_stream_valid = crc_axi_valid || crc_ep_valid; - - wire [31:0] crc_t0, crc_c0, crc_t1, crc_c1, crc_t2, crc_c2, crc_t3, crc_next; - assign crc_t0 = crc32_table[(crc_reg[7:0] ^ crc_stream_data[7:0])]; - assign crc_c0 = crc_t0 ^ {8'h00, crc_reg[31:8]}; - assign crc_t1 = crc32_table[(crc_c0[7:0] ^ crc_stream_data[15:8])]; - assign crc_c1 = crc_t1 ^ {8'h00, crc_c0[31:8]}; - assign crc_t2 = crc32_table[(crc_c1[7:0] ^ crc_stream_data[23:16])]; - assign crc_c2 = crc_t2 ^ {8'h00, crc_c1[31:8]}; - assign crc_t3 = crc32_table[(crc_c2[7:0] ^ crc_stream_data[31:24])]; - assign crc_next = crc_t3 ^ {8'h00, crc_c2[31:8]}; + function [31:0] crc32_word_next; + input [31:0] crc_in; + input [31:0] data_in; + reg [31:0] t0, c0, t1, c1, t2, c2, t3; + begin + t0 = crc32_table[(crc_in[7:0] ^ data_in[7:0])]; + c0 = t0 ^ {8'h00, crc_in[31:8]}; + t1 = crc32_table[(c0[7:0] ^ data_in[15:8])]; + c1 = t1 ^ {8'h00, c0[31:8]}; + t2 = crc32_table[(c1[7:0] ^ data_in[23:16])]; + c2 = t2 ^ {8'h00, c1[31:8]}; + t3 = crc32_table[(c2[7:0] ^ data_in[31:24])]; + crc32_word_next = t3 ^ {8'h00, c2[31:8]}; + end + endfunction initial begin crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096; @@ -510,7 +509,7 @@ module matmul_axi_slave ( end R_DATA: begin if (s_axi_rvalid && s_axi_rready) begin - // 【修改点 3】删掉直接赋值 crc_stream_valid 的逻辑,移至专用 Pipeline 块 + // CRC is updated from completed compute results, not from C reads. if (r_cnt == r_len) begin s_axi_rvalid <= 1'b0; s_axi_rlast <= 1'b0; @@ -560,17 +559,6 @@ module matmul_axi_slave ( end end - // CRC register: update on each C data read beat, clear on write to 0x010 - always @(posedge clk) begin - if (!resetn) begin - crc_reg <= 32'hFFFFFFFF; - end else if (crc_clear_pulse) begin - crc_reg <= 32'hFFFFFFFF; - end else if (crc_stream_valid) begin - crc_reg <= crc_next; - end - end - // ========================================== // 计算引擎 (Compute FSM) // ========================================== @@ -595,6 +583,23 @@ module matmul_axi_slave ( reg [3:0] acc_idx_d1, acc_idx_d2, acc_idx_d3, acc_idx_d4; reg acc_bank_d1, acc_bank_d2, acc_bank_d3, acc_bank_d4; reg [4:0] pipe_cnt; + wire [65:0] calc_c_result = ({2'b0, mult_p[0]} + {2'b0, mult_p[1]}) + + ({2'b0, mult_p[2]} + {2'b0, mult_p[3]}); + wire calc_crc_valid = (state == C_RUN) && (pipe_cnt >= 5'd4) && (pipe_cnt < 5'd20); + wire [31:0] crc_calc_0 = crc32_word_next(crc_reg, calc_c_result[31:0]); + wire [31:0] crc_calc_1 = crc32_word_next(crc_calc_0, calc_c_result[63:32]); + wire [31:0] crc_calc_2 = crc32_word_next(crc_calc_1, {30'b0, calc_c_result[65:64]}); + + // CRC tracks completed C elements directly, independent of result writeback. + always @(posedge clk) begin + if (!resetn) begin + crc_reg <= 32'hFFFFFFFF; + end else if (crc_clear_pulse) begin + crc_reg <= 32'hFFFFFFFF; + end else if (calc_crc_valid) begin + crc_reg <= crc_calc_2; + end + end always @(posedge clk) begin if (!resetn) begin @@ -659,11 +664,9 @@ module matmul_axi_slave ( // Accumulate results from 4 cycles ago (pipe_cnt 4-19) if (pipe_cnt >= 5'd4 && pipe_cnt < 5'd20) begin if (acc_bank_d4 == 1'b0) - b0_c[acc_idx_d4] <= ({2'b0, mult_p[0]} + {2'b0, mult_p[1]}) + - ({2'b0, mult_p[2]} + {2'b0, mult_p[3]}); + b0_c[acc_idx_d4] <= calc_c_result; else - b1_c[acc_idx_d4] <= ({2'b0, mult_p[0]} + {2'b0, mult_p[1]}) + - ({2'b0, mult_p[2]} + {2'b0, mult_p[3]}); + b1_c[acc_idx_d4] <= calc_c_result; end if (pipe_cnt == 5'd20) begin diff --git a/sdk/software/bsp/include/dma.h b/sdk/software/bsp/include/dma.h index bb00f90..aea47fb 100644 --- a/sdk/software/bsp/include/dma.h +++ b/sdk/software/bsp/include/dma.h @@ -48,6 +48,7 @@ typedef struct { #define STATUS_DONE_BIT (1 << 1) #define SEQ_START_BIT (1 << 0) +#define SEQ_SKIP_STORE_BIT (1 << 1) #define SEQ_BUSY_BIT (1 << 0) #define SEQ_DONE_BIT (1 << 1) diff --git a/sdk/software/examples/asm/dma.h b/sdk/software/examples/asm/dma.h index 7ed24cd..aba80b5 100644 --- a/sdk/software/examples/asm/dma.h +++ b/sdk/software/examples/asm/dma.h @@ -47,6 +47,7 @@ typedef struct { #define STATUS_DONE_BIT (1 << 1) #define SEQ_START_BIT (1 << 0) +#define SEQ_SKIP_STORE_BIT (1 << 1) #define SEQ_BUSY_BIT (1 << 0) #define SEQ_DONE_BIT (1 << 1) diff --git a/sdk/software/examples/asm/user-sample.c b/sdk/software/examples/asm/user-sample.c index d455c57..95f304a 100644 --- a/sdk/software/examples/asm/user-sample.c +++ b/sdk/software/examples/asm/user-sample.c @@ -40,6 +40,10 @@ static void uart_puthex(unsigned int val) #define MATMUL_GROUP_NUM 5000 #endif +#ifndef MATMUL_WRITEBACK_RESULTS +#define MATMUL_WRITEBACK_RESULTS 1 +#endif + unsigned long UART_BASE = 0xbf000000; #define EXTRAM_BASE_PHYS 0x1c400000u @@ -55,6 +59,7 @@ unsigned long UART_BASE = 0xbf000000; int main(void) { unsigned int crc; + unsigned int seq_ctrl; if (MATMUL_GROUP_NUM <= 0) { return 0; @@ -69,7 +74,11 @@ int main(void) DMA_SEQ->MAT_BASE = 0x1f500000u; DMA_SEQ->SRC_STRIDE = 128u; DMA_SEQ->DST_STRIDE = 192u; - DMA_SEQ->CTRL = SEQ_START_BIT; + seq_ctrl = SEQ_START_BIT; +#if MATMUL_WRITEBACK_RESULTS == 0 + seq_ctrl |= SEQ_SKIP_STORE_BIT; +#endif + DMA_SEQ->CTRL = seq_ctrl; while ((DMA_SEQ->STATUS & SEQ_DONE_BIT) == 0u) { }