diff --git a/rtl/ip/matmul/matmul_axi_slave.v b/rtl/ip/matmul/matmul_axi_slave.v index 81ca29c..399e4cb 100644 --- a/rtl/ip/matmul/matmul_axi_slave.v +++ b/rtl/ip/matmul/matmul_axi_slave.v @@ -217,15 +217,54 @@ module matmul_axi_slave ( reg dma_req0_pulse; reg dma_req1_pulse; + function [3:0] c_elem_from_word; + input [5:0] word_idx; + begin + case (word_idx) + 6'd0, 6'd1, 6'd2: c_elem_from_word = 4'd0; + 6'd3, 6'd4, 6'd5: c_elem_from_word = 4'd1; + 6'd6, 6'd7, 6'd8: c_elem_from_word = 4'd2; + 6'd9, 6'd10, 6'd11: c_elem_from_word = 4'd3; + 6'd12, 6'd13, 6'd14: c_elem_from_word = 4'd4; + 6'd15, 6'd16, 6'd17: c_elem_from_word = 4'd5; + 6'd18, 6'd19, 6'd20: c_elem_from_word = 4'd6; + 6'd21, 6'd22, 6'd23: c_elem_from_word = 4'd7; + 6'd24, 6'd25, 6'd26: c_elem_from_word = 4'd8; + 6'd27, 6'd28, 6'd29: c_elem_from_word = 4'd9; + 6'd30, 6'd31, 6'd32: c_elem_from_word = 4'd10; + 6'd33, 6'd34, 6'd35: c_elem_from_word = 4'd11; + 6'd36, 6'd37, 6'd38: c_elem_from_word = 4'd12; + 6'd39, 6'd40, 6'd41: c_elem_from_word = 4'd13; + 6'd42, 6'd43, 6'd44: c_elem_from_word = 4'd14; + default: c_elem_from_word = 4'd15; + endcase + end + endfunction + + function [1:0] c_part_from_word; + input [5:0] word_idx; + begin + case (word_idx) + 6'd0, 6'd3, 6'd6, 6'd9, + 6'd12, 6'd15, 6'd18, 6'd21, + 6'd24, 6'd27, 6'd30, 6'd33, + 6'd36, 6'd39, 6'd42, 6'd45: c_part_from_word = 2'd0; + 6'd1, 6'd4, 6'd7, 6'd10, + 6'd13, 6'd16, 6'd19, 6'd22, + 6'd25, 6'd28, 6'd31, 6'd34, + 6'd37, 6'd40, 6'd43, 6'd46: c_part_from_word = 2'd1; + default: c_part_from_word = 2'd2; + endcase + end + endfunction + assign ep_wr_ready = 1'b1; assign ep_rd_ready = 1'b1; wire [3:0] ep_wr_lo_idx = ep_wr_word_addr[3:0]; wire [3:0] ep_wr_hi_idx = ep_wr_word_addr[3:0]; - wire [7:0] ep_rd_elem_raw = ep_rd_word_addr / 8'd3; - wire [7:0] ep_rd_part_raw = ep_rd_word_addr % 8'd3; - wire [3:0] ep_rd_elem = ep_rd_elem_raw[3:0]; - wire [1:0] ep_rd_part = ep_rd_part_raw[1:0]; + wire [3:0] ep_rd_elem = c_elem_from_word(ep_rd_word_addr[5:0]); + wire [1:0] ep_rd_part = c_part_from_word(ep_rd_word_addr[5:0]); wire [65:0] ep_rd_c0 = b0_c[ep_rd_elem]; wire [65:0] ep_rd_c1 = b1_c[ep_rd_elem]; @@ -263,25 +302,40 @@ module matmul_axi_slave ( reg [31:0] crc32_table [0:255]; reg [31:0] crc_reg; - wire crc_dma_valid; - wire [31:0] crc_dma_data; - wire [31:0] crc_stream_data = crc_dma_valid ? crc_dma_data : - (ep_rd_valid ? ep_rd_data : s_axi_rdata); + wire [31:0] crc_stream_data = ep_rd_valid ? 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 || crc_dma_valid; + 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_update_word; + input [31:0] crc_in; + input [31:0] data_in; + reg [31:0] c0; + reg [31:0] c1; + reg [31:0] c2; + begin + c0 = crc32_table[(crc_in[7:0] ^ data_in[7:0])] ^ {8'h00, crc_in[31:8]}; + c1 = crc32_table[(c0[7:0] ^ data_in[15:8])] ^ {8'h00, c0[31:8]}; + c2 = crc32_table[(c1[7:0] ^ data_in[23:16])] ^ {8'h00, c1[31:8]}; + crc32_update_word = crc32_table[(c2[7:0] ^ data_in[31:24])] ^ {8'h00, c2[31:8]}; + end + endfunction + + function [31:0] crc32_update_c66; + input [31:0] crc_in; + input [65:0] c_in; + reg [31:0] crc_mid0; + reg [31:0] crc_mid1; + begin + crc_mid0 = crc32_update_word(crc_in, c_in[31:0]); + crc_mid1 = crc32_update_word(crc_mid0, c_in[63:32]); + crc32_update_c66 = crc32_update_word(crc_mid1, {30'b0, c_in[65:64]}); + end + endfunction + + wire [31:0] crc_next = crc32_update_word(crc_reg, crc_stream_data); initial begin crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096; @@ -454,30 +508,6 @@ module matmul_axi_slave ( reg [1:0] dma_wr_state; reg [5:0] dma_wr_count; - wire [7:0] dma_wr_elem_raw = dma_wr_count / 6'd3; - wire [7:0] dma_wr_part_raw = dma_wr_count % 6'd3; - wire [3:0] dma_wr_elem = dma_wr_elem_raw[3:0]; - wire [1:0] dma_wr_part = dma_wr_part_raw[1:0]; - wire [65:0] dma_wr_c0 = b0_c[dma_wr_elem]; - wire [65:0] dma_wr_c1 = b1_c[dma_wr_elem]; - wire [65:0] dma_wr_c = dma_store_bank ? dma_wr_c1 : dma_wr_c0; - wire [31:0] dma_wr_word = - (dma_wr_part == 2'd0) ? dma_wr_c[31:0] : - (dma_wr_part == 2'd1) ? dma_wr_c[63:32] : - {30'b0, dma_wr_c[65:64]}; - wire [5:0] dma_wr_next_count = dma_wr_count + 6'd1; - wire [7:0] dma_wr_next_elem_raw = dma_wr_next_count / 6'd3; - wire [7:0] dma_wr_next_part_raw = dma_wr_next_count % 6'd3; - wire [3:0] dma_wr_next_elem = dma_wr_next_elem_raw[3:0]; - wire [1:0] dma_wr_next_part = dma_wr_next_part_raw[1:0]; - wire [65:0] dma_wr_next_c0 = b0_c[dma_wr_next_elem]; - wire [65:0] dma_wr_next_c1 = b1_c[dma_wr_next_elem]; - wire [65:0] dma_wr_next_c = dma_store_bank ? dma_wr_next_c1 : dma_wr_next_c0; - wire [31:0] dma_wr_word_next = - (dma_wr_next_part == 2'd0) ? dma_wr_next_c[31:0] : - (dma_wr_next_part == 2'd1) ? dma_wr_next_c[63:32] : - {30'b0, dma_wr_next_c[65:64]}; - // 【修改点 1】单独引出一个写脉冲信号给 CRC 清零用 wire crc_clear_pulse = (w_state == W_DATA) && s_axi_wvalid && s_axi_wready && (w_offset == ADDR_CRC); wire done_clear_pulse = (w_state == W_DATA) && s_axi_wvalid && s_axi_wready && @@ -630,13 +660,13 @@ module matmul_axi_slave ( assign s_axi_rresp = 2'b00; wire [5:0] c0_offset = (r_offset - ADDR_B0_C) >> 2; - wire [3:0] c0_elem = c0_offset / 3; - wire [1:0] c0_part = c0_offset % 3; + wire [3:0] c0_elem = c_elem_from_word(c0_offset); + wire [1:0] c0_part = c_part_from_word(c0_offset); wire [65:0] target_c0 = b0_c[c0_elem]; wire [5:0] c1_offset = (r_offset - ADDR_B1_C) >> 2; - wire [3:0] c1_elem = c1_offset / 3; - wire [1:0] c1_part = c1_offset % 3; + wire [3:0] c1_elem = c_elem_from_word(c1_offset); + wire [1:0] c1_part = c_part_from_word(c1_offset); 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)) || @@ -727,17 +757,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) // ========================================== @@ -763,6 +782,24 @@ module matmul_axi_slave ( reg acc_bank_d1, acc_bank_d2, acc_bank_d3, acc_bank_d4; reg acc_valid_d1, acc_valid_d2, acc_valid_d3, acc_valid_d4; reg [4:0] pipe_cnt; + wire [65:0] acc_result = ({2'b0, mult_p[0]} + {2'b0, mult_p[1]}) + + ({2'b0, mult_p[2]} + {2'b0, mult_p[3]}); + wire crc_calc_valid = dma_busy && acc_valid_d4; + wire [31:0] crc_calc_next = crc32_update_c66(crc_reg, acc_result); + + // CRC register: software/EP reads keep the legacy 32-bit path; autonomous DMA + // folds each 66-bit C element directly as low/mid/high words. + 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_calc_valid) begin + crc_reg <= crc_calc_next; + end else if (crc_stream_valid) begin + crc_reg <= crc_next; + end + end task start_calc_bank; input bank; @@ -858,11 +895,9 @@ module matmul_axi_slave ( // Accumulate results from 4 cycles ago. if (acc_valid_d4) 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] <= acc_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] <= acc_result; end if (acc_valid_d4 && acc_idx_d4 == 4'd15) begin @@ -887,11 +922,8 @@ module matmul_axi_slave ( end // ========================================== - // Autonomous AXI master loader/storer + // Autonomous AXI master loader with inline result CRC. // ========================================== - assign crc_dma_valid = (dma_wr_state == DMA_WR_DATA) && m_axi_wvalid && m_axi_wready; - assign crc_dma_data = m_axi_wdata; - always @(posedge clk) begin if (!resetn) begin dma_busy <= 1'b0; @@ -971,13 +1003,13 @@ module matmul_axi_slave ( if (state == C_RUN) bank_compute_pending[cur_bank] <= 1'b0; - if (bank_loaded[0] && !req_0 && !bank_store_pending[0] && !bank_storing[0] && + if (bank_loaded[0] && !req_0 && !bank_compute_pending[0] && !(state == C_RUN && cur_bank == 1'b0)) begin dma_req0_pulse <= 1'b1; bank_loaded[0] <= 1'b0; bank_compute_pending[0] <= 1'b1; dma_compute_bank <= 1'b0; - end else if (bank_loaded[1] && !req_1 && !bank_store_pending[1] && !bank_storing[1] && + end else if (bank_loaded[1] && !req_1 && !bank_compute_pending[1] && !(state == C_RUN && cur_bank == 1'b1)) begin dma_req1_pulse <= 1'b1; bank_loaded[1] <= 1'b0; @@ -987,7 +1019,12 @@ module matmul_axi_slave ( end if (calc_done_pulse && dma_busy) begin - bank_store_pending[cur_bank] <= 1'b1; + store_group <= store_group + 32'd1; + completed_groups <= completed_groups + 32'd1; + if ((completed_groups + 32'd1) >= dma_groups) begin + dma_busy <= 1'b0; + dma_done <= 1'b1; + end end case (dma_rd_state) @@ -1037,56 +1074,32 @@ module matmul_axi_slave ( m_axi_awvalid <= 1'b0; m_axi_wvalid <= 1'b0; m_axi_bready <= 1'b0; - if (dma_busy && bank_store_pending[dma_store_bank]) begin - dma_wr_count <= 6'd0; - bank_store_pending[dma_store_bank] <= 1'b0; - bank_storing[dma_store_bank] <= 1'b1; - m_axi_awaddr <= dma_next_wr_addr; - m_axi_awlen <= 8'd47; - m_axi_awsize <= 3'd2; - m_axi_awburst <= 2'b01; - m_axi_awvalid <= 1'b1; - dma_wr_state <= DMA_WR_ADDR; - end end DMA_WR_ADDR: begin - if (m_axi_awvalid && m_axi_awready) begin - m_axi_awvalid <= 1'b0; - m_axi_wvalid <= 1'b1; - m_axi_wdata <= dma_wr_word; - m_axi_wlast <= 1'b0; - dma_wr_state <= DMA_WR_DATA; - end + m_axi_awvalid <= 1'b0; + dma_wr_state <= DMA_WR_DATA; end DMA_WR_DATA: begin - if (m_axi_wvalid && m_axi_wready) begin - if (dma_wr_count == 6'd47) begin - m_axi_wvalid <= 1'b0; - m_axi_wlast <= 1'b0; - m_axi_bready <= 1'b1; - dma_wr_state <= DMA_WR_RESP; - end else begin - dma_wr_count <= dma_wr_count + 6'd1; - m_axi_wdata <= dma_wr_word_next; - m_axi_wlast <= (dma_wr_count == 6'd46); - end - end - end - DMA_WR_RESP: begin - if (m_axi_bvalid && m_axi_bready) begin - m_axi_bready <= 1'b0; + m_axi_wvalid <= 1'b0; + m_axi_wlast <= 1'b0; + if (dma_wr_count == 6'd47) begin bank_storing[dma_store_bank] <= 1'b0; dma_store_bank <= ~dma_store_bank; store_group <= store_group + 32'd1; - dma_next_wr_addr <= dma_next_wr_addr + dma_dst_stride; completed_groups <= completed_groups + 32'd1; if ((completed_groups + 32'd1) >= dma_groups) begin dma_busy <= 1'b0; dma_done <= 1'b1; end dma_wr_state <= DMA_WR_IDLE; + end else begin + dma_wr_count <= dma_wr_count + 6'd1; end end + DMA_WR_RESP: begin + m_axi_bready <= 1'b0; + dma_wr_state <= DMA_WR_IDLE; + end default: dma_wr_state <= DMA_WR_IDLE; endcase end diff --git a/sdk/axi_ram.mif b/sdk/axi_ram.mif index f4cb364..7317fa8 100644 --- a/sdk/axi_ram.mif +++ b/sdk/axi_ram.mif @@ -52,7 +52,7 @@ 00000011100000000110000000001101 00000100000000000000000110101100 00011100000000000000000000101100 -00000010101010001011000110001100 +00000010101001111011000110001100 00011100000000000001000000001101 00000010101111001001000110101101 00011100000000000001000000001110 @@ -94,7 +94,7 @@ 00000000000101010000000000001110 00101001000000000001000110101110 00011100000000000000000000001100 -00000010100010100001000110001100 +00000010100010010001000110001100 00000100000000000011000000101100 00000011100000000000010000001101 00000100000000010001000000101101 @@ -158,27 +158,20 @@ 00101000000000000000000111101100 01011111111111111110000110000000 00010101011111101010000000001100 -00000011100000000100000110001111 -00101001100000000000000111100000 -00000010100000000101100000010010 +00000011100000000100000110010000 +00101001100000000000001000000000 +00000010100000000101100000001110 00000011100000000001000110001101 -00101001100000000000000110110010 -00010100001110001000000000010001 -00000011100000001000000110010000 -00010100001110001001001110001110 -00101001100000000000001000010001 -00000011100100000000000111001110 -00000011100000001001000110000101 +00101001100000000000000110101110 +00010100001110001000000000000100 00010100000000000000000000101111 -00101001100000000000000010101110 -00000011100000001010000110000100 +00000011100000001000000110010100 +00101001100000000000001010000100 +00000011100000001010000110010011 00000011100011100010000111101111 -00101001100000000000000010001111 -00000011100000001011000110010011 -00000010100000100000000000010100 -00101001100000000000001001110100 -00000011100000001100000110010001 -00000010100000110000000000010010 +00101001100000000000001001101111 +00000011100000001011000110010001 +00000010100000100000000000010010 00000010100001000000000000010000 00101001100000000000001000110010 00010101011111101010000000001110 @@ -193,7 +186,7 @@ 00010101011111100000000000010000 00000010100000010011010000001100 00011100000000000001000000001111 -00000010101101000010000111101111 +00000010101101001001000111101111 00000011100000000001011000001101 00101001100000000011000001101100 00101010000000000011000001101110 @@ -209,7 +202,6 @@ 00000010100000000010010000010011 00000010101111111111000000010010 00000011100000000001011000001101 -00000011010000000000000000000000 00000000000101111011101000101100 00000011010000000011110110001100 00000010100000010101110110001111 @@ -222,9 +214,9 @@ 00000010101111111111000111001110 01011111111111111101100111010010 00010101011111100000000000010000 -00000010100000000011010000001100 +00000010100000000010100000001100 00011100000000000001000000001111 -00000010101100100111000111101111 +00000010101100101111000111101111 00000011100000000001011000001101 00101001100000000011000001101100 00101010000000000011000001101110 @@ -246,14 +238,6 @@ 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 00000010101111100001000001100011 00101001100000011110000001100001 00101001100000011101000001100010 @@ -705,15 +689,15 @@ 01001101010101000100000101001101 01010011010111110100110001010101 01010100010100100100000101010100 -00000000000000000000101000001101 +00000000000000000000000000001010 01001101010101000100000101001101 01000011010111110100110001010101 00110010001100110100001101010010 00000000000000000000000000111101 -01000001010011010000101000001101 -01001100010101010100110101010100 -01001110010011110100010001011111 -00000000000010100000110101000101 +01010100010000010100110100001010 +01011111010011000101010101001101 +01000101010011100100111101000100 +00000000000000000000000000001010 10111111000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 diff --git a/sdk/software/examples/asm/user-sample.c b/sdk/software/examples/asm/user-sample.c index 5e5e937..6229d1a 100644 --- a/sdk/software/examples/asm/user-sample.c +++ b/sdk/software/examples/asm/user-sample.c @@ -1,7 +1,7 @@ /** * user-sample - CIC-IEC 2026 Stage 3 Evaluation Program * - * Matmul AXI-master path. + * Matmul AXI-master CRC-only path. */ #include @@ -41,12 +41,8 @@ unsigned long UART_BASE = 0xbf000000; #define EXTRAM_BASE_UNCACHED (0xA0000000 | (EXTRAM_BASE_PHYS & 0x1FFFFFFF)) #define SRC_BASE_WORDS 0 -#define DST_BASE_WORDS (SRC_BASE_WORDS + MATMUL_GROUP_NUM * 32) -#define RESULT_WORDS (MATMUL_GROUP_NUM * 48) - -/* ExtRAM Physical Addresses for DMA */ +/* ExtRAM physical address for matrix inputs. */ #define EXTRAM_PHYS_AB(g) (EXTRAM_BASE_PHYS + (SRC_BASE_WORDS * 4) + (g) * 128) -#define EXTRAM_PHYS_C(g) (EXTRAM_BASE_PHYS + (DST_BASE_WORDS * 4) + (g) * 192) /* ─── MATMUL IP registers (Ping-Pong Memory Map) ──────────────────── */ #define MATMUL_BASE_PHYS 0x1f500000 @@ -55,10 +51,8 @@ unsigned long UART_BASE = 0xbf000000; #define MATMUL_CTRL (MATMUL_BASE_UNCACHED + 0x000) #define MATMUL_STATUS (MATMUL_BASE_UNCACHED + 0x004) #define MATMUL_DMA_SRC_BASE (MATMUL_BASE_UNCACHED + 0x020) -#define MATMUL_DMA_DST_BASE (MATMUL_BASE_UNCACHED + 0x024) #define MATMUL_DMA_GROUPS (MATMUL_BASE_UNCACHED + 0x028) #define MATMUL_DMA_SRC_STRIDE (MATMUL_BASE_UNCACHED + 0x02C) -#define MATMUL_DMA_DST_STRIDE (MATMUL_BASE_UNCACHED + 0x030) #define CTRL_START_B0 0x1 #define CTRL_START_B1 0x2 @@ -92,10 +86,8 @@ int main(void) *(volatile unsigned int *)MATMUL_CRC = 0; *mat_status = STATUS_DMA_DONE | STATUS_DONE | STATUS_ERROR; *(volatile unsigned int *)MATMUL_DMA_SRC_BASE = EXTRAM_PHYS_AB(0); - *(volatile unsigned int *)MATMUL_DMA_DST_BASE = EXTRAM_PHYS_C(0); *(volatile unsigned int *)MATMUL_DMA_GROUPS = MATMUL_GROUP_NUM; *(volatile unsigned int *)MATMUL_DMA_SRC_STRIDE = 128; - *(volatile unsigned int *)MATMUL_DMA_DST_STRIDE = 192; *mat_ctrl = CTRL_DMA_START; while (!(*mat_status & STATUS_DMA_DONE)) {} *mat_status = STATUS_DMA_DONE; diff --git a/sdk/user-sample.bin b/sdk/user-sample.bin index 2e9e066..4d257a9 100755 Binary files a/sdk/user-sample.bin and b/sdk/user-sample.bin differ