1 Commits

Author SHA1 Message Date
93d2fbd935 Optimize asm matmul dma software path 2026-07-06 00:13:01 +08:00
12 changed files with 842 additions and 638 deletions

View File

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

View File

@@ -20,8 +20,7 @@
module axi2sram_sp_external #( module axi2sram_sp_external #(
parameter AXI_ID_WIDTH = 5, parameter AXI_ID_WIDTH = 5,
parameter AXI_ADDR_WIDTH = 32, parameter AXI_ADDR_WIDTH = 32,
parameter AXI_DATA_WIDTH = 32, parameter AXI_DATA_WIDTH = 32
parameter FAST_READ_BURST = 1
)( )(
input clk, input clk,
input resetn, input resetn,
@@ -65,7 +64,6 @@ 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
@@ -102,34 +100,40 @@ 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 [8: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;
wire [AXI_ADDR_WIDTH-1:0] ar_burst_bytes = function automatic [AXI_ADDR_WIDTH-1:0] get_wrap_boundary;
({{(AXI_ADDR_WIDTH-8){1'b0}}, s_arlen} + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}) << LOG_NR_BYTES; input [AXI_ADDR_WIDTH-1:0] unaligned_address;
wire [AXI_ADDR_WIDTH-1:0] aw_burst_bytes = input [7:0] len;
({{(AXI_ADDR_WIDTH-8){1'b0}}, s_awlen} + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}) << LOG_NR_BYTES; begin
wire [AXI_ADDR_WIDTH-1:0] ar_wrap_mask = ar_burst_bytes - {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}; get_wrap_boundary = 'h0;
wire [AXI_ADDR_WIDTH-1:0] aw_wrap_mask = aw_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
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] next_addr; reg [AXI_ADDR_WIDTH-1:0] aligned_address;
reg [AXI_ADDR_WIDTH-1:0] seq_addr; 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;
always @ (*) begin always @ (*) begin
seq_addr = req_addr_q + ADDR_INCR; // address generation
case (ax_req_q_burst) aligned_address = {ax_req_q_addr[AXI_ADDR_WIDTH-1:LOG_NR_BYTES], {{LOG_NR_BYTES}{1'b0}}};
FIXED: next_addr = req_addr_q; wrap_boundary = get_wrap_boundary(ax_req_q_addr, ax_req_q_len);
INCR: next_addr = seq_addr; // this will overflow
WRAP: next_addr = (req_addr_q & ~wrap_mask_q) | (seq_addr & wrap_mask_q); upper_wrap_boundary = wrap_boundary + ((ax_req_q_len + 1) << LOG_NR_BYTES);
default: next_addr = seq_addr; // calculate consecutive address
endcase cons_addr = aligned_address + (cnt_q << LOG_NR_BYTES);
// Transaction attributes // Transaction attributes
// default assignments // default assignments
@@ -141,16 +145,12 @@ 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;
@@ -183,17 +183,14 @@ 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;
wrap_mask_d = ar_wrap_mask; state_d = READ;
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 = 0; cnt_d = 1;
// ------------ // ------------
// Write // Write
// ------------ // ------------
@@ -207,9 +204,6 @@ 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;
@@ -236,65 +230,56 @@ 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 = read_data_q; s_rdata = data_i;
s_rid = ax_req_q_id; s_rid = ax_req_q_id;
s_rlast = (cnt_q == ({1'b0, ax_req_q_len} + 9'd1)); 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
if (s_rlast) begin 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; state_d = IDLE;
end // we already got everything
end end
else begin 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; state_d = READ_ADDR;
end end
end end
end end
end
READ_ADDR: begin READ_ADDR: begin
// Fill the read data register after the async-SRAM address has // keep request to memory high
// been stable for one full sys_clk cycle.
req_o = 1'b1; req_o = 1'b1;
addr_o = req_addr_q; // send the response
read_capture = 1'b1; 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
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
@@ -312,9 +297,24 @@ module axi2sram_sp_external #(
// Next address generation // Next address generation
// ---------------------------- // ----------------------------
// handle the correct burst type // handle the correct burst type
addr_o = next_addr; 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
// save the request address for the next cycle // save the request address for the next cycle
req_addr_d = next_addr; req_addr_d = addr_o;
// 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;
@@ -345,10 +345,7 @@ module axi2sram_sp_external #(
ax_req_q_len <= 8'h0; ax_req_q_len <= 8'h0;
ax_req_q_size <= 3'h0; ax_req_q_size <= 3'h0;
req_addr_q <= 'h0; req_addr_q <= 'h0;
cnt_q <= 9'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;
@@ -358,10 +355,6 @@ 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

@@ -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_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_1">0000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_2">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">59.61538</spirit:configurableElementValue> <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_ACTUAL_FREQ">50.00000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_DRIVES">BUFG</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_DUTY_CYCLE">50.0</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT1_MATCHED_ROUTING">false</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_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_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_MATCHED_ROUTING">false</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_OUT_FREQ">59.61538</spirit:configurableElementValue> <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_OUT_FREQ">50.00000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_PHASE">0.000</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_DUTY_CYCLE">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_OUT_FREQ">50.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_REQUESTED_PHASE">0.000</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_SEQUENCE_NUMBER">1</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_CLKOUT2_USED">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_DIN_PORT">din</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVCLK">0000</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_DIVIDE1_AUTO">1</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE2_AUTO">0.55</spirit:configurableElementValue> <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE2_AUTO">0.66</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE3_AUTO">0.33</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_DIVIDE4_AUTO">0.33</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DIVIDE5_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_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_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_CLKOUT0_USE_FINE_PS">FALSE</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT1_DIVIDE">26</spirit:configurableElementValue> <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT1_DIVIDE">31</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_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_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MMCM_CLKOUT1_USE_FINE_PS">FALSE</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_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_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_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__59.61538______0.000______50.0______118.808____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_ROW3">no_CLK_OUT3_output</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_ROW4">no_CLK_OUT4_output</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUTCLK_SUM_ROW5">no_CLK_OUT5_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_SEQUENCE_NUMBER">1</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT1_USED">true</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_DRIVES">BUFG</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_JITTER">118.808</spirit:configurableElementValue> <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_JITTER">122.035</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_MATCHED_ROUTING">false</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_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_DUTY_CYCLE">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_OUT_FREQ">50.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_REQUESTED_PHASE">0.000</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_SEQUENCE_NUMBER">1</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CLKOUT2_USED">true</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_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_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_CLKOUT0_USE_FINE_PS">false</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_DIVIDE">26</spirit:configurableElementValue> <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_DIVIDE">31</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_DUTY_CYCLE">0.500</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_PHASE">0.000</spirit:configurableElementValue>
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_USE_FINE_PS">false</spirit:configurableElementValue> <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MMCM_CLKOUT1_USE_FINE_PS">false</spirit:configurableElementValue>

View File

@@ -1,5 +1,7 @@
// ═══════════════════════════════════════════════════════
// 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,
@@ -41,7 +43,9 @@ 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,
@@ -92,6 +96,21 @@ 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,
@@ -138,7 +157,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;
@@ -148,7 +167,6 @@ module matmul_axi_slave (
localparam ADDR_DMA_GROUPS = 12'h028; localparam ADDR_DMA_GROUPS = 12'h028;
localparam ADDR_DMA_SRC_STRIDE = 12'h02C; localparam ADDR_DMA_SRC_STRIDE = 12'h02C;
localparam ADDR_DMA_DST_STRIDE = 12'h030; localparam ADDR_DMA_DST_STRIDE = 12'h030;
localparam ADDR_DMA_CYCLES = 12'h034;
localparam ADDR_B0_A = 12'h100; localparam ADDR_B0_A = 12'h100;
localparam ADDR_B0_B = 12'h140; localparam ADDR_B0_B = 12'h140;
@@ -159,7 +177,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;
@@ -180,11 +198,8 @@ module matmul_axi_slave (
reg [31:0] dma_groups; reg [31:0] dma_groups;
reg [31:0] dma_src_stride; reg [31:0] dma_src_stride;
reg [31:0] dma_dst_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_busy;
reg dma_done; reg dma_done;
reg dma_compute_complete;
reg [31:0] load_group; reg [31:0] load_group;
reg [31:0] store_group; reg [31:0] store_group;
reg [31:0] dma_next_rd_addr; reg [31:0] dma_next_rd_addr;
@@ -202,46 +217,32 @@ module matmul_axi_slave (
reg dma_req0_pulse; reg dma_req0_pulse;
reg dma_req1_pulse; reg dma_req1_pulse;
function [3:0] c_elem_from_word; assign ep_wr_ready = 1'b1;
input [5:0] word_idx; assign ep_rd_ready = 1'b1;
begin
case (word_idx)
6'd0, 6'd1, 6'd2: c_elem_from_word = 4'd0;
6'd3, 6'd4, 6'd5: c_elem_from_word = 4'd1;
6'd6, 6'd7, 6'd8: c_elem_from_word = 4'd2;
6'd9, 6'd10, 6'd11: c_elem_from_word = 4'd3;
6'd12, 6'd13, 6'd14: c_elem_from_word = 4'd4;
6'd15, 6'd16, 6'd17: c_elem_from_word = 4'd5;
6'd18, 6'd19, 6'd20: c_elem_from_word = 4'd6;
6'd21, 6'd22, 6'd23: c_elem_from_word = 4'd7;
6'd24, 6'd25, 6'd26: c_elem_from_word = 4'd8;
6'd27, 6'd28, 6'd29: c_elem_from_word = 4'd9;
6'd30, 6'd31, 6'd32: c_elem_from_word = 4'd10;
6'd33, 6'd34, 6'd35: c_elem_from_word = 4'd11;
6'd36, 6'd37, 6'd38: c_elem_from_word = 4'd12;
6'd39, 6'd40, 6'd41: c_elem_from_word = 4'd13;
6'd42, 6'd43, 6'd44: c_elem_from_word = 4'd14;
default: c_elem_from_word = 4'd15;
endcase
end
endfunction
function [1:0] c_part_from_word; wire [3:0] ep_wr_lo_idx = ep_wr_word_addr[3:0];
input [5:0] word_idx; wire [3:0] ep_wr_hi_idx = ep_wr_word_addr[3:0];
begin wire [7:0] ep_rd_elem_raw = ep_rd_word_addr / 8'd3;
case (word_idx) wire [7:0] ep_rd_part_raw = ep_rd_word_addr % 8'd3;
6'd0, 6'd3, 6'd6, 6'd9, wire [3:0] ep_rd_elem = ep_rd_elem_raw[3:0];
6'd12, 6'd15, 6'd18, 6'd21, wire [1:0] ep_rd_part = ep_rd_part_raw[1:0];
6'd24, 6'd27, 6'd30, 6'd33, wire [65:0] ep_rd_c0 = b0_c[ep_rd_elem];
6'd36, 6'd39, 6'd42, 6'd45: c_part_from_word = 2'd0; wire [65:0] ep_rd_c1 = b1_c[ep_rd_elem];
6'd1, 6'd4, 6'd7, 6'd10,
6'd13, 6'd16, 6'd19, 6'd22, always @(*) begin
6'd25, 6'd28, 6'd31, 6'd34, ep_rd_data = 32'b0;
6'd37, 6'd40, 6'd43, 6'd46: c_part_from_word = 2'd1; if (ep_rd_word_addr < 8'd48) begin
default: c_part_from_word = 2'd2; if (ep_rd_bank[0] == 1'b0) begin
endcase 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 end
endfunction
function [31:0] apply_wstrb; function [31:0] apply_wstrb;
input [31:0] old_value; input [31:0] old_value;
@@ -258,70 +259,29 @@ 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: 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] crc32_table [0:255];
reg [31:0] crc_reg; reg [31:0] crc_reg;
// ---- AXI-stream CRC (single-cycle) ---------------------------------- wire crc_dma_valid;
wire [31:0] crc_stream_data = s_axi_rdata; wire [31:0] crc_dma_data;
wire [31:0] crc_stream_data = crc_dma_valid ? crc_dma_data :
(ep_rd_valid ? ep_rd_data : s_axi_rdata);
wire 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_stream_valid = crc_axi_valid; wire crc_ep_valid = ep_rd_valid && ep_rd_ready && (ep_rd_word_addr < 8'd48);
wire [31:0] crc_next = crc32_update_word(crc_reg, crc_stream_data); wire crc_stream_valid = crc_axi_valid || crc_ep_valid || crc_dma_valid;
function [31:0] crc32_update_word; wire [31:0] crc_t0, crc_c0, crc_t1, crc_c1, crc_t2, crc_c2, crc_t3, crc_next;
input [31:0] crc_in; assign crc_t0 = crc32_table[(crc_reg[7:0] ^ crc_stream_data[7:0])];
input [31:0] data_in; assign crc_c0 = crc_t0 ^ {8'h00, crc_reg[31:8]};
reg [31:0] c0; assign crc_t1 = crc32_table[(crc_c0[7:0] ^ crc_stream_data[15:8])];
reg [31:0] c1; assign crc_c1 = crc_t1 ^ {8'h00, crc_c0[31:8]};
reg [31:0] c2; assign crc_t2 = crc32_table[(crc_c1[7:0] ^ crc_stream_data[23:16])];
begin assign crc_c2 = crc_t2 ^ {8'h00, crc_c1[31:8]};
c0 = crc32_table[(crc_in[7:0] ^ data_in[7:0])] ^ {8'h00, crc_in[31:8]}; assign crc_t3 = crc32_table[(crc_c2[7:0] ^ crc_stream_data[31:24])];
c1 = crc32_table[(c0[7:0] ^ data_in[15:8])] ^ {8'h00, c0[31:8]}; assign crc_next = crc_t3 ^ {8'h00, crc_c2[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 initial begin
crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096; crc32_table[0 ] = 32'h00000000; crc32_table[1 ] = 32'h77073096;
@@ -455,7 +415,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;
@@ -471,6 +431,7 @@ 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;
@@ -481,19 +442,10 @@ module matmul_axi_slave (
localparam DMA_RD_ADDR = 2'd1; localparam DMA_RD_ADDR = 2'd1;
localparam DMA_RD_DATA = 2'd2; localparam DMA_RD_DATA = 2'd2;
reg [1:0] dma_rd_state; reg [1:0] dma_rd_state;
reg [7:0] dma_rd_count; reg [4:0] dma_rd_count;
reg dma_rd_bank; 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 [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_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_IDLE = 2'd0;
localparam DMA_WR_ADDR = 2'd1; localparam DMA_WR_ADDR = 2'd1;
@@ -502,6 +454,31 @@ 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;
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 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];
@@ -527,14 +504,32 @@ 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_fill_bank == 1'b0) begin if (dma_rd_bank == 1'b0) begin
if (dma_rd_group_word_idx < 5'd16) if (dma_rd_count < 5'd16)
b0_a[dma_rd_word_idx] <= m_axi_rdata; b0_a[dma_rd_word_idx] <= m_axi_rdata;
else else
b0_b[dma_rd_word_idx] <= m_axi_rdata; b0_b[dma_rd_word_idx] <= m_axi_rdata;
end else begin end else begin
if (dma_rd_group_word_idx < 5'd16) if (dma_rd_count < 5'd16)
b1_a[dma_rd_word_idx] <= m_axi_rdata; b1_a[dma_rd_word_idx] <= m_axi_rdata;
else else
b1_b[dma_rd_word_idx] <= m_axi_rdata; b1_b[dma_rd_word_idx] <= m_axi_rdata;
@@ -579,7 +574,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);
// CRC register is now managed by the pipelined CRC engine // 【修改点 2】删除 else if (w_offset == ADDR_CRC) { crc_reg <= ... } 防止多重驱动
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)
@@ -620,7 +615,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;
@@ -635,13 +630,13 @@ module matmul_axi_slave (
assign s_axi_rresp = 2'b00; assign s_axi_rresp = 2'b00;
wire [5:0] c0_offset = (r_offset - ADDR_B0_C) >> 2; wire [5:0] c0_offset = (r_offset - ADDR_B0_C) >> 2;
wire [3:0] c0_elem = c_elem_from_word(c0_offset); wire [3:0] c0_elem = c0_offset / 3;
wire [1:0] c0_part = c_part_from_word(c0_offset); wire [1:0] c0_part = c0_offset % 3;
wire [65:0] target_c0 = b0_c[c0_elem]; wire [65:0] target_c0 = b0_c[c0_elem];
wire [5:0] c1_offset = (r_offset - ADDR_B1_C) >> 2; wire [5:0] c1_offset = (r_offset - ADDR_B1_C) >> 2;
wire [3:0] c1_elem = c_elem_from_word(c1_offset); wire [3:0] c1_elem = c1_offset / 3;
wire [1:0] c1_part = c_part_from_word(c1_offset); wire [1:0] c1_part = c1_offset % 3;
wire [65:0] target_c1 = b1_c[c1_elem]; wire [65:0] target_c1 = b1_c[c1_elem];
wire crc_read_en = (r_offset >= ADDR_B0_C && r_offset < (ADDR_B0_C + 12'h0C0)) || wire crc_read_en = (r_offset >= ADDR_B0_C && r_offset < (ADDR_B0_C + 12'h0C0)) ||
@@ -672,6 +667,7 @@ module matmul_axi_slave (
end end
R_DATA: begin R_DATA: begin
if (s_axi_rvalid && s_axi_rready) begin if (s_axi_rvalid && s_axi_rready) begin
// 【修改点 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;
@@ -699,8 +695,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 = {26'b0, (crc_c66_busy || !crc_fifo_empty), s_axi_rdata = {27'b0, dma_done, dma_busy, error, done, 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)
@@ -711,8 +706,6 @@ module matmul_axi_slave (
s_axi_rdata = dma_src_stride; s_axi_rdata = dma_src_stride;
else if (current_r_offset == ADDR_DMA_DST_STRIDE) else if (current_r_offset == ADDR_DMA_DST_STRIDE)
s_axi_rdata = 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) 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]; 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) else if (current_r_offset >= ADDR_B0_B && current_r_offset < ADDR_B0_C)
@@ -734,8 +727,19 @@ module matmul_axi_slave (
end end
end end
// CRC register: update on each C data read beat, clear on write to 0x010
always @(posedge clk) begin
if (!resetn) begin
crc_reg <= 32'hFFFFFFFF;
end else if (crc_clear_pulse) begin
crc_reg <= 32'hFFFFFFFF;
end else if (crc_stream_valid) begin
crc_reg <= crc_next;
end
end
// ========================================== // ==========================================
// Compute FSM // 计算引擎 (Compute FSM)
// ========================================== // ==========================================
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];
@@ -759,56 +763,6 @@ module matmul_axi_slave (
reg acc_bank_d1, acc_bank_d2, acc_bank_d3, acc_bank_d4; 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 acc_valid_d1, acc_valid_d2, acc_valid_d3, acc_valid_d4;
reg [4:0] pipe_cnt; 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; task start_calc_bank;
input bank; input bank;
@@ -856,7 +810,7 @@ module matmul_axi_slave (
end else begin end else begin
calc_done_pulse <= 1'b0; calc_done_pulse <= 1'b0;
// Pipeline shift (4 cycles total) // Pipeline shift: issue_idx → d1 → d2 → d3 → d4 (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;
@@ -883,10 +837,8 @@ module matmul_axi_slave (
end end
C_RUN: begin C_RUN: begin
// Issue one C element per cycle unless the CRC FIFO is // Issue 4 new operands every cycle (pipe_cnt 0-15, 16 rounds)
// approaching capacity.
if (pipe_cnt < 5'd16) begin if (pipe_cnt < 5'd16) begin
if (dma_crc_issue_ready) begin
acc_idx_d1 <= pipe_cnt[3:0]; acc_idx_d1 <= pipe_cnt[3:0];
acc_bank_d1 <= cur_bank; acc_bank_d1 <= cur_bank;
acc_valid_d1 <= 1'b1; acc_valid_d1 <= 1'b1;
@@ -901,36 +853,24 @@ 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[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]}]; 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 end
pipe_cnt <= pipe_cnt + 5'd1;
end
end end
// Accumulate results from 4 cycles ago. // Accumulate results from 4 cycles ago.
if (acc_valid_d4) begin if (acc_valid_d4) begin
if (acc_bank_d4 == 1'b0) if (acc_bank_d4 == 1'b0)
b0_c[acc_idx_d4] <= acc_result; 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]});
else else
b1_c[acc_idx_d4] <= acc_result; 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]});
end end
if (acc_valid_d4 && acc_idx_d4 == 4'd15) begin if (acc_valid_d4 && acc_idx_d4 == 4'd15) begin
calc_done_pulse <= 1'b1; calc_done_pulse <= 1'b1;
end 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; pipe_cnt <= pipe_cnt + 5'd1;
end
end else if (cur_bank == 1'b0 && req_1) begin end else if (cur_bank == 1'b0 && req_1) begin
start_calc_bank(1'b1); start_calc_bank(1'b1);
end else if (cur_bank == 1'b1 && req_0) begin end else if (cur_bank == 1'b1 && req_0) begin
@@ -942,20 +882,20 @@ module matmul_axi_slave (
pipe_cnt <= pipe_cnt + 5'd1; pipe_cnt <= pipe_cnt + 5'd1;
end end
end end
end
endcase endcase
end end
end end
// ========================================== // ==========================================
// Autonomous AXI master loader with inline result CRC. // Autonomous AXI master loader/storer
// ========================================== // ==========================================
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 always @(posedge clk) begin
if (!resetn) begin if (!resetn) begin
dma_busy <= 1'b0; dma_busy <= 1'b0;
dma_done <= 1'b0; dma_done <= 1'b0;
dma_compute_complete <= 1'b0;
dma_cycle_count <= 32'd0;
load_group <= 32'd0; load_group <= 32'd0;
store_group <= 32'd0; store_group <= 32'd0;
dma_next_rd_addr <= 32'd0; dma_next_rd_addr <= 32'd0;
@@ -969,7 +909,7 @@ module matmul_axi_slave (
dma_load_bank <= 1'b0; dma_load_bank <= 1'b0;
dma_store_bank <= 1'b0; dma_store_bank <= 1'b0;
dma_rd_state <= DMA_RD_IDLE; dma_rd_state <= DMA_RD_IDLE;
dma_rd_count <= 8'd0; dma_rd_count <= 5'd0;
dma_rd_bank <= 1'b0; dma_rd_bank <= 1'b0;
dma_wr_state <= DMA_WR_IDLE; dma_wr_state <= DMA_WR_IDLE;
dma_wr_count <= 6'd0; dma_wr_count <= 6'd0;
@@ -1011,8 +951,6 @@ module matmul_axi_slave (
if (dma_start_pulse && !dma_busy && dma_groups != 32'd0) begin if (dma_start_pulse && !dma_busy && dma_groups != 32'd0) begin
dma_busy <= 1'b1; dma_busy <= 1'b1;
dma_done <= 1'b0; dma_done <= 1'b0;
dma_compute_complete <= 1'b0;
dma_cycle_count <= 32'd0;
load_group <= 32'd0; load_group <= 32'd0;
store_group <= 32'd0; store_group <= 32'd0;
dma_next_rd_addr <= dma_src_base; dma_next_rd_addr <= dma_src_base;
@@ -1027,21 +965,19 @@ module matmul_axi_slave (
dma_store_bank <= 1'b0; dma_store_bank <= 1'b0;
dma_rd_state <= DMA_RD_IDLE; dma_rd_state <= DMA_RD_IDLE;
dma_wr_state <= DMA_WR_IDLE; dma_wr_state <= DMA_WR_IDLE;
end else if (dma_busy) begin
dma_cycle_count <= dma_cycle_count + 32'd1;
end end
if (dma_busy) begin if (dma_busy) begin
if (state == C_RUN) if (state == C_RUN)
bank_compute_pending[cur_bank] <= 1'b0; bank_compute_pending[cur_bank] <= 1'b0;
if (bank_loaded[0] && !req_0 && if (bank_loaded[0] && !req_0 && !bank_store_pending[0] && !bank_storing[0] &&
!bank_compute_pending[0] && !(state == C_RUN && cur_bank == 1'b0)) begin !bank_compute_pending[0] && !(state == C_RUN && cur_bank == 1'b0)) begin
dma_req0_pulse <= 1'b1; dma_req0_pulse <= 1'b1;
bank_loaded[0] <= 1'b0; bank_loaded[0] <= 1'b0;
bank_compute_pending[0] <= 1'b1; bank_compute_pending[0] <= 1'b1;
dma_compute_bank <= 1'b0; dma_compute_bank <= 1'b0;
end else if (bank_loaded[1] && !req_1 && end else if (bank_loaded[1] && !req_1 && !bank_store_pending[1] && !bank_storing[1] &&
!bank_compute_pending[1] && !(state == C_RUN && cur_bank == 1'b1)) begin !bank_compute_pending[1] && !(state == C_RUN && cur_bank == 1'b1)) begin
dma_req1_pulse <= 1'b1; dma_req1_pulse <= 1'b1;
bank_loaded[1] <= 1'b0; bank_loaded[1] <= 1'b0;
@@ -1051,28 +987,21 @@ module matmul_axi_slave (
end end
if (calc_done_pulse && dma_busy) begin if (calc_done_pulse && dma_busy) begin
store_group <= store_group + 32'd1; bank_store_pending[cur_bank] <= 1'b1;
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 end
case (dma_rd_state) case (dma_rd_state)
DMA_RD_IDLE: begin DMA_RD_IDLE: begin
m_axi_arvalid <= 1'b0; m_axi_arvalid <= 1'b0;
m_axi_rready <= 1'b0; m_axi_rready <= 1'b0;
if (dma_busy && load_group < dma_groups && dma_load_bank_free) begin 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
dma_rd_bank <= dma_load_bank; dma_rd_bank <= dma_load_bank;
dma_rd_count <= 8'd0; dma_rd_count <= 5'd0;
m_axi_araddr <= dma_next_rd_addr; m_axi_araddr <= dma_next_rd_addr;
m_axi_arlen <= ((dma_src_stride == 32'd128) && m_axi_arlen <= 8'd31;
((dma_groups - load_group) >= 32'd8)) ? 8'd255 : 8'd31;
m_axi_arsize <= 3'd2; m_axi_arsize <= 3'd2;
m_axi_arburst <= 2'b01; m_axi_arburst <= 2'b01;
m_axi_arvalid <= 1'b1; m_axi_arvalid <= 1'b1;
@@ -1087,54 +1016,16 @@ module matmul_axi_slave (
end end
end end
DMA_RD_DATA: begin 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_rvalid && m_axi_rready) begin
// Present the next request one beat early so the SRAM if (m_axi_rlast) begin
// slave can accept it together with the current RLAST. m_axi_rready <= 1'b0;
if ((dma_rd_count == 8'd254) && dma_busy && bank_loaded[dma_rd_bank] <= 1'b1;
((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; load_group <= load_group + 32'd1;
dma_next_rd_addr <= dma_next_rd_addr + dma_src_stride; dma_next_rd_addr <= dma_next_rd_addr + dma_src_stride;
dma_load_bank <= ~dma_load_bank; dma_load_bank <= ~dma_load_bank;
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
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; dma_rd_state <= DMA_RD_IDLE;
end
end else begin end else begin
dma_rd_count <= dma_rd_count + 8'd1; dma_rd_count <= dma_rd_count + 5'd1;
if ((dma_rd_group_word_idx == 5'd31) && !dma_rd_next_bank_free)
m_axi_rready <= 1'b0;
end end
end end
end end
@@ -1146,32 +1037,56 @@ module matmul_axi_slave (
m_axi_awvalid <= 1'b0; m_axi_awvalid <= 1'b0;
m_axi_wvalid <= 1'b0; m_axi_wvalid <= 1'b0;
m_axi_bready <= 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 end
DMA_WR_ADDR: begin DMA_WR_ADDR: begin
if (m_axi_awvalid && m_axi_awready) begin
m_axi_awvalid <= 1'b0; 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; dma_wr_state <= DMA_WR_DATA;
end end
end
DMA_WR_DATA: begin 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_wvalid <= 1'b0;
m_axi_wlast <= 1'b0; m_axi_wlast <= 1'b0;
if (dma_wr_count == 6'd47) begin 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;
bank_storing[dma_store_bank] <= 1'b0; bank_storing[dma_store_bank] <= 1'b0;
dma_store_bank <= ~dma_store_bank; dma_store_bank <= ~dma_store_bank;
store_group <= store_group + 32'd1; store_group <= store_group + 32'd1;
dma_next_wr_addr <= dma_next_wr_addr + dma_dst_stride;
completed_groups <= completed_groups + 32'd1; completed_groups <= completed_groups + 32'd1;
if ((completed_groups + 32'd1) >= dma_groups) begin if ((completed_groups + 32'd1) >= dma_groups) begin
dma_busy <= 1'b0; dma_busy <= 1'b0;
dma_done <= 1'b1; dma_done <= 1'b1;
end end
dma_wr_state <= DMA_WR_IDLE; dma_wr_state <= DMA_WR_IDLE;
end else begin
dma_wr_count <= dma_wr_count + 6'd1;
end end
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; default: dma_wr_state <= DMA_WR_IDLE;
endcase endcase
end end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/** /**
* user-sample - CIC-IEC 2026 Stage 3 Evaluation Program * user-sample - CIC-IEC 2026 Stage 3 Evaluation Program
* *
* Matmul AXI-master CRC-only path with fast startup and low-overhead UART output. * Matmul AXI-master path with fast startup and low-overhead UART output.
*/ */
#include <dma.h> #include <dma.h>
@@ -33,23 +33,6 @@ static void uart_put_matmul_start_fifo(void)
UART_THR = 'T'; 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) static inline void uart_wait_tx_empty(void)
{ {
while ((UART_LSR & LSR_THRE) == 0) { while ((UART_LSR & LSR_THRE) == 0) {
@@ -66,9 +49,24 @@ static inline unsigned char hex_digit(unsigned int val, int shift)
static void uart_put_result_fifo(unsigned int crc) static void uart_put_result_fifo(unsigned int crc)
{ {
uart_wait_tx_empty(); 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, 28);
UART_THR = hex_digit(crc, 24); UART_THR = hex_digit(crc, 24);
UART_THR = hex_digit(crc, 20); UART_THR = hex_digit(crc, 20);
uart_wait_tx_empty();
UART_THR = hex_digit(crc, 16); UART_THR = hex_digit(crc, 16);
UART_THR = hex_digit(crc, 12); UART_THR = hex_digit(crc, 12);
UART_THR = hex_digit(crc, 8); UART_THR = hex_digit(crc, 8);
@@ -99,7 +97,11 @@ unsigned long UART_BASE = 0xbf000000;
#define EXTRAM_BASE_UNCACHED (0xA0000000 | (EXTRAM_BASE_PHYS & 0x1FFFFFFF)) #define EXTRAM_BASE_UNCACHED (0xA0000000 | (EXTRAM_BASE_PHYS & 0x1FFFFFFF))
#define SRC_BASE_WORDS 0 #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_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_PHYS 0x1f500000
#define MATMUL_BASE_UNCACHED 0xbf500000 #define MATMUL_BASE_UNCACHED 0xbf500000
@@ -107,8 +109,10 @@ unsigned long UART_BASE = 0xbf000000;
#define MATMUL_CTRL (MATMUL_BASE_UNCACHED + 0x000) #define MATMUL_CTRL (MATMUL_BASE_UNCACHED + 0x000)
#define MATMUL_STATUS (MATMUL_BASE_UNCACHED + 0x004) #define MATMUL_STATUS (MATMUL_BASE_UNCACHED + 0x004)
#define MATMUL_DMA_SRC_BASE (MATMUL_BASE_UNCACHED + 0x020) #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_GROUPS (MATMUL_BASE_UNCACHED + 0x028)
#define MATMUL_DMA_SRC_STRIDE (MATMUL_BASE_UNCACHED + 0x02C) #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_B0 0x1
#define CTRL_START_B1 0x2 #define CTRL_START_B1 0x2
@@ -140,10 +144,11 @@ int main(void)
*(volatile unsigned int *)MATMUL_CRC = 0; *(volatile unsigned int *)MATMUL_CRC = 0;
*mat_status = STATUS_DMA_DONE | STATUS_DONE | STATUS_ERROR; *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_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_GROUPS = MATMUL_GROUP_NUM;
*(volatile unsigned int *)MATMUL_DMA_SRC_STRIDE = 128; *(volatile unsigned int *)MATMUL_DMA_SRC_STRIDE = 128;
*(volatile unsigned int *)MATMUL_DMA_DST_STRIDE = 192;
*mat_ctrl = CTRL_DMA_START; *mat_ctrl = CTRL_DMA_START;
uart_put_crc_prefix_fifo();
while (!(*mat_status & STATUS_DMA_DONE)) {} while (!(*mat_status & STATUS_DMA_DONE)) {}
*mat_status = STATUS_DMA_DONE; *mat_status = STATUS_DMA_DONE;

Binary file not shown.