Split CDMA matmul endpoint engines

This commit is contained in:
2026-07-04 20:42:31 +08:00
parent 2725f6eb57
commit d3a08b1f9d
3 changed files with 408 additions and 315 deletions

View File

@@ -114,16 +114,23 @@ module snix_axil_cdma_mux #(
// ==========================================
// Generic external endpoint requester
// ==========================================
input logic ext_req_valid,
output logic ext_req_ready,
input logic [1:0] ext_req_mode,
input logic [ADDR_WIDTH-1:0] ext_req_src,
input logic [ADDR_WIDTH-1:0] ext_req_dst,
input logic [31:0] ext_req_bytes,
input logic [3:0] ext_req_ep_id,
input logic [3:0] ext_req_ep_bank,
input logic [7:0] ext_req_ep_word_off,
output logic ext_req_done,
input logic ext_rd_req_valid,
output logic ext_rd_req_ready,
input logic [ADDR_WIDTH-1:0] ext_rd_req_src,
input logic [31:0] ext_rd_req_bytes,
input logic [3:0] ext_rd_req_ep_id,
input logic [3:0] ext_rd_req_ep_bank,
input logic [7:0] ext_rd_req_ep_word_off,
output logic ext_rd_req_done,
input logic ext_wr_req_valid,
output logic ext_wr_req_ready,
input logic [ADDR_WIDTH-1:0] ext_wr_req_dst,
input logic [31:0] ext_wr_req_bytes,
input logic [3:0] ext_wr_req_ep_id,
input logic [3:0] ext_wr_req_ep_bank,
input logic [7:0] ext_wr_req_ep_word_off,
output logic ext_wr_req_done,
// Global Interrupt (OR'd from all channels)
output logic dma_finish
@@ -406,71 +413,82 @@ module snix_axil_cdma_mux #(
logic [31:0] ep_bytes_left;
logic [7:0] ep_word_addr_r;
logic ext_active;
logic [1:0] ext_mode_r;
logic [ADDR_WIDTH-1:0] ext_src_r;
logic [ADDR_WIDTH-1:0] ext_dst_r;
logic [31:0] ext_bytes_r;
logic [3:0] ext_ep_id_r;
logic [3:0] ext_ep_bank_r;
logic [7:0] ext_ep_word_off_r;
typedef enum logic [1:0] {EXT_RD_IDLE, EXT_RD_AR, EXT_RD_READ} ext_rd_state_t;
typedef enum logic [1:0] {EXT_WR_IDLE, EXT_WR_AW, EXT_WR_WRITE, EXT_WR_BRESP} ext_wr_state_t;
wire ext_accept = ext_req_valid && ext_req_ready;
wire use_ep_engine = ((state == RUN) && (engine_mode != MODE_MEM2MEM)) || ext_active || ext_accept;
wire select_ext_ep = ext_active || ext_accept;
ext_rd_state_t ext_rd_state;
ext_wr_state_t ext_wr_state;
logic [ADDR_WIDTH-1:0] ext_rd_addr_r;
logic [31:0] ext_rd_bytes_left;
logic [7:0] ext_rd_word_addr_r;
logic [3:0] ext_rd_ep_id_r;
logic [3:0] ext_rd_ep_bank_r;
logic [ADDR_WIDTH-1:0] ext_wr_addr_r;
logic [31:0] ext_wr_bytes_left;
logic [7:0] ext_wr_word_addr_r;
logic [3:0] ext_wr_ep_id_r;
logic [3:0] ext_wr_ep_bank_r;
wire ext_rd_active = (ext_rd_state != EXT_RD_IDLE);
wire ext_wr_active = (ext_wr_state != EXT_WR_IDLE);
wire ext_rd_accept = ext_rd_req_valid && ext_rd_req_ready;
wire ext_wr_accept = ext_wr_req_valid && ext_wr_req_ready;
wire ext_any_busy_or_req = ext_rd_active || ext_wr_active || ext_rd_req_valid || ext_wr_req_valid;
wire use_ep_engine = ((state == RUN) && (engine_mode != MODE_MEM2MEM));
// Dynamic routing to the engine based on current active channel
assign engine_src = ext_accept ? ext_req_src : (select_ext_ep ? ext_src_r : ch_src_addr[cur_ch]);
assign engine_dst = ext_accept ? ext_req_dst : (select_ext_ep ? ext_dst_r : ch_dst_addr[cur_ch]);
assign engine_bytes = ext_accept ? ext_req_bytes : (select_ext_ep ? ext_bytes_r : ch_len[cur_ch]);
assign engine_src = ch_src_addr[cur_ch];
assign engine_dst = ch_dst_addr[cur_ch];
assign engine_bytes = ch_len[cur_ch];
assign engine_len = ch_ctrl[cur_ch][13:6];
assign engine_size = ch_ctrl[cur_ch][5:3];
assign engine_mode = ext_accept ? ext_req_mode : (select_ext_ep ? ext_mode_r : ch_mode[cur_ch][1:0]);
assign engine_ep_bank = ext_accept ? ext_req_ep_bank : (select_ext_ep ? ext_ep_bank_r : ch_ep_cfg[cur_ch][3:0]);
assign engine_ep_word_off = ext_accept ? ext_req_ep_word_off : (select_ext_ep ? ext_ep_word_off_r : ch_ep_cfg[cur_ch][15:8]);
assign engine_ep_id = ext_accept ? ext_req_ep_id : (select_ext_ep ? ext_ep_id_r : ch_ep_cfg[cur_ch][19:16]);
assign engine_mode = ch_mode[cur_ch][1:0];
assign engine_ep_bank = ch_ep_cfg[cur_ch][3:0];
assign engine_ep_word_off = ch_ep_cfg[cur_ch][15:8];
assign engine_ep_id = ch_ep_cfg[cur_ch][19:16];
assign engine_done = (engine_mode == MODE_MEM2MEM) ? mm2mm_done : ep_done;
assign mm2mm_start = engine_start && (engine_mode == MODE_MEM2MEM);
assign ep_start = ext_accept || (engine_start && (engine_mode != MODE_MEM2MEM));
assign ep_start = engine_start && (engine_mode != MODE_MEM2MEM);
assign core_awready = (!use_ep_engine) && mm2mm_awready;
assign core_wready = (!use_ep_engine) && mm2mm_wready;
assign core_arready = (!use_ep_engine) && mm2mm_arready;
assign ep_awready = use_ep_engine && mm2mm_awready;
assign ep_wready = use_ep_engine && mm2mm_wready;
assign ep_arready = use_ep_engine && mm2mm_arready;
assign core_awready = (!ext_wr_active && !use_ep_engine) && mm2mm_awready;
assign core_wready = (!ext_wr_active && !use_ep_engine) && mm2mm_wready;
assign core_arready = (!ext_rd_active && !use_ep_engine) && mm2mm_arready;
assign ep_awready = (!ext_wr_active && use_ep_engine) && mm2mm_awready;
assign ep_wready = (!ext_wr_active && use_ep_engine) && mm2mm_wready;
assign ep_arready = (!ext_rd_active && use_ep_engine) && mm2mm_arready;
assign mm2mm_awid = use_ep_engine ? ep_awid : core_awid;
assign mm2mm_awaddr = use_ep_engine ? ep_awaddr : core_awaddr;
assign mm2mm_awlen = use_ep_engine ? ep_awlen : core_awlen;
assign mm2mm_awsize = use_ep_engine ? ep_awsize : core_awsize;
assign mm2mm_awburst = use_ep_engine ? ep_awburst : core_awburst;
assign mm2mm_awlock = use_ep_engine ? ep_awlock : core_awlock;
assign mm2mm_awcache = use_ep_engine ? ep_awcache : core_awcache;
assign mm2mm_awprot = use_ep_engine ? ep_awprot : core_awprot;
assign mm2mm_awqos = use_ep_engine ? ep_awqos : core_awqos;
assign mm2mm_awuser = use_ep_engine ? ep_awuser : core_awuser;
assign mm2mm_awvalid = use_ep_engine ? ep_awvalid : core_awvalid;
assign mm2mm_awid = ext_wr_active ? '0 : (use_ep_engine ? ep_awid : core_awid);
assign mm2mm_awaddr = ext_wr_active ? ext_wr_addr_r : (use_ep_engine ? ep_awaddr : core_awaddr);
assign mm2mm_awlen = ext_wr_active ? (((ext_wr_bytes_left[31:2] == 30'd0) ? 8'd1 : ext_wr_bytes_left[9:2]) - 8'd1) : (use_ep_engine ? ep_awlen : core_awlen);
assign mm2mm_awsize = ext_wr_active ? 3'd2 : (use_ep_engine ? ep_awsize : core_awsize);
assign mm2mm_awburst = ext_wr_active ? 2'b01 : (use_ep_engine ? ep_awburst : core_awburst);
assign mm2mm_awlock = ext_wr_active ? 1'b0 : (use_ep_engine ? ep_awlock : core_awlock);
assign mm2mm_awcache = ext_wr_active ? 4'b0 : (use_ep_engine ? ep_awcache : core_awcache);
assign mm2mm_awprot = ext_wr_active ? 3'b0 : (use_ep_engine ? ep_awprot : core_awprot);
assign mm2mm_awqos = ext_wr_active ? 4'b0 : (use_ep_engine ? ep_awqos : core_awqos);
assign mm2mm_awuser = ext_wr_active ? '0 : (use_ep_engine ? ep_awuser : core_awuser);
assign mm2mm_awvalid = ext_wr_active ? (ext_wr_state == EXT_WR_AW) : (use_ep_engine ? ep_awvalid : core_awvalid);
assign mm2mm_wdata = use_ep_engine ? ep_wdata : core_wdata;
assign mm2mm_wstrb = use_ep_engine ? ep_wstrb : core_wstrb;
assign mm2mm_wlast = use_ep_engine ? ep_wlast : core_wlast;
assign mm2mm_wuser = use_ep_engine ? ep_wuser : core_wuser;
assign mm2mm_wvalid = use_ep_engine ? ep_wvalid : core_wvalid;
assign mm2mm_bready = use_ep_engine ? ep_bready : core_bready;
assign mm2mm_wdata = ext_wr_active ? ep_rd_data : (use_ep_engine ? ep_wdata : core_wdata);
assign mm2mm_wstrb = ext_wr_active ? {{(DATA_WIDTH/8){1'b1}}} : (use_ep_engine ? ep_wstrb : core_wstrb);
assign mm2mm_wlast = ext_wr_active ? ((ext_wr_bytes_left <= 32'd4) && mm2mm_wvalid) : (use_ep_engine ? ep_wlast : core_wlast);
assign mm2mm_wuser = ext_wr_active ? '0 : (use_ep_engine ? ep_wuser : core_wuser);
assign mm2mm_wvalid = ext_wr_active ? ((ext_wr_state == EXT_WR_WRITE) && ep_rd_ready) : (use_ep_engine ? ep_wvalid : core_wvalid);
assign mm2mm_bready = ext_wr_active ? (ext_wr_state == EXT_WR_BRESP) : (use_ep_engine ? ep_bready : core_bready);
assign mm2mm_arid = use_ep_engine ? ep_arid : core_arid;
assign mm2mm_araddr = use_ep_engine ? ep_araddr : core_araddr;
assign mm2mm_arlen = use_ep_engine ? ep_arlen : core_arlen;
assign mm2mm_arsize = use_ep_engine ? ep_arsize : core_arsize;
assign mm2mm_arburst = use_ep_engine ? ep_arburst : core_arburst;
assign mm2mm_arlock = use_ep_engine ? ep_arlock : core_arlock;
assign mm2mm_arcache = use_ep_engine ? ep_arcache : core_arcache;
assign mm2mm_arprot = use_ep_engine ? ep_arprot : core_arprot;
assign mm2mm_arqos = use_ep_engine ? ep_arqos : core_arqos;
assign mm2mm_aruser = use_ep_engine ? ep_aruser : core_aruser;
assign mm2mm_arvalid = use_ep_engine ? ep_arvalid : core_arvalid;
assign mm2mm_rready = use_ep_engine ? ep_rready : core_rready;
assign mm2mm_arid = ext_rd_active ? '0 : (use_ep_engine ? ep_arid : core_arid);
assign mm2mm_araddr = ext_rd_active ? ext_rd_addr_r : (use_ep_engine ? ep_araddr : core_araddr);
assign mm2mm_arlen = ext_rd_active ? (((ext_rd_bytes_left[31:2] == 30'd0) ? 8'd1 : ext_rd_bytes_left[9:2]) - 8'd1) : (use_ep_engine ? ep_arlen : core_arlen);
assign mm2mm_arsize = ext_rd_active ? 3'd2 : (use_ep_engine ? ep_arsize : core_arsize);
assign mm2mm_arburst = ext_rd_active ? 2'b01 : (use_ep_engine ? ep_arburst : core_arburst);
assign mm2mm_arlock = ext_rd_active ? 1'b0 : (use_ep_engine ? ep_arlock : core_arlock);
assign mm2mm_arcache = ext_rd_active ? 4'b0 : (use_ep_engine ? ep_arcache : core_arcache);
assign mm2mm_arprot = ext_rd_active ? 3'b0 : (use_ep_engine ? ep_arprot : core_arprot);
assign mm2mm_arqos = ext_rd_active ? 4'b0 : (use_ep_engine ? ep_arqos : core_arqos);
assign mm2mm_aruser = ext_rd_active ? '0 : (use_ep_engine ? ep_aruser : core_aruser);
assign mm2mm_arvalid = ext_rd_active ? (ext_rd_state == EXT_RD_AR) : (use_ep_engine ? ep_arvalid : core_arvalid);
assign mm2mm_rready = ext_rd_active ? ((ext_rd_state == EXT_RD_READ) && ep_wr_ready) : (use_ep_engine ? ep_rready : core_rready);
always_ff @(posedge clk) begin
if (!rst_n) begin
@@ -485,7 +503,7 @@ module snix_axil_cdma_mux #(
case (state)
IDLE: begin
if (ext_req_valid || ext_active) begin
if (ext_any_busy_or_req) begin
state <= IDLE;
end else for (int i = 0; i < PORTS; i++) begin
logic [CH_BITS:0] check_ch_ext;
@@ -572,36 +590,100 @@ module snix_axil_cdma_mux #(
wire ep_rd_done_fire = (ep_state == EP_READ) && mm2mm_rvalid && ep_rready && mm2mm_rlast;
wire ep_wr_done_fire = (ep_state == EP_BRESP) && mm2mm_bvalid && ep_bready;
wire ep_done_fast = ep_rd_done_fire || ep_wr_done_fire;
wire ext_rd_done_fire = (ext_rd_state == EXT_RD_READ) && mm2mm_rvalid && mm2mm_rready && mm2mm_rlast;
wire ext_wr_done_fire = (ext_wr_state == EXT_WR_BRESP) && mm2mm_bvalid && mm2mm_bready;
wire ext_wr_w_fire = (ext_wr_state == EXT_WR_WRITE) && mm2mm_wvalid && mm2mm_wready;
// ==========================================
// Generic external endpoint requester
// ==========================================
assign ext_req_ready = !ext_active && (state == IDLE) && (ep_state == EP_IDLE);
assign ext_req_done = ext_active && ep_done_fast;
assign ext_rd_req_ready = (state == IDLE) && (ep_state == EP_IDLE) && !ext_rd_active;
assign ext_wr_req_ready = (state == IDLE) && (ep_state == EP_IDLE) && !ext_wr_active;
assign ext_rd_req_done = ext_rd_done_fire;
assign ext_wr_req_done = ext_wr_done_fire;
always_ff @(posedge clk) begin
if (!rst_n) begin
ext_active <= 1'b0;
ext_mode_r <= MODE_MEM2EP;
ext_src_r <= '0;
ext_dst_r <= '0;
ext_bytes_r <= '0;
ext_ep_id_r <= '0;
ext_ep_bank_r <= '0;
ext_ep_word_off_r <= '0;
ext_rd_state <= EXT_RD_IDLE;
ext_rd_addr_r <= '0;
ext_rd_bytes_left <= '0;
ext_rd_word_addr_r <= '0;
ext_rd_ep_id_r <= '0;
ext_rd_ep_bank_r <= '0;
end else begin
if (ext_accept) begin
ext_active <= 1'b1;
ext_mode_r <= ext_req_mode;
ext_src_r <= ext_req_src;
ext_dst_r <= ext_req_dst;
ext_bytes_r <= ext_req_bytes;
ext_ep_id_r <= ext_req_ep_id;
ext_ep_bank_r <= ext_req_ep_bank;
ext_ep_word_off_r <= ext_req_ep_word_off;
end else if (ext_active && ep_done_fast) begin
ext_active <= 1'b0;
end
case (ext_rd_state)
EXT_RD_IDLE: begin
if (ext_rd_accept) begin
ext_rd_addr_r <= ext_rd_req_src;
ext_rd_bytes_left <= ext_rd_req_bytes;
ext_rd_word_addr_r <= ext_rd_req_ep_word_off;
ext_rd_ep_id_r <= ext_rd_req_ep_id;
ext_rd_ep_bank_r <= ext_rd_req_ep_bank;
ext_rd_state <= EXT_RD_AR;
end
end
EXT_RD_AR: begin
if (mm2mm_arvalid && mm2mm_arready)
ext_rd_state <= EXT_RD_READ;
end
EXT_RD_READ: begin
if (mm2mm_rvalid && mm2mm_rready) begin
ext_rd_word_addr_r <= ext_rd_word_addr_r + 8'd1;
ext_rd_bytes_left <= (ext_rd_bytes_left > 32'd4) ? (ext_rd_bytes_left - 32'd4) : 32'd0;
if (mm2mm_rlast)
ext_rd_state <= EXT_RD_IDLE;
end
end
default: ext_rd_state <= EXT_RD_IDLE;
endcase
end
end
always_ff @(posedge clk) begin
if (!rst_n) begin
ext_wr_state <= EXT_WR_IDLE;
ext_wr_addr_r <= '0;
ext_wr_bytes_left <= '0;
ext_wr_word_addr_r <= '0;
ext_wr_ep_id_r <= '0;
ext_wr_ep_bank_r <= '0;
end else begin
case (ext_wr_state)
EXT_WR_IDLE: begin
if (ext_wr_accept) begin
ext_wr_addr_r <= ext_wr_req_dst;
ext_wr_bytes_left <= ext_wr_req_bytes;
ext_wr_word_addr_r <= ext_wr_req_ep_word_off;
ext_wr_ep_id_r <= ext_wr_req_ep_id;
ext_wr_ep_bank_r <= ext_wr_req_ep_bank;
ext_wr_state <= EXT_WR_AW;
end
end
EXT_WR_AW: begin
if (mm2mm_awvalid && mm2mm_awready)
ext_wr_state <= EXT_WR_WRITE;
end
EXT_WR_WRITE: begin
if (ext_wr_w_fire) begin
ext_wr_word_addr_r <= ext_wr_word_addr_r + 8'd1;
ext_wr_bytes_left <= (ext_wr_bytes_left > 32'd4) ? (ext_wr_bytes_left - 32'd4) : 32'd0;
if (mm2mm_wlast)
ext_wr_state <= EXT_WR_BRESP;
end
end
EXT_WR_BRESP: begin
if (mm2mm_bvalid && mm2mm_bready)
ext_wr_state <= EXT_WR_IDLE;
end
default: ext_wr_state <= EXT_WR_IDLE;
endcase
end
end
@@ -688,10 +770,11 @@ module snix_axil_cdma_mux #(
assign ep_arvalid = (ep_state == EP_AR);
assign ep_rready = (ep_state == EP_READ) && ep_wr_ready;
assign ep_wr_valid = (ep_state == EP_READ) && mm2mm_rvalid && ep_mode_mem2ep;
assign ep_wr_id = engine_ep_id;
assign ep_wr_bank = engine_ep_bank;
assign ep_wr_word_addr = ep_word_addr_r;
assign ep_wr_valid = ext_rd_active ? ((ext_rd_state == EXT_RD_READ) && mm2mm_rvalid) :
((ep_state == EP_READ) && mm2mm_rvalid && ep_mode_mem2ep);
assign ep_wr_id = ext_rd_active ? ext_rd_ep_id_r : engine_ep_id;
assign ep_wr_bank = ext_rd_active ? ext_rd_ep_bank_r : engine_ep_bank;
assign ep_wr_word_addr = ext_rd_active ? ext_rd_word_addr_r : ep_word_addr_r;
assign ep_wr_data = mm2mm_rdata[31:0];
assign ep_awid = '0;
@@ -712,9 +795,10 @@ module snix_axil_cdma_mux #(
assign ep_wvalid = (ep_state == EP_WRITE) && ep_mode_ep2mem && ep_rd_ready;
assign ep_bready = (ep_state == EP_BRESP);
assign ep_rd_valid = (ep_state == EP_WRITE) && ep_mode_ep2mem && ep_wready;
assign ep_rd_id = engine_ep_id;
assign ep_rd_bank = engine_ep_bank;
assign ep_rd_word_addr = ep_word_addr_r;
assign ep_rd_valid = ext_wr_active ? ((ext_wr_state == EXT_WR_WRITE) && mm2mm_wready) :
((ep_state == EP_WRITE) && ep_mode_ep2mem && ep_wready);
assign ep_rd_id = ext_wr_active ? ext_wr_ep_id_r : engine_ep_id;
assign ep_rd_bank = ext_wr_active ? ext_wr_ep_bank_r : engine_ep_bank;
assign ep_rd_word_addr = ext_wr_active ? ext_wr_word_addr_r : ep_word_addr_r;
endmodule