From b3c0db19b9917adad0ed52a316147473d0b3c188 Mon Sep 17 00:00:00 2001 From: FallenSigh Date: Thu, 25 Jun 2026 20:53:56 +0800 Subject: [PATCH] Fix CRC32: use combinational stream_valid (was stuck-high causing repeated processing) --- rtl/ip/matmul/matmul_axi_slave.v | 76 ++++++++++++-------------------- 1 file changed, 29 insertions(+), 47 deletions(-) diff --git a/rtl/ip/matmul/matmul_axi_slave.v b/rtl/ip/matmul/matmul_axi_slave.v index 6b27649..3897fdf 100644 --- a/rtl/ip/matmul/matmul_axi_slave.v +++ b/rtl/ip/matmul/matmul_axi_slave.v @@ -36,7 +36,6 @@ module shift_add_mult ( busy <= 1'b0; done <= 1'b1; end else begin - // 如果 b 的当前最低位为 1,则累加 a if (b_reg[0]) begin p <= p + a_reg; end @@ -53,7 +52,7 @@ endmodule // ═══════════════════════════════════════════════════════ -// 矩阵乘法器顶层模块 (AXI Burst Slave + Ping-Pong) +// 矩阵乘法器顶层模块 (AXI Burst Slave + Ping-Pong + Stream CRC32) // ═══════════════════════════════════════════════════════ module matmul_axi_slave ( input clk, @@ -114,13 +113,12 @@ module matmul_axi_slave ( // ========================================== localparam ADDR_CTRL = 12'h000; localparam ADDR_STATUS = 12'h004; + localparam ADDR_CRC = 12'h010; - // Bank 0 (可完全当作原来的单缓冲使用) localparam ADDR_B0_A = 12'h100; localparam ADDR_B0_B = 12'h140; localparam ADDR_B0_C = 12'h180; - // Bank 1 (供无等待计算扩展使用) localparam ADDR_B1_A = 12'h300; localparam ADDR_B1_B = 12'h340; localparam ADDR_B1_C = 12'h380; @@ -157,14 +155,13 @@ module matmul_axi_slave ( // ========================================== // CRC32 Engine (IEEE 802.3, polynomial 0xEDB88320) // ========================================== - localparam ADDR_CRC = 12'h010; - reg [31:0] crc32_table [0:255]; reg [31:0] crc_reg; - // Stream CRC: triggered when AXI reads C results - reg [31:0] crc_stream_data; - reg crc_stream_valid; + wire [31:0] crc_stream_data = s_axi_rdata; + wire crc_stream_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 [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])]; @@ -176,7 +173,6 @@ module matmul_axi_slave ( 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]}; - // CRC32 Table Initialization (IEEE 802.3 reflected) initial begin crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096; crc32_table[2 ] = 32'hEE0E612C; crc32_table[3 ] = 32'h990951BA; @@ -308,19 +304,6 @@ module matmul_axi_slave ( crc32_table[254] = 32'h5A05DF1B; crc32_table[255] = 32'h2D02EF8D; end - // CRC register update: stream when reading C data, reset on write - always @(posedge clk) begin - if (!resetn) begin - crc_reg <= 32'hFFFFFFFF; - crc_stream_valid <= 1'b0; - end else begin - if (crc_stream_valid) - crc_reg <= crc_next; - else - crc_stream_valid <= 1'b0; - end - end - // ========================================== // AXI Write 通道逻辑 (支持 INCR Burst) // ========================================== @@ -346,6 +329,9 @@ module matmul_axi_slave ( reg [1:0] state; reg cur_bank; reg calc_done_pulse; + + // 【修改点 1】单独引出一个写脉冲信号给 CRC 清零用 + wire crc_clear_pulse = (w_state == W_DATA) && s_axi_wvalid && s_axi_wready && (w_offset == ADDR_CRC); always @(posedge clk) begin if (!resetn) begin @@ -358,11 +344,9 @@ module matmul_axi_slave ( done <= 1'b0; error <= 1'b0; end else begin - // 引擎接管请求后清零 if (req_0 && state == C_CALC && cur_bank == 1'b0) req_0 <= 1'b0; if (req_1 && state == C_CALC && cur_bank == 1'b1) req_1 <= 1'b0; - // 引擎计算完成,拉高通用 done 标志 if (calc_done_pulse) begin done <= 1'b1; end @@ -381,18 +365,15 @@ module matmul_axi_slave ( end W_DATA: begin if (s_axi_wvalid && s_axi_wready) begin - // ===== 写地址译码与数据装载 ===== if (w_offset == ADDR_CTRL) begin - if (s_axi_wdata[0]) req_0 <= 1'b1; // 启动 Bank 0 - if (s_axi_wdata[1]) req_1 <= 1'b1; // 启动 Bank 1 + if (s_axi_wdata[0]) req_0 <= 1'b1; + if (s_axi_wdata[1]) req_1 <= 1'b1; end else if (w_offset == ADDR_STATUS) begin if (s_axi_wdata[1]) done <= 1'b0; if (s_axi_wdata[2]) error <= 1'b0; end - else if (w_offset == ADDR_CRC) begin - crc_reg <= 32'hFFFFFFFF; // 写任意值复位 CRC - end + // 【修改点 2】删除 else if (w_offset == ADDR_CRC) { crc_reg <= ... } 防止多重驱动 else if (w_offset >= ADDR_B0_A && w_offset < ADDR_B0_B) b0_a[(w_offset - ADDR_B0_A) >> 2] <= apply_wstrb(b0_a[(w_offset - ADDR_B0_A) >> 2], s_axi_wdata, s_axi_wstrb); else if (w_offset >= ADDR_B0_B && w_offset < ADDR_B0_C) @@ -401,12 +382,10 @@ module matmul_axi_slave ( b1_a[(w_offset - ADDR_B1_A) >> 2] <= apply_wstrb(b1_a[(w_offset - ADDR_B1_A) >> 2], s_axi_wdata, s_axi_wstrb); else if (w_offset >= ADDR_B1_B && w_offset < ADDR_B1_C) b1_b[(w_offset - ADDR_B1_B) >> 2] <= apply_wstrb(b1_b[(w_offset - ADDR_B1_B) >> 2], s_axi_wdata, s_axi_wstrb); - else begin - // 访问无效地址,拉高 error 标志 + else if (w_offset != ADDR_CRC) begin error <= 1'b1; end - // ===== Burst 地址累加 ===== if (w_burst == 2'b01) w_addr <= w_addr + 32'd4; if (s_axi_wlast) begin @@ -453,6 +432,9 @@ module matmul_axi_slave ( wire [1:0] c1_part = c1_offset % 3; wire [65:0] target_c1 = b1_c[c1_elem]; + wire crc_read_en = (r_offset >= ADDR_B0_C && r_offset < (ADDR_B0_C + 12'h0C0)) || + (r_offset >= ADDR_B1_C && r_offset < (ADDR_B1_C + 12'h0C0)); + always @(posedge clk) begin if (!resetn) begin r_state <= R_IDLE; @@ -478,11 +460,7 @@ module matmul_axi_slave ( end R_DATA: begin if (s_axi_rvalid && s_axi_rready) begin - // CRC32 stream: feed read data when in C result range - if (crc_read_en) begin - crc_stream_data <= s_axi_rdata; - crc_stream_valid <= 1'b1; - end + // 【修改点 3】删掉直接赋值 crc_stream_valid 的逻辑,移至专用 Pipeline 块 if (r_cnt == r_len) begin s_axi_rvalid <= 1'b0; s_axi_rlast <= 1'b0; @@ -500,14 +478,8 @@ module matmul_axi_slave ( end end - // 修复:将 wire 声明提取到 always 块外部 wire [11:0] current_r_offset = (r_state == R_DATA) ? r_offset : s_axi_araddr[11:0]; - // CRC stream trigger: valid when reading C result data - wire crc_read_en = (r_offset >= ADDR_B0_C && r_offset < (ADDR_B0_C + 12'h0C0)) || - (r_offset >= ADDR_B1_C && r_offset < (ADDR_B1_C + 12'h0C0)); - - // 组合逻辑准备 Read 数据 always @(*) begin s_axi_rdata = 32'b0; if (r_state == R_DATA || (r_state == R_IDLE && s_axi_arvalid)) begin @@ -537,6 +509,17 @@ module matmul_axi_slave ( end 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) @@ -549,7 +532,7 @@ module matmul_axi_slave ( reg mult_start; wire mult_done [0:3]; wire [63:0] mult_p [0:3]; - reg [63:0] mult_p_r [0:3]; // registered for stable accumulation + reg [63:0] mult_p_r [0:3]; reg [31:0] m_in_a [0:3]; reg [31:0] m_in_b [0:3]; @@ -643,7 +626,6 @@ module matmul_axi_slave ( end end - // Interrupt: driven by done, cleared when software writes STATUS[1] assign intr = done; endmodule \ No newline at end of file