9 Commits

12 changed files with 626 additions and 830 deletions

View File

@@ -113,7 +113,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// FIFO parameter defines
`define UART_FIFO_WIDTH 8
`define UART_FIFO_DEPTH 16
`define UART_FIFO_POINTER_W 4
`define UART_FIFO_COUNTER_W 5
`define UART_FIFO_DEPTH 32
`define UART_FIFO_POINTER_W 5
`define UART_FIFO_COUNTER_W 6
`define UART_FIFO_REC_WIDTH 11

View File

@@ -20,7 +20,8 @@
module axi2sram_sp_external #(
parameter AXI_ID_WIDTH = 5,
parameter AXI_ADDR_WIDTH = 32,
parameter AXI_DATA_WIDTH = 32
parameter AXI_DATA_WIDTH = 32,
parameter FAST_READ_BURST = 1
)(
input clk,
input resetn,
@@ -64,6 +65,7 @@ module axi2sram_sp_external #(
output reg req_o,
output reg we_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-1:0] data_o,
input [AXI_DATA_WIDTH-1:0] data_i
@@ -100,40 +102,34 @@ module axi2sram_sp_external #(
localparam FIXED = 2'b00;
localparam INCR = 2'b01;
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 [7:0] cnt_d, cnt_q;
reg [8: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;
input [AXI_ADDR_WIDTH-1:0] unaligned_address;
input [7:0] len;
begin
get_wrap_boundary = 'h0;
// for wrapping transfers ax_len can only be of size 1, 3, 7 or 15
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
wire [AXI_ADDR_WIDTH-1:0] ar_burst_bytes =
({{(AXI_ADDR_WIDTH-8){1'b0}}, s_arlen} + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}) << LOG_NR_BYTES;
wire [AXI_ADDR_WIDTH-1:0] aw_burst_bytes =
({{(AXI_ADDR_WIDTH-8){1'b0}}, s_awlen} + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}) << LOG_NR_BYTES;
wire [AXI_ADDR_WIDTH-1:0] ar_wrap_mask = ar_burst_bytes - {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1};
wire [AXI_ADDR_WIDTH-1:0] aw_wrap_mask = aw_burst_bytes - {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1};
reg [AXI_ADDR_WIDTH-1:0] aligned_address;
reg [AXI_ADDR_WIDTH-1:0] wrap_boundary;
reg [AXI_ADDR_WIDTH-1:0] upper_wrap_boundary;
reg [AXI_ADDR_WIDTH-1:0] cons_addr;
reg [AXI_ADDR_WIDTH-1:0] next_addr;
reg [AXI_ADDR_WIDTH-1:0] seq_addr;
always @ (*) begin
// address generation
aligned_address = {ax_req_q_addr[AXI_ADDR_WIDTH-1:LOG_NR_BYTES], {{LOG_NR_BYTES}{1'b0}}};
wrap_boundary = get_wrap_boundary(ax_req_q_addr, ax_req_q_len);
// this will overflow
upper_wrap_boundary = wrap_boundary + ((ax_req_q_len + 1) << LOG_NR_BYTES);
// calculate consecutive address
cons_addr = aligned_address + (cnt_q << LOG_NR_BYTES);
seq_addr = req_addr_q + ADDR_INCR;
case (ax_req_q_burst)
FIXED: next_addr = req_addr_q;
INCR: next_addr = seq_addr;
WRAP: next_addr = (req_addr_q & ~wrap_mask_q) | (seq_addr & wrap_mask_q);
default: next_addr = seq_addr;
endcase
// Transaction attributes
// default assignments
@@ -145,12 +141,16 @@ module axi2sram_sp_external #(
ax_req_d_burst = ax_req_q_burst;
req_addr_d = req_addr_q;
cnt_d = cnt_q;
wrap_mask_d = wrap_mask_q;
req_bank_d = req_bank_q;
read_capture = 1'b0;
// Memory default assignments
data_o = s_wdata;
be_o = s_wstrb;
we_o = 1'b0;
req_o = 1'b0;
addr_o = 'h0;
bank_o = req_bank_q;
// AXI assignments
// request
s_awready = 1'b0;
@@ -183,14 +183,17 @@ module axi2sram_sp_external #(
ax_req_d_len = s_arlen;
ax_req_d_size = s_arsize;
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
req_o = 1'b1;
addr_o = s_araddr;
bank_o = s_araddr[22];
// save the address
req_addr_d = s_araddr;
// save the ar_len
cnt_d = 1;
cnt_d = 0;
// ------------
// Write
// ------------
@@ -204,6 +207,9 @@ module axi2sram_sp_external #(
ax_req_d_len = s_awlen;
ax_req_d_size = s_awsize;
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
if (s_wvalid) begin
req_o = 1'b1;
@@ -230,56 +236,65 @@ module axi2sram_sp_external #(
end
READ: begin
// keep request to memory high
req_o = 1'b1;
addr_o = req_addr_q;
// send the response
s_rvalid = 1'b1;
s_rdata = data_i;
s_rdata = read_data_q;
s_rid = ax_req_q_id;
s_rlast = (cnt_q == ax_req_q_len + 1);
s_rlast = (cnt_q == ({1'b0, ax_req_q_len} + 9'd1));
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
if (s_rready) begin
// we sent the last byte -> go back to idle
if (s_rlast) begin
if (s_arvalid) begin
// Accept the next burst without an intervening
// IDLE cycle and start its SRAM address phase.
s_arready = 1'b1;
ax_req_d_id = s_arid;
ax_req_d_addr = s_araddr;
ax_req_d_len = s_arlen;
ax_req_d_size = s_arsize;
ax_req_d_burst = s_arburst;
wrap_mask_d = ar_wrap_mask;
req_bank_d = s_araddr[22];
req_o = 1'b1;
addr_o = s_araddr;
bank_o = s_araddr[22];
req_addr_d = s_araddr;
// ARVALID was presented during the preceding
// beat, so the async-SRAM address has a full
// cycle to settle before this capture edge.
read_capture = 1'b1;
cnt_d = 1;
state_d = READ;
end else begin
state_d = IDLE;
// we already got everything
end
end
else begin
if (FAST_READ_BURST) begin
read_capture = 1'b1;
req_addr_d = next_addr;
cnt_d = cnt_q + 1;
state_d = READ;
end else begin
req_addr_d = next_addr;
state_d = READ_ADDR;
end
end
end
end
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;
// send the response
s_rvalid = 1'b0;
// ----------------------------
// 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
addr_o = req_addr_q;
read_capture = 1'b1;
cnt_d = cnt_q + 1;
// save the request address for the next cycle
req_addr_d = addr_o;
state_d = READ;
end
@@ -297,24 +312,9 @@ module axi2sram_sp_external #(
// 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
addr_o = next_addr;
// 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
cnt_d = cnt_q + 1;
@@ -345,7 +345,10 @@ module axi2sram_sp_external #(
ax_req_q_len <= 8'h0;
ax_req_q_size <= 3'h0;
req_addr_q <= 'h0;
cnt_q <= 8'h0;
cnt_q <= 9'h0;
wrap_mask_q <= 'h0;
req_bank_q <= 1'b0;
read_data_q <= 'h0;
end else begin
state_q <= state_d;
ax_req_q_addr <= ax_req_d_addr;
@@ -355,6 +358,10 @@ module axi2sram_sp_external #(
ax_req_q_size <= ax_req_d_size;
req_addr_q <= req_addr_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

View File

@@ -101,7 +101,7 @@
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT0_ACTUAL_FREQ">32.97872</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_1">0000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_2">0000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_ACTUAL_FREQ">50.00000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_ACTUAL_FREQ">59.61538</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_DRIVES">BUFG</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_DUTY_CYCLE">50.0</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_MATCHED_ROUTING">false</spirit:configurableElementValue>
@@ -117,10 +117,10 @@
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_DRIVES">BUFG</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_DUTY_CYCLE">50.0</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_MATCHED_ROUTING">false</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_OUT_FREQ">50.00000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_OUT_FREQ">59.61538</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_REQUESTED_DUTY_CYCLE">50.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_REQUESTED_OUT_FREQ">50.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_REQUESTED_OUT_FREQ">60</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_REQUESTED_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_SEQUENCE_NUMBER">1</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_USED">1</spirit:configurableElementValue>
@@ -203,7 +203,7 @@
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIN_PORT">din</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVCLK">0000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE1_AUTO">1</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE2_AUTO">0.66</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE2_AUTO">0.55</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE3_AUTO">0.33</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE4_AUTO">0.33</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE5_AUTO">0.33</spirit:configurableElementValue>
@@ -255,7 +255,7 @@
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT0_DUTY_CYCLE">0.500</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT0_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT0_USE_FINE_PS">FALSE</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT1_DIVIDE">31</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT1_DIVIDE">26</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT1_DUTY_CYCLE">0.500</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT1_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT1_USE_FINE_PS">FALSE</spirit:configurableElementValue>
@@ -293,7 +293,7 @@
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW0A"> Output Output Phase Duty Cycle Pk-to-Pk Phase</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW0B"> Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps)</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW1">_cpu_clk__32.97872______0.000______50.0______130.093____123.600</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW2">_sys_clk__50.00000______0.000______50.0______122.035____123.600</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW2">_sys_clk__59.61538______0.000______50.0______118.808____123.600</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW3">no_CLK_OUT3_output</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW4">no_CLK_OUT4_output</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW5">no_CLK_OUT5_output</spirit:configurableElementValue>
@@ -423,11 +423,11 @@
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT1_SEQUENCE_NUMBER">1</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT1_USED">true</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_DRIVES">BUFG</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_JITTER">122.035</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_JITTER">118.808</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_MATCHED_ROUTING">false</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_PHASE_ERROR">123.600</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_REQUESTED_DUTY_CYCLE">50.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_REQUESTED_OUT_FREQ">50.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_REQUESTED_OUT_FREQ">60</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_REQUESTED_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_SEQUENCE_NUMBER">1</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_USED">true</spirit:configurableElementValue>
@@ -534,7 +534,7 @@
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT0_DUTY_CYCLE">0.500</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT0_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT0_USE_FINE_PS">false</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_DIVIDE">31</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_DIVIDE">26</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_DUTY_CYCLE">0.500</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_USE_FINE_PS">false</spirit:configurableElementValue>

View File

@@ -1,7 +1,5 @@
// ═══════════════════════════════════════════════════════
// 3-stage pipelined multiplier (LUT-based, no DSP)
// latency=3, throughput=1 result/cycle
// ═══════════════════════════════════════════════════════
(* use_dsp = "no", use_dsp48 = "no", syn_multstyle = "logic" *)
module pipelined_mult_32x32 (
input clk,
@@ -43,9 +41,7 @@ module pipelined_mult_32x32 (
endmodule
// ═══════════════════════════════════════════════════════
// 矩阵乘法器顶层模块 (AXI Burst Slave + Ping-Pong + Stream CRC32)
// ═══════════════════════════════════════════════════════
// AXI Burst Slave + Ping-Pong + Stream CRC32
module matmul_axi_slave (
input clk,
input resetn,
@@ -96,21 +92,6 @@ module matmul_axi_slave (
output reg s_axi_rvalid,
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
output reg [3:0] m_axi_awid,
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_STATUS = 12'h004;
@@ -167,6 +148,7 @@ module matmul_axi_slave (
localparam ADDR_DMA_GROUPS = 12'h028;
localparam ADDR_DMA_SRC_STRIDE = 12'h02C;
localparam ADDR_DMA_DST_STRIDE = 12'h030;
localparam ADDR_DMA_CYCLES = 12'h034;
localparam ADDR_B0_A = 12'h100;
localparam ADDR_B0_B = 12'h140;
@@ -177,7 +159,7 @@ module matmul_axi_slave (
localparam ADDR_B1_C = 12'h380;
// ==========================================
// 寄存器与数据缓冲
// Registers and data buffers
// ==========================================
reg req_0, req_1;
reg busy;
@@ -198,8 +180,11 @@ module matmul_axi_slave (
reg [31:0] dma_groups;
reg [31:0] dma_src_stride;
reg [31:0] dma_dst_stride;
// Full sys_clk cycles spent in dma_busy; held after DMA completion.
reg [31:0] dma_cycle_count;
reg dma_busy;
reg dma_done;
reg dma_compute_complete;
reg [31:0] load_group;
reg [31:0] store_group;
reg [31:0] dma_next_rd_addr;
@@ -217,32 +202,46 @@ module matmul_axi_slave (
reg dma_req0_pulse;
reg dma_req1_pulse;
assign ep_wr_ready = 1'b1;
assign ep_rd_ready = 1'b1;
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
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 [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
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
function [31:0] apply_wstrb;
input [31:0] old_value;
@@ -259,29 +258,70 @@ module matmul_axi_slave (
// ==========================================
// 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: two 6-byte CRC steps per 66-bit C-element. A result FIFO
// absorbs the 16-cycle compute burst so the recursive CRC state never
// backpressures the multiplier under the normal DMA load cadence.
// ==========================================
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);
// ---- 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 &&
((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;
wire [31:0] crc_next = crc32_update_word(crc_reg, crc_stream_data);
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_6bytes;
input [31:0] crc_in;
input [47:0] data_in;
reg [31:0] c;
integer byte_idx;
begin
c = crc_in;
for (byte_idx = 0; byte_idx < 6; byte_idx = byte_idx + 1)
c = crc32_table[(c[7:0] ^ data_in[byte_idx*8 +: 8])] ^
{8'h00, c[31:8]};
crc32_update_6bytes = c;
end
endfunction
// ---- DMA result FIFO and two-cycle recursive CRC consumer -----------
localparam CRC_FIFO_DEPTH = 32;
reg [65:0] crc_fifo [0:CRC_FIFO_DEPTH-1];
reg [4:0] crc_fifo_wr_ptr;
reg [4:0] crc_fifo_rd_ptr;
reg [5:0] crc_fifo_count;
reg crc_c66_busy;
reg [65:0] crc_c66_data;
reg [31:0] crc_c66_half;
wire crc_fifo_empty = (crc_fifo_count == 6'd0);
wire crc_fifo_push = dma_busy && acc_valid_d4;
wire crc_fifo_pop = !crc_c66_busy && !crc_fifo_empty;
wire [31:0] crc_c66_first_next =
crc32_update_6bytes(crc_reg, crc_fifo[crc_fifo_rd_ptr][47:0]);
wire [47:0] crc_c66_second_data = {30'b0, crc_c66_data[65:48]};
wire [31:0] crc_c66_final_next =
crc32_update_6bytes(crc_c66_half, crc_c66_second_data);
initial begin
crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096;
@@ -415,7 +455,7 @@ module matmul_axi_slave (
end
// ==========================================
// AXI Write 通道逻辑 (支持 INCR Burst)
// AXI Write (INCR Burst)
// ==========================================
localparam W_IDLE = 2'd0;
localparam W_DATA = 2'd1;
@@ -431,7 +471,6 @@ module matmul_axi_slave (
assign s_axi_bid = w_id;
assign s_axi_bresp = 2'b00;
// 前向声明引擎的状态
localparam C_IDLE = 2'd0;
localparam C_RUN = 2'd1;
reg [1:0] state;
@@ -442,10 +481,19 @@ module matmul_axi_slave (
localparam DMA_RD_ADDR = 2'd1;
localparam DMA_RD_DATA = 2'd2;
reg [1:0] dma_rd_state;
reg [4:0] dma_rd_count;
reg [7:0] dma_rd_count;
reg dma_rd_bank;
wire [4:0] dma_rd_group_word_idx = dma_rd_count[4:0];
wire [3:0] dma_rd_word_idx = dma_rd_count[3:0];
wire dma_rd_fill_bank = dma_rd_bank ^ dma_rd_count[5];
wire dma_rd_commit = (dma_rd_state == DMA_RD_DATA) && m_axi_rvalid && m_axi_rready;
wire dma_bank0_free = !bank_loaded[0] && !bank_compute_pending[0] && !req_0 &&
!(state == C_RUN && cur_bank == 1'b0);
wire dma_bank1_free = !bank_loaded[1] && !bank_compute_pending[1] && !req_1 &&
!(state == C_RUN && cur_bank == 1'b1);
wire dma_load_bank_free = dma_load_bank ? dma_bank1_free : dma_bank0_free;
wire dma_rd_fill_bank_free = dma_rd_fill_bank ? dma_bank1_free : dma_bank0_free;
wire dma_rd_next_bank_free = dma_rd_fill_bank ? dma_bank0_free : dma_bank1_free;
localparam DMA_WR_IDLE = 2'd0;
localparam DMA_WR_ADDR = 2'd1;
@@ -454,31 +502,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 &&
(w_offset == ADDR_STATUS) && s_axi_wdata[1];
@@ -504,32 +527,14 @@ module matmul_axi_slave (
dma_start_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_bank == 1'b0) begin
if (dma_rd_count < 5'd16)
if (dma_rd_fill_bank == 1'b0) begin
if (dma_rd_group_word_idx < 5'd16)
b0_a[dma_rd_word_idx] <= m_axi_rdata;
else
b0_b[dma_rd_word_idx] <= m_axi_rdata;
end else begin
if (dma_rd_count < 5'd16)
if (dma_rd_group_word_idx < 5'd16)
b1_a[dma_rd_word_idx] <= m_axi_rdata;
else
b1_b[dma_rd_word_idx] <= m_axi_rdata;
@@ -574,7 +579,7 @@ module matmul_axi_slave (
dma_src_stride <= apply_wstrb(dma_src_stride, s_axi_wdata, s_axi_wstrb);
else if (w_offset == ADDR_DMA_DST_STRIDE)
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)
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)
@@ -615,7 +620,7 @@ module matmul_axi_slave (
end
// ==========================================
// AXI Read 通道逻辑 (支持 INCR Burst)
// AXI Read (INCR Burst)
// ==========================================
localparam R_IDLE = 2'd0;
localparam R_DATA = 2'd1;
@@ -630,13 +635,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)) ||
@@ -667,7 +672,6 @@ module matmul_axi_slave (
end
R_DATA: begin
if (s_axi_rvalid && s_axi_rready) begin
// 【修改点 3】删掉直接赋值 crc_stream_valid 的逻辑,移至专用 Pipeline 块
if (r_cnt == r_len) begin
s_axi_rvalid <= 1'b0;
s_axi_rlast <= 1'b0;
@@ -695,7 +699,8 @@ module matmul_axi_slave (
else if (current_r_offset == ADDR_CRC)
s_axi_rdata = crc_reg ^ 32'hFFFFFFFF;
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 || !crc_fifo_empty),
dma_done, dma_busy, error, done, busy};
else if (current_r_offset == ADDR_DMA_SRC_BASE)
s_axi_rdata = dma_src_base;
else if (current_r_offset == ADDR_DMA_DST_BASE)
@@ -706,6 +711,8 @@ module matmul_axi_slave (
s_axi_rdata = dma_src_stride;
else if (current_r_offset == ADDR_DMA_DST_STRIDE)
s_axi_rdata = dma_dst_stride;
else if (current_r_offset == ADDR_DMA_CYCLES)
s_axi_rdata = dma_cycle_count;
else if (current_r_offset >= ADDR_B0_A && current_r_offset < ADDR_B0_B)
s_axi_rdata = b0_a[(current_r_offset - ADDR_B0_A) >> 2];
else if (current_r_offset >= ADDR_B0_B && current_r_offset < ADDR_B0_C)
@@ -727,19 +734,8 @@ 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)
// Compute FSM
// ==========================================
wire [63:0] mult_p [0:3];
reg [31:0] m_in_a [0:3];
@@ -763,6 +759,56 @@ 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]});
// Leave eight entries for results already in the multiplier pipeline.
// Under the normal DMA cadence the FIFO stays well below this threshold.
wire dma_crc_issue_ready = !dma_busy || (crc_fifo_count < 6'd24);
// DMA CRC takes priority over the software-driven AXI read stream.
always @(posedge clk) begin
if (!resetn) begin
crc_reg <= 32'hFFFFFFFF;
crc_fifo_wr_ptr <= 5'd0;
crc_fifo_rd_ptr <= 5'd0;
crc_fifo_count <= 6'd0;
crc_c66_busy <= 1'b0;
crc_c66_data <= 66'd0;
crc_c66_half <= 32'd0;
end else if (crc_clear_pulse) begin
crc_reg <= 32'hFFFFFFFF;
crc_fifo_wr_ptr <= 5'd0;
crc_fifo_rd_ptr <= 5'd0;
crc_fifo_count <= 6'd0;
crc_c66_busy <= 1'b0;
crc_c66_data <= 66'd0;
crc_c66_half <= 32'd0;
end else begin
if (crc_fifo_push) begin
crc_fifo[crc_fifo_wr_ptr] <= acc_result;
crc_fifo_wr_ptr <= crc_fifo_wr_ptr + 5'd1;
end
case ({crc_fifo_push, crc_fifo_pop})
2'b10: crc_fifo_count <= crc_fifo_count + 6'd1;
2'b01: crc_fifo_count <= crc_fifo_count - 6'd1;
default: crc_fifo_count <= crc_fifo_count;
endcase
if (crc_c66_busy) begin
crc_reg <= crc_c66_final_next;
crc_c66_busy <= 1'b0;
end else if (crc_fifo_pop) begin
crc_c66_data <= crc_fifo[crc_fifo_rd_ptr];
crc_c66_half <= crc_c66_first_next;
crc_c66_busy <= 1'b1;
crc_fifo_rd_ptr <= crc_fifo_rd_ptr + 5'd1;
end else if (crc_stream_valid) begin
crc_reg <= crc_next;
end
end
end
task start_calc_bank;
input bank;
@@ -810,7 +856,7 @@ module matmul_axi_slave (
end else begin
calc_done_pulse <= 1'b0;
// Pipeline shift: issue_idx → d1 → d2 → d3 → d4 (4 cycles total)
// Pipeline shift (4 cycles total)
acc_idx_d4 <= acc_idx_d3;
acc_idx_d3 <= acc_idx_d2;
acc_idx_d2 <= acc_idx_d1;
@@ -837,8 +883,10 @@ module matmul_axi_slave (
end
C_RUN: begin
// Issue 4 new operands every cycle (pipe_cnt 0-15, 16 rounds)
// Issue one C element per cycle unless the CRC FIFO is
// approaching capacity.
if (pipe_cnt < 5'd16) begin
if (dma_crc_issue_ready) begin
acc_idx_d1 <= pipe_cnt[3:0];
acc_bank_d1 <= cur_bank;
acc_valid_d1 <= 1'b1;
@@ -853,24 +901,36 @@ module matmul_axi_slave (
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
pipe_cnt <= pipe_cnt + 5'd1;
end
end
// 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
calc_done_pulse <= 1'b1;
end
if (pipe_cnt < 5'd16) begin
if (pipe_cnt >= 5'd16) begin
if (dma_busy) begin
if (acc_valid_d4 && acc_idx_d4 == 4'd15) begin
if (cur_bank == 1'b0 && req_1)
start_calc_bank(1'b1);
else if (cur_bank == 1'b1 && req_0)
start_calc_bank(1'b0);
else begin
busy <= 1'b0;
state <= C_IDLE;
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
@@ -882,20 +942,20 @@ module matmul_axi_slave (
pipe_cnt <= pipe_cnt + 5'd1;
end
end
end
endcase
end
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;
dma_done <= 1'b0;
dma_compute_complete <= 1'b0;
dma_cycle_count <= 32'd0;
load_group <= 32'd0;
store_group <= 32'd0;
dma_next_rd_addr <= 32'd0;
@@ -909,7 +969,7 @@ module matmul_axi_slave (
dma_load_bank <= 1'b0;
dma_store_bank <= 1'b0;
dma_rd_state <= DMA_RD_IDLE;
dma_rd_count <= 5'd0;
dma_rd_count <= 8'd0;
dma_rd_bank <= 1'b0;
dma_wr_state <= DMA_WR_IDLE;
dma_wr_count <= 6'd0;
@@ -951,6 +1011,8 @@ module matmul_axi_slave (
if (dma_start_pulse && !dma_busy && dma_groups != 32'd0) begin
dma_busy <= 1'b1;
dma_done <= 1'b0;
dma_compute_complete <= 1'b0;
dma_cycle_count <= 32'd0;
load_group <= 32'd0;
store_group <= 32'd0;
dma_next_rd_addr <= dma_src_base;
@@ -965,19 +1027,21 @@ module matmul_axi_slave (
dma_store_bank <= 1'b0;
dma_rd_state <= DMA_RD_IDLE;
dma_wr_state <= DMA_WR_IDLE;
end else if (dma_busy) begin
dma_cycle_count <= dma_cycle_count + 32'd1;
end
if (dma_busy) begin
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,21 +1051,28 @@ 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)
dma_compute_complete <= 1'b1;
end
if (dma_compute_complete && crc_fifo_empty && !crc_c66_busy) begin
dma_busy <= 1'b0;
dma_done <= 1'b1;
dma_compute_complete <= 1'b0;
end
case (dma_rd_state)
DMA_RD_IDLE: begin
m_axi_arvalid <= 1'b0;
m_axi_rready <= 1'b0;
if (dma_busy && load_group < dma_groups && !bank_loaded[dma_load_bank] &&
!bank_compute_pending[dma_load_bank] &&
!((dma_load_bank == 1'b0) ? req_0 : req_1) &&
!(state == C_RUN && cur_bank == dma_load_bank)) begin
if (dma_busy && load_group < dma_groups && dma_load_bank_free) begin
dma_rd_bank <= dma_load_bank;
dma_rd_count <= 5'd0;
dma_rd_count <= 8'd0;
m_axi_araddr <= dma_next_rd_addr;
m_axi_arlen <= 8'd31;
m_axi_arlen <= ((dma_src_stride == 32'd128) &&
((dma_groups - load_group) >= 32'd8)) ? 8'd255 : 8'd31;
m_axi_arsize <= 3'd2;
m_axi_arburst <= 2'b01;
m_axi_arvalid <= 1'b1;
@@ -1016,16 +1087,54 @@ module matmul_axi_slave (
end
end
DMA_RD_DATA: begin
if (!m_axi_rready && dma_rd_fill_bank_free)
m_axi_rready <= 1'b1;
if (m_axi_rvalid && m_axi_rready) begin
if (m_axi_rlast) begin
m_axi_rready <= 1'b0;
bank_loaded[dma_rd_bank] <= 1'b1;
// Present the next request one beat early so the SRAM
// slave can accept it together with the current RLAST.
if ((dma_rd_count == 8'd254) && dma_busy &&
((load_group + 32'd1) < dma_groups) && dma_rd_next_bank_free) begin
m_axi_araddr <= dma_next_rd_addr + dma_src_stride;
m_axi_arlen <= ((dma_src_stride == 32'd128) &&
((dma_groups - (load_group + 32'd1)) >= 32'd8)) ?
8'd255 : 8'd31;
m_axi_arvalid <= 1'b1;
end
if (dma_rd_group_word_idx == 5'd31) begin
bank_loaded[dma_rd_fill_bank] <= 1'b1;
load_group <= load_group + 32'd1;
dma_next_rd_addr <= dma_next_rd_addr + dma_src_stride;
dma_load_bank <= ~dma_load_bank;
dma_rd_state <= DMA_RD_IDLE;
end
if (m_axi_rlast) begin
m_axi_rready <= 1'b0;
if (dma_busy && ((load_group + 32'd1) < dma_groups) &&
dma_rd_next_bank_free) begin
dma_rd_bank <= ~dma_rd_fill_bank;
dma_rd_count <= 8'd0;
if (m_axi_arvalid && m_axi_arready) begin
m_axi_arvalid <= 1'b0;
m_axi_rready <= 1'b1;
dma_rd_state <= DMA_RD_DATA;
end else begin
dma_rd_count <= dma_rd_count + 5'd1;
m_axi_araddr <= dma_next_rd_addr + dma_src_stride;
m_axi_arlen <= ((dma_src_stride == 32'd128) &&
((dma_groups - (load_group + 32'd1)) >= 32'd8)) ?
8'd255 : 8'd31;
m_axi_arvalid <= 1'b1;
dma_rd_state <= DMA_RD_ADDR;
end
end else begin
m_axi_arvalid <= 1'b0;
dma_rd_state <= DMA_RD_IDLE;
end
end else begin
dma_rd_count <= dma_rd_count + 8'd1;
if ((dma_rd_group_word_idx == 5'd31) && !dma_rd_next_bank_free)
m_axi_rready <= 1'b0;
end
end
end
@@ -1037,56 +1146,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
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;
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

View File

@@ -75,21 +75,21 @@ module axi_wrap_ram_sp_external (
output axi_bvalid ,
input axi_bready ,
//BaseRAM信号
inout [31:0] base_ram_data, //BaseRAM数据,低8位与CPLD串口控制器共享
output [19:0] base_ram_addr, //BaseRAM地址
output [ 3:0] base_ram_be_n, //BaseRAM字节使能,低有效。如果不使用字节使能,请保持为0
output base_ram_ce_n, //BaseRAM片选,低有效
output base_ram_oe_n, //BaseRAM读使能,低有效
output base_ram_we_n, //BaseRAM写使能,低有效
// BaseRAM
inout [31:0] base_ram_data,
output [19:0] base_ram_addr,
output [ 3:0] base_ram_be_n,
output base_ram_ce_n,
output base_ram_oe_n,
output base_ram_we_n,
//ExtRAM信号
inout [31:0] ext_ram_data, //ExtRAM数据
output [19:0] ext_ram_addr, //ExtRAM地址
output [ 3:0] ext_ram_be_n, //ExtRAM字节使能,低有效。如果不使用字节使能,请保持为0
output ext_ram_ce_n, //ExtRAM片选,低有效
output ext_ram_oe_n, //ExtRAM读使能,低有效
output ext_ram_we_n //ExtRAM写使能,低有效
// ExtRAM
inout [31:0] ext_ram_data,
output [19:0] ext_ram_addr,
output [ 3:0] ext_ram_be_n,
output ext_ram_ce_n,
output ext_ram_oe_n,
output ext_ram_we_n
);
@@ -139,6 +139,7 @@ wire ram_bready ;
wire [31:0] soc_sram_addr;
wire soc_sram_cs;
wire soc_sram_we;
wire soc_sram_bank;
wire [3:0] soc_sram_be;
wire [31:0] soc_sram_wdata;
wire [31:0] soc_sram_rdata;
@@ -188,7 +189,8 @@ assign ram_bready = axi_bready ;
axi2sram_sp_external #(
.AXI_ID_WIDTH ( 5 ),
.AXI_ADDR_WIDTH ( 32 ),
.AXI_DATA_WIDTH ( 32 ))
.AXI_DATA_WIDTH ( 32 ),
.FAST_READ_BURST( 1 ))
u_axi_sram_sp (
.clk ( aclk ),
.resetn ( aresetn ),
@@ -232,12 +234,13 @@ axi2sram_sp_external #(
.req_o ( soc_sram_cs ),
.we_o ( soc_sram_we ),
.addr_o ( soc_sram_addr ),
.bank_o ( soc_sram_bank ),
.be_o ( soc_sram_be ),
.data_o ( soc_sram_wdata ),
.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;
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 reset,
//图像输出信号
output [2:0] video_red, //红色像素,3位
output [2:0] video_green, //绿色像素,3位
output [1:0] video_blue, //蓝色像素,2位
output video_hsync, //行同步(水平同步)信号
output video_vsync, //场同步(垂直同步)信号
output video_clk, //像素时钟输出
output video_de, //行数据有效信号,用于区分消隐区
output [2:0] video_red,
output [2:0] video_green,
output [1:0] video_blue,
output video_hsync,
output video_vsync,
output video_clk,
output video_de,
input [3:0] touch_btn, //BTN1~BTN4,按钮开关,按下时为1
input [31:0] dip_sw, //32位拨码开关,拨到“ON”时为1
output [15:0] leds, //16位LED,输出时1点亮
output [7:0] dpy0, //数码管低位信号,包括小数点,输出1点亮
output [7:0] dpy1, //数码管高位信号,包括小数点,输出1点亮
input [3:0] touch_btn,
input [31:0] dip_sw,
output [15:0] leds,
output [7:0] dpy0,
output [7:0] dpy1,
//BaseRAM信号
inout [31:0] base_ram_data, //BaseRAM数据,低8位与CPLD串口控制器共享
output [19:0] base_ram_addr, //BaseRAM地址
output [ 3:0] base_ram_be_n, //BaseRAM字节使能,低有效。如果不使用字节使能,请保持为0
output base_ram_ce_n, //BaseRAM片选,低有效
output base_ram_oe_n, //BaseRAM读使能,低有效
output base_ram_we_n, //BaseRAM写使能,低有效
//ExtRAM信号
inout [31:0] ext_ram_data, //ExtRAM数据
output [19:0] ext_ram_addr, //ExtRAM地址
output [ 3:0] ext_ram_be_n, //ExtRAM字节使能,低有效。如果不使用字节使能,请保持为0
output ext_ram_ce_n, //ExtRAM片选,低有效
output ext_ram_oe_n, //ExtRAM读使能,低有效
output ext_ram_we_n, //ExtRAM写使能,低有效
// BaseRAM signals
inout [31:0] base_ram_data,
output [19:0] base_ram_addr,
output [ 3:0] base_ram_be_n,
output base_ram_ce_n,
output base_ram_oe_n,
output base_ram_we_n,
// ExtRAM signals
inout [31:0] ext_ram_data,
output [19:0] ext_ram_addr,
output [ 3:0] ext_ram_be_n,
output ext_ram_ce_n,
output ext_ram_oe_n,
output ext_ram_we_n,
//------uart-------
inout UART_RX, //串口RX接收
inout UART_TX //串口TX发送
inout UART_RX,
inout UART_TX
);
wire cpu_clk;
@@ -360,44 +359,6 @@ wire [3 :0] dma_m_bid ;
wire [1 :0] dma_m_bresp ;
wire dma_m_bvalid ;
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 [31:0] dma_s_araddr ;
wire [7 :0] dma_s_arlen ;
@@ -433,7 +394,7 @@ wire [4 :0] dma_s_bid ;
wire [1 :0] dma_s_bresp ;
wire dma_s_bvalid ;
wire dma_s_bready ;
wire dma_finish ;
wire dma_finish = 1'b0;
// reserved
wire [4 :0] axiOut_1_arid ;
@@ -641,7 +602,6 @@ wire axiOut_7_bready ;
wire confreg_int;
wire matmul_intr;
wire mlkem_intr;
AxiCrossbar_2x8 u_AxiCrossbar_2x8 (
.clk ( sys_clk ),
@@ -1073,8 +1033,8 @@ AxiCrossbar_2x8 u_AxiCrossbar_2x8 (
core_top u_cpu(
.intrpt ({4'd0, mlkem_intr, matmul_intr, dma_finish, confreg_int}), //high active
// intrpt[3]=mlkem, intrpt[2]=matmul, intrpt[1]=dma, intrpt[0]=confreg
.intrpt ({4'd0, 1'b0, matmul_intr, dma_finish, confreg_int}), //high active
// intrpt[2]=matmul, intrpt[1]=dma, intrpt[0]=confreg
.aclk (cpu_clk ),
.aresetn (cpu_resetn ), //low active
@@ -1349,13 +1309,12 @@ axi_uart_controller u_axi_uart_controller
confreg #(
.SIMULATION(SIMULATION)
) u_confreg (
// 时钟与复位
.aclk (sys_clk), // AXI总线时钟
.aresetn (sys_resetn), // AXI总线复位
.cpu_clk (cpu_clk), // CPU时钟
.cpu_resetn (cpu_resetn), // CPU复位
.aclk (sys_clk),
.aresetn (sys_resetn),
.cpu_clk (cpu_clk),
.cpu_resetn (cpu_resetn),
// AXI写地址通道
// AXI Write Address
.s_awid (confreg_awid),
.s_awaddr (confreg_awaddr),
.s_awlen (confreg_awlen),
@@ -1367,7 +1326,7 @@ confreg #(
.s_awvalid (confreg_awvalid),
.s_awready (confreg_awready),
// AXI写数据通道
// AXI Write Data
.s_wid (confreg_wid),
.s_wdata (confreg_wdata),
.s_wstrb (confreg_wstrb),
@@ -1375,13 +1334,13 @@ confreg #(
.s_wvalid (confreg_wvalid),
.s_wready (confreg_wready),
// AXI写响应通道
// AXI Write Response
.s_bid (confreg_bid),
.s_bresp (confreg_bresp),
.s_bvalid (confreg_bvalid),
.s_bready (confreg_bready),
// AXI读地址通道
// AXI Read Address
.s_arid (confreg_arid),
.s_araddr (confreg_araddr),
.s_arlen (confreg_arlen),
@@ -1393,7 +1352,7 @@ confreg #(
.s_arvalid (confreg_arvalid),
.s_arready (confreg_arready),
// AXI读数据通道
// AXI Read Data
.s_rid (confreg_rid),
.s_rdata (confreg_rdata),
.s_rresp (confreg_rresp),
@@ -1401,19 +1360,17 @@ confreg #(
.s_rvalid (confreg_rvalid),
.s_rready (confreg_rready),
// IO外设接口 (与soc_top顶层引脚相连)
.led (leds), // 顶层引脚名称为
.dpy0 (dpy0), // 低位数码管
.dpy1 (dpy1), // 高位数码管
.switch (dip_sw), // 拨码开关,顶层名称为 dip_sw
.touch_btn (touch_btn), // 触摸按钮
// IO
.led (leds),
.dpy0 (dpy0),
.dpy1 (dpy1),
.switch (dip_sw),
.touch_btn (touch_btn),
// 中断与状态信号
.uart0_int (uart0_int), // UART0中断
.fft_finish (fft_finish), // FFT完成信号
.confreg_int(confreg_int) // 输出中断给CPU
.uart0_int (uart0_int),
.fft_finish (fft_finish),
.confreg_int(confreg_int)
);
axi_dvi u_axi_dvi (
.s_awvalid ( dvi_awvalid ),
.s_awaddr ( dvi_awaddr ),
@@ -1462,69 +1419,20 @@ axi_dvi u_axi_dvi (
.video_blue ( video_blue )
);
// slave 6 - ML-KEM accelerator (0x1f400000, virtual 0xbf400000)
// Bus runs at sys_clk; the core is internally clocked at sys_clk/2 (25 MHz).
mlkem_axi_slave u_mlkem_axi_slave (
.clk (sys_clk),
.resetn (sys_resetn),
.s_axi_awid (fft_awid ),
.s_axi_awaddr (fft_awaddr ),
.s_axi_awlen (fft_awlen ),
.s_axi_awsize (fft_awsize ),
.s_axi_awburst (fft_awburst),
.s_axi_awlock (fft_awlock ),
.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 6 reserved (mlkem removed)
assign fft_arready = 1'b1;
assign fft_rid = 5'b0;
assign fft_rdata = 32'b0;
assign fft_rresp = 2'b0;
assign fft_rlast = 1'b0;
assign fft_rvalid = 1'b0;
assign fft_awready = 1'b1;
assign fft_wready = 1'b1;
assign fft_bid = 5'b0;
assign fft_bresp = 2'b0;
assign fft_bvalid = 1'b0;
//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 (
.clk (sys_clk),
.resetn (sys_resetn),
@@ -1570,19 +1478,6 @@ matmul_axi_slave u_matmul_axi_slave (
.s_axi_rvalid (axiOut_7_rvalid),
.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_awaddr (dma_m_awaddr),
.m_axi_awlen (dma_m_awlen),
@@ -1622,186 +1517,16 @@ matmul_axi_slave u_matmul_axi_slave (
.intr (matmul_intr)
);
wire [31:0] cdma_s_awaddr;
wire [2:0] cdma_s_awprot;
wire cdma_s_awvalid;
wire cdma_s_awready;
wire [31:0] cdma_s_wdata;
wire [3:0] cdma_s_wstrb;
wire cdma_s_wvalid;
wire cdma_s_wready;
wire [1:0] cdma_s_bresp;
wire cdma_s_bvalid;
wire cdma_s_bready;
wire [31:0] cdma_s_araddr;
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)
);
//slave 5 reserved (cdma adapter removed)
assign dma_s_arready = 1'b1;
assign dma_s_rid = 5'b0;
assign dma_s_rdata = 32'b0;
assign dma_s_rresp = 2'b0;
assign dma_s_rlast = 1'b0;
assign dma_s_rvalid = 1'b0;
assign dma_s_awready = 1'b1;
assign dma_s_wready = 1'b1;
assign dma_s_bid = 5'b0;
assign dma_s_bresp = 2'b0;
assign dma_s_bvalid = 1'b0;
endmodule

View File

@@ -24,7 +24,7 @@
00010101011111100100000111101110
00000011100101000000000111001110
00101000100000000000000111001110
00000011100000000110110000001101
00000011100000001000000000001101
01011000000000000000100000001110
00000011100000000000010000001101
00101001000000000000000110001101
@@ -39,160 +39,142 @@
01010000000000000000000000000000
00000000000000000000000000000000
00010101011111100000000000001100
00000010100000010011010000010000
00101001000000000000000110010000
00000010100000010000010000010010
00101001000000000000000110010010
00000010100000010101000000001111
00000010100000010011010000001111
00101001000000000000000110001111
00000010100000010000010000010001
00101001000000000000000110010001
00000010100000010101000000010000
00101001000000000000000110010000
00000010100000010101010000000110
00101001000000000000000110000110
00000010100000010011000000001010
00101001000000000000000110001010
00000010100000010111110000000101
00101001000000000000000110001111
00000010100000010101010000000101
00101001000000000000000110000101
00000010100000010100110000010100
00101001000000000000000110010100
00101001000000000000000110001111
00101001000000000000000110010010
00000010100000010100100000000100
00000010100000010011000000000100
00101001000000000000000110000100
00010101011111101010000000001101
00101001000000000000000110001111
00000011100000000100000110110011
00101001100000000000001001100000
00000011100000000001000110101110
00000010100000000101100000001001
00000010100000010111110000010100
00101001000000000000000110010100
00000010100000010100110000000111
00101001000000000000000110000111
00101001000000000000000110010000
00101001000000000000000110010001
00000010100000010100100000010011
00101001000000000000000110010011
00010101011111101010000000001110
00101001000000000000000110010000
00000011100000000100000111010010
00101001100000000000001001000000
00000010100000000101100000000110
00000011100000000001000111001101
00101001100000000000000110100110
00000011100000001000000111001000
00010100001110001000000000001001
00010100000000000000000000110010
00101001100000000000000100001001
00000011100000001010000111000111
00000011100011100010001001010010
00101001100000000000000011110010
00000011100000001011000111000110
00000010100000100000000000000111
00101001100000000000000011000111
00000010100001000000000000001001
00101001100000000000000111001001
00000011100000001000000110100111
00010100001110001000000000001000
00010100001110001001001110010001
00101001100000000000000011101000
00000011100000001001000110100110
00000011100100000000001000110001
00010100000000000000000000110000
00101001100000000000000011010001
00000011100000001010000110100101
00000011100011100010001000010000
00101001100000000000000010110000
00000011100000001011000110110100
00000010100000100000000000000100
00101001100000000000001010000100
00000011100000001100000110110010
00000010100000110000000000010011
00000010100001000000000000001100
00101001100000000000001001010011
00101001000000000000000110001111
00101001000000000000000110010001
00101001000000000000000110010000
00101001000000000000000110001111
00101001000000000000000110000101
00101001000000000000000110000100
00101001000000000000000110010100
00000010100000010000110000010010
00101001000000000000000110010010
00101001000000000000000110010011
00101001000000000000000110010010
00000010100000001100110000001000
00101001000000000000000110001000
00000010100000001100100000000111
00000010100000001111010000000110
00101001000000000000000110000111
00000010101111111100000001100011
00010101011111101010000000001111
00101001100000000000000110101100
00101000100000000000000111001100
00101001000000000000000110000110
00101000100000000000000110101100
00000011010000000100000110001100
01011011111111111111100110000000
00000010100000000100000000010000
00000011100000000100000111101100
00101001100000000000000111010000
00101000100000000000000110001110
00010101011111100000000000001101
00000011100000000001010110101111
00101010000000000000000111101100
00000010100000000100000000001111
00000011100000000100000111001100
00101001100000000000000110101111
00101000100000000000000110001101
00010101011111100000000000001110
00000011100000000001010111001110
00101010000000000000000111001100
00000011010000001000000110001100
01011011111111111111100110000000
00000010100000010011010000010000
00101001000000000000000110110000
00000010100000010000010000001100
00101001000000000000000110101100
00000010100000010101000000010001
00101001000000000000000110110001
00000000010001001111000111001100
00000000010001001111000110101100
00101001100000000011000001101100
00101010000000000011000001110001
00000010100000010101010000001000
00101001000000000000000110110000
00101001000000000000000110101000
00000010100000010011000000000111
00101001000000000000000110100111
00000010100000010111110000000110
00101001000000000000000110100110
00000010100000010000110000001111
00101001000000000000000110101111
00000010100000010100100000000101
00101001000000000000000110100101
00101001000000000000000110101111
00000010100000001100110000000100
00101001000000000000000110100100
00000010100000001100100000010100
00000010100000001111010000010011
00101001000000000000000110110100
00000010100000000010010000010010
00101001000000000000000110110011
00000010100000010101111000110000
01101000000000000000101001001100
00000010100000001100001000110000
00010101011111100000000000001101
00000000010001001110000111001100
00000011010000000011110110001100
00101001000000000000000110110000
00000010100000000010010000001111
00000010100000010101110110001101
01101000000000000000100111101100
00000010100000001100000110001101
00010101011111100000000000001111
00000000010001001101000111001100
00000011010000000011110110001100
00101001000000000000000111101101
00101010000000000011000001101111
00000010100000000010010000010000
00000010100000010101110110001111
01101100000000010001101000001100
00010101011111100000000000001101
00101001000000000000000110101111
00000011100000000001010110101101
00101010000000000000000110101100
00000011010000001000000110001100
01011011111111111111100110000000
00000000010001001100000111001100
00000011010000000011110110001100
00000010100000000010010000001111
00000010100000010101110110001101
01101000000000000000100111101100
00000010100000001100000110001101
00000010100000010101110111101110
01101000000000000000101000001100
00000010100000001100000111101110
00010101011111100000000000010000
00000000010001001011000111001100
00000000010001001110000110101100
00000011010000000011110110001100
00101001000000000000001000001101
00101001000000000000001000001110
00000010100000000010010000001111
00000010100000010101110110001101
00000010100000010101110110001110
01101000000000000000100111101100
00000010100000001100000110001101
00000010100000001100000110001110
00010101011111100000000000010000
00000000010001001010000111001100
00000000010001001101000110101100
00000011010000000011110110001100
00101001000000000000001000001101
00101001000000000000001000001110
00000010100000000010010000001111
00000010100000010101110110001101
00000010100000010101110110001110
01101000000000000000100111101100
00000010100000001100000110001101
00000010100000001100000110001110
00010101011111100000000000010000
00000000010001001001000111001100
00000000010001001100000110101100
00000011010000000011110110001100
00101001000000000000001000001101
00101001000000000000001000001110
00000010100000000010010000001111
00000010100000010101110110001101
00000010100000010101110110001110
01101000000000000000100111101100
00000010100000001100000110001101
00000010100000001100000110001110
00010101011111100000000000010000
00000000010001001011000110101100
00000011010000000011110110001100
00101001000000000000001000001110
00000010100000000010010000001111
00000010100000010101110110001110
01101000000000000000100111101100
00000010100000001100000110001110
00010101011111100000000000010000
00000000010001001010000110101100
00000011010000000011110110001100
00101001000000000000001000001110
00000010100000000010010000001111
00000010100000010101110110001110
01101000000000000000100111101100
00000010100000001100000110001110
00010101011111100000000000010000
00000000010001001001000110101100
00000011010000000011110110001100
00101001000000000000001000001110
00000010100000000010010000001111
00000010100000010101110110001110
01101000000000000000100111101100
00000010100000001100000110001110
00010101011111100000000000001111
00000011010000000011110111001110
00101001000000000000000111101101
00000011010000000011110110101101
00101001000000000000000111101110
00000010100000000010010000001100
00000010100000010101110111001111
01101000000000000000100110001110
00000010100000001100000111001111
00000010100000010101110110101110
01101000000000000000100110001101
00000010100000001100000110101110
00010101011111100000000000001100
00101001000000000000000110001111
00101001000000000000000110001110
00000010100000010011010000001101
00101001000000000000000110001101
00000010100000010000010000001110
00101001000000000000000110001110
00000010100000010000010000000100
00101001000000000000000110000100
00000010100000010101000000000101
00101001000000000000000110000101
00101001000000000000000110001101
@@ -213,8 +195,6 @@
00000000000101010000000000000100
00000010100000000100000001100011
01001100000000000000000000100000
00000010100000001100000110001111
01010011111111101110101111111111
00000011010000000000000000000000
00000011010000000000000000000000
00000011010000000000000000000000

View File

@@ -118,7 +118,7 @@ _start:
#WRITE(li.wne,OFS_DIVISOR_LSB, divisor & 0xff);
li.w t3, 0xbf20f500
ld.w t3, t3, 0
li.w t2, 0x1b
li.w t2, 0x20
beq zero, t3, 1f
li.w t2, 0x1
1:

View File

@@ -18,6 +18,7 @@ BSP_USE_TRAP := 0
BSP_USE_DRIVERS := 0
endif
LA32RSOC_WINDOWS_HOME?=../../../..
include ../../bsp/common.mk
# Strip picolibc: no -lc -lm -lg -lsemihost, keep -lgcc only

View File

@@ -36,7 +36,7 @@ _start:
st.b zero, t0, 1
li.w t2, 0xbf20f500
ld.w t2, t2, 0
li.w t1, 0x1b
li.w t1, 0x20
beq zero, t2, 1f
li.w t1, 0x1
1:

View File

@@ -1,7 +1,7 @@
/**
* user-sample - CIC-IEC 2026 Stage 3 Evaluation Program
*
* Matmul AXI-master path with fast startup and low-overhead UART output.
* Matmul AXI-master CRC-only path with fast startup and low-overhead UART output.
*/
#include <dma.h>
@@ -33,6 +33,23 @@ static void uart_put_matmul_start_fifo(void)
UART_THR = 'T';
}
static void uart_put_crc_prefix_fifo(void)
{
UART_THR = 'M';
UART_THR = 'A';
UART_THR = 'T';
UART_THR = 'M';
UART_THR = 'U';
UART_THR = 'L';
UART_THR = '_';
UART_THR = 'C';
UART_THR = 'R';
UART_THR = 'C';
UART_THR = '3';
UART_THR = '2';
UART_THR = '=';
}
static inline void uart_wait_tx_empty(void)
{
while ((UART_LSR & LSR_THRE) == 0) {
@@ -49,24 +66,9 @@ static inline unsigned char hex_digit(unsigned int val, int shift)
static void uart_put_result_fifo(unsigned int crc)
{
uart_wait_tx_empty();
UART_THR = 'M';
UART_THR = 'A';
UART_THR = 'T';
UART_THR = 'M';
UART_THR = 'U';
UART_THR = 'L';
UART_THR = '_';
UART_THR = 'C';
UART_THR = 'R';
UART_THR = 'C';
UART_THR = '3';
UART_THR = '2';
UART_THR = '=';
UART_THR = hex_digit(crc, 28);
UART_THR = hex_digit(crc, 24);
UART_THR = hex_digit(crc, 20);
uart_wait_tx_empty();
UART_THR = hex_digit(crc, 16);
UART_THR = hex_digit(crc, 12);
UART_THR = hex_digit(crc, 8);
@@ -97,11 +99,7 @@ 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)
#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)
#define MATMUL_BASE_PHYS 0x1f500000
#define MATMUL_BASE_UNCACHED 0xbf500000
@@ -109,10 +107,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
@@ -144,11 +140,10 @@ 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;
uart_put_crc_prefix_fifo();
while (!(*mat_status & STATUS_DMA_DONE)) {}
*mat_status = STATUS_DMA_DONE;

Binary file not shown.