Fix CRC32: use combinational stream_valid (was stuck-high causing repeated processing)
This commit is contained in:
@@ -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)
|
||||
// ==========================================
|
||||
@@ -347,6 +330,9 @@ module matmul_axi_slave (
|
||||
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
|
||||
w_state <= W_IDLE;
|
||||
@@ -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
|
||||
@@ -538,6 +510,17 @@ 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)
|
||||
// ==========================================
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user