This commit is contained in:
2026-07-13 07:10:30 +08:00
parent 886ae8ad3f
commit 7c60da78cb
4 changed files with 286 additions and 579 deletions

View File

@@ -65,6 +65,7 @@ module axi2sram_sp_external #(
output reg req_o, output reg req_o,
output reg we_o, output reg we_o,
output reg [AXI_ADDR_WIDTH-1:0] addr_o, output reg [AXI_ADDR_WIDTH-1:0] addr_o,
output reg bank_o,
output reg [AXI_DATA_WIDTH/8-1:0] be_o, output reg [AXI_DATA_WIDTH/8-1:0] be_o,
output reg [AXI_DATA_WIDTH-1:0] data_o, output reg [AXI_DATA_WIDTH-1:0] data_o,
input [AXI_DATA_WIDTH-1:0] data_i input [AXI_DATA_WIDTH-1:0] data_i
@@ -101,40 +102,34 @@ module axi2sram_sp_external #(
localparam FIXED = 2'b00; localparam FIXED = 2'b00;
localparam INCR = 2'b01; localparam INCR = 2'b01;
localparam WRAP = 2'b10; localparam WRAP = 2'b10;
localparam [AXI_ADDR_WIDTH-1:0] ADDR_INCR =
{{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1} << LOG_NR_BYTES;
reg [AXI_ADDR_WIDTH-1:0] req_addr_d, req_addr_q; reg [AXI_ADDR_WIDTH-1:0] req_addr_d, req_addr_q;
reg [7:0] cnt_d, cnt_q; reg [7:0] cnt_d, cnt_q;
reg [AXI_ADDR_WIDTH-1:0] wrap_mask_d, wrap_mask_q;
reg req_bank_d, req_bank_q;
reg [AXI_DATA_WIDTH-1:0] read_data_q;
reg read_capture;
function automatic [AXI_ADDR_WIDTH-1:0] get_wrap_boundary; wire [AXI_ADDR_WIDTH-1:0] ar_burst_bytes =
input [AXI_ADDR_WIDTH-1:0] unaligned_address; ({{(AXI_ADDR_WIDTH-8){1'b0}}, s_arlen} + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}) << LOG_NR_BYTES;
input [7:0] len; wire [AXI_ADDR_WIDTH-1:0] aw_burst_bytes =
begin ({{(AXI_ADDR_WIDTH-8){1'b0}}, s_awlen} + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}) << LOG_NR_BYTES;
get_wrap_boundary = 'h0; wire [AXI_ADDR_WIDTH-1:0] ar_wrap_mask = ar_burst_bytes - {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1};
// for wrapping transfers ax_len can only be of size 1, 3, 7 or 15 wire [AXI_ADDR_WIDTH-1:0] aw_wrap_mask = aw_burst_bytes - {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1};
if (len == 4'b1)
get_wrap_boundary[AXI_ADDR_WIDTH-1:1+LOG_NR_BYTES] = unaligned_address[AXI_ADDR_WIDTH-1:1+LOG_NR_BYTES];
else if (len == 4'b11)
get_wrap_boundary[AXI_ADDR_WIDTH-1:2+LOG_NR_BYTES] = unaligned_address[AXI_ADDR_WIDTH-1:2+LOG_NR_BYTES];
else if (len == 4'b111)
get_wrap_boundary[AXI_ADDR_WIDTH-1:3+LOG_NR_BYTES] = unaligned_address[AXI_ADDR_WIDTH-3:2+LOG_NR_BYTES];
else if (len == 4'b1111)
get_wrap_boundary[AXI_ADDR_WIDTH-1:4+LOG_NR_BYTES] = unaligned_address[AXI_ADDR_WIDTH-3:4+LOG_NR_BYTES];
end
endfunction
reg [AXI_ADDR_WIDTH-1:0] aligned_address; reg [AXI_ADDR_WIDTH-1:0] next_addr;
reg [AXI_ADDR_WIDTH-1:0] wrap_boundary; reg [AXI_ADDR_WIDTH-1:0] seq_addr;
reg [AXI_ADDR_WIDTH-1:0] upper_wrap_boundary;
reg [AXI_ADDR_WIDTH-1:0] cons_addr;
always @ (*) begin always @ (*) begin
// address generation seq_addr = req_addr_q + ADDR_INCR;
aligned_address = {ax_req_q_addr[AXI_ADDR_WIDTH-1:LOG_NR_BYTES], {{LOG_NR_BYTES}{1'b0}}}; case (ax_req_q_burst)
wrap_boundary = get_wrap_boundary(ax_req_q_addr, ax_req_q_len); FIXED: next_addr = req_addr_q;
// this will overflow INCR: next_addr = seq_addr;
upper_wrap_boundary = wrap_boundary + ((ax_req_q_len + 1) << LOG_NR_BYTES); WRAP: next_addr = (req_addr_q & ~wrap_mask_q) | (seq_addr & wrap_mask_q);
// calculate consecutive address default: next_addr = seq_addr;
cons_addr = aligned_address + (cnt_q << LOG_NR_BYTES); endcase
// Transaction attributes // Transaction attributes
// default assignments // default assignments
@@ -146,12 +141,16 @@ module axi2sram_sp_external #(
ax_req_d_burst = ax_req_q_burst; ax_req_d_burst = ax_req_q_burst;
req_addr_d = req_addr_q; req_addr_d = req_addr_q;
cnt_d = cnt_q; cnt_d = cnt_q;
wrap_mask_d = wrap_mask_q;
req_bank_d = req_bank_q;
read_capture = 1'b0;
// Memory default assignments // Memory default assignments
data_o = s_wdata; data_o = s_wdata;
be_o = s_wstrb; be_o = s_wstrb;
we_o = 1'b0; we_o = 1'b0;
req_o = 1'b0; req_o = 1'b0;
addr_o = 'h0; addr_o = 'h0;
bank_o = req_bank_q;
// AXI assignments // AXI assignments
// request // request
s_awready = 1'b0; s_awready = 1'b0;
@@ -184,14 +183,17 @@ module axi2sram_sp_external #(
ax_req_d_len = s_arlen; ax_req_d_len = s_arlen;
ax_req_d_size = s_arsize; ax_req_d_size = s_arsize;
ax_req_d_burst = s_arburst; ax_req_d_burst = s_arburst;
state_d = READ; wrap_mask_d = ar_wrap_mask;
req_bank_d = s_araddr[22];
state_d = READ_ADDR;
// we can request the first address, this saves us time // we can request the first address, this saves us time
req_o = 1'b1; req_o = 1'b1;
addr_o = s_araddr; addr_o = s_araddr;
bank_o = s_araddr[22];
// save the address // save the address
req_addr_d = s_araddr; req_addr_d = s_araddr;
// save the ar_len // save the ar_len
cnt_d = 1; cnt_d = 0;
// ------------ // ------------
// Write // Write
// ------------ // ------------
@@ -205,6 +207,9 @@ module axi2sram_sp_external #(
ax_req_d_len = s_awlen; ax_req_d_len = s_awlen;
ax_req_d_size = s_awsize; ax_req_d_size = s_awsize;
ax_req_d_burst = s_awburst; ax_req_d_burst = s_awburst;
wrap_mask_d = aw_wrap_mask;
req_bank_d = s_awaddr[22];
bank_o = s_awaddr[22];
// we've got our first w_valid so start the write process // we've got our first w_valid so start the write process
if (s_wvalid) begin if (s_wvalid) begin
req_o = 1'b1; req_o = 1'b1;
@@ -231,14 +236,15 @@ module axi2sram_sp_external #(
end end
READ: begin READ: begin
// keep request to memory high
req_o = 1'b1;
addr_o = req_addr_q;
// send the response // send the response
s_rvalid = 1'b1; s_rvalid = 1'b1;
s_rdata = data_i; s_rdata = read_data_q;
s_rid = ax_req_q_id; s_rid = ax_req_q_id;
s_rlast = (cnt_q == ax_req_q_len + 1); s_rlast = (cnt_q == ax_req_q_len + 1);
if (FAST_READ_BURST && !s_rlast) begin
req_o = 1'b1;
addr_o = next_addr;
end
// check that the master is ready, the slave must not wait on this // check that the master is ready, the slave must not wait on this
if (s_rready) begin if (s_rready) begin
// we sent the last byte -> go back to idle // we sent the last byte -> go back to idle
@@ -248,23 +254,12 @@ module axi2sram_sp_external #(
end end
else begin else begin
if (FAST_READ_BURST) begin if (FAST_READ_BURST) begin
// Queue the next async-SRAM address for the clock read_capture = 1'b1;
// edge after the current read data is sampled. req_addr_d = next_addr;
case (ax_req_q_burst)
FIXED, INCR: req_addr_d = cons_addr;
WRAP: begin
if (cons_addr == upper_wrap_boundary) begin
req_addr_d = wrap_boundary;
end else if (cons_addr > upper_wrap_boundary) begin
req_addr_d = ax_req_q_addr + ((cnt_q - ax_req_q_len) << LOG_NR_BYTES);
end else begin
req_addr_d = cons_addr;
end
end
endcase
cnt_d = cnt_q + 1; cnt_d = cnt_q + 1;
state_d = READ; state_d = READ;
end else begin end else begin
req_addr_d = next_addr;
state_d = READ_ADDR; state_d = READ_ADDR;
end end
end end
@@ -272,34 +267,12 @@ module axi2sram_sp_external #(
end end
READ_ADDR: begin READ_ADDR: begin
// keep request to memory high // Fill the read data register after the async-SRAM address has
// been stable for one full sys_clk cycle.
req_o = 1'b1; req_o = 1'b1;
// send the response addr_o = req_addr_q;
s_rvalid = 1'b0; read_capture = 1'b1;
// ----------------------------
// Next address generation
// ----------------------------
// handle the correct burst type
case (ax_req_q_burst)
FIXED, INCR: addr_o = cons_addr;
WRAP: begin
// check if the address reached warp boundary
if (cons_addr == upper_wrap_boundary) begin
addr_o = wrap_boundary;
// address warped beyond boundary
end else if (cons_addr > upper_wrap_boundary) begin
addr_o = ax_req_q_addr + ((cnt_q - ax_req_q_len) << LOG_NR_BYTES);
// we are still in the incremental regime
end else begin
addr_o = cons_addr;
end
end
endcase
// we need to change the address here for the upcoming request
// we can decrease the counter as the master has consumed the read data
cnt_d = cnt_q + 1; cnt_d = cnt_q + 1;
// save the request address for the next cycle
req_addr_d = addr_o;
state_d = READ; state_d = READ;
end end
@@ -317,24 +290,9 @@ module axi2sram_sp_external #(
// Next address generation // Next address generation
// ---------------------------- // ----------------------------
// handle the correct burst type // handle the correct burst type
case (ax_req_q_burst) addr_o = next_addr;
FIXED, INCR: addr_o = cons_addr;
WRAP: begin
// check if the address reached warp boundary
if (cons_addr == upper_wrap_boundary) begin
addr_o = wrap_boundary;
// address warped beyond boundary
end else if (cons_addr > upper_wrap_boundary) begin
addr_o = ax_req_q_addr + ((cnt_q - ax_req_q_len) << LOG_NR_BYTES);
// we are still in the incremental regime
end else begin
addr_o = cons_addr;
end
end
endcase
// save the request address for the next cycle // save the request address for the next cycle
req_addr_d = addr_o; req_addr_d = next_addr;
// we can decrease the counter as the master has consumed the read data // we can decrease the counter as the master has consumed the read data
cnt_d = cnt_q + 1; cnt_d = cnt_q + 1;
@@ -366,6 +324,9 @@ module axi2sram_sp_external #(
ax_req_q_size <= 3'h0; ax_req_q_size <= 3'h0;
req_addr_q <= 'h0; req_addr_q <= 'h0;
cnt_q <= 8'h0; cnt_q <= 8'h0;
wrap_mask_q <= 'h0;
req_bank_q <= 1'b0;
read_data_q <= 'h0;
end else begin end else begin
state_q <= state_d; state_q <= state_d;
ax_req_q_addr <= ax_req_d_addr; ax_req_q_addr <= ax_req_d_addr;
@@ -375,6 +336,10 @@ module axi2sram_sp_external #(
ax_req_q_size <= ax_req_d_size; ax_req_q_size <= ax_req_d_size;
req_addr_q <= req_addr_d; req_addr_q <= req_addr_d;
cnt_q <= cnt_d; cnt_q <= cnt_d;
wrap_mask_q <= wrap_mask_d;
req_bank_q <= req_bank_d;
if (read_capture)
read_data_q <= data_i;
end end
end end

View File

@@ -1,7 +1,5 @@
// ═══════════════════════════════════════════════════════ // 3-stage pipelined multiplier (LUT-based, no DSP)
// 3-stage pipelined multiplier (LUT-based, no DSP) // latency=3, throughput=1 result/cycle
// latency=3, throughput=1 result/cycle
// ═══════════════════════════════════════════════════════
(* use_dsp = "no", use_dsp48 = "no", syn_multstyle = "logic" *) (* use_dsp = "no", use_dsp48 = "no", syn_multstyle = "logic" *)
module pipelined_mult_32x32 ( module pipelined_mult_32x32 (
input clk, input clk,
@@ -43,9 +41,7 @@ module pipelined_mult_32x32 (
endmodule endmodule
// ═══════════════════════════════════════════════════════ // AXI Burst Slave + Ping-Pong + Stream CRC32
// 矩阵乘法器顶层模块 (AXI Burst Slave + Ping-Pong + Stream CRC32)
// ═══════════════════════════════════════════════════════
module matmul_axi_slave ( module matmul_axi_slave (
input clk, input clk,
input resetn, input resetn,
@@ -96,21 +92,6 @@ module matmul_axi_slave (
output reg s_axi_rvalid, output reg s_axi_rvalid,
input s_axi_rready, input s_axi_rready,
// CDMA local endpoint port
input ep_wr_valid,
input [3:0] ep_wr_id,
input [3:0] ep_wr_bank,
input [7:0] ep_wr_word_addr,
input [31:0] ep_wr_data,
output ep_wr_ready,
input ep_rd_valid,
input [3:0] ep_rd_id,
input [3:0] ep_rd_bank,
input [7:0] ep_rd_word_addr,
output reg [31:0] ep_rd_data,
output ep_rd_ready,
// AXI master port for autonomous matrix stream load/store // AXI master port for autonomous matrix stream load/store
output reg [3:0] m_axi_awid, output reg [3:0] m_axi_awid,
output reg [31:0] m_axi_awaddr, output reg [31:0] m_axi_awaddr,
@@ -157,7 +138,7 @@ module matmul_axi_slave (
); );
// ========================================== // ==========================================
// 内存地址映射 (Memory Map) // Memory Map
// ========================================== // ==========================================
localparam ADDR_CTRL = 12'h000; localparam ADDR_CTRL = 12'h000;
localparam ADDR_STATUS = 12'h004; localparam ADDR_STATUS = 12'h004;
@@ -177,7 +158,7 @@ module matmul_axi_slave (
localparam ADDR_B1_C = 12'h380; localparam ADDR_B1_C = 12'h380;
// ========================================== // ==========================================
// 寄存器与数据缓冲 // Registers and data buffers
// ========================================== // ==========================================
reg req_0, req_1; reg req_0, req_1;
reg busy; reg busy;
@@ -258,31 +239,6 @@ module matmul_axi_slave (
end end
endfunction 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 [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];
always @(*) begin
ep_rd_data = 32'b0;
if (ep_rd_word_addr < 8'd48) begin
if (ep_rd_bank[0] == 1'b0) begin
if (ep_rd_part == 2'd0) ep_rd_data = ep_rd_c0[31:0];
else if (ep_rd_part == 2'd1) ep_rd_data = ep_rd_c0[63:32];
else ep_rd_data = {30'b0, ep_rd_c0[65:64]};
end else begin
if (ep_rd_part == 2'd0) ep_rd_data = ep_rd_c1[31:0];
else if (ep_rd_part == 2'd1) ep_rd_data = ep_rd_c1[63:32];
else ep_rd_data = {30'b0, ep_rd_c1[65:64]};
end
end
end
function [31:0] apply_wstrb; function [31:0] apply_wstrb;
input [31:0] old_value; input [31:0] old_value;
input [31:0] new_value; input [31:0] new_value;
@@ -298,16 +254,24 @@ module matmul_axi_slave (
// ========================================== // ==========================================
// CRC32 Engine (IEEE 802.3, polynomial 0xEDB88320) // CRC32 Engine (IEEE 802.3, polynomial 0xEDB88320)
//
// AXI-stream: single-cycle crc32_update_word (4 LUT lookup depth, ok for
// AXI timing—the bus runs at or below internal compute rate).
// DMA-calc: 2-stage pipelined word engine (2 bytes/stage) + 6-cycle
// serial FSM for 66-bit C-elements, with 16-deep FIFO to absorb the
// compute pipeline burst. Critical path: 2 table lookups + 1 XOR per
// stage vs 12 table lookups in the original single-cycle design.
// ========================================== // ==========================================
reg [31:0] crc32_table [0:255]; reg [31:0] crc32_table [0:255];
reg [31:0] crc_reg; reg [31:0] crc_reg;
wire [31:0] crc_stream_data = ep_rd_valid ? ep_rd_data : s_axi_rdata; // ---- AXI-stream CRC (single-cycle) ----------------------------------
wire [31:0] crc_stream_data = s_axi_rdata;
wire crc_axi_valid = (r_state == R_DATA) && s_axi_rvalid && s_axi_rready && 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_B0_C && r_offset < (ADDR_B0_C + 12'h0C0)) ||
(r_offset >= ADDR_B1_C && r_offset < (ADDR_B1_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;
wire crc_stream_valid = crc_axi_valid || crc_ep_valid; wire [31:0] crc_next = crc32_update_word(crc_reg, crc_stream_data);
function [31:0] crc32_update_word; function [31:0] crc32_update_word;
input [31:0] crc_in; input [31:0] crc_in;
@@ -323,19 +287,23 @@ module matmul_axi_slave (
end end
endfunction endfunction
function [31:0] crc32_update_c66; // ---- DMA-calc 3-stage shift register pipeline -----------------------
input [31:0] crc_in; // Stage 0: capture acc_result, compute word0 CRC.
input [65:0] c_in; // Stage 1: shift, compute word1 CRC.
reg [31:0] crc_mid0; // Final: crc_reg updated when stage 1 valid (word2 CRC).
reg [31:0] crc_mid1; // Latency 3 cycles; compute FSM inserts issue gaps so result spacing
begin // is ≥3 cycles, ensuring crc_reg is committed before the next capture.
crc_mid0 = crc32_update_word(crc_in, c_in[31:0]); reg crc_c66_s0_valid, crc_c66_s1_valid;
crc_mid1 = crc32_update_word(crc_mid0, c_in[63:32]); reg [31:0] crc_c66_s0_crc, crc_c66_s1_crc;
crc32_update_c66 = crc32_update_word(crc_mid1, {30'b0, c_in[65:64]}); reg [31:0] crc_c66_s0_word1, crc_c66_s1_word2;
end reg [31:0] crc_c66_s0_word2;
endfunction reg crc_c66_s0_last, crc_c66_s1_last;
wire [31:0] crc_next = crc32_update_word(crc_reg, crc_stream_data); wire [31:0] crc_c66_s0_next = crc32_update_word(crc_reg, acc_result[31:0]);
wire [31:0] crc_c66_s1_next = crc32_update_word(crc_c66_s0_crc, crc_c66_s0_word1);
wire [31:0] crc_c66_final_next = crc32_update_word(crc_c66_s1_crc, crc_c66_s1_word2);
wire crc_c66_busy = crc_c66_s0_valid || crc_c66_s1_valid;
initial begin initial begin
crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096; crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096;
@@ -469,7 +437,7 @@ module matmul_axi_slave (
end end
// ========================================== // ==========================================
// AXI Write 通道逻辑 (支持 INCR Burst) // AXI Write (INCR Burst)
// ========================================== // ==========================================
localparam W_IDLE = 2'd0; localparam W_IDLE = 2'd0;
localparam W_DATA = 2'd1; localparam W_DATA = 2'd1;
@@ -485,7 +453,6 @@ module matmul_axi_slave (
assign s_axi_bid = w_id; assign s_axi_bid = w_id;
assign s_axi_bresp = 2'b00; assign s_axi_bresp = 2'b00;
// 前向声明引擎的状态
localparam C_IDLE = 2'd0; localparam C_IDLE = 2'd0;
localparam C_RUN = 2'd1; localparam C_RUN = 2'd1;
reg [1:0] state; reg [1:0] state;
@@ -508,7 +475,6 @@ module matmul_axi_slave (
reg [1:0] dma_wr_state; reg [1:0] dma_wr_state;
reg [5:0] dma_wr_count; reg [5:0] dma_wr_count;
// 【修改点 1】单独引出一个写脉冲信号给 CRC 清零用
wire crc_clear_pulse = (w_state == W_DATA) && s_axi_wvalid && s_axi_wready && (w_offset == ADDR_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 && wire done_clear_pulse = (w_state == W_DATA) && s_axi_wvalid && s_axi_wready &&
(w_offset == ADDR_STATUS) && s_axi_wdata[1]; (w_offset == ADDR_STATUS) && s_axi_wdata[1];
@@ -534,24 +500,6 @@ module matmul_axi_slave (
dma_start_pulse <= 1'b0; dma_start_pulse <= 1'b0;
dma_done_clear_pulse <= 1'b0; dma_done_clear_pulse <= 1'b0;
if (ep_wr_valid && ep_wr_ready) begin
if (ep_wr_bank[0] == 1'b0) begin
if (ep_wr_word_addr < 8'd16)
b0_a[ep_wr_lo_idx] <= ep_wr_data;
else if (ep_wr_word_addr < 8'd32)
b0_b[ep_wr_hi_idx] <= ep_wr_data;
else
error <= 1'b1;
end else begin
if (ep_wr_word_addr < 8'd16)
b1_a[ep_wr_lo_idx] <= ep_wr_data;
else if (ep_wr_word_addr < 8'd32)
b1_b[ep_wr_hi_idx] <= ep_wr_data;
else
error <= 1'b1;
end
end
if (dma_rd_commit) begin if (dma_rd_commit) begin
if (dma_rd_bank == 1'b0) begin if (dma_rd_bank == 1'b0) begin
if (dma_rd_count < 5'd16) if (dma_rd_count < 5'd16)
@@ -604,7 +552,7 @@ module matmul_axi_slave (
dma_src_stride <= apply_wstrb(dma_src_stride, s_axi_wdata, s_axi_wstrb); dma_src_stride <= apply_wstrb(dma_src_stride, s_axi_wdata, s_axi_wstrb);
else if (w_offset == ADDR_DMA_DST_STRIDE) else if (w_offset == ADDR_DMA_DST_STRIDE)
dma_dst_stride <= apply_wstrb(dma_dst_stride, s_axi_wdata, s_axi_wstrb); dma_dst_stride <= apply_wstrb(dma_dst_stride, s_axi_wdata, s_axi_wstrb);
// 【修改点 2】删除 else if (w_offset == ADDR_CRC) { crc_reg <= ... } 防止多重驱动 // CRC register is now managed by the pipelined CRC engine
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)
@@ -645,7 +593,7 @@ module matmul_axi_slave (
end end
// ========================================== // ==========================================
// AXI Read 通道逻辑 (支持 INCR Burst) // AXI Read (INCR Burst)
// ========================================== // ==========================================
localparam R_IDLE = 2'd0; localparam R_IDLE = 2'd0;
localparam R_DATA = 2'd1; localparam R_DATA = 2'd1;
@@ -697,7 +645,6 @@ 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
// 【修改点 3】删掉直接赋值 crc_stream_valid 的逻辑,移至专用 Pipeline 块
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;
@@ -725,7 +672,7 @@ module matmul_axi_slave (
else if (current_r_offset == ADDR_CRC) else if (current_r_offset == ADDR_CRC)
s_axi_rdata = crc_reg ^ 32'hFFFFFFFF; s_axi_rdata = crc_reg ^ 32'hFFFFFFFF;
else if (current_r_offset == ADDR_STATUS) else if (current_r_offset == ADDR_STATUS)
s_axi_rdata = {27'b0, dma_done, dma_busy, error, done, busy}; s_axi_rdata = {26'b0, crc_c66_busy, dma_done, dma_busy, error, done, busy};
else if (current_r_offset == ADDR_DMA_SRC_BASE) else if (current_r_offset == ADDR_DMA_SRC_BASE)
s_axi_rdata = dma_src_base; s_axi_rdata = dma_src_base;
else if (current_r_offset == ADDR_DMA_DST_BASE) else if (current_r_offset == ADDR_DMA_DST_BASE)
@@ -758,7 +705,7 @@ module matmul_axi_slave (
end end
// ========================================== // ==========================================
// 计算引擎 (Compute FSM) // Compute FSM
// ========================================== // ==========================================
wire [63:0] mult_p [0:3]; wire [63:0] mult_p [0:3];
reg [31:0] m_in_a [0:3]; reg [31:0] m_in_a [0:3];
@@ -785,19 +732,66 @@ module matmul_axi_slave (
wire [65:0] acc_result = ({2'b0, mult_p[0]} + {2'b0, mult_p[1]}) + 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]}); ({2'b0, mult_p[2]} + {2'b0, mult_p[3]});
wire crc_calc_valid = dma_busy && acc_valid_d4; 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 // DMA CRC issue spacing: compute FSM stalls via this counter to ensure
// folds each 66-bit C element directly as low/mid/high words. // ≥3 cycles between consecutive acc_result captures, matching the 3-stage
// CRC pipeline latency so crc_reg is committed before the next element.
reg [1:0] dma_crc_issue_gap;
wire dma_crc_issue_ready = !dma_busy || ((dma_crc_issue_gap == 2'd0) && !crc_c66_busy);
// CRC register update: DMA calc result (pipelined, 3-cycle latency)
// takes priority over AXI-stream (single-cycle). The stream path is
// only permitted when the DMA pipeline is idle (!crc_c66_busy).
always @(posedge clk) begin always @(posedge clk) begin
if (!resetn) begin if (!resetn) begin
crc_reg <= 32'hFFFFFFFF; crc_reg <= 32'hFFFFFFFF;
crc_c66_s0_valid <= 1'b0;
crc_c66_s0_crc <= 32'b0;
crc_c66_s0_word1 <= 32'b0;
crc_c66_s0_word2 <= 32'b0;
crc_c66_s0_last <= 1'b0;
crc_c66_s1_valid <= 1'b0;
crc_c66_s1_crc <= 32'b0;
crc_c66_s1_word2 <= 32'b0;
crc_c66_s1_last <= 1'b0;
end else if (crc_clear_pulse) begin end else if (crc_clear_pulse) begin
crc_reg <= 32'hFFFFFFFF; crc_reg <= 32'hFFFFFFFF;
end else if (crc_calc_valid) begin crc_c66_s0_valid <= 1'b0;
crc_reg <= crc_calc_next; crc_c66_s0_crc <= 32'b0;
end else if (crc_stream_valid) begin crc_c66_s0_word1 <= 32'b0;
crc_reg <= crc_next; crc_c66_s0_word2 <= 32'b0;
crc_c66_s0_last <= 1'b0;
crc_c66_s1_valid <= 1'b0;
crc_c66_s1_crc <= 32'b0;
crc_c66_s1_word2 <= 32'b0;
crc_c66_s1_last <= 1'b0;
end else begin
// Stage 1 → crc_reg finalize (word2 CRC)
if (crc_c66_s1_valid)
crc_reg <= crc_c66_final_next;
else if (crc_stream_valid && !crc_c66_busy)
crc_reg <= crc_next;
// Stage 0 → Stage 1 shift
crc_c66_s1_valid <= crc_c66_s0_valid;
if (crc_c66_s0_valid) begin
crc_c66_s1_crc <= crc_c66_s1_next;
crc_c66_s1_word2 <= crc_c66_s0_word2;
crc_c66_s1_last <= crc_c66_s0_last;
end else begin
crc_c66_s1_last <= 1'b0;
end
// Capture → Stage 0
crc_c66_s0_valid <= crc_calc_valid;
if (crc_calc_valid) begin
crc_c66_s0_crc <= crc_c66_s0_next;
crc_c66_s0_word1 <= acc_result[63:32];
crc_c66_s0_word2 <= {30'b0, acc_result[65:64]};
crc_c66_s0_last <= (acc_idx_d4 == 4'd15);
end else begin
crc_c66_s0_last <= 1'b0;
end
end end
end end
@@ -808,6 +802,7 @@ module matmul_axi_slave (
busy <= 1'b1; busy <= 1'b1;
state <= C_RUN; state <= C_RUN;
pipe_cnt <= 5'd1; pipe_cnt <= 5'd1;
dma_crc_issue_gap <= dma_busy ? 2'd2 : 2'd0;
acc_idx_d1 <= 4'd0; acc_idx_d1 <= 4'd0;
acc_bank_d1 <= bank; acc_bank_d1 <= bank;
acc_valid_d1 <= 1'b1; acc_valid_d1 <= 1'b1;
@@ -832,6 +827,7 @@ module matmul_axi_slave (
cur_bank <= 1'b0; cur_bank <= 1'b0;
calc_done_pulse <= 1'b0; calc_done_pulse <= 1'b0;
pipe_cnt <= 5'd0; pipe_cnt <= 5'd0;
dma_crc_issue_gap <= 2'd0;
acc_idx_d1 <= 4'd0; acc_idx_d1 <= 4'd0;
acc_idx_d2 <= 4'd0; acc_idx_d2 <= 4'd0;
acc_idx_d3 <= 4'd0; acc_idx_d3 <= 4'd0;
@@ -846,8 +842,10 @@ module matmul_axi_slave (
acc_valid_d4 <= 1'b0; acc_valid_d4 <= 1'b0;
end else begin end else begin
calc_done_pulse <= 1'b0; calc_done_pulse <= 1'b0;
if (dma_crc_issue_gap != 2'd0)
dma_crc_issue_gap <= dma_crc_issue_gap - 2'd1;
// Pipeline shift: issue_idx → d1 → d2 → d3 → d4 (4 cycles total) // Pipeline shift (4 cycles total)
acc_idx_d4 <= acc_idx_d3; acc_idx_d4 <= acc_idx_d3;
acc_idx_d3 <= acc_idx_d2; acc_idx_d3 <= acc_idx_d2;
acc_idx_d2 <= acc_idx_d1; acc_idx_d2 <= acc_idx_d1;
@@ -874,21 +872,28 @@ module matmul_axi_slave (
end end
C_RUN: begin C_RUN: begin
// Issue 4 new operands every cycle (pipe_cnt 0-15, 16 rounds) // Issue 4 new operands per round. DMA mode inserts gap
// so the 3-stage CRC pipeline can commit before the next
// C-element capture.
if (pipe_cnt < 5'd16) begin if (pipe_cnt < 5'd16) begin
acc_idx_d1 <= pipe_cnt[3:0]; if (dma_crc_issue_ready) begin
acc_bank_d1 <= cur_bank; acc_idx_d1 <= pipe_cnt[3:0];
acc_valid_d1 <= 1'b1; acc_bank_d1 <= cur_bank;
if (cur_bank == 1'b0) begin acc_valid_d1 <= 1'b1;
m_in_a[0] <= b0_a[{pipe_cnt[3:2], 2'd0}]; m_in_b[0] <= b0_b[{2'd0, pipe_cnt[1:0]}]; if (cur_bank == 1'b0) begin
m_in_a[1] <= b0_a[{pipe_cnt[3:2], 2'd1}]; m_in_b[1] <= b0_b[{2'd1, pipe_cnt[1:0]}]; m_in_a[0] <= b0_a[{pipe_cnt[3:2], 2'd0}]; m_in_b[0] <= b0_b[{2'd0, pipe_cnt[1:0]}];
m_in_a[2] <= b0_a[{pipe_cnt[3:2], 2'd2}]; m_in_b[2] <= b0_b[{2'd2, pipe_cnt[1:0]}]; m_in_a[1] <= b0_a[{pipe_cnt[3:2], 2'd1}]; m_in_b[1] <= b0_b[{2'd1, pipe_cnt[1:0]}];
m_in_a[3] <= b0_a[{pipe_cnt[3:2], 2'd3}]; m_in_b[3] <= b0_b[{2'd3, pipe_cnt[1:0]}]; m_in_a[2] <= b0_a[{pipe_cnt[3:2], 2'd2}]; m_in_b[2] <= b0_b[{2'd2, pipe_cnt[1:0]}];
end else begin m_in_a[3] <= b0_a[{pipe_cnt[3:2], 2'd3}]; m_in_b[3] <= b0_b[{2'd3, pipe_cnt[1:0]}];
m_in_a[0] <= b1_a[{pipe_cnt[3:2], 2'd0}]; m_in_b[0] <= b1_b[{2'd0, pipe_cnt[1:0]}]; end else begin
m_in_a[1] <= b1_a[{pipe_cnt[3:2], 2'd1}]; m_in_b[1] <= b1_b[{2'd1, pipe_cnt[1:0]}]; m_in_a[0] <= b1_a[{pipe_cnt[3:2], 2'd0}]; m_in_b[0] <= b1_b[{2'd0, pipe_cnt[1:0]}];
m_in_a[2] <= b1_a[{pipe_cnt[3:2], 2'd2}]; m_in_b[2] <= b1_b[{2'd2, pipe_cnt[1:0]}]; m_in_a[1] <= b1_a[{pipe_cnt[3:2], 2'd1}]; m_in_b[1] <= b1_b[{2'd1, pipe_cnt[1:0]}];
m_in_a[3] <= b1_a[{pipe_cnt[3:2], 2'd3}]; m_in_b[3] <= b1_b[{2'd3, pipe_cnt[1:0]}]; m_in_a[2] <= b1_a[{pipe_cnt[3:2], 2'd2}]; m_in_b[2] <= b1_b[{2'd2, pipe_cnt[1:0]}];
m_in_a[3] <= b1_a[{pipe_cnt[3:2], 2'd3}]; m_in_b[3] <= b1_b[{2'd3, pipe_cnt[1:0]}];
end
if (dma_busy)
dma_crc_issue_gap <= 2'd2;
pipe_cnt <= pipe_cnt + 5'd1;
end end
end end
@@ -904,17 +909,30 @@ module matmul_axi_slave (
calc_done_pulse <= 1'b1; calc_done_pulse <= 1'b1;
end end
if (pipe_cnt < 5'd16) begin if (pipe_cnt >= 5'd16) begin
pipe_cnt <= pipe_cnt + 5'd1; if (dma_busy) begin
end else if (cur_bank == 1'b0 && req_1) begin if (acc_valid_d4 && acc_idx_d4 == 4'd15) begin
start_calc_bank(1'b1); if (cur_bank == 1'b0 && req_1)
end else if (cur_bank == 1'b1 && req_0) begin start_calc_bank(1'b1);
start_calc_bank(1'b0); else if (cur_bank == 1'b1 && req_0)
end else if (acc_valid_d4 && acc_idx_d4 == 4'd15) begin start_calc_bank(1'b0);
busy <= 1'b0; else begin
state <= C_IDLE; busy <= 1'b0;
end else begin state <= C_IDLE;
pipe_cnt <= pipe_cnt + 5'd1; end
end else begin
pipe_cnt <= pipe_cnt + 5'd1;
end
end else if (cur_bank == 1'b0 && req_1) begin
start_calc_bank(1'b1);
end else if (cur_bank == 1'b1 && req_0) begin
start_calc_bank(1'b0);
end else if (acc_valid_d4 && acc_idx_d4 == 4'd15) begin
busy <= 1'b0;
state <= C_IDLE;
end else begin
pipe_cnt <= pipe_cnt + 5'd1;
end
end end
end end
endcase endcase

View File

@@ -75,21 +75,17 @@ module axi_wrap_ram_sp_external (
output axi_bvalid , output axi_bvalid ,
input axi_bready , input axi_bready ,
//BaseRAM信号 //BaseRAM\Uffffffff\Uffffffff\Uffffffff inout [31:0] base_ram_data, //BaseRAM\Uffffffff\Uffffffff\u0763\Uffffffff\Uffffffff\Uffffffff\u03bb\UffffffffCPLD\Uffffffff\Uffffffff\Uffffffff\u06bf\Uffffffff\Uffffffff\Uffffffff\Uffffffff output [19:0] base_ram_addr, //BaseRAM\Uffffffff\Uffffffff\Uffffffff
inout [31:0] base_ram_data, //BaseRAM数据,低8位与CPLD串口控制器共享 output [ 3:0] base_ram_be_n, //BaseRAM\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff0
output [19:0] base_ram_addr, //BaseRAM地址 output base_ram_ce_n, //BaseRAM\u01ac\u0461\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff
output [ 3:0] base_ram_be_n, //BaseRAM字节使能,低有效。如果不使用字节使能,请保持为0 output base_ram_oe_n, //BaseRAM\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff
output base_ram_ce_n, //BaseRAM片选,低有效 output base_ram_we_n, //BaseRAM\u0434\u02b9\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff
output base_ram_oe_n, //BaseRAM读使能,低有效
output base_ram_we_n, //BaseRAM写使能,低有效
//ExtRAM信号 //ExtRAM\Uffffffff\Uffffffff\Uffffffff inout [31:0] ext_ram_data, //ExtRAM\Uffffffff\Uffffffff\Uffffffff output [19:0] ext_ram_addr, //ExtRAM\Uffffffff\Uffffffff\Uffffffff
inout [31:0] ext_ram_data, //ExtRAM数据 output [ 3:0] ext_ram_be_n, //ExtRAM\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff0
output [19:0] ext_ram_addr, //ExtRAM地址 output ext_ram_ce_n, //ExtRAM\u01ac\u0461\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff
output [ 3:0] ext_ram_be_n, //ExtRAM字节使能,低有效。如果不使用字节使能,请保持为0 output ext_ram_oe_n, //ExtRAM\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff
output ext_ram_ce_n, //ExtRAM片选,低有效 output ext_ram_we_n //ExtRAM\u0434\u02b9\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff\Uffffffff
output ext_ram_oe_n, //ExtRAM读使能,低有效
output ext_ram_we_n //ExtRAM写使能,低有效
); );
@@ -139,6 +135,7 @@ wire ram_bready ;
wire [31:0] soc_sram_addr; wire [31:0] soc_sram_addr;
wire soc_sram_cs; wire soc_sram_cs;
wire soc_sram_we; wire soc_sram_we;
wire soc_sram_bank;
wire [3:0] soc_sram_be; wire [3:0] soc_sram_be;
wire [31:0] soc_sram_wdata; wire [31:0] soc_sram_wdata;
wire [31:0] soc_sram_rdata; wire [31:0] soc_sram_rdata;
@@ -188,7 +185,8 @@ assign ram_bready = axi_bready ;
axi2sram_sp_external #( axi2sram_sp_external #(
.AXI_ID_WIDTH ( 5 ), .AXI_ID_WIDTH ( 5 ),
.AXI_ADDR_WIDTH ( 32 ), .AXI_ADDR_WIDTH ( 32 ),
.AXI_DATA_WIDTH ( 32 )) .AXI_DATA_WIDTH ( 32 ),
.FAST_READ_BURST( 1 ))
u_axi_sram_sp ( u_axi_sram_sp (
.clk ( aclk ), .clk ( aclk ),
.resetn ( aresetn ), .resetn ( aresetn ),
@@ -232,12 +230,13 @@ axi2sram_sp_external #(
.req_o ( soc_sram_cs ), .req_o ( soc_sram_cs ),
.we_o ( soc_sram_we ), .we_o ( soc_sram_we ),
.addr_o ( soc_sram_addr ), .addr_o ( soc_sram_addr ),
.bank_o ( soc_sram_bank ),
.be_o ( soc_sram_be ), .be_o ( soc_sram_be ),
.data_o ( soc_sram_wdata ), .data_o ( soc_sram_wdata ),
.data_i ( soc_sram_rdata ) .data_i ( soc_sram_rdata )
); );
wire choose_sram = soc_sram_addr[22];//1:ExtRAM 0:BaseRAM wire choose_sram = soc_sram_bank;//1:ExtRAM 0:BaseRAM
wire [3:0] be_out = soc_sram_we ? soc_sram_be : 4'b1111; wire [3:0] be_out = soc_sram_we ? soc_sram_be : 4'b1111;
assign base_ram_addr = soc_sram_addr[21:2]; assign base_ram_addr = soc_sram_addr[21:2];

View File

@@ -44,39 +44,38 @@ module soc_top #(parameter SIMULATION=1'b0)
input clk, input clk,
input reset, input reset,
//图像输出信号 output [2:0] video_red,
output [2:0] video_red, //红色像素,3位 output [2:0] video_green,
output [2:0] video_green, //绿色像素,3位 output [1:0] video_blue,
output [1:0] video_blue, //蓝色像素,2位 output video_hsync,
output video_hsync, //行同步(水平同步)信号 output video_vsync,
output video_vsync, //场同步(垂直同步)信号 output video_clk,
output video_clk, //像素时钟输出 output video_de,
output video_de, //行数据有效信号,用于区分消隐区
input [3:0] touch_btn, //BTN1~BTN4,按钮开关,按下时为1 input [3:0] touch_btn,
input [31:0] dip_sw, //32位拨码开关,拨到“ON”时为1 input [31:0] dip_sw,
output [15:0] leds, //16位LED,输出时1点亮 output [15:0] leds,
output [7:0] dpy0, //数码管低位信号,包括小数点,输出1点亮 output [7:0] dpy0,
output [7:0] dpy1, //数码管高位信号,包括小数点,输出1点亮 output [7:0] dpy1,
//BaseRAM信号 // BaseRAM signals
inout [31:0] base_ram_data, //BaseRAM数据,低8位与CPLD串口控制器共享 inout [31:0] base_ram_data,
output [19:0] base_ram_addr, //BaseRAM地址 output [19:0] base_ram_addr,
output [ 3:0] base_ram_be_n, //BaseRAM字节使能,低有效。如果不使用字节使能,请保持为0 output [ 3:0] base_ram_be_n,
output base_ram_ce_n, //BaseRAM片选,低有效 output base_ram_ce_n,
output base_ram_oe_n, //BaseRAM读使能,低有效 output base_ram_oe_n,
output base_ram_we_n, //BaseRAM写使能,低有效 output base_ram_we_n,
//ExtRAM信号 // ExtRAM signals
inout [31:0] ext_ram_data, //ExtRAM数据 inout [31:0] ext_ram_data,
output [19:0] ext_ram_addr, //ExtRAM地址 output [19:0] ext_ram_addr,
output [ 3:0] ext_ram_be_n, //ExtRAM字节使能,低有效。如果不使用字节使能,请保持为0 output [ 3:0] ext_ram_be_n,
output ext_ram_ce_n, //ExtRAM片选,低有效 output ext_ram_ce_n,
output ext_ram_oe_n, //ExtRAM读使能,低有效 output ext_ram_oe_n,
output ext_ram_we_n, //ExtRAM写使能,低有效 output ext_ram_we_n,
//------uart------- //------uart-------
inout UART_RX, //串口RX接收 inout UART_RX,
inout UART_TX //串口TX发送 inout UART_TX
); );
wire cpu_clk; wire cpu_clk;
@@ -360,44 +359,6 @@ wire [3 :0] dma_m_bid ;
wire [1 :0] dma_m_bresp ; wire [1 :0] dma_m_bresp ;
wire dma_m_bvalid ; wire dma_m_bvalid ;
wire dma_m_bready ; wire dma_m_bready ;
wire [3 :0] cdma_m_arid ;
wire [31:0] cdma_m_araddr ;
wire [7 :0] cdma_m_arlen ;
wire [2 :0] cdma_m_arsize ;
wire [1 :0] cdma_m_arburst;
wire cdma_m_arlock ;
wire [3 :0] cdma_m_arcache;
wire [2 :0] cdma_m_arprot ;
wire cdma_m_arvalid;
wire cdma_m_arready = 1'b0;
wire [3 :0] cdma_m_rid = 4'd0;
wire [31:0] cdma_m_rdata = 32'd0;
wire [1 :0] cdma_m_rresp = 2'd0;
wire cdma_m_rlast = 1'b0;
wire cdma_m_rvalid = 1'b0;
wire cdma_m_rready ;
wire [3 :0] cdma_m_awid ;
wire [31:0] cdma_m_awaddr ;
wire [7 :0] cdma_m_awlen ;
wire [2 :0] cdma_m_awsize ;
wire [1 :0] cdma_m_awburst;
wire cdma_m_awlock ;
wire [3 :0] cdma_m_awcache;
wire [2 :0] cdma_m_awprot ;
wire cdma_m_awvalid;
wire cdma_m_awready = 1'b0;
wire [3 :0] cdma_m_wid ;
wire [31:0] cdma_m_wdata ;
wire [3 :0] cdma_m_wstrb ;
wire cdma_m_wlast ;
wire cdma_m_wvalid ;
wire cdma_m_wready = 1'b0;
wire [3 :0] cdma_m_bid = 4'd0;
wire [1 :0] cdma_m_bresp = 2'd0;
wire cdma_m_bvalid = 1'b0;
wire cdma_m_bready ;
wire [4 :0] dma_s_arid ; wire [4 :0] dma_s_arid ;
wire [31:0] dma_s_araddr ; wire [31:0] dma_s_araddr ;
wire [7 :0] dma_s_arlen ; wire [7 :0] dma_s_arlen ;
@@ -433,7 +394,7 @@ wire [4 :0] dma_s_bid ;
wire [1 :0] dma_s_bresp ; wire [1 :0] dma_s_bresp ;
wire dma_s_bvalid ; wire dma_s_bvalid ;
wire dma_s_bready ; wire dma_s_bready ;
wire dma_finish ; wire dma_finish = 1'b0;
// reserved // reserved
wire [4 :0] axiOut_1_arid ; wire [4 :0] axiOut_1_arid ;
@@ -641,7 +602,6 @@ wire axiOut_7_bready ;
wire confreg_int; wire confreg_int;
wire matmul_intr; wire matmul_intr;
wire mlkem_intr;
AxiCrossbar_2x8 u_AxiCrossbar_2x8 ( AxiCrossbar_2x8 u_AxiCrossbar_2x8 (
.clk ( sys_clk ), .clk ( sys_clk ),
@@ -1073,8 +1033,8 @@ AxiCrossbar_2x8 u_AxiCrossbar_2x8 (
core_top u_cpu( core_top u_cpu(
.intrpt ({4'd0, mlkem_intr, matmul_intr, dma_finish, confreg_int}), //high active .intrpt ({4'd0, 1'b0, matmul_intr, dma_finish, confreg_int}), //high active
// intrpt[3]=mlkem, intrpt[2]=matmul, intrpt[1]=dma, intrpt[0]=confreg // intrpt[2]=matmul, intrpt[1]=dma, intrpt[0]=confreg
.aclk (cpu_clk ), .aclk (cpu_clk ),
.aresetn (cpu_resetn ), //low active .aresetn (cpu_resetn ), //low active
@@ -1349,13 +1309,12 @@ axi_uart_controller u_axi_uart_controller
confreg #( confreg #(
.SIMULATION(SIMULATION) .SIMULATION(SIMULATION)
) u_confreg ( ) u_confreg (
// 时钟与复位 .aclk (sys_clk),
.aclk (sys_clk), // AXI总线时钟 .aresetn (sys_resetn),
.aresetn (sys_resetn), // AXI总线复位 .cpu_clk (cpu_clk),
.cpu_clk (cpu_clk), // CPU时钟 .cpu_resetn (cpu_resetn),
.cpu_resetn (cpu_resetn), // CPU复位
// AXI写地址通道 // AXI Write Address
.s_awid (confreg_awid), .s_awid (confreg_awid),
.s_awaddr (confreg_awaddr), .s_awaddr (confreg_awaddr),
.s_awlen (confreg_awlen), .s_awlen (confreg_awlen),
@@ -1367,7 +1326,7 @@ confreg #(
.s_awvalid (confreg_awvalid), .s_awvalid (confreg_awvalid),
.s_awready (confreg_awready), .s_awready (confreg_awready),
// AXI写数据通道 // AXI Write Data
.s_wid (confreg_wid), .s_wid (confreg_wid),
.s_wdata (confreg_wdata), .s_wdata (confreg_wdata),
.s_wstrb (confreg_wstrb), .s_wstrb (confreg_wstrb),
@@ -1375,13 +1334,13 @@ confreg #(
.s_wvalid (confreg_wvalid), .s_wvalid (confreg_wvalid),
.s_wready (confreg_wready), .s_wready (confreg_wready),
// AXI写响应通道 // AXI Write Response
.s_bid (confreg_bid), .s_bid (confreg_bid),
.s_bresp (confreg_bresp), .s_bresp (confreg_bresp),
.s_bvalid (confreg_bvalid), .s_bvalid (confreg_bvalid),
.s_bready (confreg_bready), .s_bready (confreg_bready),
// AXI读地址通道 // AXI Read Address
.s_arid (confreg_arid), .s_arid (confreg_arid),
.s_araddr (confreg_araddr), .s_araddr (confreg_araddr),
.s_arlen (confreg_arlen), .s_arlen (confreg_arlen),
@@ -1393,7 +1352,7 @@ confreg #(
.s_arvalid (confreg_arvalid), .s_arvalid (confreg_arvalid),
.s_arready (confreg_arready), .s_arready (confreg_arready),
// AXI读数据通道 // AXI Read Data
.s_rid (confreg_rid), .s_rid (confreg_rid),
.s_rdata (confreg_rdata), .s_rdata (confreg_rdata),
.s_rresp (confreg_rresp), .s_rresp (confreg_rresp),
@@ -1401,19 +1360,17 @@ confreg #(
.s_rvalid (confreg_rvalid), .s_rvalid (confreg_rvalid),
.s_rready (confreg_rready), .s_rready (confreg_rready),
// IO外设接口 (与soc_top顶层引脚相连) // IO
.led (leds), // 顶层引脚名称为 .led (leds),
.dpy0 (dpy0), // 低位数码管 .dpy0 (dpy0),
.dpy1 (dpy1), // 高位数码管 .dpy1 (dpy1),
.switch (dip_sw), // 拨码开关,顶层名称为 dip_sw .switch (dip_sw),
.touch_btn (touch_btn), // 触摸按钮 .touch_btn (touch_btn),
// 中断与状态信号 .uart0_int (uart0_int),
.uart0_int (uart0_int), // UART0中断 .fft_finish (fft_finish),
.fft_finish (fft_finish), // FFT完成信号 .confreg_int(confreg_int)
.confreg_int(confreg_int) // 输出中断给CPU
); );
axi_dvi u_axi_dvi ( axi_dvi u_axi_dvi (
.s_awvalid ( dvi_awvalid ), .s_awvalid ( dvi_awvalid ),
.s_awaddr ( dvi_awaddr ), .s_awaddr ( dvi_awaddr ),
@@ -1462,69 +1419,20 @@ axi_dvi u_axi_dvi (
.video_blue ( video_blue ) .video_blue ( video_blue )
); );
// slave 6 - ML-KEM accelerator (0x1f400000, virtual 0xbf400000) // slave 6 reserved (mlkem removed)
// Bus runs at sys_clk; the core is internally clocked at sys_clk/2 (25 MHz). assign fft_arready = 1'b1;
mlkem_axi_slave u_mlkem_axi_slave ( assign fft_rid = 5'b0;
.clk (sys_clk), assign fft_rdata = 32'b0;
.resetn (sys_resetn), assign fft_rresp = 2'b0;
assign fft_rlast = 1'b0;
.s_axi_awid (fft_awid ), assign fft_rvalid = 1'b0;
.s_axi_awaddr (fft_awaddr ), assign fft_awready = 1'b1;
.s_axi_awlen (fft_awlen ), assign fft_wready = 1'b1;
.s_axi_awsize (fft_awsize ), assign fft_bid = 5'b0;
.s_axi_awburst (fft_awburst), assign fft_bresp = 2'b0;
.s_axi_awlock (fft_awlock ), assign fft_bvalid = 1'b0;
.s_axi_awcache (fft_awcache),
.s_axi_awprot (fft_awprot ),
.s_axi_awvalid (fft_awvalid),
.s_axi_awready (fft_awready),
.s_axi_wid (fft_wid ),
.s_axi_wdata (fft_wdata ),
.s_axi_wstrb (fft_wstrb ),
.s_axi_wlast (fft_wlast ),
.s_axi_wvalid (fft_wvalid),
.s_axi_wready (fft_wready),
.s_axi_bid (fft_bid ),
.s_axi_bresp (fft_bresp ),
.s_axi_bvalid (fft_bvalid),
.s_axi_bready (fft_bready),
.s_axi_arid (fft_arid ),
.s_axi_araddr (fft_araddr ),
.s_axi_arlen (fft_arlen ),
.s_axi_arsize (fft_arsize ),
.s_axi_arburst (fft_arburst),
.s_axi_arlock (fft_arlock ),
.s_axi_arcache (fft_arcache),
.s_axi_arprot (fft_arprot ),
.s_axi_arvalid (fft_arvalid),
.s_axi_arready (fft_arready),
.s_axi_rid (fft_rid ),
.s_axi_rdata (fft_rdata ),
.s_axi_rresp (fft_rresp ),
.s_axi_rlast (fft_rlast ),
.s_axi_rvalid (fft_rvalid),
.s_axi_rready (fft_rready),
.intr (mlkem_intr)
);
//slave 7 - matmul accelerator //slave 7 - matmul accelerator
wire dma_ep_wr_valid;
wire [3:0] dma_ep_wr_id;
wire [3:0] dma_ep_wr_bank;
wire [7:0] dma_ep_wr_word_addr;
wire [31:0] dma_ep_wr_data;
wire dma_ep_wr_ready;
wire dma_ep_rd_valid;
wire [3:0] dma_ep_rd_id;
wire [3:0] dma_ep_rd_bank;
wire [7:0] dma_ep_rd_word_addr;
wire [31:0] dma_ep_rd_data;
wire dma_ep_rd_ready;
matmul_axi_slave u_matmul_axi_slave ( matmul_axi_slave u_matmul_axi_slave (
.clk (sys_clk), .clk (sys_clk),
.resetn (sys_resetn), .resetn (sys_resetn),
@@ -1570,19 +1478,6 @@ matmul_axi_slave u_matmul_axi_slave (
.s_axi_rvalid (axiOut_7_rvalid), .s_axi_rvalid (axiOut_7_rvalid),
.s_axi_rready (axiOut_7_rready), .s_axi_rready (axiOut_7_rready),
.ep_wr_valid (dma_ep_wr_valid),
.ep_wr_id (dma_ep_wr_id),
.ep_wr_bank (dma_ep_wr_bank),
.ep_wr_word_addr(dma_ep_wr_word_addr),
.ep_wr_data (dma_ep_wr_data),
.ep_wr_ready (dma_ep_wr_ready),
.ep_rd_valid (dma_ep_rd_valid),
.ep_rd_id (dma_ep_rd_id),
.ep_rd_bank (dma_ep_rd_bank),
.ep_rd_word_addr(dma_ep_rd_word_addr),
.ep_rd_data (dma_ep_rd_data),
.ep_rd_ready (dma_ep_rd_ready),
.m_axi_awid (dma_m_awid), .m_axi_awid (dma_m_awid),
.m_axi_awaddr (dma_m_awaddr), .m_axi_awaddr (dma_m_awaddr),
.m_axi_awlen (dma_m_awlen), .m_axi_awlen (dma_m_awlen),
@@ -1622,186 +1517,16 @@ matmul_axi_slave u_matmul_axi_slave (
.intr (matmul_intr) .intr (matmul_intr)
); );
wire [31:0] cdma_s_awaddr; //slave 5 reserved (cdma adapter removed)
wire [2:0] cdma_s_awprot; assign dma_s_arready = 1'b1;
wire cdma_s_awvalid; assign dma_s_rid = 5'b0;
wire cdma_s_awready; assign dma_s_rdata = 32'b0;
wire [31:0] cdma_s_wdata; assign dma_s_rresp = 2'b0;
wire [3:0] cdma_s_wstrb; assign dma_s_rlast = 1'b0;
wire cdma_s_wvalid; assign dma_s_rvalid = 1'b0;
wire cdma_s_wready; assign dma_s_awready = 1'b1;
wire [1:0] cdma_s_bresp; assign dma_s_wready = 1'b1;
wire cdma_s_bvalid; assign dma_s_bid = 5'b0;
wire cdma_s_bready; assign dma_s_bresp = 2'b0;
wire [31:0] cdma_s_araddr; assign dma_s_bvalid = 1'b0;
wire [2:0] cdma_s_arprot;
wire cdma_s_arvalid;
wire cdma_s_arready;
wire [31:0] cdma_s_rdata;
wire [1:0] cdma_s_rresp;
wire cdma_s_rvalid;
wire cdma_s_rready;
axi_axil_adapter #(
.ADDR_WIDTH(32),
.AXI_DATA_WIDTH(32),
.AXI_ID_WIDTH(5),
.AXIL_DATA_WIDTH(32),
.CONVERT_BURST(1),
.CONVERT_NARROW_BURST(0)
)
u_axi_axil_adapter(
.clk(sys_clk),
.rst(~sys_resetn),
.s_axi_awid(dma_s_awid),
.s_axi_awaddr(dma_s_awaddr),
.s_axi_awlen(dma_s_awlen),
.s_axi_awsize(dma_s_awsize),
.s_axi_awburst(dma_s_awburst),
.s_axi_awlock(dma_s_awlock),
.s_axi_awcache(dma_s_awcache),
.s_axi_awprot(dma_s_awprot),
.s_axi_awvalid(dma_s_awvalid),
.s_axi_awready(dma_s_awready),
.s_axi_wdata(dma_s_wdata),
.s_axi_wstrb(dma_s_wstrb),
.s_axi_wlast(dma_s_wlast),
.s_axi_wvalid(dma_s_wvalid),
.s_axi_wready(dma_s_wready),
.s_axi_bid(dma_s_bid),
.s_axi_bresp(dma_s_bresp),
.s_axi_bvalid(dma_s_bvalid),
.s_axi_bready(dma_s_bready),
.s_axi_arid(dma_s_arid),
.s_axi_araddr(dma_s_araddr),
.s_axi_arlen(dma_s_arlen),
.s_axi_arsize(dma_s_arsize),
.s_axi_arburst(dma_s_arburst),
.s_axi_arlock(dma_s_arlock),
.s_axi_arcache(dma_s_arcache),
.s_axi_arprot(dma_s_arprot),
.s_axi_arvalid(dma_s_arvalid),
.s_axi_arready(dma_s_arready),
.s_axi_rid(dma_s_rid),
.s_axi_rdata(dma_s_rdata),
.s_axi_rresp(dma_s_rresp),
.s_axi_rlast(dma_s_rlast),
.s_axi_rvalid(dma_s_rvalid),
.s_axi_rready(dma_s_rready),
.m_axil_awaddr(cdma_s_awaddr),
.m_axil_awprot(cdma_s_awprot),
.m_axil_awvalid(cdma_s_awvalid),
.m_axil_awready(cdma_s_awready),
.m_axil_wdata(cdma_s_wdata),
.m_axil_wstrb(cdma_s_wstrb),
.m_axil_wvalid(cdma_s_wvalid),
.m_axil_wready(cdma_s_wready),
.m_axil_bresp(cdma_s_bresp),
.m_axil_bvalid(cdma_s_bvalid),
.m_axil_bready(cdma_s_bready),
.m_axil_araddr(cdma_s_araddr),
.m_axil_arprot(cdma_s_arprot),
.m_axil_arvalid(cdma_s_arvalid),
.m_axil_arready(cdma_s_arready),
.m_axil_rdata(cdma_s_rdata),
.m_axil_rresp(cdma_s_rresp),
.m_axil_rvalid(cdma_s_rvalid),
.m_axil_rready(cdma_s_rready)
);
// 8 通道 DMA
snix_axil_cdma_mux #(
.ADDR_WIDTH (32),
.DATA_WIDTH (32), // 适配你的 32-bit 总线
.AXIL_ADDR_WIDTH (32),
.AXIL_DATA_WIDTH (32),
.ID_WIDTH (4), // 匹配 Crossbar 的 Master ID 宽度
.USER_WIDTH (1),
.PORTS (4), // 8 个通道
.FIFO_DEPTH (64)
) u_snix_axil_cdma_mux_8ch (
.clk (sys_clk),
.rst_n (sys_resetn), // 低电平复位
// AXI-Lite 从机接口 (接 CPU 发来的配置请求)
.s_axil_awaddr (cdma_s_awaddr),
.s_axil_awvalid (cdma_s_awvalid),
.s_axil_awready (cdma_s_awready),
.s_axil_wdata (cdma_s_wdata),
.s_axil_wstrb (cdma_s_wstrb),
.s_axil_wvalid (cdma_s_wvalid),
.s_axil_wready (cdma_s_wready),
.s_axil_bresp (cdma_s_bresp),
.s_axil_bvalid (cdma_s_bvalid),
.s_axil_bready (cdma_s_bready),
.s_axil_araddr (cdma_s_araddr),
.s_axil_arvalid (cdma_s_arvalid),
.s_axil_arready (cdma_s_arready),
.s_axil_rdata (cdma_s_rdata),
.s_axil_rresp (cdma_s_rresp),
.s_axil_rvalid (cdma_s_rvalid),
.s_axil_rready (cdma_s_rready),
// AXI4 主机接口 (接 Crossbar 去搬运数据)
.mm2mm_awid (cdma_m_awid),
.mm2mm_awaddr (cdma_m_awaddr),
.mm2mm_awlen (cdma_m_awlen),
.mm2mm_awsize (cdma_m_awsize),
.mm2mm_awburst (cdma_m_awburst),
.mm2mm_awlock (cdma_m_awlock),
.mm2mm_awcache (cdma_m_awcache),
.mm2mm_awprot (cdma_m_awprot),
.mm2mm_awqos (), // 悬空即可
.mm2mm_awuser (), // 悬空即可
.mm2mm_awvalid (cdma_m_awvalid),
.mm2mm_awready (cdma_m_awready),
.mm2mm_wdata (cdma_m_wdata),
.mm2mm_wstrb (cdma_m_wstrb),
.mm2mm_wlast (cdma_m_wlast),
.mm2mm_wuser (), // 悬空即可
.mm2mm_wvalid (cdma_m_wvalid),
.mm2mm_wready (cdma_m_wready),
.mm2mm_bid (cdma_m_bid),
.mm2mm_bresp (cdma_m_bresp),
.mm2mm_buser (1'b0),
.mm2mm_bvalid (cdma_m_bvalid),
.mm2mm_bready (cdma_m_bready),
.mm2mm_arid (cdma_m_arid),
.mm2mm_araddr (cdma_m_araddr),
.mm2mm_arlen (cdma_m_arlen),
.mm2mm_arsize (cdma_m_arsize),
.mm2mm_arburst (cdma_m_arburst),
.mm2mm_arlock (cdma_m_arlock),
.mm2mm_arcache (cdma_m_arcache),
.mm2mm_arprot (cdma_m_arprot),
.mm2mm_arqos (), // 悬空即可
.mm2mm_aruser (), // 悬空即可
.mm2mm_arvalid (cdma_m_arvalid),
.mm2mm_arready (cdma_m_arready),
.mm2mm_rid (cdma_m_rid),
.mm2mm_rdata (cdma_m_rdata),
.mm2mm_rresp (cdma_m_rresp),
.mm2mm_rlast (cdma_m_rlast),
.mm2mm_ruser (1'b0),
.mm2mm_rvalid (cdma_m_rvalid),
.mm2mm_rready (cdma_m_rready),
.ep_wr_valid (dma_ep_wr_valid),
.ep_wr_id (dma_ep_wr_id),
.ep_wr_bank (dma_ep_wr_bank),
.ep_wr_word_addr (dma_ep_wr_word_addr),
.ep_wr_data (dma_ep_wr_data),
.ep_wr_ready (dma_ep_wr_ready),
.ep_rd_valid (dma_ep_rd_valid),
.ep_rd_id (dma_ep_rd_id),
.ep_rd_bank (dma_ep_rd_bank),
.ep_rd_word_addr (dma_ep_rd_word_addr),
.ep_rd_data (dma_ep_rd_data),
.ep_rd_ready (dma_ep_rd_ready),
// 全局中断输出
.dma_finish (dma_finish)
);
endmodule endmodule