Fix CRC32: use combinational stream_valid (was stuck-high causing repeated processing)

This commit is contained in:
2026-06-25 20:53:56 +08:00
parent f8459f2478
commit b3c0db19b9

View File

@@ -36,7 +36,6 @@ module shift_add_mult (
busy <= 1'b0; busy <= 1'b0;
done <= 1'b1; done <= 1'b1;
end else begin end else begin
// 如果 b 的当前最低位为 1,则累加 a
if (b_reg[0]) begin if (b_reg[0]) begin
p <= p + a_reg; p <= p + a_reg;
end end
@@ -53,7 +52,7 @@ endmodule
// ═══════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════
// 矩阵乘法器顶层模块 (AXI Burst Slave + Ping-Pong) // 矩阵乘法器顶层模块 (AXI Burst Slave + Ping-Pong + Stream CRC32)
// ═══════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════
module matmul_axi_slave ( module matmul_axi_slave (
input clk, input clk,
@@ -114,13 +113,12 @@ module matmul_axi_slave (
// ========================================== // ==========================================
localparam ADDR_CTRL = 12'h000; localparam ADDR_CTRL = 12'h000;
localparam ADDR_STATUS = 12'h004; localparam ADDR_STATUS = 12'h004;
localparam ADDR_CRC = 12'h010;
// Bank 0 (可完全当作原来的单缓冲使用)
localparam ADDR_B0_A = 12'h100; localparam ADDR_B0_A = 12'h100;
localparam ADDR_B0_B = 12'h140; localparam ADDR_B0_B = 12'h140;
localparam ADDR_B0_C = 12'h180; localparam ADDR_B0_C = 12'h180;
// Bank 1 (供无等待计算扩展使用)
localparam ADDR_B1_A = 12'h300; localparam ADDR_B1_A = 12'h300;
localparam ADDR_B1_B = 12'h340; localparam ADDR_B1_B = 12'h340;
localparam ADDR_B1_C = 12'h380; localparam ADDR_B1_C = 12'h380;
@@ -157,14 +155,13 @@ module matmul_axi_slave (
// ========================================== // ==========================================
// CRC32 Engine (IEEE 802.3, polynomial 0xEDB88320) // CRC32 Engine (IEEE 802.3, polynomial 0xEDB88320)
// ========================================== // ==========================================
localparam ADDR_CRC = 12'h010;
reg [31:0] crc32_table [0:255]; reg [31:0] crc32_table [0:255];
reg [31:0] crc_reg; reg [31:0] crc_reg;
// Stream CRC: triggered when AXI reads C results wire [31:0] crc_stream_data = s_axi_rdata;
reg [31:0] crc_stream_data; wire crc_stream_valid = (r_state == R_DATA) && s_axi_rvalid && s_axi_rready &&
reg crc_stream_valid; ((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; 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_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_t3 = crc32_table[(crc_c2[7:0] ^ crc_stream_data[31:24])];
assign crc_next = crc_t3 ^ {8'h00, crc_c2[31:8]}; assign crc_next = crc_t3 ^ {8'h00, crc_c2[31:8]};
// CRC32 Table Initialization (IEEE 802.3 reflected)
initial begin initial begin
crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096; crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096;
crc32_table[2 ] = 32'hEE0E612C; crc32_table[3 ] = 32'h990951BA; 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; crc32_table[254] = 32'h5A05DF1B; crc32_table[255] = 32'h2D02EF8D;
end 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) // AXI Write 通道逻辑 (支持 INCR Burst)
// ========================================== // ==========================================
@@ -347,6 +330,9 @@ module matmul_axi_slave (
reg cur_bank; reg cur_bank;
reg calc_done_pulse; 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 always @(posedge clk) begin
if (!resetn) begin if (!resetn) begin
w_state <= W_IDLE; w_state <= W_IDLE;
@@ -358,11 +344,9 @@ module matmul_axi_slave (
done <= 1'b0; done <= 1'b0;
error <= 1'b0; error <= 1'b0;
end else begin end else begin
// 引擎接管请求后清零
if (req_0 && state == C_CALC && cur_bank == 1'b0) req_0 <= 1'b0; 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; if (req_1 && state == C_CALC && cur_bank == 1'b1) req_1 <= 1'b0;
// 引擎计算完成,拉高通用 done 标志
if (calc_done_pulse) begin if (calc_done_pulse) begin
done <= 1'b1; done <= 1'b1;
end end
@@ -381,18 +365,15 @@ module matmul_axi_slave (
end end
W_DATA: begin W_DATA: begin
if (s_axi_wvalid && s_axi_wready) begin if (s_axi_wvalid && s_axi_wready) begin
// ===== 写地址译码与数据装载 =====
if (w_offset == ADDR_CTRL) begin if (w_offset == ADDR_CTRL) begin
if (s_axi_wdata[0]) req_0 <= 1'b1; // 启动 Bank 0 if (s_axi_wdata[0]) req_0 <= 1'b1;
if (s_axi_wdata[1]) req_1 <= 1'b1; // 启动 Bank 1 if (s_axi_wdata[1]) req_1 <= 1'b1;
end end
else if (w_offset == ADDR_STATUS) begin else if (w_offset == ADDR_STATUS) begin
if (s_axi_wdata[1]) done <= 1'b0; if (s_axi_wdata[1]) done <= 1'b0;
if (s_axi_wdata[2]) error <= 1'b0; if (s_axi_wdata[2]) error <= 1'b0;
end end
else if (w_offset == ADDR_CRC) begin // 【修改点 2】删除 else if (w_offset == ADDR_CRC) { crc_reg <= ... } 防止多重驱动
crc_reg <= 32'hFFFFFFFF; // 写任意值复位 CRC
end
else if (w_offset >= ADDR_B0_A && w_offset < ADDR_B0_B) 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); 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) 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); 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) 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); 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 else if (w_offset != ADDR_CRC) begin
// 访问无效地址,拉高 error 标志
error <= 1'b1; error <= 1'b1;
end end
// ===== Burst 地址累加 =====
if (w_burst == 2'b01) w_addr <= w_addr + 32'd4; if (w_burst == 2'b01) w_addr <= w_addr + 32'd4;
if (s_axi_wlast) begin if (s_axi_wlast) begin
@@ -453,6 +432,9 @@ module matmul_axi_slave (
wire [1:0] c1_part = c1_offset % 3; wire [1:0] c1_part = c1_offset % 3;
wire [65:0] target_c1 = b1_c[c1_elem]; 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 always @(posedge clk) begin
if (!resetn) begin if (!resetn) begin
r_state <= R_IDLE; r_state <= R_IDLE;
@@ -478,11 +460,7 @@ module matmul_axi_slave (
end end
R_DATA: begin R_DATA: begin
if (s_axi_rvalid && s_axi_rready) begin if (s_axi_rvalid && s_axi_rready) begin
// CRC32 stream: feed read data when in C result range // 【修改点 3】删掉直接赋值 crc_stream_valid 的逻辑,移至专用 Pipeline 块
if (crc_read_en) begin
crc_stream_data <= s_axi_rdata;
crc_stream_valid <= 1'b1;
end
if (r_cnt == r_len) begin if (r_cnt == r_len) begin
s_axi_rvalid <= 1'b0; s_axi_rvalid <= 1'b0;
s_axi_rlast <= 1'b0; s_axi_rlast <= 1'b0;
@@ -500,14 +478,8 @@ module matmul_axi_slave (
end end
end end
// 修复:将 wire 声明提取到 always 块外部
wire [11:0] current_r_offset = (r_state == R_DATA) ? r_offset : s_axi_araddr[11:0]; 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 always @(*) begin
s_axi_rdata = 32'b0; s_axi_rdata = 32'b0;
if (r_state == R_DATA || (r_state == R_IDLE && s_axi_arvalid)) begin if (r_state == R_DATA || (r_state == R_IDLE && s_axi_arvalid)) begin
@@ -538,6 +510,17 @@ module matmul_axi_slave (
end 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) // 计算引擎 (Compute FSM)
// ========================================== // ==========================================
@@ -549,7 +532,7 @@ module matmul_axi_slave (
reg mult_start; reg mult_start;
wire mult_done [0:3]; wire mult_done [0:3];
wire [63:0] mult_p [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_a [0:3];
reg [31:0] m_in_b [0:3]; reg [31:0] m_in_b [0:3];
@@ -643,7 +626,6 @@ module matmul_axi_slave (
end end
end end
// Interrupt: driven by done, cleared when software writes STATUS[1]
assign intr = done; assign intr = done;
endmodule endmodule