From 225aaa4b0d15fa0e4b59df1a7c02915ab5b582d1 Mon Sep 17 00:00:00 2001 From: Thomas Benz Date: Thu, 20 Jun 2024 17:14:32 +0200 Subject: [PATCH 01/13] Multichannel PULP DMAC --- src/dmac_wrap.sv | 693 ++++++++++++++++++++++++ src/frontend/reg/tpl/idma_reg.hjson.tpl | 8 + src/frontend/reg/tpl/idma_reg.sv.tpl | 4 + util/mario/frontend.py | 5 +- 4 files changed, 709 insertions(+), 1 deletion(-) create mode 100644 src/dmac_wrap.sv diff --git a/src/dmac_wrap.sv b/src/dmac_wrap.sv new file mode 100644 index 00000000..4ed24cb6 --- /dev/null +++ b/src/dmac_wrap.sv @@ -0,0 +1,693 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +/* + * dmac_wrap.sv + * Thomas Benz + * Michael Rogenmoser + */ + +// DMA Core wrapper + +`include "axi/assign.svh" +`include "axi/typedef.svh" +`include "idma/typedef.svh" +`include "register_interface/typedef.svh" + +module dmac_wrap #( + parameter int unsigned NB_CORES = 4, + parameter int unsigned AXI_ADDR_WIDTH = 32, + parameter int unsigned AXI_DATA_WIDTH = 64, + parameter int unsigned AXI_USER_WIDTH = 6, + parameter int unsigned AXI_ID_WIDTH = 4, + parameter int unsigned PE_ID_WIDTH = 1, + parameter int unsigned NB_PE_PORTS = 1, + parameter int unsigned DATA_WIDTH = 32, + parameter int unsigned ADDR_WIDTH = 32, + parameter int unsigned BE_WIDTH = DATA_WIDTH/8, + parameter int unsigned NUM_BIDIR_STREAMS = 1, // bidirectional streams: range 1 to 8 + parameter int unsigned NB_OUTSND_BURSTS = 8, + parameter int unsigned GLOBAL_QUEUE_DEPTH = 2 // per-stream +) ( + input logic clk_i, + input logic rst_ni, + input logic test_mode_i, + XBAR_PERIPH_BUS.Slave pe_ctrl_slave[NB_PE_PORTS-1:0], + XBAR_TCDM_BUS.Slave ctrl_slave[NB_CORES-1:0], + hci_core_intf.master tcdm_master[6*NUM_BIDIR_STREAMS-1:0], + AXI_BUS.Master ext_master[NUM_BIDIR_STREAMS-1:0], + output logic [NB_CORES-1:0] term_event_o, + output logic [NB_CORES-1:0] term_irq_o, + output logic [NB_PE_PORTS-1:0] term_event_pe_o, + output logic [NB_PE_PORTS-1:0] term_irq_pe_o, + output logic busy_o +); + + localparam int unsigned NumRegs = NB_CORES + NB_PE_PORTS; + localparam int unsigned NumStreams = 32'd2 * NUM_BIDIR_STREAMS; + localparam int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams); + + // CORE --> MCHAN CTRL INTERFACE BUS SIGNALS + logic [NumRegs-1:0][DATA_WIDTH-1:0] config_wdata; + logic [NumRegs-1:0][ADDR_WIDTH-1:0] config_add; + logic [NumRegs-1:0] config_req; + logic [NumRegs-1:0] config_wen; + logic [NumRegs-1:0][BE_WIDTH-1:0] config_be; + logic [NumRegs-1:0][PE_ID_WIDTH-1:0] config_id; + logic [NumRegs-1:0] config_gnt; + logic [NumRegs-1:0][DATA_WIDTH-1:0] config_r_rdata; + logic [NumRegs-1:0] config_r_valid; + logic [NumRegs-1:0] config_r_opc; + logic [NumRegs-1:0][PE_ID_WIDTH-1:0] config_r_id; + + // tie-off pe control ports + for (genvar i = 0; i < NB_CORES; i++) begin : gen_ctrl_registers + assign config_add[i] = ctrl_slave[i].add; + assign config_req[i] = ctrl_slave[i].req; + assign config_wdata[i] = ctrl_slave[i].wdata; + assign config_wen[i] = ctrl_slave[i].wen; + assign config_be[i] = ctrl_slave[i].be; + assign config_id[i] = '0; + assign ctrl_slave[i].gnt = config_gnt[i]; + assign ctrl_slave[i].r_opc = config_r_opc[i]; + assign ctrl_slave[i].r_valid = config_r_valid[i]; + assign ctrl_slave[i].r_rdata = config_r_rdata[i]; + end + + for (genvar i = 0; i < NB_PE_PORTS; i++) begin : gen_pe_ctrl_registers + assign config_add[NB_CORES+i] = pe_ctrl_slave[i].add; + assign config_req[NB_CORES+i] = pe_ctrl_slave[i].req; + assign config_wdata[NB_CORES+i] = pe_ctrl_slave[i].wdata; + assign config_wen[NB_CORES+i] = pe_ctrl_slave[i].wen; + assign config_be[NB_CORES+i] = pe_ctrl_slave[i].be; + assign config_id[NB_CORES+i] = pe_ctrl_slave[i].id; + assign pe_ctrl_slave[i].gnt = config_gnt[NB_CORES+i]; + assign pe_ctrl_slave[i].r_opc = config_r_opc[NB_CORES+i]; + assign pe_ctrl_slave[i].r_valid = config_r_valid[NB_CORES+i]; + assign pe_ctrl_slave[i].r_rdata = config_r_rdata[NB_CORES+i]; + assign pe_ctrl_slave[i].r_id = config_r_id[NB_CORES+i]; + end + + // Types types + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [ADDR_WIDTH-1:0] mem_addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_ID_WIDTH-1:0] id_t; + typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; + + // // AXI4+ATOP channels typedefs + `AXI_TYPEDEF_ALL(axi, addr_t, id_t, data_t, strb_t, user_t) + + // Memory Init typedefs + /// init read request + typedef struct packed { + logic [AXI_ADDR_WIDTH-1:0] cfg; + logic [AXI_DATA_WIDTH-1:0] term; + logic [AXI_STRB_WIDTH-1:0] strb; + logic [AXI_ID_WIDTH-1:0] id; + } init_req_chan_t; + + typedef struct packed { + init_req_chan_t req_chan; + logic req_valid; + logic rsp_ready; + } init_req_t; + + typedef struct packed { + logic [AXI_DATA_WIDTH-1:0] init; + } init_rsp_chan_t; + + typedef struct packed { + init_rsp_chan_t rsp_chan; + logic rsp_valid; + logic req_ready; + } init_rsp_t; + + // OBI typedefs + `OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) + `OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) + `OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) + `OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + `OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) + `OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) + + obi_req_t [NUM_BIDIR_STREAMS-1:0] obi_read_req, obi_reorg_req, obi_write_req, obi_tcdm_req; + obi_rsp_t [NUM_BIDIR_STREAMS-1:0] obi_read_rsp, obi_reorg_rsp, obi_write_rsp, obi_tcdm_rsp; + + // BUS definitions + axi_req_t [NUM_BIDIR_STREAMS-1:0] soc_req; + axi_resp_t [NUM_BIDIR_STREAMS-1:0] soc_rsp; + axi_req_t [NumStreams-1:0] dma_req; + axi_resp_t [NumStreams-1:0] dma_rsp; + + // interface to structs + for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin : gen_connect_interface + `AXI_ASSIGN_FROM_REQ(ext_master[s], soc_req[s]) + `AXI_ASSIGN_TO_RESP(soc_rsp[s], ext_master[s]) + end + + // connect RW axi buses + for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin : gen_rw_axi_connection + axi_rw_join #( + .axi_req_t ( axi_req_t ), + .axi_resp_t ( axi_resp_t ) + ) i_init_axi_rw_join ( + .clk_i, + .rst_ni, + .slv_read_req_i ( dma_req[2*s+1] ), + .slv_read_resp_o ( dma_rsp[2*s+1] ), + .slv_write_req_i ( dma_req[2*s] ), + .slv_write_resp_o ( dma_rsp[2*s] ), + .mst_req_o ( soc_req[s] ), + .mst_resp_i ( soc_rsp[s] ) + ); + end + + // Register BUS definitions + localparam int unsigned RegAddrWidth = 32'd10; + `REG_BUS_TYPEDEF_ALL(dma_regs, logic[RegAddrWidth-1:0], logic[DATA_WIDTH-1:0], logic[BE_WIDTH-1:0]) + dma_regs_req_t [NumRegs-1:0] dma_regs_req; + dma_regs_rsp_t [NumRegs-1:0] dma_regs_rsp; + + // iDMA struct definitions + localparam int unsigned TFLenWidth = AXI_ADDR_WIDTH; + localparam int unsigned NumDim = 32'd3; // Support 2D midend for 2D transfers + localparam int unsigned RepWidth = 32'd32; + localparam int unsigned StrideWidth = 32'd32; + typedef logic [TFLenWidth-1:0] tf_len_t; + typedef logic [RepWidth-1:0] reps_t; + typedef logic [StrideWidth-1:0] strides_t; + + // iDMA request / response types + `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, slv_id_t, addr_t, tf_len_t) + `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, addr_t) + + // iDMA ND request + `IDMA_TYPEDEF_FULL_ND_REQ_T(idma_nd_req_t, idma_req_t, reps_t, strides_t) + + logic [StreamWidth-1:0] stream_idx; + + idma_nd_req_t [NumStreams-1:0] twod_req, twod_req_queue; + idma_req_t [NumStreams-1:0] idma_req; + idma_rsp_t [NumStreams-1:0] idma_rsp; + + logic one_fe_valid; + logic [NumStreams-1:0] fe_valid, twod_queue_valid, be_valid, be_rsp_valid; + logic [NumStreams-1:0] fe_ready, twod_queue_ready, be_ready, be_rsp_ready; + logic [NumStreams-1:0] trans_complete, midend_busy; + idma_pkg::idma_busy_t [NumStreams-1:0] idma_busy; + + logic [31:0][NumStreams-1:0] done_id, next_id; + + // ------------------------------------------------------ + // FRONTEND + // ------------------------------------------------------ + + for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs + periph_to_reg #( + .AW ( RegAddrWidth ), + .DW ( DATA_WIDTH ), + .BW ( BE_WIDTH ), + .IW ( PE_ID_WIDTH ), + .req_t ( dma_regs_req_t ), + .rsp_t ( dma_regs_rsp_t ) + ) i_pe_translate ( + .clk_i, + .rst_ni, + .req_i ( config_req [i] ), + .add_i ( config_add [i][RegAddrWidth-1:0] ), + .wen_i ( config_wen [i] ), + .wdata_i ( config_wdata [i] ), + .be_i ( config_be [i] ), + .id_i ( config_id [i] ), + .gnt_o ( config_gnt [i] ), + .r_rdata_o ( config_r_rdata [i] ), + .r_opc_o ( config_r_opc [i] ), + .r_id_o ( config_r_id [i] ), + .r_valid_o ( config_r_valid [i] ), + .reg_req_o ( dma_regs_req [i] ), + .reg_rsp_i ( dma_regs_rsp [i] ) + ); + end + + idma_reg32_3d #( + .NumRegs ( NumRegs ), + .NumStreams ( NumStreams ), + .IdCounterWidth ( 32'd32 ), + .reg_req_t ( dma_regs_req_t ), + .reg_rsp_t ( dma_regs_rsp_t ), + .dma_req_t ( idma_nd_req_t ) + ) i_idma_reg32_3d ( + .clk_i, + .rst_ni, + .dma_ctrl_req_i ( dma_regs_req ), + .dma_ctrl_rsp_o ( dma_regs_rsp ), + .dma_req_o ( twod_req ), + .req_valid_o ( one_fe_valid ), + .req_ready_i ( fe_ready[stream_idx] ), + .next_id_i ( next_id[stream_idx] ), + .stream_idx_o ( stream_idx ), + .done_id_i ( done_id ), + .busy_i ( idma_busy ), + .midend_busy_i ( midend_busy ) + ); + + always_comb begin : proc_connect_valids + fe_valid = '0; + fe_valid [stream_idx] = one_fe_valid; + end + + // interrupts and events (currently broadcast tx_cplt event only) + assign term_event_pe_o = |trans_complete ? '1 : '0; + assign term_irq_pe_o = '0; + assign term_event_o = |trans_complete ? '1 : '0; + assign term_irq_o = '0; + + assign busy_o = |midend_busy | |idma_busy; + + for (genvar s = 0; s < NumStreams; s++) begin : gen_streams + + // ------------------------------------------------------ + // ID counters + // ------------------------------------------------------ + idma_transfer_id_gen #( + .IdWidth ( 32'd32 ) + ) i_idma_transfer_id_gen ( + .clk_i, + .rst_ni, + .issue_i ( fe_valid [s] & fe_ready [s] ), + .retire_i ( trans_complete [s] ), + .next_o ( next_id [s] ), + .completed_o ( done_id [s] ) + ); + + + // ------------------------------------------------------ + // MIDEND + // ------------------------------------------------------ + // global (2D) request FIFO + stream_fifo #( + .DEPTH ( GLOBAL_QUEUE_DEPTH ), + .T ( idma_nd_req_t ) + ) i_3D_request_fifo ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .testmode_i ( test_mode_i ), + .usage_o (/*NOT CONNECTED*/ ), + .data_i ( twod_req ), + .valid_i ( fe_valid [s] ), + .ready_o ( fe_ready [s] ), + .data_o ( twod_req_queue [s] ), + .valid_o ( twod_queue_valid [s] ), + .ready_i ( twod_queue_ready [s] ) + ); + + localparam logic [1:0][31:0] RepWidths = '{default: 32'd32}; + + idma_nd_midend #( + .NumDim ( NumDim ), + .addr_t ( addr_t ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_nd_req_t( idma_nd_req_t ), + .RepWidths ( RepWidths ) + ) i_idma_3D_midend ( + .clk_i, + .rst_ni, + .nd_req_i ( twod_req_queue [s] ), + .nd_req_valid_i ( twod_queue_valid [s] ), + .nd_req_ready_o ( twod_queue_ready [s] ), + .nd_rsp_o (/*NOT CONNECTED*/ ), + .nd_rsp_valid_o ( trans_complete [s] ), + .nd_rsp_ready_i ( 1'b1 ), // Always ready to accept completed transfers + .burst_req_o ( idma_req [s] ), + .burst_req_valid_o( be_valid [s] ), + .burst_req_ready_i( be_ready [s] ), + .burst_rsp_i ( idma_rsp [s] ), + .burst_rsp_valid_i( be_rsp_valid [s] ), + .burst_rsp_ready_o( be_rsp_ready [s] ), + .busy_o ( midend_busy [s] ) + ); + + // ------------------------------------------------------ + // BACKEND + // ------------------------------------------------------ + + // even channels: copy out data + if (s[0] == 1'b0) begin : gen_cpy_out + + // Meta Channel Widths + localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AXI_ADDR_WIDTH, AXI_ID_WIDTH, AXI_USER_WIDTH); + localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); + localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + + function int unsigned max_width(input int unsigned a, b); + return (a > b) ? a : b; + endfunction + + typedef struct packed { + init_req_chan_t req_chan; + logic[max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; + } init_read_req_chan_padded_t; + + typedef struct packed { + obi_a_chan_t a_chan; + logic[max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + } obi_read_a_chan_padded_t; + + typedef union packed { + init_read_req_chan_padded_t init; + obi_read_a_chan_padded_t obi; + } read_meta_channel_t; + + typedef struct packed { + axi_aw_chan_t aw_chan; + logic[max_width(axi_aw_chan_width, init_req_chan_width)-axi_aw_chan_width:0] padding; + } axi_write_aw_chan_padded_t; + + typedef struct packed { + init_req_chan_t req_chan; + logic[max_width(axi_aw_chan_width, init_req_chan_width)-init_req_chan_width:0] padding; + } init_write_req_chan_padded_t; + + typedef union packed { + axi_write_aw_chan_padded_t axi; + init_write_req_chan_padded_t init; + } write_meta_channel_t; + + // local buses + init_req_t init_read_req, init_write_req; + init_rsp_t init_read_rsp, init_write_rsp + + idma_backend_r_obi_rw_init_w_axi #( + .DataWidth ( AXI_DATA_WIDTH ), + .AddrWidth ( AXI_ADDR_WIDTH ), + .UserWidth ( AXI_USER_WIDTH ), + .AxiIdWidth ( AXI_ID_WIDTH ), + .NumAxInFlight ( NB_OUTSND_BURSTS ), + .BufferDepth ( 32'd3 ), + .TFLenWidth ( TFLenWidth ), + .MemSysDepth ( 32'd0 ), + .CombinedShifter ( 1'b1 ), + .RAWCouplingAvail ( 1'b1 ), + .MaskInvalidData ( 1'b0 ), + .HardwareLegalizer ( 1'b1 ), + .RejectZeroTransfers ( 1'b1 ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .init_req_t ( init_req_t ), + .init_rsp_t ( init_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .write_meta_channel_t ( write_meta_channel_t ) + ) i_idma_backend_r_obi_rw_init_w_axi ( + .clk_i, + .rst_ni, + .testmode_i ( test_mode_i ), + .idma_req_i ( idma_req [s] ), + .req_valid_i ( be_valid [s] ), + .req_ready_o ( be_ready [s] ), + .idma_rsp_o ( idma_rsp [s] ), + .rsp_valid_o ( be_rsp_valid [s] ), + .rsp_ready_i ( be_rsp_ready [s] ), + .idma_eh_req_i ( 'b0 ), + .eh_req_valid_i ( 1'b0 ), + .eh_req_ready_o ( /* NOT CONNECTED */ ), + .init_read_req_o ( init_read_req ), + .init_read_rsp_i ( init_read_rsp ), + .obi_read_req_o ( obi_read_req [s/2] ), + .obi_read_rsp_i ( obi_read_rsp [s/2] ), + .axi_write_req_o ( dma_req [s] ), + .axi_write_rsp_i ( dma_rsp [s] ), + .init_write_req_o ( init_write_req ), + .init_write_rsp_i ( init_write_rsp ), + .busy_o ( idma_busy [s] ) + ); + + // implement zero memory using init protocol + init_read_rsp.rsp_chan.init = '0; + init_read_rsp.rsp_valid = init_read_req.req_valid; // might need spill register + init_read_rsp.req_ready = 1'b1; + + // implement /dev/null + init_write_rsp.rsp_chan.init = '0; + init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register + init_write_rsp.req_ready = 1'b1; + + + // odd channels: copy in data + end else begin : gen_cpy_in + + // Meta Channel Widths + localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AXI_ADDR_WIDTH, AXI_ID_WIDTH, AXI_USER_WIDTH); + localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); + localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + + function int unsigned max_width(input int unsigned a, b); + return (a > b) ? a : b; + endfunction + + typedef struct packed { + axi_ar_chan_t ar_chan; + logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-axi_ar_chan_width:0] padding; + } axi_read_ar_chan_padded_t; + + typedef struct packed { + init_req_chan_t req_chan; + logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-init_req_chan_width:0] padding; + } init_read_req_chan_padded_t; + + typedef struct packed { + obi_a_chan_t a_chan; + logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-obi_a_chan_width:0] padding; + } obi_read_a_chan_padded_t; + + typedef union packed { + axi_read_ar_chan_padded_t axi; + init_read_req_chan_padded_t init; + obi_read_a_chan_padded_t obi; + } read_meta_channel_t; + + typedef struct packed { + init_req_chan_t req_chan; + logic[max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; + } init_write_req_chan_padded_t; + + typedef struct packed { + obi_a_chan_t a_chan; + logic[max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + } obi_write_a_chan_padded_t; + + typedef union packed { + init_write_req_chan_padded_t init; + obi_write_a_chan_padded_t obi; + } write_meta_channel_t; + + // local buses + init_req_t init_read_req, init_write_req; + init_rsp_t init_read_rsp, init_write_rsp; + + idma_backend_r_axi_rw_init_rw_obi #( + .DataWidth ( AXI_DATA_WIDTH ), + .AddrWidth ( AXI_ADDR_WIDTH ), + .UserWidth ( AXI_USER_WIDTH ), + .AxiIdWidth ( AXI_ID_WIDTH ), + .NumAxInFlight ( NB_OUTSND_BURSTS ), + .BufferDepth ( 32'd3 ), + .TFLenWidth ( TFLenWidth ), + .MemSysDepth ( 32'd0 ), + .CombinedShifter ( 1'b1 ), + .RAWCouplingAvail ( 1'b1 ), + .MaskInvalidData ( 1'b0 ), + .HardwareLegalizer ( 1'b1 ), + .RejectZeroTransfers ( 1'b1 ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .init_req_t ( init_req_t ), + .init_rsp_t ( init_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .write_meta_channel_t ( write_meta_channel_t ) + ) i_idma_backend_r_axi_rw_init_rw_obi ( + .clk_i, + .rst_ni, + .testmode_i ( test_mode_i ), + .idma_req_i ( idma_req [s] ), + .req_valid_i ( be_valid [s] ), + .req_ready_o ( be_ready [s] ), + .idma_rsp_o ( idma_rsp [s] ), + .rsp_valid_o ( be_rsp_valid [s] ), + .rsp_ready_i ( be_rsp_ready [s] ), + .idma_eh_req_i ( 'b0 ), + .eh_req_valid_i ( 1'b0 ), + .eh_req_ready_o ( /* NOT CONNECTED */ ), + .axi_read_req_o ( dma_req [s] ), + .axi_read_rsp_i ( dma_rsp [s] ), + .init_read_req_o ( init_read_req ), + .init_read_rsp_i ( init_read_rsp ), + .obi_read_req_o ( obi_reorg_req [s/2] ), + .obi_read_rsp_i ( obi_reorg_rsp [s/2] ), + .init_write_req_o ( init_write_req ), + .init_write_rsp_i ( init_write_rsp ), + .obi_write_req_o ( obi_write_req [s/2] ), + .obi_write_rsp_i ( obi_write_rsp [s/2] ), + .busy_o ( idma_busy [s] ) + ); + + // implement zero memory using init protocol + init_read_rsp.rsp_chan.init = '0; + init_read_rsp.rsp_valid = init_read_req.req_valid; // might need spill register + init_read_rsp.req_ready = 1'b1; + + // implement /dev/null + init_write_rsp.rsp_chan.init = '0; + init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register + init_write_rsp.req_ready = 1'b1; + end + + + // ------------------------------------------------------ + // TCDM connections + // ------------------------------------------------------ + + for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin + + logic tcdm_master_we_0; + logic tcdm_master_we_1; + logic tcdm_master_we_2; + logic tcdm_master_we_3; + logic tcdm_master_we_4; + logic tcdm_master_we_5; + + mem_to_banks #( + .AddrWidth ( AXI_ADDR_WIDTH ), + .DataWidth ( AXI_DATA_WIDTH ), + .NumBanks ( 32'd2 ), + .HideStrb ( 1'b1 ), + .MaxTrans ( 32'd1 ), + .FifoDepth ( 32'd1 ) + ) i_mem_to_banks_read ( + .clk_i, + .rst_ni, + .req_i ( obi_read_req[s].req ), + .gnt_o ( obi_read_rsp[s].gnt ), + .addr_i ( obi_read_req[s].a.addr ), + .wdata_i ( obi_read_req[s].a.wdata ), + .strb_i ( obi_read_req[s].a.be ), + .atop_i ( '0 ), + .we_i ( obi_read_req[s].a.we ), + .rvalid_o ( obi_read_rsp[s].rvalid ), + .rdata_o ( obi_read_rsp[s].r.data ), + .bank_req_o ( {tcdm_master[6*s+1].req, tcdm_master[6*s].req} ), + .bank_gnt_i ( {tcdm_master[6*s+1].gnt, tcdm_master[6*s].gnt} ), + .bank_addr_o ( {tcdm_master[6*s+1].add, tcdm_master[6*s].add} ), + .bank_wdata_o ( {tcdm_master[6*s+1].data, tcdm_master[6*s].data} ), + .bank_strb_o ( {tcdm_master[6*s+1].be, tcdm_master[6*s].be} ), + .bank_atop_o ( /* NOT CONNECTED */ ), + .bank_we_o ( {tcdm_master_we_1, tcdm_master_we_0} ), + .bank_rvalid_i ( {tcdm_master[6*s+1].r_valid, tcdm_master[6*s].r_valid} ), + .bank_rdata_i ( {tcdm_master[6*s+1].r_data, tcdm_master[6*s].r_data} ) + ); + + assign tcdm_master[0].boffs = '0; + assign tcdm_master[0].lrdy = '0; + assign tcdm_master[0].user = '0; + assign tcdm_master[1].boffs = '0; + assign tcdm_master[1].lrdy = '0; + assign tcdm_master[1].user = '0; + assign tcdm_master[0].wen = !tcdm_master_we_0; + assign tcdm_master[1].wen = !tcdm_master_we_1; + + mem_to_banks #( + .AddrWidth ( AXI_ADDR_WIDTH ), + .DataWidth ( AXI_DATA_WIDTH ), + .NumBanks ( 32'd2 ), + .HideStrb ( 1'b1 ), + .MaxTrans ( 32'd1 ), + .FifoDepth ( 32'd1 ) + ) i_mem_to_banks_reorg ( + .clk_i, + .rst_ni, + .req_i ( obi_reorg_req[s].req ), + .gnt_o ( obi_reorg_rsp[s].gnt ), + .addr_i ( obi_reorg_req[s].a.addr ), + .wdata_i ( obi_reorg_req[s].a.wdata ), + .strb_i ( obi_reorg_req[s].a.be ), + .atop_i ( '0 ), + .we_i ( obi_reorg_req[s].a.we ), + .rvalid_o ( obi_reorg_rsp[s].rvalid ), + .rdata_o ( obi_reorg_rsp[s].r.data ), + .bank_req_o ( {tcdm_master[6*s+3].req, tcdm_master[6*s+2].req} ), + .bank_gnt_i ( {tcdm_master[6*s+3].gnt, tcdm_master[6*s+2].gnt} ), + .bank_addr_o ( {tcdm_master[6*s+3].add, tcdm_master[6*s+2].add} ), + .bank_wdata_o ( {tcdm_master[6*s+3].data, tcdm_master[6*s+2].data} ), + .bank_strb_o ( {tcdm_master[6*s+3].be, tcdm_master[6*s+2].be} ), + .bank_atop_o ( /* NOT CONNECTED */ ), + .bank_we_o ( {tcdm_master_we_3, tcdm_master_we_2} ), + .bank_rvalid_i ( {tcdm_master[6*s+3].r_valid, tcdm_master[6*s+2].r_valid} ), + .bank_rdata_i ( {tcdm_master[6*s+3].r_data, tcdm_master[6*s+2].r_data} ) + ); + + assign tcdm_master[2].boffs = '0; + assign tcdm_master[2].lrdy = '0; + assign tcdm_master[2].user = '0; + assign tcdm_master[3].boffs = '0; + assign tcdm_master[3].lrdy = '0; + assign tcdm_master[3].user = '0; + assign tcdm_master[2].wen = !tcdm_master_we_2; + assign tcdm_master[3].wen = !tcdm_master_we_3; + + mem_to_banks #( + .AddrWidth ( AXI_ADDR_WIDTH ), + .DataWidth ( AXI_DATA_WIDTH ), + .NumBanks ( 32'd2 ), + .HideStrb ( 1'b1 ), + .MaxTrans ( 32'd1 ), + .FifoDepth ( 32'd1 ) + ) i_mem_to_banks_write ( + .clk_i, + .rst_ni, + .req_i ( obi_write_req[s].req ), + .gnt_o ( obi_write_rsp[s].gnt ), + .addr_i ( obi_write_req[s].a.addr ), + .wdata_i ( obi_write_req[s].a.wdata ), + .strb_i ( obi_write_req[s].a.be ), + .atop_i ( '0 ), + .we_i ( obi_write_req[s].a.we ), + .rvalid_o ( obi_write_rsp[s].rvalid ), + .rdata_o ( obi_write_rsp[s].r.data ), + .bank_req_o ( {tcdm_master[6*s+5].req, tcdm_master[6*s+4].req} ), + .bank_gnt_i ( {tcdm_master[6*s+5].gnt, tcdm_master[6*s+4].gnt} ), + .bank_addr_o ( {tcdm_master[6*s+5].add, tcdm_master[6*s+4].add} ), + .bank_wdata_o ( {tcdm_master[6*s+5].data, tcdm_master[6*s+4].data} ), + .bank_strb_o ( {tcdm_master[6*s+5].be, tcdm_master[6*s+4].be} ), + .bank_atop_o ( /* NOT CONNECTED */ ), + .bank_we_o ( {tcdm_master_we_5, tcdm_master_we_4} ), + .bank_rvalid_i ( {tcdm_master[6*s+5].r_valid, tcdm_master[6*s+4].r_valid} ), + .bank_rdata_i ( {tcdm_master[6*s+5].r_data, tcdm_master[6*s+4].r_data} ) + ); + + assign tcdm_master[4].boffs = '0; + assign tcdm_master[4].lrdy = '0; + assign tcdm_master[4].user = '0; + assign tcdm_master[5].boffs = '0; + assign tcdm_master[5].lrdy = '0; + assign tcdm_master[5].user = '0; + assign tcdm_master[4].wen = !tcdm_master_we_4; + assign tcdm_master[5].wen = !tcdm_master_we_5; + end + +endmodule diff --git a/src/frontend/reg/tpl/idma_reg.hjson.tpl b/src/frontend/reg/tpl/idma_reg.hjson.tpl index 5df3293d..5a5a4c33 100644 --- a/src/frontend/reg/tpl/idma_reg.hjson.tpl +++ b/src/frontend/reg/tpl/idma_reg.hjson.tpl @@ -53,6 +53,14 @@ ${params} name: "enable_nd", desc: "ND-extension enabled" } + { bits: "${src_prot_range}", + name: "src_protocol", + desc: "Selection of the source protocol" + } + { bits: "${dst_prot_range}", + name: "dst_protocol", + desc: "Selection of the destination protocol" + } ] }, { multireg: diff --git a/src/frontend/reg/tpl/idma_reg.sv.tpl b/src/frontend/reg/tpl/idma_reg.sv.tpl index 94660408..1183d9f1 100644 --- a/src/frontend/reg/tpl/idma_reg.sv.tpl +++ b/src/frontend/reg/tpl/idma_reg.sv.tpl @@ -113,6 +113,10 @@ module idma_${identifier} #( arb_dma_req[i]${sep}dst_addr = {dma_reg2hw[i].dst_addr_high.q, dma_reg2hw[i].dst_addr_low.q}; % endif + // Protocols + arb_dma_req[i]${sep}src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); + arb_dma_req[i]${sep}dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); + // Current backend only supports incremental burst arb_dma_req[i]${sep}opt.src.burst = axi_pkg::BURST_INCR; arb_dma_req[i]${sep}opt.dst.burst = axi_pkg::BURST_INCR; diff --git a/util/mario/frontend.py b/util/mario/frontend.py index c96f4eea..70c31901 100644 --- a/util/mario/frontend.py +++ b/util/mario/frontend.py @@ -11,6 +11,7 @@ import math from mako.template import Template +NUM_PROT_BITS = 3 - 1 def render_register(content: dict): """Render a register""" @@ -129,7 +130,9 @@ def render_reg_hjson(fe_ids: dict, tpl_file: str) -> str: 'identifier': fe_id, 'params': params, 'registers': regs, - 'dim_range': f'{10+num_dim_bits}:10' + 'dim_range': f'{10+num_dim_bits}:10', + 'src_prot_range': f'{10+num_dim_bits+NUM_PROT_BITS}:{10+num_dim_bits}', + 'dst_prot_range': f'{10+num_dim_bits+2*NUM_PROT_BITS}:{10+num_dim_bits+NUM_PROT_BITS}' } # render From 17f7411e3094b95f598f121d50b33ac05e30cd80 Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Fri, 21 Jun 2024 17:30:46 +0200 Subject: [PATCH 02/13] [WIP] rename dmac_wrap --- src/{dmac_wrap.sv => pulp_idma_wrap.sv} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{dmac_wrap.sv => pulp_idma_wrap.sv} (100%) diff --git a/src/dmac_wrap.sv b/src/pulp_idma_wrap.sv similarity index 100% rename from src/dmac_wrap.sv rename to src/pulp_idma_wrap.sv From 599ae078a4e8c988f5b225994fb34d238c5922a1 Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Fri, 21 Jun 2024 17:31:35 +0200 Subject: [PATCH 03/13] [WIP] PULP iDMA wrap: allow mux of rd ports, use axi structs --- src/pulp_idma_wrap.sv | 857 ++++++++++++++++++++++++------------------ 1 file changed, 487 insertions(+), 370 deletions(-) diff --git a/src/pulp_idma_wrap.sv b/src/pulp_idma_wrap.sv index 4ed24cb6..412eb7fa 100644 --- a/src/pulp_idma_wrap.sv +++ b/src/pulp_idma_wrap.sv @@ -6,57 +6,68 @@ * dmac_wrap.sv * Thomas Benz * Michael Rogenmoser + * Georg Rutishauser */ // DMA Core wrapper `include "axi/assign.svh" `include "axi/typedef.svh" +`include "obi/typedef.svh" `include "idma/typedef.svh" `include "register_interface/typedef.svh" -module dmac_wrap #( - parameter int unsigned NB_CORES = 4, - parameter int unsigned AXI_ADDR_WIDTH = 32, - parameter int unsigned AXI_DATA_WIDTH = 64, - parameter int unsigned AXI_USER_WIDTH = 6, - parameter int unsigned AXI_ID_WIDTH = 4, - parameter int unsigned PE_ID_WIDTH = 1, - parameter int unsigned NB_PE_PORTS = 1, - parameter int unsigned DATA_WIDTH = 32, - parameter int unsigned ADDR_WIDTH = 32, - parameter int unsigned BE_WIDTH = DATA_WIDTH/8, - parameter int unsigned NUM_BIDIR_STREAMS = 1, // bidirectional streams: range 1 to 8 - parameter int unsigned NB_OUTSND_BURSTS = 8, - parameter int unsigned GLOBAL_QUEUE_DEPTH = 2 // per-stream -) ( - input logic clk_i, - input logic rst_ni, - input logic test_mode_i, - XBAR_PERIPH_BUS.Slave pe_ctrl_slave[NB_PE_PORTS-1:0], - XBAR_TCDM_BUS.Slave ctrl_slave[NB_CORES-1:0], - hci_core_intf.master tcdm_master[6*NUM_BIDIR_STREAMS-1:0], - AXI_BUS.Master ext_master[NUM_BIDIR_STREAMS-1:0], - output logic [NB_CORES-1:0] term_event_o, - output logic [NB_CORES-1:0] term_irq_o, - output logic [NB_PE_PORTS-1:0] term_event_pe_o, - output logic [NB_PE_PORTS-1:0] term_irq_pe_o, - output logic busy_o -); - - localparam int unsigned NumRegs = NB_CORES + NB_PE_PORTS; - localparam int unsigned NumStreams = 32'd2 * NUM_BIDIR_STREAMS; +module pulp_idma_wrap #( + parameter int unsigned NB_CORES = 4, + parameter int unsigned AXI_ADDR_WIDTH = 32, + parameter int unsigned AXI_DATA_WIDTH = 64, + parameter int unsigned AXI_USER_WIDTH = 6, + parameter int unsigned AXI_ID_WIDTH = 4, + parameter int unsigned PE_ID_WIDTH = 1, + parameter int unsigned NB_PE_PORTS = 1, + parameter int unsigned DATA_WIDTH = 32, + parameter int unsigned ADDR_WIDTH = 32, + parameter int unsigned BE_WIDTH = DATA_WIDTH / 8, + parameter type axi_req_t = logic, + parameter type axi_resp_t = logic, + // bidirectional streams: range 1 to 8 + parameter int unsigned NUM_BIDIR_STREAMS = 1, + parameter int unsigned NB_OUTSND_BURSTS = 8, + // queue depth per stream + parameter int unsigned GLOBAL_QUEUE_DEPTH = 2, + // mux read ports between tcdm-tcdm and tcdm-axi? + parameter bit MUX_READ = 1'b0, + // 4 ports per stream if read ports muxed, otherwise 6 + localparam int unsigned NB_TCDM_PORTS_PER_STRM = 4 + (~MUX_READ) * 2 +) ( // verilog_format: off // verible does not manage to align this :( + input logic clk_i, + input logic rst_ni, + input logic test_mode_i, + XBAR_PERIPH_BUS.Slave pe_ctrl_slave[NB_PE_PORTS-1:0], + XBAR_TCDM_BUS.Slave ctrl_slave[NB_CORES-1:0], + hci_core_intf.master tcdm_master[NB_TCDM_PORTS_PER_STRM*NUM_BIDIR_STREAMS-1:0], + output axi_req_t [NUM_BIDIR_STREAMS-1:0] ext_master_req_o, + input axi_resp_t [NUM_BIDIR_STREAMS-1:0] ext_master_rsp_i, + output logic [NB_CORES-1:0] term_event_o, + output logic [NB_CORES-1:0] term_irq_o, + output logic [NB_PE_PORTS-1:0] term_event_pe_o, + output logic [NB_PE_PORTS-1:0] term_irq_pe_o, + output logic busy_o +); // verilog_format: on + + localparam int unsigned NumRegs = NB_CORES + NB_PE_PORTS; + localparam int unsigned NumStreams = 32'd2 * NUM_BIDIR_STREAMS; localparam int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams); // CORE --> MCHAN CTRL INTERFACE BUS SIGNALS - logic [NumRegs-1:0][DATA_WIDTH-1:0] config_wdata; - logic [NumRegs-1:0][ADDR_WIDTH-1:0] config_add; + logic [NumRegs-1:0][ DATA_WIDTH-1:0] config_wdata; + logic [NumRegs-1:0][ ADDR_WIDTH-1:0] config_add; logic [NumRegs-1:0] config_req; logic [NumRegs-1:0] config_wen; - logic [NumRegs-1:0][BE_WIDTH-1:0] config_be; + logic [NumRegs-1:0][ BE_WIDTH-1:0] config_be; logic [NumRegs-1:0][PE_ID_WIDTH-1:0] config_id; logic [NumRegs-1:0] config_gnt; - logic [NumRegs-1:0][DATA_WIDTH-1:0] config_r_rdata; + logic [NumRegs-1:0][ DATA_WIDTH-1:0] config_r_rdata; logic [NumRegs-1:0] config_r_valid; logic [NumRegs-1:0] config_r_opc; logic [NumRegs-1:0][PE_ID_WIDTH-1:0] config_r_id; @@ -76,12 +87,12 @@ module dmac_wrap #( end for (genvar i = 0; i < NB_PE_PORTS; i++) begin : gen_pe_ctrl_registers - assign config_add[NB_CORES+i] = pe_ctrl_slave[i].add; - assign config_req[NB_CORES+i] = pe_ctrl_slave[i].req; - assign config_wdata[NB_CORES+i] = pe_ctrl_slave[i].wdata; - assign config_wen[NB_CORES+i] = pe_ctrl_slave[i].wen; - assign config_be[NB_CORES+i] = pe_ctrl_slave[i].be; - assign config_id[NB_CORES+i] = pe_ctrl_slave[i].id; + assign config_add[NB_CORES+i] = pe_ctrl_slave[i].add; + assign config_req[NB_CORES+i] = pe_ctrl_slave[i].req; + assign config_wdata[NB_CORES+i] = pe_ctrl_slave[i].wdata; + assign config_wen[NB_CORES+i] = pe_ctrl_slave[i].wen; + assign config_be[NB_CORES+i] = pe_ctrl_slave[i].be; + assign config_id[NB_CORES+i] = pe_ctrl_slave[i].id; assign pe_ctrl_slave[i].gnt = config_gnt[NB_CORES+i]; assign pe_ctrl_slave[i].r_opc = config_r_opc[NB_CORES+i]; assign pe_ctrl_slave[i].r_valid = config_r_valid[NB_CORES+i]; @@ -90,12 +101,12 @@ module dmac_wrap #( end // Types types - typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; - typedef logic [ADDR_WIDTH-1:0] mem_addr_t; - typedef logic [AXI_DATA_WIDTH-1:0] data_t; - typedef logic [AXI_ID_WIDTH-1:0] id_t; + typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; + typedef logic [ADDR_WIDTH-1:0] mem_addr_t; + typedef logic [AXI_DATA_WIDTH-1:0] data_t; + typedef logic [AXI_ID_WIDTH-1:0] id_t; typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t; - typedef logic [AXI_USER_WIDTH-1:0] user_t; + typedef logic [AXI_USER_WIDTH-1:0] user_t; // // AXI4+ATOP channels typedefs `AXI_TYPEDEF_ALL(axi, addr_t, id_t, data_t, strb_t, user_t) @@ -103,10 +114,10 @@ module dmac_wrap #( // Memory Init typedefs /// init read request typedef struct packed { - logic [AXI_ADDR_WIDTH-1:0] cfg; - logic [AXI_DATA_WIDTH-1:0] term; - logic [AXI_STRB_WIDTH-1:0] strb; - logic [AXI_ID_WIDTH-1:0] id; + logic [AXI_ADDR_WIDTH-1:0] cfg; + logic [AXI_DATA_WIDTH-1:0] term; + logic [AXI_STRB_WIDTH-1:0] strb; + logic [AXI_ID_WIDTH-1:0] id; } init_req_chan_t; typedef struct packed { @@ -115,9 +126,7 @@ module dmac_wrap #( logic rsp_ready; } init_req_t; - typedef struct packed { - logic [AXI_DATA_WIDTH-1:0] init; - } init_rsp_chan_t; + typedef struct packed {logic [AXI_DATA_WIDTH-1:0] init;} init_rsp_chan_t; typedef struct packed { init_rsp_chan_t rsp_chan; @@ -128,56 +137,64 @@ module dmac_wrap #( // OBI typedefs `OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) `OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) - `OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) - `OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + `OBI_TYPEDEF_A_CHAN_T(obi_a_chan_t, AXI_ADDR_WIDTH, AXI_DATA_WIDTH, 0, a_optional_t) + `OBI_TYPEDEF_R_CHAN_T(obi_r_chan_t, AXI_DATA_WIDTH, 0, r_optional_t) `OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) `OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) - obi_req_t [NUM_BIDIR_STREAMS-1:0] obi_read_req, obi_reorg_req, obi_write_req, obi_tcdm_req; - obi_rsp_t [NUM_BIDIR_STREAMS-1:0] obi_read_rsp, obi_reorg_rsp, obi_write_rsp, obi_tcdm_rsp; + + obi_req_t [NUM_BIDIR_STREAMS-1:0] + obi_read_req_from_dma, obi_reorg_req, obi_write_req, obi_read_req_muxed; + obi_rsp_t [NUM_BIDIR_STREAMS-1:0] + obi_read_rsp_to_dma, obi_reorg_rsp, obi_write_rsp, obi_read_rsp_to_mux; + // BUS definitions axi_req_t [NUM_BIDIR_STREAMS-1:0] soc_req; axi_resp_t [NUM_BIDIR_STREAMS-1:0] soc_rsp; - axi_req_t [NumStreams-1:0] dma_req; - axi_resp_t [NumStreams-1:0] dma_rsp; + axi_req_t [ NumStreams-1:0] dma_req; + axi_resp_t [ NumStreams-1:0] dma_rsp; // interface to structs for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin : gen_connect_interface - `AXI_ASSIGN_FROM_REQ(ext_master[s], soc_req[s]) - `AXI_ASSIGN_TO_RESP(soc_rsp[s], ext_master[s]) + // `AXI_ASSIGN_FROM_REQ(ext_master[s], soc_req[s]) + // `AXI_ASSIGN_TO_RESP(soc_rsp[s], ext_master[s]) + assign ext_master_req_o[s] = soc_req[s]; + assign soc_rsp[s] = ext_master_resp_i[s]; end + // connect RW axi buses for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin : gen_rw_axi_connection axi_rw_join #( - .axi_req_t ( axi_req_t ), - .axi_resp_t ( axi_resp_t ) + .axi_req_t (axi_req_t), + .axi_resp_t(axi_resp_t) ) i_init_axi_rw_join ( .clk_i, .rst_ni, - .slv_read_req_i ( dma_req[2*s+1] ), - .slv_read_resp_o ( dma_rsp[2*s+1] ), - .slv_write_req_i ( dma_req[2*s] ), - .slv_write_resp_o ( dma_rsp[2*s] ), - .mst_req_o ( soc_req[s] ), - .mst_resp_i ( soc_rsp[s] ) + .slv_read_req_i (dma_req[2*s+1]), + .slv_read_resp_o (dma_rsp[2*s+1]), + .slv_write_req_i (dma_req[2*s]), + .slv_write_resp_o(dma_rsp[2*s]), + .mst_req_o (soc_req[s]), + .mst_resp_i (soc_rsp[s]) ); end // Register BUS definitions localparam int unsigned RegAddrWidth = 32'd10; - `REG_BUS_TYPEDEF_ALL(dma_regs, logic[RegAddrWidth-1:0], logic[DATA_WIDTH-1:0], logic[BE_WIDTH-1:0]) + `REG_BUS_TYPEDEF_ALL(dma_regs, logic[RegAddrWidth-1:0], logic[DATA_WIDTH-1:0], + logic[BE_WIDTH-1:0]) dma_regs_req_t [NumRegs-1:0] dma_regs_req; dma_regs_rsp_t [NumRegs-1:0] dma_regs_rsp; // iDMA struct definitions - localparam int unsigned TFLenWidth = AXI_ADDR_WIDTH; - localparam int unsigned NumDim = 32'd3; // Support 2D midend for 2D transfers - localparam int unsigned RepWidth = 32'd32; + localparam int unsigned TFLenWidth = AXI_ADDR_WIDTH; + localparam int unsigned NumDim = 32'd3; // Support 2D midend for 2D transfers + localparam int unsigned RepWidth = 32'd32; localparam int unsigned StrideWidth = 32'd32; - typedef logic [TFLenWidth-1:0] tf_len_t; - typedef logic [RepWidth-1:0] reps_t; + typedef logic [TFLenWidth-1:0] tf_len_t; + typedef logic [RepWidth-1:0] reps_t; typedef logic [StrideWidth-1:0] strides_t; // iDMA request / response types @@ -190,10 +207,10 @@ module dmac_wrap #( logic [StreamWidth-1:0] stream_idx; idma_nd_req_t [NumStreams-1:0] twod_req, twod_req_queue; - idma_req_t [NumStreams-1:0] idma_req; - idma_rsp_t [NumStreams-1:0] idma_rsp; + idma_req_t [NumStreams-1:0] idma_req; + idma_rsp_t [NumStreams-1:0] idma_rsp; - logic one_fe_valid; + logic one_fe_valid; logic [NumStreams-1:0] fe_valid, twod_queue_valid, be_valid, be_rsp_valid; logic [NumStreams-1:0] fe_ready, twod_queue_ready, be_ready, be_rsp_ready; logic [NumStreams-1:0] trans_complete, midend_busy; @@ -207,56 +224,56 @@ module dmac_wrap #( for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs periph_to_reg #( - .AW ( RegAddrWidth ), - .DW ( DATA_WIDTH ), - .BW ( BE_WIDTH ), - .IW ( PE_ID_WIDTH ), - .req_t ( dma_regs_req_t ), - .rsp_t ( dma_regs_rsp_t ) + .AW (RegAddrWidth), + .DW (DATA_WIDTH), + .BW (BE_WIDTH), + .IW (PE_ID_WIDTH), + .req_t(dma_regs_req_t), + .rsp_t(dma_regs_rsp_t) ) i_pe_translate ( .clk_i, .rst_ni, - .req_i ( config_req [i] ), - .add_i ( config_add [i][RegAddrWidth-1:0] ), - .wen_i ( config_wen [i] ), - .wdata_i ( config_wdata [i] ), - .be_i ( config_be [i] ), - .id_i ( config_id [i] ), - .gnt_o ( config_gnt [i] ), - .r_rdata_o ( config_r_rdata [i] ), - .r_opc_o ( config_r_opc [i] ), - .r_id_o ( config_r_id [i] ), - .r_valid_o ( config_r_valid [i] ), - .reg_req_o ( dma_regs_req [i] ), - .reg_rsp_i ( dma_regs_rsp [i] ) + .req_i (config_req[i]), + .add_i (config_add[i][RegAddrWidth-1:0]), + .wen_i (config_wen[i]), + .wdata_i (config_wdata[i]), + .be_i (config_be[i]), + .id_i (config_id[i]), + .gnt_o (config_gnt[i]), + .r_rdata_o(config_r_rdata[i]), + .r_opc_o (config_r_opc[i]), + .r_id_o (config_r_id[i]), + .r_valid_o(config_r_valid[i]), + .reg_req_o(dma_regs_req[i]), + .reg_rsp_i(dma_regs_rsp[i]) ); end idma_reg32_3d #( - .NumRegs ( NumRegs ), - .NumStreams ( NumStreams ), - .IdCounterWidth ( 32'd32 ), - .reg_req_t ( dma_regs_req_t ), - .reg_rsp_t ( dma_regs_rsp_t ), - .dma_req_t ( idma_nd_req_t ) + .NumRegs (NumRegs), + .NumStreams (NumStreams), + .IdCounterWidth(32'd32), + .reg_req_t (dma_regs_req_t), + .reg_rsp_t (dma_regs_rsp_t), + .dma_req_t (idma_nd_req_t) ) i_idma_reg32_3d ( .clk_i, .rst_ni, - .dma_ctrl_req_i ( dma_regs_req ), - .dma_ctrl_rsp_o ( dma_regs_rsp ), - .dma_req_o ( twod_req ), - .req_valid_o ( one_fe_valid ), - .req_ready_i ( fe_ready[stream_idx] ), - .next_id_i ( next_id[stream_idx] ), - .stream_idx_o ( stream_idx ), - .done_id_i ( done_id ), - .busy_i ( idma_busy ), - .midend_busy_i ( midend_busy ) + .dma_ctrl_req_i(dma_regs_req), + .dma_ctrl_rsp_o(dma_regs_rsp), + .dma_req_o (twod_req), + .req_valid_o (one_fe_valid), + .req_ready_i (fe_ready[stream_idx]), + .next_id_i (next_id[stream_idx]), + .stream_idx_o (stream_idx), + .done_id_i (done_id), + .busy_i (idma_busy), + .midend_busy_i (midend_busy) ); always_comb begin : proc_connect_valids - fe_valid = '0; - fe_valid [stream_idx] = one_fe_valid; + fe_valid = '0; + fe_valid[stream_idx] = one_fe_valid; end // interrupts and events (currently broadcast tx_cplt event only) @@ -265,7 +282,7 @@ module dmac_wrap #( assign term_event_o = |trans_complete ? '1 : '0; assign term_irq_o = '0; - assign busy_o = |midend_busy | |idma_busy; + assign busy_o = |midend_busy | |idma_busy; for (genvar s = 0; s < NumStreams; s++) begin : gen_streams @@ -273,14 +290,14 @@ module dmac_wrap #( // ID counters // ------------------------------------------------------ idma_transfer_id_gen #( - .IdWidth ( 32'd32 ) + .IdWidth(32'd32) ) i_idma_transfer_id_gen ( .clk_i, .rst_ni, - .issue_i ( fe_valid [s] & fe_ready [s] ), - .retire_i ( trans_complete [s] ), - .next_o ( next_id [s] ), - .completed_o ( done_id [s] ) + .issue_i (fe_valid[s] & fe_ready[s]), + .retire_i (trans_complete[s]), + .next_o (next_id[s]), + .completed_o(done_id[s]) ); @@ -289,47 +306,47 @@ module dmac_wrap #( // ------------------------------------------------------ // global (2D) request FIFO stream_fifo #( - .DEPTH ( GLOBAL_QUEUE_DEPTH ), - .T ( idma_nd_req_t ) + .DEPTH(GLOBAL_QUEUE_DEPTH), + .T (idma_nd_req_t) ) i_3D_request_fifo ( .clk_i, .rst_ni, - .flush_i ( 1'b0 ), - .testmode_i ( test_mode_i ), - .usage_o (/*NOT CONNECTED*/ ), - .data_i ( twod_req ), - .valid_i ( fe_valid [s] ), - .ready_o ( fe_ready [s] ), - .data_o ( twod_req_queue [s] ), - .valid_o ( twod_queue_valid [s] ), - .ready_i ( twod_queue_ready [s] ) + .flush_i (1'b0), + .testmode_i(test_mode_i), + .usage_o ( /*NOT CONNECTED*/), + .data_i (twod_req), + .valid_i (fe_valid[s]), + .ready_o (fe_ready[s]), + .data_o (twod_req_queue[s]), + .valid_o (twod_queue_valid[s]), + .ready_i (twod_queue_ready[s]) ); localparam logic [1:0][31:0] RepWidths = '{default: 32'd32}; idma_nd_midend #( - .NumDim ( NumDim ), - .addr_t ( addr_t ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_nd_req_t( idma_nd_req_t ), - .RepWidths ( RepWidths ) + .NumDim (NumDim), + .addr_t (addr_t), + .idma_req_t (idma_req_t), + .idma_rsp_t (idma_rsp_t), + .idma_nd_req_t(idma_nd_req_t), + .RepWidths (RepWidths) ) i_idma_3D_midend ( .clk_i, .rst_ni, - .nd_req_i ( twod_req_queue [s] ), - .nd_req_valid_i ( twod_queue_valid [s] ), - .nd_req_ready_o ( twod_queue_ready [s] ), - .nd_rsp_o (/*NOT CONNECTED*/ ), - .nd_rsp_valid_o ( trans_complete [s] ), - .nd_rsp_ready_i ( 1'b1 ), // Always ready to accept completed transfers - .burst_req_o ( idma_req [s] ), - .burst_req_valid_o( be_valid [s] ), - .burst_req_ready_i( be_ready [s] ), - .burst_rsp_i ( idma_rsp [s] ), - .burst_rsp_valid_i( be_rsp_valid [s] ), - .burst_rsp_ready_o( be_rsp_ready [s] ), - .busy_o ( midend_busy [s] ) + .nd_req_i (twod_req_queue[s]), + .nd_req_valid_i (twod_queue_valid[s]), + .nd_req_ready_o (twod_queue_ready[s]), + .nd_rsp_o ( /*NOT CONNECTED*/), + .nd_rsp_valid_o (trans_complete[s]), + .nd_rsp_ready_i (1'b1), // Always ready to accept completed transfers + .burst_req_o (idma_req[s]), + .burst_req_valid_o(be_valid[s]), + .burst_req_ready_i(be_ready[s]), + .burst_rsp_i (idma_rsp[s]), + .burst_rsp_valid_i(be_rsp_valid[s]), + .burst_rsp_ready_o(be_rsp_ready[s]), + .busy_o (midend_busy[s]) ); // ------------------------------------------------------ @@ -340,7 +357,9 @@ module dmac_wrap #( if (s[0] == 1'b0) begin : gen_cpy_out // Meta Channel Widths - localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AXI_ADDR_WIDTH, AXI_ID_WIDTH, AXI_USER_WIDTH); + localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width( + AXI_ADDR_WIDTH, AXI_ID_WIDTH, AXI_USER_WIDTH + ); localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); @@ -350,12 +369,12 @@ module dmac_wrap #( typedef struct packed { init_req_chan_t req_chan; - logic[max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; + logic [max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; } init_read_req_chan_padded_t; typedef struct packed { obi_a_chan_t a_chan; - logic[max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + logic [max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; } obi_read_a_chan_padded_t; typedef union packed { @@ -365,89 +384,91 @@ module dmac_wrap #( typedef struct packed { axi_aw_chan_t aw_chan; - logic[max_width(axi_aw_chan_width, init_req_chan_width)-axi_aw_chan_width:0] padding; + logic [max_width(axi_aw_chan_width, init_req_chan_width)-axi_aw_chan_width:0] padding; } axi_write_aw_chan_padded_t; typedef struct packed { init_req_chan_t req_chan; - logic[max_width(axi_aw_chan_width, init_req_chan_width)-init_req_chan_width:0] padding; + logic [max_width(axi_aw_chan_width, init_req_chan_width)-init_req_chan_width:0] padding; } init_write_req_chan_padded_t; typedef union packed { - axi_write_aw_chan_padded_t axi; + axi_write_aw_chan_padded_t axi; init_write_req_chan_padded_t init; } write_meta_channel_t; // local buses init_req_t init_read_req, init_write_req; - init_rsp_t init_read_rsp, init_write_rsp + init_rsp_t init_read_rsp, init_write_rsp; idma_backend_r_obi_rw_init_w_axi #( - .DataWidth ( AXI_DATA_WIDTH ), - .AddrWidth ( AXI_ADDR_WIDTH ), - .UserWidth ( AXI_USER_WIDTH ), - .AxiIdWidth ( AXI_ID_WIDTH ), - .NumAxInFlight ( NB_OUTSND_BURSTS ), - .BufferDepth ( 32'd3 ), - .TFLenWidth ( TFLenWidth ), - .MemSysDepth ( 32'd0 ), - .CombinedShifter ( 1'b1 ), - .RAWCouplingAvail ( 1'b1 ), - .MaskInvalidData ( 1'b0 ), - .HardwareLegalizer ( 1'b1 ), - .RejectZeroTransfers ( 1'b1 ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .init_req_t ( init_req_t ), - .init_rsp_t ( init_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .write_meta_channel_t ( write_meta_channel_t ) + .DataWidth (AXI_DATA_WIDTH), + .AddrWidth (AXI_ADDR_WIDTH), + .UserWidth (AXI_USER_WIDTH), + .AxiIdWidth (AXI_ID_WIDTH), + .NumAxInFlight (NB_OUTSND_BURSTS), + .BufferDepth (32'd3), + .TFLenWidth (TFLenWidth), + .MemSysDepth (32'd0), + .CombinedShifter (1'b1), + .RAWCouplingAvail (1'b1), + .MaskInvalidData (1'b0), + .HardwareLegalizer (1'b1), + .RejectZeroTransfers (1'b1), + .idma_req_t (idma_req_t), + .idma_rsp_t (idma_rsp_t), + .idma_eh_req_t (idma_pkg::idma_eh_req_t), + .idma_busy_t (idma_pkg::idma_busy_t), + .axi_req_t (axi_req_t), + .axi_rsp_t (axi_rsp_t), + .init_req_t (init_req_t), + .init_rsp_t (init_rsp_t), + .obi_req_t (obi_req_t), + .obi_rsp_t (obi_rsp_t), + .read_meta_channel_t (read_meta_channel_t), + .write_meta_channel_t(write_meta_channel_t) ) i_idma_backend_r_obi_rw_init_w_axi ( .clk_i, .rst_ni, - .testmode_i ( test_mode_i ), - .idma_req_i ( idma_req [s] ), - .req_valid_i ( be_valid [s] ), - .req_ready_o ( be_ready [s] ), - .idma_rsp_o ( idma_rsp [s] ), - .rsp_valid_o ( be_rsp_valid [s] ), - .rsp_ready_i ( be_rsp_ready [s] ), - .idma_eh_req_i ( 'b0 ), - .eh_req_valid_i ( 1'b0 ), - .eh_req_ready_o ( /* NOT CONNECTED */ ), - .init_read_req_o ( init_read_req ), - .init_read_rsp_i ( init_read_rsp ), - .obi_read_req_o ( obi_read_req [s/2] ), - .obi_read_rsp_i ( obi_read_rsp [s/2] ), - .axi_write_req_o ( dma_req [s] ), - .axi_write_rsp_i ( dma_rsp [s] ), - .init_write_req_o ( init_write_req ), - .init_write_rsp_i ( init_write_rsp ), - .busy_o ( idma_busy [s] ) + .testmode_i (test_mode_i), + .idma_req_i (idma_req[s]), + .req_valid_i (be_valid[s]), + .req_ready_o (be_ready[s]), + .idma_rsp_o (idma_rsp[s]), + .rsp_valid_o (be_rsp_valid[s]), + .rsp_ready_i (be_rsp_ready[s]), + .idma_eh_req_i ('b0), + .eh_req_valid_i (1'b0), + .eh_req_ready_o ( /* NOT CONNECTED */), + .init_read_req_o (init_read_req), + .init_read_rsp_i (init_read_rsp), + .obi_read_req_o (obi_read_req_from_dma[s/2]), + .obi_read_rsp_i (obi_read_rsp_to_dma[s/2]), + .axi_write_req_o (dma_req[s]), + .axi_write_rsp_i (dma_rsp[s]), + .init_write_req_o(init_write_req), + .init_write_rsp_i(init_write_rsp), + .busy_o (idma_busy[s]) ); // implement zero memory using init protocol - init_read_rsp.rsp_chan.init = '0; - init_read_rsp.rsp_valid = init_read_req.req_valid; // might need spill register - init_read_rsp.req_ready = 1'b1; + assign init_read_rsp.rsp_chan.init = '0; + assign init_read_rsp.rsp_valid = init_read_req.req_valid; // might need spill register + assign init_read_rsp.req_ready = 1'b1; // implement /dev/null - init_write_rsp.rsp_chan.init = '0; - init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register - init_write_rsp.req_ready = 1'b1; + assign init_write_rsp.rsp_chan.init = '0; + assign init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register + assign init_write_rsp.req_ready = 1'b1; - // odd channels: copy in data + // odd channels: copy in data end else begin : gen_cpy_in // Meta Channel Widths - localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AXI_ADDR_WIDTH, AXI_ID_WIDTH, AXI_USER_WIDTH); + localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width( + AXI_ADDR_WIDTH, AXI_ID_WIDTH, AXI_USER_WIDTH + ); localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); @@ -457,17 +478,23 @@ module dmac_wrap #( typedef struct packed { axi_ar_chan_t ar_chan; - logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-axi_ar_chan_width:0] padding; + logic [max_width( +axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) +)-axi_ar_chan_width:0] padding; } axi_read_ar_chan_padded_t; typedef struct packed { init_req_chan_t req_chan; - logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-init_req_chan_width:0] padding; + logic [max_width( +axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) +)-init_req_chan_width:0] padding; } init_read_req_chan_padded_t; typedef struct packed { obi_a_chan_t a_chan; - logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-obi_a_chan_width:0] padding; + logic [max_width( +axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) +)-obi_a_chan_width:0] padding; } obi_read_a_chan_padded_t; typedef union packed { @@ -478,12 +505,12 @@ module dmac_wrap #( typedef struct packed { init_req_chan_t req_chan; - logic[max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; + logic [max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; } init_write_req_chan_padded_t; typedef struct packed { obi_a_chan_t a_chan; - logic[max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + logic [max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; } obi_write_a_chan_padded_t; typedef union packed { @@ -496,73 +523,112 @@ module dmac_wrap #( init_rsp_t init_read_rsp, init_write_rsp; idma_backend_r_axi_rw_init_rw_obi #( - .DataWidth ( AXI_DATA_WIDTH ), - .AddrWidth ( AXI_ADDR_WIDTH ), - .UserWidth ( AXI_USER_WIDTH ), - .AxiIdWidth ( AXI_ID_WIDTH ), - .NumAxInFlight ( NB_OUTSND_BURSTS ), - .BufferDepth ( 32'd3 ), - .TFLenWidth ( TFLenWidth ), - .MemSysDepth ( 32'd0 ), - .CombinedShifter ( 1'b1 ), - .RAWCouplingAvail ( 1'b1 ), - .MaskInvalidData ( 1'b0 ), - .HardwareLegalizer ( 1'b1 ), - .RejectZeroTransfers ( 1'b1 ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .init_req_t ( init_req_t ), - .init_rsp_t ( init_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .write_meta_channel_t ( write_meta_channel_t ) + .DataWidth (AXI_DATA_WIDTH), + .AddrWidth (AXI_ADDR_WIDTH), + .UserWidth (AXI_USER_WIDTH), + .AxiIdWidth (AXI_ID_WIDTH), + .NumAxInFlight (NB_OUTSND_BURSTS), + .BufferDepth (32'd3), + .TFLenWidth (TFLenWidth), + .MemSysDepth (32'd0), + .CombinedShifter (1'b1), + .RAWCouplingAvail (1'b1), + .MaskInvalidData (1'b0), + .HardwareLegalizer (1'b1), + .RejectZeroTransfers (1'b1), + .idma_req_t (idma_req_t), + .idma_rsp_t (idma_rsp_t), + .idma_eh_req_t (idma_pkg::idma_eh_req_t), + .idma_busy_t (idma_pkg::idma_busy_t), + .axi_req_t (axi_req_t), + .axi_rsp_t (axi_rsp_t), + .init_req_t (init_req_t), + .init_rsp_t (init_rsp_t), + .obi_req_t (obi_req_t), + .obi_rsp_t (obi_rsp_t), + .read_meta_channel_t (read_meta_channel_t), + .write_meta_channel_t(write_meta_channel_t) ) i_idma_backend_r_axi_rw_init_rw_obi ( .clk_i, .rst_ni, - .testmode_i ( test_mode_i ), - .idma_req_i ( idma_req [s] ), - .req_valid_i ( be_valid [s] ), - .req_ready_o ( be_ready [s] ), - .idma_rsp_o ( idma_rsp [s] ), - .rsp_valid_o ( be_rsp_valid [s] ), - .rsp_ready_i ( be_rsp_ready [s] ), - .idma_eh_req_i ( 'b0 ), - .eh_req_valid_i ( 1'b0 ), - .eh_req_ready_o ( /* NOT CONNECTED */ ), - .axi_read_req_o ( dma_req [s] ), - .axi_read_rsp_i ( dma_rsp [s] ), - .init_read_req_o ( init_read_req ), - .init_read_rsp_i ( init_read_rsp ), - .obi_read_req_o ( obi_reorg_req [s/2] ), - .obi_read_rsp_i ( obi_reorg_rsp [s/2] ), - .init_write_req_o ( init_write_req ), - .init_write_rsp_i ( init_write_rsp ), - .obi_write_req_o ( obi_write_req [s/2] ), - .obi_write_rsp_i ( obi_write_rsp [s/2] ), - .busy_o ( idma_busy [s] ) + .testmode_i (test_mode_i), + .idma_req_i (idma_req[s]), + .req_valid_i (be_valid[s]), + .req_ready_o (be_ready[s]), + .idma_rsp_o (idma_rsp[s]), + .rsp_valid_o (be_rsp_valid[s]), + .rsp_ready_i (be_rsp_ready[s]), + .idma_eh_req_i ('b0), + .eh_req_valid_i (1'b0), + .eh_req_ready_o ( /* NOT CONNECTED */), + .axi_read_req_o (dma_req[s]), + .axi_read_rsp_i (dma_rsp[s]), + .init_read_req_o (init_read_req), + .init_read_rsp_i (init_read_rsp), + .obi_read_req_o (obi_reorg_req[s/2]), + .obi_read_rsp_i (obi_reorg_rsp[s/2]), + .init_write_req_o(init_write_req), + .init_write_rsp_i(init_write_rsp), + .obi_write_req_o (obi_write_req[s/2]), + .obi_write_rsp_i (obi_write_rsp[s/2]), + .busy_o (idma_busy[s]) ); // implement zero memory using init protocol - init_read_rsp.rsp_chan.init = '0; - init_read_rsp.rsp_valid = init_read_req.req_valid; // might need spill register - init_read_rsp.req_ready = 1'b1; + assign init_read_rsp.rsp_chan.init = '0; + assign init_read_rsp.rsp_valid = init_read_req.req_valid; // might need spill register + assign init_read_rsp.req_ready = 1'b1; // implement /dev/null - init_write_rsp.rsp_chan.init = '0; - init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register - init_write_rsp.req_ready = 1'b1; + assign init_write_rsp.rsp_chan.init = '0; + assign init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register + assign init_write_rsp.req_ready = 1'b1; + end // block: gen_cpy_in + end // block: gen_streams + + + // ------------------------------------------------------ + // MUX read OBI connections if specified + // ------------------------------------------------------ + for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin + if (MUX_READ) begin + obi_pkg::obi_cfg_t sbr_obi_cfg; + assign sbr_obi_cfg = obi_pkg::obi_default_cfg( + AXI_ADDR_WIDTH, AXI_DATA_WIDTH, 0, obi_pkg::ObiMinimalOptionalConfig + ); + + obi_mux #( + .SbrPortObiCfg (sbr_obi_cfg), + .MgrPortObiCfg (sbr_obi_cfg), + .sbr_port_obi_req_t(obi_req_t), + .sbr_port_a_chan_t (obi_a_chan_t), + .sbr_port_obi_rsp_t(obi_rsp_t), + .sbr_port_r_chan_t (obi_r_chan_t), + .mgr_port_obi_req_t(obi_req_t), + .mgr_port_obi_rsp_t(obi_rsp_t), + .NumSbrPorts (2), + .NumMaxTrans (1), + .UseIdForRouting (1'b0) + ) obi_read_mux_i ( + .clk_i, + .rst_ni, + .testmode_i (test_mode_i), + .sbr_ports_req_i({obi_reorg_req, obi_read_req_from_dma}), + .sbr_ports_rsp_o({obi_reorg_rsp, obi_read_rsp_to_dma}), + .mgr_port_req_o (obi_read_req_muxed), + .mgr_port_rsp_i (obi_read_rsp_to_mux) + ); + end else begin // if (MUX_READ) + // pass through the read req/rsp from/to dma + assign obi_read_req_muxed = obi_read_req_from_dma; + assign obi_read_rsp_to_dma = obi_read_rsp_to_mux; end + end // ------------------------------------------------------ // TCDM connections // ------------------------------------------------------ - for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin logic tcdm_master_we_0; @@ -573,121 +639,172 @@ module dmac_wrap #( logic tcdm_master_we_5; mem_to_banks #( - .AddrWidth ( AXI_ADDR_WIDTH ), - .DataWidth ( AXI_DATA_WIDTH ), - .NumBanks ( 32'd2 ), - .HideStrb ( 1'b1 ), - .MaxTrans ( 32'd1 ), - .FifoDepth ( 32'd1 ) + .AddrWidth(AXI_ADDR_WIDTH), + .DataWidth(AXI_DATA_WIDTH), + .NumBanks (32'd2), + .HideStrb (1'b1), + .MaxTrans (32'd1), + .FifoDepth(32'd1) ) i_mem_to_banks_read ( .clk_i, .rst_ni, - .req_i ( obi_read_req[s].req ), - .gnt_o ( obi_read_rsp[s].gnt ), - .addr_i ( obi_read_req[s].a.addr ), - .wdata_i ( obi_read_req[s].a.wdata ), - .strb_i ( obi_read_req[s].a.be ), - .atop_i ( '0 ), - .we_i ( obi_read_req[s].a.we ), - .rvalid_o ( obi_read_rsp[s].rvalid ), - .rdata_o ( obi_read_rsp[s].r.data ), - .bank_req_o ( {tcdm_master[6*s+1].req, tcdm_master[6*s].req} ), - .bank_gnt_i ( {tcdm_master[6*s+1].gnt, tcdm_master[6*s].gnt} ), - .bank_addr_o ( {tcdm_master[6*s+1].add, tcdm_master[6*s].add} ), - .bank_wdata_o ( {tcdm_master[6*s+1].data, tcdm_master[6*s].data} ), - .bank_strb_o ( {tcdm_master[6*s+1].be, tcdm_master[6*s].be} ), - .bank_atop_o ( /* NOT CONNECTED */ ), - .bank_we_o ( {tcdm_master_we_1, tcdm_master_we_0} ), - .bank_rvalid_i ( {tcdm_master[6*s+1].r_valid, tcdm_master[6*s].r_valid} ), - .bank_rdata_i ( {tcdm_master[6*s+1].r_data, tcdm_master[6*s].r_data} ) + .req_i(obi_read_req_muxed[s].req), + .gnt_o(obi_read_rsp_to_mux[s].gnt), + .addr_i(obi_read_req_muxed[s].a.addr), + .wdata_i(obi_read_req_muxed[s].a.wdata), + .strb_i(obi_read_req_muxed[s].a.be), + .atop_i('0), + .we_i(obi_read_req_muxed[s].a.we), + .rvalid_o(obi_read_rsp_to_mux[s].rvalid), + .rdata_o(obi_read_rsp_to_mux[s].r.data), + .bank_req_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].req + }), + .bank_gnt_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].gnt, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].gnt + }), + .bank_addr_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].add, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].add + }), + .bank_wdata_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].data, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].data + }), + .bank_strb_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].be, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].be + }), + .bank_atop_o( /* NOT CONNECTED */), + .bank_we_o({tcdm_master_we_3, tcdm_master_we_2}), + .bank_rvalid_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].r_valid, + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].r_valid + }), + .bank_rdata_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].r_data, + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].r_data + }) ); - assign tcdm_master[0].boffs = '0; - assign tcdm_master[0].lrdy = '0; - assign tcdm_master[0].user = '0; - assign tcdm_master[1].boffs = '0; - assign tcdm_master[1].lrdy = '0; - assign tcdm_master[1].user = '0; - assign tcdm_master[0].wen = !tcdm_master_we_0; - assign tcdm_master[1].wen = !tcdm_master_we_1; - mem_to_banks #( - .AddrWidth ( AXI_ADDR_WIDTH ), - .DataWidth ( AXI_DATA_WIDTH ), - .NumBanks ( 32'd2 ), - .HideStrb ( 1'b1 ), - .MaxTrans ( 32'd1 ), - .FifoDepth ( 32'd1 ) - ) i_mem_to_banks_reorg ( - .clk_i, - .rst_ni, - .req_i ( obi_reorg_req[s].req ), - .gnt_o ( obi_reorg_rsp[s].gnt ), - .addr_i ( obi_reorg_req[s].a.addr ), - .wdata_i ( obi_reorg_req[s].a.wdata ), - .strb_i ( obi_reorg_req[s].a.be ), - .atop_i ( '0 ), - .we_i ( obi_reorg_req[s].a.we ), - .rvalid_o ( obi_reorg_rsp[s].rvalid ), - .rdata_o ( obi_reorg_rsp[s].r.data ), - .bank_req_o ( {tcdm_master[6*s+3].req, tcdm_master[6*s+2].req} ), - .bank_gnt_i ( {tcdm_master[6*s+3].gnt, tcdm_master[6*s+2].gnt} ), - .bank_addr_o ( {tcdm_master[6*s+3].add, tcdm_master[6*s+2].add} ), - .bank_wdata_o ( {tcdm_master[6*s+3].data, tcdm_master[6*s+2].data} ), - .bank_strb_o ( {tcdm_master[6*s+3].be, tcdm_master[6*s+2].be} ), - .bank_atop_o ( /* NOT CONNECTED */ ), - .bank_we_o ( {tcdm_master_we_3, tcdm_master_we_2} ), - .bank_rvalid_i ( {tcdm_master[6*s+3].r_valid, tcdm_master[6*s+2].r_valid} ), - .bank_rdata_i ( {tcdm_master[6*s+3].r_data, tcdm_master[6*s+2].r_data} ) - ); + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].boffs = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].lrdy = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].user = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].boffs = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].lrdy = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].user = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].wen = !tcdm_master_we_2; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].wen = !tcdm_master_we_3; + + if (!MUX_READ) begin // if we don't mux the read, we have 6*NUM_BIDIR_STREAMS interfaces and the reorg + // interface goes straight to TCDM masters 5 and 4. + mem_to_banks #( + .AddrWidth(AXI_ADDR_WIDTH), + .DataWidth(AXI_DATA_WIDTH), + .NumBanks (32'd2), + .HideStrb (1'b1), + .MaxTrans (32'd1), + .FifoDepth(32'd1) + ) i_mem_to_banks_reorg ( + .clk_i, + .rst_ni, + .req_i(obi_reorg_req[s].req), + .gnt_o(obi_reorg_rsp[s].gnt), + .addr_i(obi_reorg_req[s].a.addr), + .wdata_i(obi_reorg_req[s].a.wdata), + .strb_i(obi_reorg_req[s].a.be), + .atop_i('0), + .we_i(obi_reorg_req[s].a.we), + .rvalid_o(obi_reorg_rsp[s].rvalid), + .rdata_o(obi_reorg_rsp[s].r.data), + .bank_req_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].req + }), + .bank_gnt_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].gnt, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].gnt + }), + .bank_addr_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].add, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].add + }), + .bank_wdata_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].data, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].data + }), + .bank_strb_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].be, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].be + }), + .bank_atop_o( /* NOT CONNECTED */), + .bank_we_o({tcdm_master_we_5, tcdm_master_we_4}), + .bank_rvalid_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].r_valid, + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].r_valid + }), + .bank_rdata_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].r_data, + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].r_data + }) + ); - assign tcdm_master[2].boffs = '0; - assign tcdm_master[2].lrdy = '0; - assign tcdm_master[2].user = '0; - assign tcdm_master[3].boffs = '0; - assign tcdm_master[3].lrdy = '0; - assign tcdm_master[3].user = '0; - assign tcdm_master[2].wen = !tcdm_master_we_2; - assign tcdm_master[3].wen = !tcdm_master_we_3; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].boffs = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].lrdy = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].user = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].boffs = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].lrdy = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].user = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].wen = !tcdm_master_we_4; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].wen = !tcdm_master_we_5; + end mem_to_banks #( - .AddrWidth ( AXI_ADDR_WIDTH ), - .DataWidth ( AXI_DATA_WIDTH ), - .NumBanks ( 32'd2 ), - .HideStrb ( 1'b1 ), - .MaxTrans ( 32'd1 ), - .FifoDepth ( 32'd1 ) + .AddrWidth(AXI_ADDR_WIDTH), + .DataWidth(AXI_DATA_WIDTH), + .NumBanks (32'd2), + .HideStrb (1'b1), + .MaxTrans (32'd1), + .FifoDepth(32'd1) ) i_mem_to_banks_write ( .clk_i, .rst_ni, - .req_i ( obi_write_req[s].req ), - .gnt_o ( obi_write_rsp[s].gnt ), - .addr_i ( obi_write_req[s].a.addr ), - .wdata_i ( obi_write_req[s].a.wdata ), - .strb_i ( obi_write_req[s].a.be ), - .atop_i ( '0 ), - .we_i ( obi_write_req[s].a.we ), - .rvalid_o ( obi_write_rsp[s].rvalid ), - .rdata_o ( obi_write_rsp[s].r.data ), - .bank_req_o ( {tcdm_master[6*s+5].req, tcdm_master[6*s+4].req} ), - .bank_gnt_i ( {tcdm_master[6*s+5].gnt, tcdm_master[6*s+4].gnt} ), - .bank_addr_o ( {tcdm_master[6*s+5].add, tcdm_master[6*s+4].add} ), - .bank_wdata_o ( {tcdm_master[6*s+5].data, tcdm_master[6*s+4].data} ), - .bank_strb_o ( {tcdm_master[6*s+5].be, tcdm_master[6*s+4].be} ), - .bank_atop_o ( /* NOT CONNECTED */ ), - .bank_we_o ( {tcdm_master_we_5, tcdm_master_we_4} ), - .bank_rvalid_i ( {tcdm_master[6*s+5].r_valid, tcdm_master[6*s+4].r_valid} ), - .bank_rdata_i ( {tcdm_master[6*s+5].r_data, tcdm_master[6*s+4].r_data} ) + .req_i(obi_write_req[s].req), + .gnt_o(obi_write_rsp[s].gnt), + .addr_i(obi_write_req[s].a.addr), + .wdata_i(obi_write_req[s].a.wdata), + .strb_i(obi_write_req[s].a.be), + .atop_i('0), + .we_i(obi_write_req[s].a.we), + .rvalid_o(obi_write_rsp[s].rvalid), + .rdata_o(obi_write_rsp[s].r.data), + .bank_req_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].req + }), + .bank_gnt_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].gnt, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].gnt + }), + .bank_addr_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].add, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].add + }), + .bank_wdata_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].data, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].data + }), + .bank_strb_o({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].be, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].be + }), + .bank_atop_o( /* NOT CONNECTED */), + .bank_we_o({tcdm_master_we_0, tcdm_master_we_0}), + .bank_rvalid_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].r_valid, + tcdm_master[NB_TCDM_PORTS_PER_STRM*s].r_valid + }), + .bank_rdata_i({ + tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].r_data, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].r_data + }) ); - assign tcdm_master[4].boffs = '0; - assign tcdm_master[4].lrdy = '0; - assign tcdm_master[4].user = '0; - assign tcdm_master[5].boffs = '0; - assign tcdm_master[5].lrdy = '0; - assign tcdm_master[5].user = '0; - assign tcdm_master[4].wen = !tcdm_master_we_4; - assign tcdm_master[5].wen = !tcdm_master_we_5; - end + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+0].boffs = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+0].lrdy = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+0].user = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].boffs = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].lrdy = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].user = '0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+0].wen = !tcdm_master_we_0; + assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].wen = !tcdm_master_we_1; + end endmodule From 70b1254b228341e66e9c1466acee7b01c2e4ff82 Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Fri, 21 Jun 2024 18:02:17 +0200 Subject: [PATCH 04/13] [WIP] add generated iDMA code to allow bender inclusion --- target/rtl/.gitignore | 1 + target/rtl/idma_generated.sv | 22077 +++++++++++++++++++++++++++++++++ 2 files changed, 22078 insertions(+) create mode 100644 target/rtl/idma_generated.sv diff --git a/target/rtl/.gitignore b/target/rtl/.gitignore index a2e0e0a0..f25db02f 100644 --- a/target/rtl/.gitignore +++ b/target/rtl/.gitignore @@ -1,4 +1,5 @@ Bender.yml include *.sv +!idma_generated.sv *.hjson diff --git a/target/rtl/idma_generated.sv b/target/rtl/idma_generated.sv new file mode 100644 index 00000000..13c47c20 --- /dev/null +++ b/target/rtl/idma_generated.sv @@ -0,0 +1,22077 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "idma/guard.svh" +`include "common_cells/registers.svh" + +/// Implementing the transport layer in the iDMA backend. +module idma_transport_layer_rw_axi #( + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `w_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_rsp_t` type: + parameter type r_dp_rsp_t = logic, + /// `w_dp_rsp_t` type: + parameter type w_dp_rsp_t = logic, + /// Write Meta channel type + parameter type write_meta_channel_t = logic, + /// Read Meta channel type + parameter type read_meta_channel_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input read_meta_channel_t ar_req_i, + /// Read meta request valid + input logic ar_valid_i, + /// Read meta request ready + output logic ar_ready_o, + + /// Write meta request + input write_meta_channel_t aw_req_i, + /// Write meta request valid + input logic aw_valid_i, + /// Write meta request ready + output logic aw_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Response channel valid and ready + output logic r_chan_ready_o, + output logic r_chan_valid_o, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // inbound control signals to the read buffer: controlled by the read process + strb_t buffer_in_valid; + + strb_t buffer_in_ready; + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid, buffer_out_valid_shifted; + strb_t + buffer_out_ready, buffer_out_ready_shifted; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] + buffer_in, buffer_in_shifted; + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; + + //-------------------------------------- + // Read Ports + //-------------------------------------- + + idma_axi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .ar_chan_t ( read_meta_channel_t ), + .read_req_t ( axi_req_t ), + .read_rsp_t ( axi_rsp_t ) + ) i_idma_axi_read ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( r_dp_valid_i ), + .r_dp_ready_o ( r_dp_ready_o ), + .r_dp_rsp_o ( r_dp_rsp_o ), + .r_dp_valid_o ( r_dp_valid_o ), + .r_dp_ready_i ( r_dp_ready_i ), + .ar_req_i ( ar_req_i ), + .ar_valid_i ( ar_valid_i ), + .ar_ready_o ( ar_ready_o ), + .read_req_o ( axi_read_req_o ), + .read_rsp_i ( axi_read_rsp_i ), + .r_chan_valid_o ( r_chan_valid_o ), + .r_chan_ready_o ( r_chan_ready_o ), + .buffer_in_o ( buffer_in ), + .buffer_in_valid_o ( buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + //-------------------------------------- + // Read Barrel shifter + //-------------------------------------- + + assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); + + //-------------------------------------- + // Buffer + //-------------------------------------- + + idma_dataflow_element #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_dataflow_element ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .data_i ( buffer_in_shifted ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready_shifted ) + ); + + //-------------------------------------- + // Write Barrel shifter + //-------------------------------------- + + assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); + assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; + assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; + + //-------------------------------------- + // Write Ports + //-------------------------------------- + + idma_axi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .aw_chan_t ( write_meta_channel_t ), + .write_req_t ( axi_req_t ), + .write_rsp_t ( axi_rsp_t ) + ) i_idma_axi_write ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( w_dp_valid_i ), + .w_dp_ready_o ( w_dp_ready_o ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( w_dp_rsp_o ), + .w_dp_valid_o ( w_dp_valid_o ), + .w_dp_ready_i ( w_dp_ready_i ), + .aw_req_i ( aw_req_i ), + .aw_valid_i ( aw_valid_i ), + .aw_ready_o ( aw_ready_o ), + .write_req_o ( axi_write_req_o ), + .write_rsp_i ( axi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( buffer_out_ready ) + ); + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = |buffer_out_valid; + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "idma/guard.svh" +`include "common_cells/registers.svh" + +/// Implementing the transport layer in the iDMA backend. +module idma_transport_layer_r_obi_w_axi #( + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `w_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_rsp_t` type: + parameter type r_dp_rsp_t = logic, + /// `w_dp_rsp_t` type: + parameter type w_dp_rsp_t = logic, + /// Write Meta channel type + parameter type write_meta_channel_t = logic, + /// Read Meta channel type + parameter type read_meta_channel_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input read_meta_channel_t ar_req_i, + /// Read meta request valid + input logic ar_valid_i, + /// Read meta request ready + output logic ar_ready_o, + + /// Write meta request + input write_meta_channel_t aw_req_i, + /// Write meta request valid + input logic aw_valid_i, + /// Write meta request ready + output logic aw_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Response channel valid and ready + output logic r_chan_ready_o, + output logic r_chan_valid_o, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // inbound control signals to the read buffer: controlled by the read process + strb_t buffer_in_valid; + + strb_t buffer_in_ready; + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid, buffer_out_valid_shifted; + strb_t + buffer_out_ready, buffer_out_ready_shifted; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] + buffer_in, buffer_in_shifted; + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; + + //-------------------------------------- + // Read Ports + //-------------------------------------- + + idma_obi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .read_meta_chan_t ( read_meta_channel_t ), + .read_req_t ( obi_req_t ), + .read_rsp_t ( obi_rsp_t ) + ) i_idma_obi_read ( + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( r_dp_valid_i ), + .r_dp_ready_o ( r_dp_ready_o ), + .r_dp_rsp_o ( r_dp_rsp_o ), + .r_dp_valid_o ( r_dp_valid_o ), + .r_dp_ready_i ( r_dp_ready_i ), + .read_meta_req_i ( ar_req_i ), + .read_meta_valid_i ( ar_valid_i ), + .read_meta_ready_o ( ar_ready_o ), + .read_req_o ( obi_read_req_o ), + .read_rsp_i ( obi_read_rsp_i ), + .r_chan_valid_o ( r_chan_valid_o ), + .r_chan_ready_o ( r_chan_ready_o ), + .buffer_in_o ( buffer_in ), + .buffer_in_valid_o ( buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + //-------------------------------------- + // Read Barrel shifter + //-------------------------------------- + + assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); + + //-------------------------------------- + // Buffer + //-------------------------------------- + + idma_dataflow_element #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_dataflow_element ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .data_i ( buffer_in_shifted ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready_shifted ) + ); + + //-------------------------------------- + // Write Barrel shifter + //-------------------------------------- + + assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); + assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; + assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; + + //-------------------------------------- + // Write Ports + //-------------------------------------- + + idma_axi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .aw_chan_t ( write_meta_channel_t ), + .write_req_t ( axi_req_t ), + .write_rsp_t ( axi_rsp_t ) + ) i_idma_axi_write ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( w_dp_valid_i ), + .w_dp_ready_o ( w_dp_ready_o ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( w_dp_rsp_o ), + .w_dp_valid_o ( w_dp_valid_o ), + .w_dp_ready_i ( w_dp_ready_i ), + .aw_req_i ( aw_req_i ), + .aw_valid_i ( aw_valid_i ), + .aw_ready_o ( aw_ready_o ), + .write_req_o ( axi_write_req_o ), + .write_rsp_i ( axi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( buffer_out_ready ) + ); + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = |buffer_out_valid; + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "idma/guard.svh" +`include "common_cells/registers.svh" + +/// Implementing the transport layer in the iDMA backend. +module idma_transport_layer_r_axi_w_obi #( + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `w_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_rsp_t` type: + parameter type r_dp_rsp_t = logic, + /// `w_dp_rsp_t` type: + parameter type w_dp_rsp_t = logic, + /// Write Meta channel type + parameter type write_meta_channel_t = logic, + /// Read Meta channel type + parameter type read_meta_channel_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input read_meta_channel_t ar_req_i, + /// Read meta request valid + input logic ar_valid_i, + /// Read meta request ready + output logic ar_ready_o, + + /// Write meta request + input write_meta_channel_t aw_req_i, + /// Write meta request valid + input logic aw_valid_i, + /// Write meta request ready + output logic aw_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Response channel valid and ready + output logic r_chan_ready_o, + output logic r_chan_valid_o, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // inbound control signals to the read buffer: controlled by the read process + strb_t buffer_in_valid; + + strb_t buffer_in_ready; + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid, buffer_out_valid_shifted; + strb_t + buffer_out_ready, buffer_out_ready_shifted; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] + buffer_in, buffer_in_shifted; + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; + + //-------------------------------------- + // Read Ports + //-------------------------------------- + + idma_axi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .ar_chan_t ( read_meta_channel_t ), + .read_req_t ( axi_req_t ), + .read_rsp_t ( axi_rsp_t ) + ) i_idma_axi_read ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( r_dp_valid_i ), + .r_dp_ready_o ( r_dp_ready_o ), + .r_dp_rsp_o ( r_dp_rsp_o ), + .r_dp_valid_o ( r_dp_valid_o ), + .r_dp_ready_i ( r_dp_ready_i ), + .ar_req_i ( ar_req_i ), + .ar_valid_i ( ar_valid_i ), + .ar_ready_o ( ar_ready_o ), + .read_req_o ( axi_read_req_o ), + .read_rsp_i ( axi_read_rsp_i ), + .r_chan_valid_o ( r_chan_valid_o ), + .r_chan_ready_o ( r_chan_ready_o ), + .buffer_in_o ( buffer_in ), + .buffer_in_valid_o ( buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + //-------------------------------------- + // Read Barrel shifter + //-------------------------------------- + + assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); + + //-------------------------------------- + // Buffer + //-------------------------------------- + + idma_dataflow_element #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_dataflow_element ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .data_i ( buffer_in_shifted ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready_shifted ) + ); + + //-------------------------------------- + // Write Barrel shifter + //-------------------------------------- + + assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); + assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; + assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; + + //-------------------------------------- + // Write Ports + //-------------------------------------- + + idma_obi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_req_t ( obi_req_t ), + .write_rsp_t ( obi_rsp_t ) + ) i_idma_obi_write ( + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( w_dp_valid_i ), + .w_dp_ready_o ( w_dp_ready_o ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( w_dp_rsp_o ), + .w_dp_valid_o ( w_dp_valid_o ), + .w_dp_ready_i ( w_dp_ready_i ), + .aw_req_i ( aw_req_i ), + .aw_valid_i ( aw_valid_i ), + .aw_ready_o ( aw_ready_o ), + .write_req_o ( obi_write_req_o ), + .write_rsp_i ( obi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( buffer_out_ready ) + ); + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = |buffer_out_valid; + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "idma/guard.svh" +`include "common_cells/registers.svh" + +/// Implementing the transport layer in the iDMA backend. +module idma_transport_layer_rw_axi_rw_axis #( + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `w_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_rsp_t` type: + parameter type r_dp_rsp_t = logic, + /// `w_dp_rsp_t` type: + parameter type w_dp_rsp_t = logic, + /// Write Meta channel type + parameter type write_meta_channel_t = logic, + parameter type write_meta_channel_tagged_t = logic, + /// Read Meta channel type + parameter type read_meta_channel_t = logic, + parameter type read_meta_channel_tagged_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// AXI Stream Request and Response channel type + parameter type axis_req_t = logic, + parameter type axis_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// AXI Stream read request + input axis_req_t axis_read_req_i, + /// AXI Stream read response + output axis_rsp_t axis_read_rsp_o, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// AXI Stream write request + output axis_req_t axis_write_req_o, + /// AXI Stream write response + input axis_rsp_t axis_write_rsp_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input read_meta_channel_tagged_t ar_req_i, + /// Read meta request valid + input logic ar_valid_i, + /// Read meta request ready + output logic ar_ready_o, + + /// Write meta request + input write_meta_channel_tagged_t aw_req_i, + /// Write meta request valid + input logic aw_valid_i, + /// Write meta request ready + output logic aw_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Response channel valid and ready + output logic r_chan_ready_o, + output logic r_chan_valid_o, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // inbound control signals to the read buffer: controlled by the read process + strb_t axi_buffer_in_valid, axis_buffer_in_valid, buffer_in_valid; + + strb_t buffer_in_ready; + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid, buffer_out_valid_shifted; + strb_t axi_buffer_out_ready, axis_buffer_out_ready, + buffer_out_ready, buffer_out_ready_shifted; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] axi_buffer_in, axis_buffer_in, + buffer_in, buffer_in_shifted; + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; + + // Read multiplexed signals + logic axi_r_chan_valid, axis_r_chan_valid; + logic axi_r_chan_ready, axis_r_chan_ready; + logic axi_r_dp_valid, axis_r_dp_valid; + logic axi_r_dp_ready, axis_r_dp_ready; + r_dp_rsp_t axi_r_dp_rsp, axis_r_dp_rsp; + + logic axi_ar_ready, axis_ar_ready; + + // Write multiplexed signals + logic axi_w_dp_rsp_valid, axis_w_dp_rsp_valid; + logic axi_w_dp_rsp_ready, axis_w_dp_rsp_ready; + logic axi_w_dp_ready, axis_w_dp_ready; + w_dp_rsp_t axi_w_dp_rsp, axis_w_dp_rsp; + + logic axi_aw_ready, axis_aw_ready; + logic w_dp_req_valid, w_dp_req_ready; + logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; + logic w_dp_rsp_valid, w_dp_rsp_ready; + w_dp_rsp_t w_dp_rsp_mux; + + // Write Response FIFO signals + logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; + idma_pkg::protocol_e w_resp_fifo_out_protocol; + logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; + + //-------------------------------------- + // Read Ports + //-------------------------------------- + + idma_axi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .ar_chan_t ( read_meta_channel_t ), + .read_req_t ( axi_req_t ), + .read_rsp_t ( axi_rsp_t ) + ) i_idma_axi_read ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_valid_i ), + .r_dp_ready_o ( axi_r_dp_ready ), + .r_dp_rsp_o ( axi_r_dp_rsp ), + .r_dp_valid_o ( axi_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_ready_i ), + .ar_req_i ( ar_req_i.ar_req ), + .ar_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI) & ar_valid_i ), + .ar_ready_o ( axi_ar_ready ), + .read_req_o ( axi_read_req_o ), + .read_rsp_i ( axi_read_rsp_i ), + .r_chan_valid_o ( axi_r_chan_valid ), + .r_chan_ready_o ( axi_r_chan_ready ), + .buffer_in_o ( axi_buffer_in ), + .buffer_in_valid_o ( axi_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + idma_axis_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .read_meta_chan_t ( read_meta_channel_t ), + .read_req_t ( axis_req_t ), + .read_rsp_t ( axis_rsp_t ) + ) i_idma_axis_read ( + .r_dp_req_i ( r_dp_req_i ), + .r_dp_req_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI_STREAM) & r_dp_valid_i ), + .r_dp_req_ready_o ( axis_r_dp_ready ), + .r_dp_rsp_o ( axis_r_dp_rsp ), + .r_dp_rsp_valid_o ( axis_r_dp_valid ), + .r_dp_rsp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI_STREAM) & r_dp_ready_i ), + .read_meta_req_i ( ar_req_i.ar_req ), + .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI_STREAM) & ar_valid_i ), + .read_meta_ready_o ( axis_ar_ready ), + .read_req_i ( axis_read_req_i ), + .read_rsp_o ( axis_read_rsp_o ), + .r_chan_valid_o ( axis_r_chan_valid ), + .r_chan_ready_o ( axis_r_chan_ready ), + .buffer_in_o ( axis_buffer_in ), + .buffer_in_valid_o ( axis_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + //-------------------------------------- + // Read Multiplexers + //-------------------------------------- + + always_comb begin : gen_read_meta_channel_multiplexer + case(ar_req_i.src_protocol) + idma_pkg::AXI: ar_ready_o = axi_ar_ready; + idma_pkg::AXI_STREAM: ar_ready_o = axis_ar_ready; + default: ar_ready_o = 1'b0; + endcase + end + + always_comb begin : gen_read_multiplexer + case(r_dp_req_i.src_protocol) + idma_pkg::AXI: begin + r_chan_valid_o = axi_r_chan_valid; + r_chan_ready_o = axi_r_chan_ready; + + r_dp_ready_o = axi_r_dp_ready; + r_dp_rsp_o = axi_r_dp_rsp; + r_dp_valid_o = axi_r_dp_valid; + + buffer_in = axi_buffer_in; + buffer_in_valid = axi_buffer_in_valid; + end + idma_pkg::AXI_STREAM: begin + r_chan_valid_o = axis_r_chan_valid; + r_chan_ready_o = axis_r_chan_ready; + + r_dp_ready_o = axis_r_dp_ready; + r_dp_rsp_o = axis_r_dp_rsp; + r_dp_valid_o = axis_r_dp_valid; + + buffer_in = axis_buffer_in; + buffer_in_valid = axis_buffer_in_valid; + end + default: begin + r_chan_valid_o = 1'b0; + r_chan_ready_o = 1'b0; + + r_dp_ready_o = 1'b0; + r_dp_rsp_o = '0; + r_dp_valid_o = 1'b0; + + buffer_in = '0; + buffer_in_valid = '0; + end + endcase + end + + //-------------------------------------- + // Read Barrel shifter + //-------------------------------------- + + assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); + + //-------------------------------------- + // Buffer + //-------------------------------------- + + idma_dataflow_element #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_dataflow_element ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .data_i ( buffer_in_shifted ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready_shifted ) + ); + + //-------------------------------------- + // Write Barrel shifter + //-------------------------------------- + + assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); + assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; + assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; + + //-------------------------------------- + // Write Request Demultiplexer + //-------------------------------------- + + // Split write request to write response fifo and write ports + stream_fork #( + .N_OUP ( 2 ) + ) i_write_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( w_dp_valid_i ), + .ready_o ( w_dp_ready_o ), + .valid_o ( { w_resp_fifo_in_valid, w_dp_req_valid } ), + .ready_i ( { w_resp_fifo_in_ready, w_dp_req_ready } ) + ); + + // Demux write request to correct write port + always_comb begin : gen_write_multiplexer + case(w_dp_req_i.dst_protocol) + idma_pkg::AXI: begin + w_dp_req_ready = axi_w_dp_ready; + buffer_out_ready = axi_buffer_out_ready; + end + idma_pkg::AXI_STREAM: begin + w_dp_req_ready = axis_w_dp_ready; + buffer_out_ready = axis_buffer_out_ready; + end + default: begin + w_dp_req_ready = 1'b0; + buffer_out_ready = '0; + end + endcase + end + + // Demux write meta channel to correct write port + always_comb begin : gen_write_meta_channel_multiplexer + case(aw_req_i.dst_protocol) + idma_pkg::AXI: aw_ready_o = axi_aw_ready; + idma_pkg::AXI_STREAM: aw_ready_o = axis_aw_ready; + default: aw_ready_o = 1'b0; + endcase + end + + //-------------------------------------- + // Write Ports + //-------------------------------------- + + idma_axi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .aw_chan_t ( write_meta_channel_t ), + .write_req_t ( axi_req_t ), + .write_rsp_t ( axi_rsp_t ) + ) i_idma_axi_write ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::AXI) & w_dp_req_valid ), + .w_dp_ready_o ( axi_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( axi_w_dp_rsp ), + .w_dp_valid_o ( axi_w_dp_rsp_valid ), + .w_dp_ready_i ( axi_w_dp_rsp_ready ), + .aw_req_i ( aw_req_i.aw_req ), + .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::AXI) & aw_valid_i ), + .aw_ready_o ( axi_aw_ready ), + .write_req_o ( axi_write_req_o ), + .write_rsp_i ( axi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( axi_buffer_out_ready ) + ); + + idma_axis_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_req_t ( axis_req_t ), + .write_rsp_t ( axis_rsp_t ) + ) i_idma_axis_write ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .w_dp_req_i ( w_dp_req_i ), + .w_dp_req_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::AXI_STREAM) & w_dp_req_valid ), + .w_dp_req_ready_o ( axis_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( axis_w_dp_rsp ), + .w_dp_rsp_valid_o ( axis_w_dp_rsp_valid ), + .w_dp_rsp_ready_i ( axis_w_dp_rsp_ready ), + .aw_req_i ( aw_req_i.aw_req ), + .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::AXI_STREAM) & aw_valid_i ), + .aw_ready_o ( axis_aw_ready ), + .write_req_o ( axis_write_req_o ), + .write_rsp_i ( axis_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( axis_buffer_out_ready ) + ); + + //-------------------------------------- + // Write Response FIFO + //-------------------------------------- + // Needed to be able to route the write reponses properly + // Insert when data write happens + // Remove when write response comes + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( idma_pkg::protocol_e ), + .PrintInfo ( PrintFifoInfo ) + ) i_write_response_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_dp_req_i.dst_protocol ), + .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), + .ready_o ( w_resp_fifo_in_ready ), + .data_o ( w_resp_fifo_out_protocol ), + .valid_o ( w_resp_fifo_out_valid ), + .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) + ); + + //-------------------------------------- + // Write Request Demultiplexer + //-------------------------------------- + + // Mux write port responses + always_comb begin : gen_write_reponse_multiplexer + w_dp_rsp_mux = '0; + w_dp_rsp_mux_valid = 1'b0; + axi_w_dp_rsp_ready = 1'b0; + axis_w_dp_rsp_ready = 1'b0; + if ( w_resp_fifo_out_valid ) begin + case(w_resp_fifo_out_protocol) + idma_pkg::AXI: begin + w_dp_rsp_mux_valid = axi_w_dp_rsp_valid; + w_dp_rsp_mux = axi_w_dp_rsp; + axi_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end + idma_pkg::AXI_STREAM: begin + w_dp_rsp_mux_valid = axis_w_dp_rsp_valid; + w_dp_rsp_mux = axis_w_dp_rsp; + axis_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end + default: begin + w_dp_rsp_mux_valid = 1'b0; + w_dp_rsp_mux = '0; + end + endcase + end + end + + // Fall through register for the write response to be ready + fall_through_register #( + .T ( w_dp_rsp_t ) + ) i_write_rsp_channel_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clr_i ( 1'b0 ), + .testmode_i ( testmode_i ), + + .valid_i ( w_dp_rsp_mux_valid ), + .ready_o ( w_dp_rsp_mux_ready ), + .data_i ( w_dp_rsp_mux ), + + .valid_o ( w_dp_rsp_valid ), + .ready_i ( w_dp_rsp_ready ), + .data_o ( w_dp_rsp_o ) + ); + + // Join write response fifo and write port responses + stream_join #( + .N_INP ( 2 ) + ) i_write_stream_join ( + .inp_valid_i ( { w_resp_fifo_out_valid, w_dp_rsp_valid } ), + .inp_ready_o ( { w_resp_fifo_out_ready, w_dp_rsp_ready } ), + + .oup_valid_o ( w_dp_valid_o ), + .oup_ready_i ( w_dp_ready_i ) + ); + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = |buffer_out_valid; + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "idma/guard.svh" +`include "common_cells/registers.svh" + +/// Implementing the transport layer in the iDMA backend. +module idma_transport_layer_rw_axi_rw_obi #( + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `w_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_rsp_t` type: + parameter type r_dp_rsp_t = logic, + /// `w_dp_rsp_t` type: + parameter type w_dp_rsp_t = logic, + /// Write Meta channel type + parameter type write_meta_channel_t = logic, + parameter type write_meta_channel_tagged_t = logic, + /// Read Meta channel type + parameter type read_meta_channel_t = logic, + parameter type read_meta_channel_tagged_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input read_meta_channel_tagged_t ar_req_i, + /// Read meta request valid + input logic ar_valid_i, + /// Read meta request ready + output logic ar_ready_o, + + /// Write meta request + input write_meta_channel_tagged_t aw_req_i, + /// Write meta request valid + input logic aw_valid_i, + /// Write meta request ready + output logic aw_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Response channel valid and ready + output logic r_chan_ready_o, + output logic r_chan_valid_o, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // inbound control signals to the read buffer: controlled by the read process + strb_t axi_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; + + strb_t buffer_in_ready; + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid, buffer_out_valid_shifted; + strb_t axi_buffer_out_ready, obi_buffer_out_ready, + buffer_out_ready, buffer_out_ready_shifted; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] axi_buffer_in, obi_buffer_in, + buffer_in, buffer_in_shifted; + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; + + // Read multiplexed signals + logic axi_r_chan_valid, obi_r_chan_valid; + logic axi_r_chan_ready, obi_r_chan_ready; + logic axi_r_dp_valid, obi_r_dp_valid; + logic axi_r_dp_ready, obi_r_dp_ready; + r_dp_rsp_t axi_r_dp_rsp, obi_r_dp_rsp; + + logic axi_ar_ready, obi_ar_ready; + + // Write multiplexed signals + logic axi_w_dp_rsp_valid, obi_w_dp_rsp_valid; + logic axi_w_dp_rsp_ready, obi_w_dp_rsp_ready; + logic axi_w_dp_ready, obi_w_dp_ready; + w_dp_rsp_t axi_w_dp_rsp, obi_w_dp_rsp; + + logic axi_aw_ready, obi_aw_ready; + logic w_dp_req_valid, w_dp_req_ready; + logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; + logic w_dp_rsp_valid, w_dp_rsp_ready; + w_dp_rsp_t w_dp_rsp_mux; + + // Write Response FIFO signals + logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; + idma_pkg::protocol_e w_resp_fifo_out_protocol; + logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; + + //-------------------------------------- + // Read Ports + //-------------------------------------- + + idma_axi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .ar_chan_t ( read_meta_channel_t ), + .read_req_t ( axi_req_t ), + .read_rsp_t ( axi_rsp_t ) + ) i_idma_axi_read ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_valid_i ), + .r_dp_ready_o ( axi_r_dp_ready ), + .r_dp_rsp_o ( axi_r_dp_rsp ), + .r_dp_valid_o ( axi_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_ready_i ), + .ar_req_i ( ar_req_i.ar_req ), + .ar_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI) & ar_valid_i ), + .ar_ready_o ( axi_ar_ready ), + .read_req_o ( axi_read_req_o ), + .read_rsp_i ( axi_read_rsp_i ), + .r_chan_valid_o ( axi_r_chan_valid ), + .r_chan_ready_o ( axi_r_chan_ready ), + .buffer_in_o ( axi_buffer_in ), + .buffer_in_valid_o ( axi_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + idma_obi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .read_meta_chan_t ( read_meta_channel_t ), + .read_req_t ( obi_req_t ), + .read_rsp_t ( obi_rsp_t ) + ) i_idma_obi_read ( + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_valid_i ), + .r_dp_ready_o ( obi_r_dp_ready ), + .r_dp_rsp_o ( obi_r_dp_rsp ), + .r_dp_valid_o ( obi_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_ready_i ), + .read_meta_req_i ( ar_req_i.ar_req ), + .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::OBI) & ar_valid_i ), + .read_meta_ready_o ( obi_ar_ready ), + .read_req_o ( obi_read_req_o ), + .read_rsp_i ( obi_read_rsp_i ), + .r_chan_valid_o ( obi_r_chan_valid ), + .r_chan_ready_o ( obi_r_chan_ready ), + .buffer_in_o ( obi_buffer_in ), + .buffer_in_valid_o ( obi_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + //-------------------------------------- + // Read Multiplexers + //-------------------------------------- + + always_comb begin : gen_read_meta_channel_multiplexer + case(ar_req_i.src_protocol) + idma_pkg::AXI: ar_ready_o = axi_ar_ready; + idma_pkg::OBI: ar_ready_o = obi_ar_ready; + default: ar_ready_o = 1'b0; + endcase + end + + always_comb begin : gen_read_multiplexer + case(r_dp_req_i.src_protocol) + idma_pkg::AXI: begin + r_chan_valid_o = axi_r_chan_valid; + r_chan_ready_o = axi_r_chan_ready; + + r_dp_ready_o = axi_r_dp_ready; + r_dp_rsp_o = axi_r_dp_rsp; + r_dp_valid_o = axi_r_dp_valid; + + buffer_in = axi_buffer_in; + buffer_in_valid = axi_buffer_in_valid; + end + idma_pkg::OBI: begin + r_chan_valid_o = obi_r_chan_valid; + r_chan_ready_o = obi_r_chan_ready; + + r_dp_ready_o = obi_r_dp_ready; + r_dp_rsp_o = obi_r_dp_rsp; + r_dp_valid_o = obi_r_dp_valid; + + buffer_in = obi_buffer_in; + buffer_in_valid = obi_buffer_in_valid; + end + default: begin + r_chan_valid_o = 1'b0; + r_chan_ready_o = 1'b0; + + r_dp_ready_o = 1'b0; + r_dp_rsp_o = '0; + r_dp_valid_o = 1'b0; + + buffer_in = '0; + buffer_in_valid = '0; + end + endcase + end + + //-------------------------------------- + // Read Barrel shifter + //-------------------------------------- + + assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); + + //-------------------------------------- + // Buffer + //-------------------------------------- + + idma_dataflow_element #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_dataflow_element ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .data_i ( buffer_in_shifted ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready_shifted ) + ); + + //-------------------------------------- + // Write Barrel shifter + //-------------------------------------- + + assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); + assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; + assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; + + //-------------------------------------- + // Write Request Demultiplexer + //-------------------------------------- + + // Split write request to write response fifo and write ports + stream_fork #( + .N_OUP ( 2 ) + ) i_write_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( w_dp_valid_i ), + .ready_o ( w_dp_ready_o ), + .valid_o ( { w_resp_fifo_in_valid, w_dp_req_valid } ), + .ready_i ( { w_resp_fifo_in_ready, w_dp_req_ready } ) + ); + + // Demux write request to correct write port + always_comb begin : gen_write_multiplexer + case(w_dp_req_i.dst_protocol) + idma_pkg::AXI: begin + w_dp_req_ready = axi_w_dp_ready; + buffer_out_ready = axi_buffer_out_ready; + end + idma_pkg::OBI: begin + w_dp_req_ready = obi_w_dp_ready; + buffer_out_ready = obi_buffer_out_ready; + end + default: begin + w_dp_req_ready = 1'b0; + buffer_out_ready = '0; + end + endcase + end + + // Demux write meta channel to correct write port + always_comb begin : gen_write_meta_channel_multiplexer + case(aw_req_i.dst_protocol) + idma_pkg::AXI: aw_ready_o = axi_aw_ready; + idma_pkg::OBI: aw_ready_o = obi_aw_ready; + default: aw_ready_o = 1'b0; + endcase + end + + //-------------------------------------- + // Write Ports + //-------------------------------------- + + idma_axi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .aw_chan_t ( write_meta_channel_t ), + .write_req_t ( axi_req_t ), + .write_rsp_t ( axi_rsp_t ) + ) i_idma_axi_write ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::AXI) & w_dp_req_valid ), + .w_dp_ready_o ( axi_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( axi_w_dp_rsp ), + .w_dp_valid_o ( axi_w_dp_rsp_valid ), + .w_dp_ready_i ( axi_w_dp_rsp_ready ), + .aw_req_i ( aw_req_i.aw_req ), + .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::AXI) & aw_valid_i ), + .aw_ready_o ( axi_aw_ready ), + .write_req_o ( axi_write_req_o ), + .write_rsp_i ( axi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( axi_buffer_out_ready ) + ); + + idma_obi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_req_t ( obi_req_t ), + .write_rsp_t ( obi_rsp_t ) + ) i_idma_obi_write ( + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::OBI) & w_dp_req_valid ), + .w_dp_ready_o ( obi_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( obi_w_dp_rsp ), + .w_dp_valid_o ( obi_w_dp_rsp_valid ), + .w_dp_ready_i ( obi_w_dp_rsp_ready ), + .aw_req_i ( aw_req_i.aw_req ), + .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::OBI) & aw_valid_i ), + .aw_ready_o ( obi_aw_ready ), + .write_req_o ( obi_write_req_o ), + .write_rsp_i ( obi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( obi_buffer_out_ready ) + ); + + //-------------------------------------- + // Write Response FIFO + //-------------------------------------- + // Needed to be able to route the write reponses properly + // Insert when data write happens + // Remove when write response comes + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( idma_pkg::protocol_e ), + .PrintInfo ( PrintFifoInfo ) + ) i_write_response_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_dp_req_i.dst_protocol ), + .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), + .ready_o ( w_resp_fifo_in_ready ), + .data_o ( w_resp_fifo_out_protocol ), + .valid_o ( w_resp_fifo_out_valid ), + .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) + ); + + //-------------------------------------- + // Write Request Demultiplexer + //-------------------------------------- + + // Mux write port responses + always_comb begin : gen_write_reponse_multiplexer + w_dp_rsp_mux = '0; + w_dp_rsp_mux_valid = 1'b0; + axi_w_dp_rsp_ready = 1'b0; + obi_w_dp_rsp_ready = 1'b0; + if ( w_resp_fifo_out_valid ) begin + case(w_resp_fifo_out_protocol) + idma_pkg::AXI: begin + w_dp_rsp_mux_valid = axi_w_dp_rsp_valid; + w_dp_rsp_mux = axi_w_dp_rsp; + axi_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end + idma_pkg::OBI: begin + w_dp_rsp_mux_valid = obi_w_dp_rsp_valid; + w_dp_rsp_mux = obi_w_dp_rsp; + obi_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end + default: begin + w_dp_rsp_mux_valid = 1'b0; + w_dp_rsp_mux = '0; + end + endcase + end + end + + // Fall through register for the write response to be ready + fall_through_register #( + .T ( w_dp_rsp_t ) + ) i_write_rsp_channel_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clr_i ( 1'b0 ), + .testmode_i ( testmode_i ), + + .valid_i ( w_dp_rsp_mux_valid ), + .ready_o ( w_dp_rsp_mux_ready ), + .data_i ( w_dp_rsp_mux ), + + .valid_o ( w_dp_rsp_valid ), + .ready_i ( w_dp_rsp_ready ), + .data_o ( w_dp_rsp_o ) + ); + + // Join write response fifo and write port responses + stream_join #( + .N_INP ( 2 ) + ) i_write_stream_join ( + .inp_valid_i ( { w_resp_fifo_out_valid, w_dp_rsp_valid } ), + .inp_ready_o ( { w_resp_fifo_out_ready, w_dp_rsp_ready } ), + + .oup_valid_o ( w_dp_valid_o ), + .oup_ready_i ( w_dp_ready_i ) + ); + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = |buffer_out_valid; + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "idma/guard.svh" +`include "common_cells/registers.svh" + +/// Implementing the transport layer in the iDMA backend. +module idma_transport_layer_r_obi_rw_init_w_axi #( + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `w_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_rsp_t` type: + parameter type r_dp_rsp_t = logic, + /// `w_dp_rsp_t` type: + parameter type w_dp_rsp_t = logic, + /// Write Meta channel type + parameter type write_meta_channel_t = logic, + parameter type write_meta_channel_tagged_t = logic, + /// Read Meta channel type + parameter type read_meta_channel_t = logic, + parameter type read_meta_channel_tagged_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// Memory Init Request and Response channel type + parameter type init_req_t = logic, + parameter type init_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// Memory Init read request + output init_req_t init_read_req_o, + /// Memory Init read response + input init_rsp_t init_read_rsp_i, + + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// Memory Init write request + output init_req_t init_write_req_o, + /// Memory Init write response + input init_rsp_t init_write_rsp_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input read_meta_channel_tagged_t ar_req_i, + /// Read meta request valid + input logic ar_valid_i, + /// Read meta request ready + output logic ar_ready_o, + + /// Write meta request + input write_meta_channel_tagged_t aw_req_i, + /// Write meta request valid + input logic aw_valid_i, + /// Write meta request ready + output logic aw_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Response channel valid and ready + output logic r_chan_ready_o, + output logic r_chan_valid_o, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // inbound control signals to the read buffer: controlled by the read process + strb_t init_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; + + strb_t buffer_in_ready; + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid, buffer_out_valid_shifted; + strb_t axi_buffer_out_ready, init_buffer_out_ready, + buffer_out_ready, buffer_out_ready_shifted; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] init_buffer_in, obi_buffer_in, + buffer_in, buffer_in_shifted; + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; + + // Read multiplexed signals + logic init_r_chan_valid, obi_r_chan_valid; + logic init_r_chan_ready, obi_r_chan_ready; + logic init_r_dp_valid, obi_r_dp_valid; + logic init_r_dp_ready, obi_r_dp_ready; + r_dp_rsp_t init_r_dp_rsp, obi_r_dp_rsp; + + logic init_ar_ready, obi_ar_ready; + + // Write multiplexed signals + logic axi_w_dp_rsp_valid, init_w_dp_rsp_valid; + logic axi_w_dp_rsp_ready, init_w_dp_rsp_ready; + logic axi_w_dp_ready, init_w_dp_ready; + w_dp_rsp_t axi_w_dp_rsp, init_w_dp_rsp; + + logic axi_aw_ready, init_aw_ready; + logic w_dp_req_valid, w_dp_req_ready; + logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; + logic w_dp_rsp_valid, w_dp_rsp_ready; + w_dp_rsp_t w_dp_rsp_mux; + + // Write Response FIFO signals + logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; + idma_pkg::protocol_e w_resp_fifo_out_protocol; + logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; + + //-------------------------------------- + // Read Ports + //-------------------------------------- + + idma_init_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .read_meta_chan_t ( read_meta_channel_t ), + .read_req_t ( init_req_t ), + .read_rsp_t ( init_rsp_t ) + ) i_idma_init_read ( + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_valid_i ), + .r_dp_ready_o ( init_r_dp_ready ), + .r_dp_rsp_o ( init_r_dp_rsp ), + .r_dp_valid_o ( init_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_ready_i ), + .read_meta_req_i ( ar_req_i.ar_req ), + .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::INIT) & ar_valid_i ), + .read_meta_ready_o ( init_ar_ready ), + .read_req_o ( init_read_req_o ), + .read_rsp_i ( init_read_rsp_i ), + .r_chan_valid_o ( init_r_chan_valid ), + .r_chan_ready_o ( init_r_chan_ready ), + .buffer_in_o ( init_buffer_in ), + .buffer_in_valid_o ( init_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + idma_obi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .read_meta_chan_t ( read_meta_channel_t ), + .read_req_t ( obi_req_t ), + .read_rsp_t ( obi_rsp_t ) + ) i_idma_obi_read ( + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_valid_i ), + .r_dp_ready_o ( obi_r_dp_ready ), + .r_dp_rsp_o ( obi_r_dp_rsp ), + .r_dp_valid_o ( obi_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_ready_i ), + .read_meta_req_i ( ar_req_i.ar_req ), + .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::OBI) & ar_valid_i ), + .read_meta_ready_o ( obi_ar_ready ), + .read_req_o ( obi_read_req_o ), + .read_rsp_i ( obi_read_rsp_i ), + .r_chan_valid_o ( obi_r_chan_valid ), + .r_chan_ready_o ( obi_r_chan_ready ), + .buffer_in_o ( obi_buffer_in ), + .buffer_in_valid_o ( obi_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + //-------------------------------------- + // Read Multiplexers + //-------------------------------------- + + always_comb begin : gen_read_meta_channel_multiplexer + case(ar_req_i.src_protocol) + idma_pkg::INIT: ar_ready_o = init_ar_ready; + idma_pkg::OBI: ar_ready_o = obi_ar_ready; + default: ar_ready_o = 1'b0; + endcase + end + + always_comb begin : gen_read_multiplexer + case(r_dp_req_i.src_protocol) + idma_pkg::INIT: begin + r_chan_valid_o = init_r_chan_valid; + r_chan_ready_o = init_r_chan_ready; + + r_dp_ready_o = init_r_dp_ready; + r_dp_rsp_o = init_r_dp_rsp; + r_dp_valid_o = init_r_dp_valid; + + buffer_in = init_buffer_in; + buffer_in_valid = init_buffer_in_valid; + end + idma_pkg::OBI: begin + r_chan_valid_o = obi_r_chan_valid; + r_chan_ready_o = obi_r_chan_ready; + + r_dp_ready_o = obi_r_dp_ready; + r_dp_rsp_o = obi_r_dp_rsp; + r_dp_valid_o = obi_r_dp_valid; + + buffer_in = obi_buffer_in; + buffer_in_valid = obi_buffer_in_valid; + end + default: begin + r_chan_valid_o = 1'b0; + r_chan_ready_o = 1'b0; + + r_dp_ready_o = 1'b0; + r_dp_rsp_o = '0; + r_dp_valid_o = 1'b0; + + buffer_in = '0; + buffer_in_valid = '0; + end + endcase + end + + //-------------------------------------- + // Read Barrel shifter + //-------------------------------------- + + assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); + + //-------------------------------------- + // Buffer + //-------------------------------------- + + idma_dataflow_element #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_dataflow_element ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .data_i ( buffer_in_shifted ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready_shifted ) + ); + + //-------------------------------------- + // Write Barrel shifter + //-------------------------------------- + + assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); + assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; + assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; + + //-------------------------------------- + // Write Request Demultiplexer + //-------------------------------------- + + // Split write request to write response fifo and write ports + stream_fork #( + .N_OUP ( 2 ) + ) i_write_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( w_dp_valid_i ), + .ready_o ( w_dp_ready_o ), + .valid_o ( { w_resp_fifo_in_valid, w_dp_req_valid } ), + .ready_i ( { w_resp_fifo_in_ready, w_dp_req_ready } ) + ); + + // Demux write request to correct write port + always_comb begin : gen_write_multiplexer + case(w_dp_req_i.dst_protocol) + idma_pkg::AXI: begin + w_dp_req_ready = axi_w_dp_ready; + buffer_out_ready = axi_buffer_out_ready; + end + idma_pkg::INIT: begin + w_dp_req_ready = init_w_dp_ready; + buffer_out_ready = init_buffer_out_ready; + end + default: begin + w_dp_req_ready = 1'b0; + buffer_out_ready = '0; + end + endcase + end + + // Demux write meta channel to correct write port + always_comb begin : gen_write_meta_channel_multiplexer + case(aw_req_i.dst_protocol) + idma_pkg::AXI: aw_ready_o = axi_aw_ready; + idma_pkg::INIT: aw_ready_o = init_aw_ready; + default: aw_ready_o = 1'b0; + endcase + end + + //-------------------------------------- + // Write Ports + //-------------------------------------- + + idma_axi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .aw_chan_t ( write_meta_channel_t ), + .write_req_t ( axi_req_t ), + .write_rsp_t ( axi_rsp_t ) + ) i_idma_axi_write ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::AXI) & w_dp_req_valid ), + .w_dp_ready_o ( axi_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( axi_w_dp_rsp ), + .w_dp_valid_o ( axi_w_dp_rsp_valid ), + .w_dp_ready_i ( axi_w_dp_rsp_ready ), + .aw_req_i ( aw_req_i.aw_req ), + .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::AXI) & aw_valid_i ), + .aw_ready_o ( axi_aw_ready ), + .write_req_o ( axi_write_req_o ), + .write_rsp_i ( axi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( axi_buffer_out_ready ) + ); + + idma_init_write #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_req_t ( init_req_t ), + .write_rsp_t ( init_rsp_t ) + ) i_idma_init_write ( + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::INIT) & w_dp_req_valid ), + .w_dp_ready_o ( init_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( init_w_dp_rsp ), + .w_dp_valid_o ( init_w_dp_rsp_valid ), + .w_dp_ready_i ( init_w_dp_rsp_ready ), + .write_meta_req_i ( aw_req_i.aw_req ), + .write_meta_valid_i ( (aw_req_i.dst_protocol == idma_pkg::INIT) & aw_valid_i ), + .write_meta_ready_o ( init_aw_ready ), + .write_req_o ( init_write_req_o ), + .write_rsp_i ( init_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( init_buffer_out_ready ) + ); + + //-------------------------------------- + // Write Response FIFO + //-------------------------------------- + // Needed to be able to route the write reponses properly + // Insert when data write happens + // Remove when write response comes + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( idma_pkg::protocol_e ), + .PrintInfo ( PrintFifoInfo ) + ) i_write_response_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_dp_req_i.dst_protocol ), + .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), + .ready_o ( w_resp_fifo_in_ready ), + .data_o ( w_resp_fifo_out_protocol ), + .valid_o ( w_resp_fifo_out_valid ), + .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) + ); + + //-------------------------------------- + // Write Request Demultiplexer + //-------------------------------------- + + // Mux write port responses + always_comb begin : gen_write_reponse_multiplexer + w_dp_rsp_mux = '0; + w_dp_rsp_mux_valid = 1'b0; + axi_w_dp_rsp_ready = 1'b0; + init_w_dp_rsp_ready = 1'b0; + if ( w_resp_fifo_out_valid ) begin + case(w_resp_fifo_out_protocol) + idma_pkg::AXI: begin + w_dp_rsp_mux_valid = axi_w_dp_rsp_valid; + w_dp_rsp_mux = axi_w_dp_rsp; + axi_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end + idma_pkg::INIT: begin + w_dp_rsp_mux_valid = init_w_dp_rsp_valid; + w_dp_rsp_mux = init_w_dp_rsp; + init_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end + default: begin + w_dp_rsp_mux_valid = 1'b0; + w_dp_rsp_mux = '0; + end + endcase + end + end + + // Fall through register for the write response to be ready + fall_through_register #( + .T ( w_dp_rsp_t ) + ) i_write_rsp_channel_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clr_i ( 1'b0 ), + .testmode_i ( testmode_i ), + + .valid_i ( w_dp_rsp_mux_valid ), + .ready_o ( w_dp_rsp_mux_ready ), + .data_i ( w_dp_rsp_mux ), + + .valid_o ( w_dp_rsp_valid ), + .ready_i ( w_dp_rsp_ready ), + .data_o ( w_dp_rsp_o ) + ); + + // Join write response fifo and write port responses + stream_join #( + .N_INP ( 2 ) + ) i_write_stream_join ( + .inp_valid_i ( { w_resp_fifo_out_valid, w_dp_rsp_valid } ), + .inp_ready_o ( { w_resp_fifo_out_ready, w_dp_rsp_ready } ), + + .oup_valid_o ( w_dp_valid_o ), + .oup_ready_i ( w_dp_ready_i ) + ); + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = |buffer_out_valid; + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "idma/guard.svh" +`include "common_cells/registers.svh" + +/// Implementing the transport layer in the iDMA backend. +module idma_transport_layer_r_axi_rw_init_rw_obi #( + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// `r_dp_req_t` type: + parameter type r_dp_req_t = logic, + /// `w_dp_req_t` type: + parameter type w_dp_req_t = logic, + /// `r_dp_rsp_t` type: + parameter type r_dp_rsp_t = logic, + /// `w_dp_rsp_t` type: + parameter type w_dp_rsp_t = logic, + /// Write Meta channel type + parameter type write_meta_channel_t = logic, + parameter type write_meta_channel_tagged_t = logic, + /// Read Meta channel type + parameter type read_meta_channel_t = logic, + parameter type read_meta_channel_tagged_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// Memory Init Request and Response channel type + parameter type init_req_t = logic, + parameter type init_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// Memory Init read request + output init_req_t init_read_req_o, + /// Memory Init read response + input init_rsp_t init_read_rsp_i, + + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// Memory Init write request + output init_req_t init_write_req_o, + /// Memory Init write response + input init_rsp_t init_write_rsp_i, + + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, + + /// Read datapath request + input r_dp_req_t r_dp_req_i, + /// Read datapath request valid + input logic r_dp_valid_i, + /// Read datapath request ready + output logic r_dp_ready_o, + + /// Read datapath response + output r_dp_rsp_t r_dp_rsp_o, + /// Read datapath response valid + output logic r_dp_valid_o, + /// Read datapath response valid + input logic r_dp_ready_i, + + /// Write datapath request + input w_dp_req_t w_dp_req_i, + /// Write datapath request valid + input logic w_dp_valid_i, + /// Write datapath request ready + output logic w_dp_ready_o, + + /// Write datapath response + output w_dp_rsp_t w_dp_rsp_o, + /// Write datapath response valid + output logic w_dp_valid_o, + /// Write datapath response valid + input logic w_dp_ready_i, + + /// Read meta request + input read_meta_channel_tagged_t ar_req_i, + /// Read meta request valid + input logic ar_valid_i, + /// Read meta request ready + output logic ar_ready_o, + + /// Write meta request + input write_meta_channel_tagged_t aw_req_i, + /// Write meta request valid + input logic aw_valid_i, + /// Write meta request ready + output logic aw_ready_o, + + /// Datapath poison signal + input logic dp_poison_i, + + /// Response channel valid and ready + output logic r_chan_ready_o, + output logic r_chan_valid_o, + + /// Read part of the datapath is busy + output logic r_dp_busy_o, + /// Write part of the datapath is busy + output logic w_dp_busy_o, + /// Buffer is busy + output logic buffer_busy_o +); + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + + /// Data type + typedef logic [DataWidth-1:0] data_t; + /// Offset type + typedef logic [StrbWidth-1:0] strb_t; + /// Byte type + typedef logic [7:0] byte_t; + + // inbound control signals to the read buffer: controlled by the read process + strb_t axi_buffer_in_valid, init_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; + + strb_t buffer_in_ready; + // outbound control signals of the buffer: controlled by the write process + strb_t buffer_out_valid, buffer_out_valid_shifted; + strb_t init_buffer_out_ready, obi_buffer_out_ready, + buffer_out_ready, buffer_out_ready_shifted; + + // shifted data flowing into the buffer + byte_t [StrbWidth-1:0] axi_buffer_in, init_buffer_in, obi_buffer_in, + buffer_in, buffer_in_shifted; + // aligned and coalesced data leaving the buffer + byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; + + // Read multiplexed signals + logic axi_r_chan_valid, init_r_chan_valid, obi_r_chan_valid; + logic axi_r_chan_ready, init_r_chan_ready, obi_r_chan_ready; + logic axi_r_dp_valid, init_r_dp_valid, obi_r_dp_valid; + logic axi_r_dp_ready, init_r_dp_ready, obi_r_dp_ready; + r_dp_rsp_t axi_r_dp_rsp, init_r_dp_rsp, obi_r_dp_rsp; + + logic axi_ar_ready, init_ar_ready, obi_ar_ready; + + // Write multiplexed signals + logic init_w_dp_rsp_valid, obi_w_dp_rsp_valid; + logic init_w_dp_rsp_ready, obi_w_dp_rsp_ready; + logic init_w_dp_ready, obi_w_dp_ready; + w_dp_rsp_t init_w_dp_rsp, obi_w_dp_rsp; + + logic init_aw_ready, obi_aw_ready; + logic w_dp_req_valid, w_dp_req_ready; + logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; + logic w_dp_rsp_valid, w_dp_rsp_ready; + w_dp_rsp_t w_dp_rsp_mux; + + // Write Response FIFO signals + logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; + idma_pkg::protocol_e w_resp_fifo_out_protocol; + logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; + + //-------------------------------------- + // Read Ports + //-------------------------------------- + + idma_axi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .ar_chan_t ( read_meta_channel_t ), + .read_req_t ( axi_req_t ), + .read_rsp_t ( axi_rsp_t ) + ) i_idma_axi_read ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_valid_i ), + .r_dp_ready_o ( axi_r_dp_ready ), + .r_dp_rsp_o ( axi_r_dp_rsp ), + .r_dp_valid_o ( axi_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_ready_i ), + .ar_req_i ( ar_req_i.ar_req ), + .ar_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI) & ar_valid_i ), + .ar_ready_o ( axi_ar_ready ), + .read_req_o ( axi_read_req_o ), + .read_rsp_i ( axi_read_rsp_i ), + .r_chan_valid_o ( axi_r_chan_valid ), + .r_chan_ready_o ( axi_r_chan_ready ), + .buffer_in_o ( axi_buffer_in ), + .buffer_in_valid_o ( axi_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + idma_init_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .read_meta_chan_t ( read_meta_channel_t ), + .read_req_t ( init_req_t ), + .read_rsp_t ( init_rsp_t ) + ) i_idma_init_read ( + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_valid_i ), + .r_dp_ready_o ( init_r_dp_ready ), + .r_dp_rsp_o ( init_r_dp_rsp ), + .r_dp_valid_o ( init_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_ready_i ), + .read_meta_req_i ( ar_req_i.ar_req ), + .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::INIT) & ar_valid_i ), + .read_meta_ready_o ( init_ar_ready ), + .read_req_o ( init_read_req_o ), + .read_rsp_i ( init_read_rsp_i ), + .r_chan_valid_o ( init_r_chan_valid ), + .r_chan_ready_o ( init_r_chan_ready ), + .buffer_in_o ( init_buffer_in ), + .buffer_in_valid_o ( init_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + idma_obi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .read_meta_chan_t ( read_meta_channel_t ), + .read_req_t ( obi_req_t ), + .read_rsp_t ( obi_rsp_t ) + ) i_idma_obi_read ( + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_valid_i ), + .r_dp_ready_o ( obi_r_dp_ready ), + .r_dp_rsp_o ( obi_r_dp_rsp ), + .r_dp_valid_o ( obi_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_ready_i ), + .read_meta_req_i ( ar_req_i.ar_req ), + .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::OBI) & ar_valid_i ), + .read_meta_ready_o ( obi_ar_ready ), + .read_req_o ( obi_read_req_o ), + .read_rsp_i ( obi_read_rsp_i ), + .r_chan_valid_o ( obi_r_chan_valid ), + .r_chan_ready_o ( obi_r_chan_ready ), + .buffer_in_o ( obi_buffer_in ), + .buffer_in_valid_o ( obi_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + + //-------------------------------------- + // Read Multiplexers + //-------------------------------------- + + always_comb begin : gen_read_meta_channel_multiplexer + case(ar_req_i.src_protocol) + idma_pkg::AXI: ar_ready_o = axi_ar_ready; + idma_pkg::INIT: ar_ready_o = init_ar_ready; + idma_pkg::OBI: ar_ready_o = obi_ar_ready; + default: ar_ready_o = 1'b0; + endcase + end + + always_comb begin : gen_read_multiplexer + case(r_dp_req_i.src_protocol) + idma_pkg::AXI: begin + r_chan_valid_o = axi_r_chan_valid; + r_chan_ready_o = axi_r_chan_ready; + + r_dp_ready_o = axi_r_dp_ready; + r_dp_rsp_o = axi_r_dp_rsp; + r_dp_valid_o = axi_r_dp_valid; + + buffer_in = axi_buffer_in; + buffer_in_valid = axi_buffer_in_valid; + end + idma_pkg::INIT: begin + r_chan_valid_o = init_r_chan_valid; + r_chan_ready_o = init_r_chan_ready; + + r_dp_ready_o = init_r_dp_ready; + r_dp_rsp_o = init_r_dp_rsp; + r_dp_valid_o = init_r_dp_valid; + + buffer_in = init_buffer_in; + buffer_in_valid = init_buffer_in_valid; + end + idma_pkg::OBI: begin + r_chan_valid_o = obi_r_chan_valid; + r_chan_ready_o = obi_r_chan_ready; + + r_dp_ready_o = obi_r_dp_ready; + r_dp_rsp_o = obi_r_dp_rsp; + r_dp_valid_o = obi_r_dp_valid; + + buffer_in = obi_buffer_in; + buffer_in_valid = obi_buffer_in_valid; + end + default: begin + r_chan_valid_o = 1'b0; + r_chan_ready_o = 1'b0; + + r_dp_ready_o = 1'b0; + r_dp_rsp_o = '0; + r_dp_valid_o = 1'b0; + + buffer_in = '0; + buffer_in_valid = '0; + end + endcase + end + + //-------------------------------------- + // Read Barrel shifter + //-------------------------------------- + + assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); + + //-------------------------------------- + // Buffer + //-------------------------------------- + + idma_dataflow_element #( + .BufferDepth ( BufferDepth ), + .StrbWidth ( StrbWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .strb_t ( strb_t ), + .byte_t ( byte_t ) + ) i_dataflow_element ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .data_i ( buffer_in_shifted ), + .valid_i ( buffer_in_valid ), + .ready_o ( buffer_in_ready ), + .data_o ( buffer_out ), + .valid_o ( buffer_out_valid ), + .ready_i ( buffer_out_ready_shifted ) + ); + + //-------------------------------------- + // Write Barrel shifter + //-------------------------------------- + + assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); + assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; + assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; + + //-------------------------------------- + // Write Request Demultiplexer + //-------------------------------------- + + // Split write request to write response fifo and write ports + stream_fork #( + .N_OUP ( 2 ) + ) i_write_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( w_dp_valid_i ), + .ready_o ( w_dp_ready_o ), + .valid_o ( { w_resp_fifo_in_valid, w_dp_req_valid } ), + .ready_i ( { w_resp_fifo_in_ready, w_dp_req_ready } ) + ); + + // Demux write request to correct write port + always_comb begin : gen_write_multiplexer + case(w_dp_req_i.dst_protocol) + idma_pkg::INIT: begin + w_dp_req_ready = init_w_dp_ready; + buffer_out_ready = init_buffer_out_ready; + end + idma_pkg::OBI: begin + w_dp_req_ready = obi_w_dp_ready; + buffer_out_ready = obi_buffer_out_ready; + end + default: begin + w_dp_req_ready = 1'b0; + buffer_out_ready = '0; + end + endcase + end + + // Demux write meta channel to correct write port + always_comb begin : gen_write_meta_channel_multiplexer + case(aw_req_i.dst_protocol) + idma_pkg::INIT: aw_ready_o = init_aw_ready; + idma_pkg::OBI: aw_ready_o = obi_aw_ready; + default: aw_ready_o = 1'b0; + endcase + end + + //-------------------------------------- + // Write Ports + //-------------------------------------- + + idma_init_write #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_req_t ( init_req_t ), + .write_rsp_t ( init_rsp_t ) + ) i_idma_init_write ( + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::INIT) & w_dp_req_valid ), + .w_dp_ready_o ( init_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( init_w_dp_rsp ), + .w_dp_valid_o ( init_w_dp_rsp_valid ), + .w_dp_ready_i ( init_w_dp_rsp_ready ), + .write_meta_req_i ( aw_req_i.aw_req ), + .write_meta_valid_i ( (aw_req_i.dst_protocol == idma_pkg::INIT) & aw_valid_i ), + .write_meta_ready_o ( init_aw_ready ), + .write_req_o ( init_write_req_o ), + .write_rsp_i ( init_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( init_buffer_out_ready ) + ); + + idma_obi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_req_t ( obi_req_t ), + .write_rsp_t ( obi_rsp_t ) + ) i_idma_obi_write ( + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::OBI) & w_dp_req_valid ), + .w_dp_ready_o ( obi_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( obi_w_dp_rsp ), + .w_dp_valid_o ( obi_w_dp_rsp_valid ), + .w_dp_ready_i ( obi_w_dp_rsp_ready ), + .aw_req_i ( aw_req_i.aw_req ), + .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::OBI) & aw_valid_i ), + .aw_ready_o ( obi_aw_ready ), + .write_req_o ( obi_write_req_o ), + .write_rsp_i ( obi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( obi_buffer_out_ready ) + ); + + //-------------------------------------- + // Write Response FIFO + //-------------------------------------- + // Needed to be able to route the write reponses properly + // Insert when data write happens + // Remove when write response comes + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( idma_pkg::protocol_e ), + .PrintInfo ( PrintFifoInfo ) + ) i_write_response_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_dp_req_i.dst_protocol ), + .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), + .ready_o ( w_resp_fifo_in_ready ), + .data_o ( w_resp_fifo_out_protocol ), + .valid_o ( w_resp_fifo_out_valid ), + .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) + ); + + //-------------------------------------- + // Write Request Demultiplexer + //-------------------------------------- + + // Mux write port responses + always_comb begin : gen_write_reponse_multiplexer + w_dp_rsp_mux = '0; + w_dp_rsp_mux_valid = 1'b0; + init_w_dp_rsp_ready = 1'b0; + obi_w_dp_rsp_ready = 1'b0; + if ( w_resp_fifo_out_valid ) begin + case(w_resp_fifo_out_protocol) + idma_pkg::INIT: begin + w_dp_rsp_mux_valid = init_w_dp_rsp_valid; + w_dp_rsp_mux = init_w_dp_rsp; + init_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end + idma_pkg::OBI: begin + w_dp_rsp_mux_valid = obi_w_dp_rsp_valid; + w_dp_rsp_mux = obi_w_dp_rsp; + obi_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end + default: begin + w_dp_rsp_mux_valid = 1'b0; + w_dp_rsp_mux = '0; + end + endcase + end + end + + // Fall through register for the write response to be ready + fall_through_register #( + .T ( w_dp_rsp_t ) + ) i_write_rsp_channel_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clr_i ( 1'b0 ), + .testmode_i ( testmode_i ), + + .valid_i ( w_dp_rsp_mux_valid ), + .ready_o ( w_dp_rsp_mux_ready ), + .data_i ( w_dp_rsp_mux ), + + .valid_o ( w_dp_rsp_valid ), + .ready_i ( w_dp_rsp_ready ), + .data_o ( w_dp_rsp_o ) + ); + + // Join write response fifo and write port responses + stream_join #( + .N_INP ( 2 ) + ) i_write_stream_join ( + .inp_valid_i ( { w_resp_fifo_out_valid, w_dp_rsp_valid } ), + .inp_ready_o ( { w_resp_fifo_out_ready, w_dp_rsp_ready } ), + + .oup_valid_o ( w_dp_valid_o ), + .oup_ready_i ( w_dp_ready_i ) + ); + + //-------------------------------------- + // Module Control + //-------------------------------------- + assign r_dp_busy_o = r_dp_valid_i; + assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; + assign buffer_busy_o = |buffer_out_valid; + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "common_cells/registers.svh" +`include "common_cells/assertions.svh" +`include "idma/guard.svh" + +/// Legalizes a generic 1D transfer according to the rules given by the +/// used protocol. +module idma_legalizer_rw_axi #( + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + parameter type idma_req_t = logic, + /// Read request type + parameter type idma_r_req_t = logic, + /// Write request type + parameter type idma_w_req_t = logic, + /// Mutable transfer type + parameter type idma_mut_tf_t = logic, + /// Mutable options type + parameter type idma_mut_tf_opt_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + /// 1D request + input idma_req_t req_i, + /// 1D request valid + input logic valid_i, + /// 1D request ready + output logic ready_o, + + /// Read request; contains datapath and meta information + output idma_r_req_t r_req_o, + /// Read request valid + output logic r_valid_o, + /// Read request ready + input logic r_ready_i, + + /// Write request; contains datapath and meta information + output idma_w_req_t w_req_o, + /// Write request valid + output logic w_valid_o, + /// Write request ready + input logic w_ready_i, + + /// Invalidate the current burst transfer, stops emission of requests + input logic flush_i, + /// Kill the active 1D transfer; reload a new transfer + input logic kill_i, + + /// Read machine of the legalizer is busy + output logic r_busy_o, + /// Write machine of the legalizer is busy + output logic w_busy_o +); + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + /// The size of a page in byte + localparam int unsigned PageSize = 256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth; + /// The width of page offset byte addresses + localparam int unsigned PageAddrWidth = $clog2(PageSize); + + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address type + typedef logic [ AddrWidth-1:0] addr_t; + /// Page address type + typedef logic [PageAddrWidth-1:0] page_addr_t; + /// Page length type + typedef logic [ PageAddrWidth:0] page_len_t; + + + // state: internally hold one transfer, this is mutated + idma_mut_tf_t r_tf_d, r_tf_q; + idma_mut_tf_t w_tf_d, w_tf_q; + idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + + // enable signals for next mutable transfer storage + logic r_tf_ena; + logic w_tf_ena; + + // page boundaries + page_len_t r_page_num_bytes_to_pb; + page_len_t r_num_bytes_to_pb; + page_len_t w_page_num_bytes_to_pb; + page_len_t w_num_bytes_to_pb; + page_len_t c_num_bytes_to_pb; + + // read process + page_len_t r_num_bytes_possible; + page_len_t r_num_bytes; + offset_t r_addr_offset; + logic r_done; + + // write process + page_len_t w_num_bytes_possible; + page_len_t w_num_bytes; + offset_t w_addr_offset; + logic w_done; + + + //-------------------------------------- + // read boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_read_page_splitter ( + .not_bursting_i ( 1'b0 ), + + .reduce_len_i ( opt_tf_q.src_reduce_len ), + .max_llen_i ( opt_tf_q.src_max_llen ), + + .addr_i ( r_tf_q.addr ), + .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) + ); + + assign r_num_bytes_to_pb = r_page_num_bytes_to_pb; + + //-------------------------------------- + // write boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_write_page_splitter ( + .not_bursting_i ( 1'b0 ), + + .reduce_len_i ( opt_tf_q.dst_reduce_len ), + .max_llen_i ( opt_tf_q.dst_max_llen ), + + .addr_i ( w_tf_q.addr ), + .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) + ); + + assign w_num_bytes_to_pb = w_page_num_bytes_to_pb; + + //-------------------------------------- + // page boundary check + //-------------------------------------- + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; + + + //-------------------------------------- + // Synchronized R/W process + //-------------------------------------- + always_comb begin : proc_num_bytes_possible + // Default: Coupled + r_num_bytes_possible = c_num_bytes_to_pb; + w_num_bytes_possible = c_num_bytes_to_pb; + + if (opt_tf_q.decouple_rw) begin + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; + end + end + + assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; + assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + + // legalization process -> read and write is coupled together + always_comb begin : proc_read_write_transaction + + // default: keep state + r_tf_d = r_tf_q; + w_tf_d = w_tf_q; + opt_tf_d = opt_tf_q; + + // default: not done + r_done = 1'b0; + w_done = 1'b0; + + //-------------------------------------- + // Legalize read transaction + //-------------------------------------- + // more bytes remaining than we can read + if (r_tf_q.length > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + r_tf_d.length = r_tf_q.length - r_num_bytes_possible; + // next address + r_tf_d.addr = r_tf_q.addr + r_num_bytes; + + // remaining bytes fit in one burst + end else begin + r_num_bytes = r_tf_q.length[PageAddrWidth:0]; + // finished + r_tf_d.valid = 1'b0; + r_done = 1'b1; + end + + //-------------------------------------- + // Legalize write transaction + //-------------------------------------- + // more bytes remaining than we can write + if (w_tf_q.length > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + w_tf_d.length = w_tf_q.length - w_num_bytes_possible; + // next address + w_tf_d.addr = w_tf_q.addr + w_num_bytes; + + // remaining bytes fit in one burst + end else begin + w_num_bytes = w_tf_q.length[PageAddrWidth:0]; + // finished + w_tf_d.valid = 1'b0; + w_done = 1'b1; + end + + //-------------------------------------- + // Kill + //-------------------------------------- + if (kill_i) begin + // kill the current state + r_tf_d = '0; + w_tf_d = '0; + r_done = 1'b1; + w_done = 1'b1; + end + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o & valid_i) begin + + // load all three mutable objects (source, destination, option) + // source or read + r_tf_d = '{ + length: req_i.length, + addr: req_i.src_addr, + valid: 1'b1, + base_addr: req_i.src_addr + }; + // destination or write + w_tf_d = '{ + length: req_i.length, + addr: req_i.dst_addr, + valid: 1'b1, + base_addr: req_i.dst_addr + }; + // options + opt_tf_d = '{ + src_protocol: req_i.opt.src_protocol, + dst_protocol: req_i.opt.dst_protocol, + read_shift: '0, + write_shift: '0, + decouple_rw: req_i.opt.beo.decouple_rw, + decouple_aw: req_i.opt.beo.decouple_aw, + src_max_llen: req_i.opt.beo.src_max_llen, + dst_max_llen: req_i.opt.beo.dst_max_llen, + src_reduce_len: req_i.opt.beo.src_reduce_len, + dst_reduce_len: req_i.opt.beo.dst_reduce_len, + axi_id: req_i.opt.axi_id, + src_axi_opt: req_i.opt.src, + dst_axi_opt: req_i.opt.dst, + super_last: req_i.opt.last + }; + // determine shift amount + if (CombinedShifter) begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = '0; + end else begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + end + end + end + + + //-------------------------------------- + // Connect outputs + //-------------------------------------- + + // Read meta channel + always_comb begin + r_req_o.ar_req.axi.ar_chan = '{ + id: opt_tf_q.axi_id, + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 + }; + + end + + // assign the signals needed to set-up the read data path + assign r_req_o.r_dp_req = '{ + src_protocol: opt_tf_q.src_protocol, + offset: r_addr_offset, + tailer: OffsetWidth'(r_num_bytes + r_addr_offset), + shift: opt_tf_q.read_shift, + decouple_aw: opt_tf_q.decouple_aw, + is_single: r_num_bytes <= StrbWidth + }; + + // Write meta channel and data path + always_comb begin + w_req_o.aw_req.axi.aw_chan = '{ + id: opt_tf_q.axi_id, + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.dst_axi_opt.burst, + lock: opt_tf_q.dst_axi_opt.lock, + cache: opt_tf_q.dst_axi_opt.cache, + prot: opt_tf_q.dst_axi_opt.prot, + qos: opt_tf_q.dst_axi_opt.qos, + region: opt_tf_q.dst_axi_opt.region, + user: '0, + atop: '0 + }; + + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: w_req_o.aw_req.axi.aw_chan.len, + is_single: w_req_o.aw_req.axi.aw_chan.len == '0 + }; + + end + + // last burst in generic 1D transfer? + assign w_req_o.last = w_done; + + // last burst indicated by midend + assign w_req_o.super_last = opt_tf_q.super_last; + + // assign aw decouple flag + assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + + // busy output + assign r_busy_o = r_tf_q.valid; + assign w_busy_o = w_tf_q.valid; + + + //-------------------------------------- + // Flow Control + //-------------------------------------- + // only advance to next state if: + // * rw_coupled: both machines advance + // * rw_decoupled: either machine advances + + always_comb begin : proc_legalizer_flow_control + if ( opt_tf_q.decouple_rw) begin + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; + end else begin + r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end + end + + // load next idma request: if both machines are done! + assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; + + + //-------------------------------------- + // State + //-------------------------------------- + `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) + `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) + `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + + + //-------------------------------------- + // Assertions + //-------------------------------------- + // only support the decomposition of incremental bursts + `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & + req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & + req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "common_cells/registers.svh" +`include "common_cells/assertions.svh" +`include "idma/guard.svh" + +/// Legalizes a generic 1D transfer according to the rules given by the +/// used protocol. +module idma_legalizer_r_obi_w_axi #( + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + parameter type idma_req_t = logic, + /// Read request type + parameter type idma_r_req_t = logic, + /// Write request type + parameter type idma_w_req_t = logic, + /// Mutable transfer type + parameter type idma_mut_tf_t = logic, + /// Mutable options type + parameter type idma_mut_tf_opt_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + /// 1D request + input idma_req_t req_i, + /// 1D request valid + input logic valid_i, + /// 1D request ready + output logic ready_o, + + /// Read request; contains datapath and meta information + output idma_r_req_t r_req_o, + /// Read request valid + output logic r_valid_o, + /// Read request ready + input logic r_ready_i, + + /// Write request; contains datapath and meta information + output idma_w_req_t w_req_o, + /// Write request valid + output logic w_valid_o, + /// Write request ready + input logic w_ready_i, + + /// Invalidate the current burst transfer, stops emission of requests + input logic flush_i, + /// Kill the active 1D transfer; reload a new transfer + input logic kill_i, + + /// Read machine of the legalizer is busy + output logic r_busy_o, + /// Write machine of the legalizer is busy + output logic w_busy_o +); + function int unsigned max_size(input int unsigned a, b); + return a > b ? a : b; + endfunction + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + /// The size of a page in byte + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); + /// The width of page offset byte addresses + localparam int unsigned PageAddrWidth = $clog2(PageSize); + + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address type + typedef logic [ AddrWidth-1:0] addr_t; + /// Page address type + typedef logic [PageAddrWidth-1:0] page_addr_t; + /// Page length type + typedef logic [ PageAddrWidth:0] page_len_t; + + + // state: internally hold one transfer, this is mutated + idma_mut_tf_t r_tf_d, r_tf_q; + idma_mut_tf_t w_tf_d, w_tf_q; + idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + + // enable signals for next mutable transfer storage + logic r_tf_ena; + logic w_tf_ena; + + // page boundaries + page_len_t r_page_num_bytes_to_pb; + page_len_t r_num_bytes_to_pb; + page_len_t w_page_num_bytes_to_pb; + page_len_t w_num_bytes_to_pb; + page_len_t c_num_bytes_to_pb; + + // read process + page_len_t r_num_bytes_possible; + page_len_t r_num_bytes; + offset_t r_addr_offset; + logic r_done; + + // write process + page_len_t w_num_bytes_possible; + page_len_t w_num_bytes; + offset_t w_addr_offset; + logic w_done; + + + //-------------------------------------- + // read boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_read_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.src_reduce_len ), + .max_llen_i ( opt_tf_q.src_max_llen ), + + .addr_i ( r_tf_q.addr ), + .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) + ); + + assign r_num_bytes_to_pb = r_page_num_bytes_to_pb; + + //-------------------------------------- + // write boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_write_page_splitter ( + .not_bursting_i ( opt_tf_q.dst_protocol inside { idma_pkg::OBI} ), + + .reduce_len_i ( opt_tf_q.dst_reduce_len ), + .max_llen_i ( opt_tf_q.dst_max_llen ), + + .addr_i ( w_tf_q.addr ), + .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) + ); + + assign w_num_bytes_to_pb = w_page_num_bytes_to_pb; + + //-------------------------------------- + // page boundary check + //-------------------------------------- + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; + + + //-------------------------------------- + // Synchronized R/W process + //-------------------------------------- + always_comb begin : proc_num_bytes_possible + // Default: Coupled + r_num_bytes_possible = c_num_bytes_to_pb; + w_num_bytes_possible = c_num_bytes_to_pb; + + if (opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::OBI })) begin + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; + end + end + + assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; + assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + + // legalization process -> read and write is coupled together + always_comb begin : proc_read_write_transaction + + // default: keep state + r_tf_d = r_tf_q; + w_tf_d = w_tf_q; + opt_tf_d = opt_tf_q; + + // default: not done + r_done = 1'b0; + w_done = 1'b0; + + //-------------------------------------- + // Legalize read transaction + //-------------------------------------- + // more bytes remaining than we can read + if (r_tf_q.length > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + r_tf_d.length = r_tf_q.length - r_num_bytes_possible; + // next address + r_tf_d.addr = r_tf_q.addr + r_num_bytes; + + // remaining bytes fit in one burst + end else begin + r_num_bytes = r_tf_q.length[PageAddrWidth:0]; + // finished + r_tf_d.valid = 1'b0; + r_done = 1'b1; + end + + //-------------------------------------- + // Legalize write transaction + //-------------------------------------- + // more bytes remaining than we can write + if (w_tf_q.length > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + w_tf_d.length = w_tf_q.length - w_num_bytes_possible; + // next address + w_tf_d.addr = w_tf_q.addr + w_num_bytes; + + // remaining bytes fit in one burst + end else begin + w_num_bytes = w_tf_q.length[PageAddrWidth:0]; + // finished + w_tf_d.valid = 1'b0; + w_done = 1'b1; + end + + //-------------------------------------- + // Kill + //-------------------------------------- + if (kill_i) begin + // kill the current state + r_tf_d = '0; + w_tf_d = '0; + r_done = 1'b1; + w_done = 1'b1; + end + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o & valid_i) begin + + // load all three mutable objects (source, destination, option) + // source or read + r_tf_d = '{ + length: req_i.length, + addr: req_i.src_addr, + valid: 1'b1, + base_addr: req_i.src_addr + }; + // destination or write + w_tf_d = '{ + length: req_i.length, + addr: req_i.dst_addr, + valid: 1'b1, + base_addr: req_i.dst_addr + }; + // options + opt_tf_d = '{ + src_protocol: req_i.opt.src_protocol, + dst_protocol: req_i.opt.dst_protocol, + read_shift: '0, + write_shift: '0, + decouple_rw: req_i.opt.beo.decouple_rw, + decouple_aw: req_i.opt.beo.decouple_aw, + src_max_llen: req_i.opt.beo.src_max_llen, + dst_max_llen: req_i.opt.beo.dst_max_llen, + src_reduce_len: req_i.opt.beo.src_reduce_len, + dst_reduce_len: req_i.opt.beo.dst_reduce_len, + axi_id: req_i.opt.axi_id, + src_axi_opt: req_i.opt.src, + dst_axi_opt: req_i.opt.dst, + super_last: req_i.opt.last + }; + // determine shift amount + if (CombinedShifter) begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = '0; + end else begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + end + end + end + + + //-------------------------------------- + // Connect outputs + //-------------------------------------- + + // Read meta channel + always_comb begin + r_req_o.ar_req.obi.a_chan = '{ + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '1, + we: 1'b0, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 + }; + + end + + // assign the signals needed to set-up the read data path + assign r_req_o.r_dp_req = '{ + src_protocol: opt_tf_q.src_protocol, + offset: r_addr_offset, + tailer: OffsetWidth'(r_num_bytes + r_addr_offset), + shift: opt_tf_q.read_shift, + decouple_aw: opt_tf_q.decouple_aw, + is_single: r_num_bytes <= StrbWidth + }; + + // Write meta channel and data path + always_comb begin + w_req_o.aw_req.axi.aw_chan = '{ + id: opt_tf_q.axi_id, + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.dst_axi_opt.burst, + lock: opt_tf_q.dst_axi_opt.lock, + cache: opt_tf_q.dst_axi_opt.cache, + prot: opt_tf_q.dst_axi_opt.prot, + qos: opt_tf_q.dst_axi_opt.qos, + region: opt_tf_q.dst_axi_opt.region, + user: '0, + atop: '0 + }; + + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: w_req_o.aw_req.axi.aw_chan.len, + is_single: w_req_o.aw_req.axi.aw_chan.len == '0 + }; + + end + + // last burst in generic 1D transfer? + assign w_req_o.last = w_done; + + // last burst indicated by midend + assign w_req_o.super_last = opt_tf_q.super_last; + + // assign aw decouple flag + assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + + // busy output + assign r_busy_o = r_tf_q.valid; + assign w_busy_o = w_tf_q.valid; + + + //-------------------------------------- + // Flow Control + //-------------------------------------- + // only advance to next state if: + // * rw_coupled: both machines advance + // * rw_decoupled: either machine advances + + always_comb begin : proc_legalizer_flow_control + if ( opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::OBI })) begin + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; + end else begin + r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end + end + + // load next idma request: if both machines are done! + assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; + + + //-------------------------------------- + // State + //-------------------------------------- + `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) + `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) + `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + + + //-------------------------------------- + // Assertions + //-------------------------------------- + // only support the decomposition of incremental bursts + `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & + req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & + req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "common_cells/registers.svh" +`include "common_cells/assertions.svh" +`include "idma/guard.svh" + +/// Legalizes a generic 1D transfer according to the rules given by the +/// used protocol. +module idma_legalizer_r_axi_w_obi #( + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + parameter type idma_req_t = logic, + /// Read request type + parameter type idma_r_req_t = logic, + /// Write request type + parameter type idma_w_req_t = logic, + /// Mutable transfer type + parameter type idma_mut_tf_t = logic, + /// Mutable options type + parameter type idma_mut_tf_opt_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + /// 1D request + input idma_req_t req_i, + /// 1D request valid + input logic valid_i, + /// 1D request ready + output logic ready_o, + + /// Read request; contains datapath and meta information + output idma_r_req_t r_req_o, + /// Read request valid + output logic r_valid_o, + /// Read request ready + input logic r_ready_i, + + /// Write request; contains datapath and meta information + output idma_w_req_t w_req_o, + /// Write request valid + output logic w_valid_o, + /// Write request ready + input logic w_ready_i, + + /// Invalidate the current burst transfer, stops emission of requests + input logic flush_i, + /// Kill the active 1D transfer; reload a new transfer + input logic kill_i, + + /// Read machine of the legalizer is busy + output logic r_busy_o, + /// Write machine of the legalizer is busy + output logic w_busy_o +); + function int unsigned max_size(input int unsigned a, b); + return a > b ? a : b; + endfunction + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + /// The size of a page in byte + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); + /// The width of page offset byte addresses + localparam int unsigned PageAddrWidth = $clog2(PageSize); + + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address type + typedef logic [ AddrWidth-1:0] addr_t; + /// Page address type + typedef logic [PageAddrWidth-1:0] page_addr_t; + /// Page length type + typedef logic [ PageAddrWidth:0] page_len_t; + + + // state: internally hold one transfer, this is mutated + idma_mut_tf_t r_tf_d, r_tf_q; + idma_mut_tf_t w_tf_d, w_tf_q; + idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + + // enable signals for next mutable transfer storage + logic r_tf_ena; + logic w_tf_ena; + + // page boundaries + page_len_t r_page_num_bytes_to_pb; + page_len_t r_num_bytes_to_pb; + page_len_t w_page_num_bytes_to_pb; + page_len_t w_num_bytes_to_pb; + page_len_t c_num_bytes_to_pb; + + // read process + page_len_t r_num_bytes_possible; + page_len_t r_num_bytes; + offset_t r_addr_offset; + logic r_done; + + // write process + page_len_t w_num_bytes_possible; + page_len_t w_num_bytes; + offset_t w_addr_offset; + logic w_done; + + + //-------------------------------------- + // read boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_read_page_splitter ( + .not_bursting_i ( opt_tf_q.src_protocol inside { idma_pkg::OBI} ), + + .reduce_len_i ( opt_tf_q.src_reduce_len ), + .max_llen_i ( opt_tf_q.src_max_llen ), + + .addr_i ( r_tf_q.addr ), + .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) + ); + + assign r_num_bytes_to_pb = r_page_num_bytes_to_pb; + + //-------------------------------------- + // write boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_write_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.dst_reduce_len ), + .max_llen_i ( opt_tf_q.dst_max_llen ), + + .addr_i ( w_tf_q.addr ), + .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) + ); + + assign w_num_bytes_to_pb = w_page_num_bytes_to_pb; + + //-------------------------------------- + // page boundary check + //-------------------------------------- + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; + + + //-------------------------------------- + // Synchronized R/W process + //-------------------------------------- + always_comb begin : proc_num_bytes_possible + // Default: Coupled + r_num_bytes_possible = c_num_bytes_to_pb; + w_num_bytes_possible = c_num_bytes_to_pb; + + if (opt_tf_q.decouple_rw + || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; + end + end + + assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; + assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + + // legalization process -> read and write is coupled together + always_comb begin : proc_read_write_transaction + + // default: keep state + r_tf_d = r_tf_q; + w_tf_d = w_tf_q; + opt_tf_d = opt_tf_q; + + // default: not done + r_done = 1'b0; + w_done = 1'b0; + + //-------------------------------------- + // Legalize read transaction + //-------------------------------------- + // more bytes remaining than we can read + if (r_tf_q.length > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + r_tf_d.length = r_tf_q.length - r_num_bytes_possible; + // next address + r_tf_d.addr = r_tf_q.addr + r_num_bytes; + + // remaining bytes fit in one burst + end else begin + r_num_bytes = r_tf_q.length[PageAddrWidth:0]; + // finished + r_tf_d.valid = 1'b0; + r_done = 1'b1; + end + + //-------------------------------------- + // Legalize write transaction + //-------------------------------------- + // more bytes remaining than we can write + if (w_tf_q.length > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + w_tf_d.length = w_tf_q.length - w_num_bytes_possible; + // next address + w_tf_d.addr = w_tf_q.addr + w_num_bytes; + + // remaining bytes fit in one burst + end else begin + w_num_bytes = w_tf_q.length[PageAddrWidth:0]; + // finished + w_tf_d.valid = 1'b0; + w_done = 1'b1; + end + + //-------------------------------------- + // Kill + //-------------------------------------- + if (kill_i) begin + // kill the current state + r_tf_d = '0; + w_tf_d = '0; + r_done = 1'b1; + w_done = 1'b1; + end + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o & valid_i) begin + + // load all three mutable objects (source, destination, option) + // source or read + r_tf_d = '{ + length: req_i.length, + addr: req_i.src_addr, + valid: 1'b1, + base_addr: req_i.src_addr + }; + // destination or write + w_tf_d = '{ + length: req_i.length, + addr: req_i.dst_addr, + valid: 1'b1, + base_addr: req_i.dst_addr + }; + // options + opt_tf_d = '{ + src_protocol: req_i.opt.src_protocol, + dst_protocol: req_i.opt.dst_protocol, + read_shift: '0, + write_shift: '0, + decouple_rw: req_i.opt.beo.decouple_rw, + decouple_aw: req_i.opt.beo.decouple_aw, + src_max_llen: req_i.opt.beo.src_max_llen, + dst_max_llen: req_i.opt.beo.dst_max_llen, + src_reduce_len: req_i.opt.beo.src_reduce_len, + dst_reduce_len: req_i.opt.beo.dst_reduce_len, + axi_id: req_i.opt.axi_id, + src_axi_opt: req_i.opt.src, + dst_axi_opt: req_i.opt.dst, + super_last: req_i.opt.last + }; + // determine shift amount + if (CombinedShifter) begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = '0; + end else begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + end + end + end + + + //-------------------------------------- + // Connect outputs + //-------------------------------------- + + // Read meta channel + always_comb begin + r_req_o.ar_req.axi.ar_chan = '{ + id: opt_tf_q.axi_id, + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 + }; + + end + + // assign the signals needed to set-up the read data path + assign r_req_o.r_dp_req = '{ + src_protocol: opt_tf_q.src_protocol, + offset: r_addr_offset, + tailer: OffsetWidth'(r_num_bytes + r_addr_offset), + shift: opt_tf_q.read_shift, + decouple_aw: opt_tf_q.decouple_aw, + is_single: r_num_bytes <= StrbWidth + }; + + // Write meta channel and data path + always_comb begin + w_req_o.aw_req.obi.a_chan = '{ + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '0, + we: 1, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 + }; + + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: 'd0, + is_single: 1'b1 + }; + end + + // last burst in generic 1D transfer? + assign w_req_o.last = w_done; + + // last burst indicated by midend + assign w_req_o.super_last = opt_tf_q.super_last; + + // assign aw decouple flag + assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + + // busy output + assign r_busy_o = r_tf_q.valid; + assign w_busy_o = w_tf_q.valid; + + + //-------------------------------------- + // Flow Control + //-------------------------------------- + // only advance to next state if: + // * rw_coupled: both machines advance + // * rw_decoupled: either machine advances + + always_comb begin : proc_legalizer_flow_control + if ( opt_tf_q.decouple_rw + || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; + end else begin + r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end + end + + // load next idma request: if both machines are done! + assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; + + + //-------------------------------------- + // State + //-------------------------------------- + `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) + `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) + `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + + + //-------------------------------------- + // Assertions + //-------------------------------------- + // only support the decomposition of incremental bursts + `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & + req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & + req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "common_cells/registers.svh" +`include "common_cells/assertions.svh" +`include "idma/guard.svh" + +/// Legalizes a generic 1D transfer according to the rules given by the +/// used protocol. +module idma_legalizer_rw_axi_rw_axis #( + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + parameter type idma_req_t = logic, + /// Read request type + parameter type idma_r_req_t = logic, + /// Write request type + parameter type idma_w_req_t = logic, + /// Mutable transfer type + parameter type idma_mut_tf_t = logic, + /// Mutable options type + parameter type idma_mut_tf_opt_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + /// 1D request + input idma_req_t req_i, + /// 1D request valid + input logic valid_i, + /// 1D request ready + output logic ready_o, + + /// Read request; contains datapath and meta information + output idma_r_req_t r_req_o, + /// Read request valid + output logic r_valid_o, + /// Read request ready + input logic r_ready_i, + + /// Write request; contains datapath and meta information + output idma_w_req_t w_req_o, + /// Write request valid + output logic w_valid_o, + /// Write request ready + input logic w_ready_i, + + /// Invalidate the current burst transfer, stops emission of requests + input logic flush_i, + /// Kill the active 1D transfer; reload a new transfer + input logic kill_i, + + /// Read machine of the legalizer is busy + output logic r_busy_o, + /// Write machine of the legalizer is busy + output logic w_busy_o +); + function int unsigned max_size(input int unsigned a, b); + return a > b ? a : b; + endfunction + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + /// The size of a page in byte + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); + /// The width of page offset byte addresses + localparam int unsigned PageAddrWidth = $clog2(PageSize); + + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address type + typedef logic [ AddrWidth-1:0] addr_t; + /// Page address type + typedef logic [PageAddrWidth-1:0] page_addr_t; + /// Page length type + typedef logic [ PageAddrWidth:0] page_len_t; + + + // state: internally hold one transfer, this is mutated + idma_mut_tf_t r_tf_d, r_tf_q; + idma_mut_tf_t w_tf_d, w_tf_q; + idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + + // enable signals for next mutable transfer storage + logic r_tf_ena; + logic w_tf_ena; + + // page boundaries + page_len_t r_page_num_bytes_to_pb; + page_len_t r_num_bytes_to_pb; + page_len_t w_page_num_bytes_to_pb; + page_len_t w_num_bytes_to_pb; + page_len_t c_num_bytes_to_pb; + + // read process + page_len_t r_num_bytes_possible; + page_len_t r_num_bytes; + offset_t r_addr_offset; + logic r_done; + + // write process + page_len_t w_num_bytes_possible; + page_len_t w_num_bytes; + offset_t w_addr_offset; + logic w_done; + + + //-------------------------------------- + // read boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_read_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.src_reduce_len ), + .max_llen_i ( opt_tf_q.src_max_llen ), + + .addr_i ( r_tf_q.addr ), + .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) + ); + + always_comb begin : gen_read_num_bytes_to_pb_logic + case (opt_tf_q.src_protocol) + idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::AXI_STREAM: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + default: r_num_bytes_to_pb = '0; + endcase + end + + //-------------------------------------- + // write boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_write_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.dst_reduce_len ), + .max_llen_i ( opt_tf_q.dst_max_llen ), + + .addr_i ( w_tf_q.addr ), + .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) + ); + + always_comb begin : gen_write_num_bytes_to_pb_logic + case (opt_tf_q.dst_protocol) + idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + idma_pkg::AXI_STREAM: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + default: w_num_bytes_to_pb = '0; + endcase + end + + //-------------------------------------- + // page boundary check + //-------------------------------------- + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; + + + //-------------------------------------- + // Synchronized R/W process + //-------------------------------------- + always_comb begin : proc_num_bytes_possible + // Default: Coupled + r_num_bytes_possible = c_num_bytes_to_pb; + w_num_bytes_possible = c_num_bytes_to_pb; + + if (opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM }) + || (opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM })) begin + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; + end + end + + assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; + assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + + // legalization process -> read and write is coupled together + always_comb begin : proc_read_write_transaction + + // default: keep state + r_tf_d = r_tf_q; + w_tf_d = w_tf_q; + opt_tf_d = opt_tf_q; + + // default: not done + r_done = 1'b0; + w_done = 1'b0; + + //-------------------------------------- + // Legalize read transaction + //-------------------------------------- + // more bytes remaining than we can read + if (r_tf_q.length > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + r_tf_d.length = r_tf_q.length - r_num_bytes_possible; + // next address + r_tf_d.addr = r_tf_q.addr + r_num_bytes; + + // remaining bytes fit in one burst + end else begin + r_num_bytes = r_tf_q.length[PageAddrWidth:0]; + // finished + r_tf_d.valid = 1'b0; + r_done = 1'b1; + end + + //-------------------------------------- + // Legalize write transaction + //-------------------------------------- + // more bytes remaining than we can write + if (w_tf_q.length > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + w_tf_d.length = w_tf_q.length - w_num_bytes_possible; + // next address + w_tf_d.addr = w_tf_q.addr + w_num_bytes; + + // remaining bytes fit in one burst + end else begin + w_num_bytes = w_tf_q.length[PageAddrWidth:0]; + // finished + w_tf_d.valid = 1'b0; + w_done = 1'b1; + end + + //-------------------------------------- + // Kill + //-------------------------------------- + if (kill_i) begin + // kill the current state + r_tf_d = '0; + w_tf_d = '0; + r_done = 1'b1; + w_done = 1'b1; + end + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o & valid_i) begin + + // load all three mutable objects (source, destination, option) + // source or read + r_tf_d = '{ + length: req_i.length, + addr: req_i.src_addr, + valid: 1'b1, + base_addr: req_i.src_addr + }; + // destination or write + w_tf_d = '{ + length: req_i.length, + addr: req_i.dst_addr, + valid: 1'b1, + base_addr: req_i.dst_addr + }; + // options + opt_tf_d = '{ + src_protocol: req_i.opt.src_protocol, + dst_protocol: req_i.opt.dst_protocol, + read_shift: '0, + write_shift: '0, + decouple_rw: req_i.opt.beo.decouple_rw, + decouple_aw: req_i.opt.beo.decouple_aw, + src_max_llen: req_i.opt.beo.src_max_llen, + dst_max_llen: req_i.opt.beo.dst_max_llen, + src_reduce_len: req_i.opt.beo.src_reduce_len, + dst_reduce_len: req_i.opt.beo.dst_reduce_len, + axi_id: req_i.opt.axi_id, + src_axi_opt: req_i.opt.src, + dst_axi_opt: req_i.opt.dst, + super_last: req_i.opt.last + }; + // determine shift amount + if (CombinedShifter) begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = '0; + end else begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + end + end + end + + + //-------------------------------------- + // Connect outputs + //-------------------------------------- + + // Read meta channel + always_comb begin : gen_read_meta_channel + r_req_o.ar_req = '0; + case(opt_tf_q.src_protocol) + idma_pkg::AXI: begin + r_req_o.ar_req.axi.ar_chan = '{ + id: opt_tf_q.axi_id, + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 + }; + + end + idma_pkg::AXI_STREAM: begin + r_req_o.ar_req = '0; + + end + default: + r_req_o.ar_req = '0; + endcase + end + + // assign the signals needed to set-up the read data path + assign r_req_o.r_dp_req = '{ + src_protocol: opt_tf_q.src_protocol, + offset: r_addr_offset, + tailer: OffsetWidth'(r_num_bytes + r_addr_offset), + shift: opt_tf_q.read_shift, + decouple_aw: opt_tf_q.decouple_aw, + is_single: r_num_bytes <= StrbWidth + }; + + // Write meta channel and data path + always_comb begin : gen_write_meta_channel + w_req_o.aw_req = '0; + case(opt_tf_q.dst_protocol) + idma_pkg::AXI: begin + w_req_o.aw_req.axi.aw_chan = '{ + id: opt_tf_q.axi_id, + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.dst_axi_opt.burst, + lock: opt_tf_q.dst_axi_opt.lock, + cache: opt_tf_q.dst_axi_opt.cache, + prot: opt_tf_q.dst_axi_opt.prot, + qos: opt_tf_q.dst_axi_opt.qos, + region: opt_tf_q.dst_axi_opt.region, + user: '0, + atop: '0 + }; + + end + idma_pkg::AXI_STREAM: begin + w_req_o.aw_req.axis.t_chan = '{ + data: '0, + strb: '1, + keep: '0, + last: w_tf_q.length == w_num_bytes, + id: opt_tf_q.axi_id, + dest: w_tf_q.base_addr[$bits(w_req_o.aw_req.axis.t_chan.dest)-1:0], + user: w_tf_q.base_addr[$bits(w_req_o.aw_req.axis.t_chan.user)-1+:$bits(w_req_o.aw_req.axis.t_chan.dest)] + }; + + end + default: + w_req_o.aw_req = '0; + endcase + end + + // assign the signals needed to set-up the write data path + always_comb begin : gen_write_data_path + case (opt_tf_q.dst_protocol) + idma_pkg::AXI: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: w_req_o.aw_req.axi.aw_chan.len, + is_single: w_req_o.aw_req.axi.aw_chan.len == '0 + }; + + default: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: 'd0, + is_single: 1'b1 + }; + endcase + end + + + // last burst in generic 1D transfer? + assign w_req_o.last = w_done; + + // last burst indicated by midend + assign w_req_o.super_last = opt_tf_q.super_last; + + // assign aw decouple flag + assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + + // busy output + assign r_busy_o = r_tf_q.valid; + assign w_busy_o = w_tf_q.valid; + + + //-------------------------------------- + // Flow Control + //-------------------------------------- + // only advance to next state if: + // * rw_coupled: both machines advance + // * rw_decoupled: either machine advances + + always_comb begin : proc_legalizer_flow_control + if ( opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM }) + || (opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM })) begin + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; + end else begin + r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end + end + + // load next idma request: if both machines are done! + assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; + + + //-------------------------------------- + // State + //-------------------------------------- + `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) + `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) + `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + + + //-------------------------------------- + // Assertions + //-------------------------------------- + // only support the decomposition of incremental bursts + `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & + req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & + req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "common_cells/registers.svh" +`include "common_cells/assertions.svh" +`include "idma/guard.svh" + +/// Legalizes a generic 1D transfer according to the rules given by the +/// used protocol. +module idma_legalizer_rw_axi_rw_obi #( + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + parameter type idma_req_t = logic, + /// Read request type + parameter type idma_r_req_t = logic, + /// Write request type + parameter type idma_w_req_t = logic, + /// Mutable transfer type + parameter type idma_mut_tf_t = logic, + /// Mutable options type + parameter type idma_mut_tf_opt_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + /// 1D request + input idma_req_t req_i, + /// 1D request valid + input logic valid_i, + /// 1D request ready + output logic ready_o, + + /// Read request; contains datapath and meta information + output idma_r_req_t r_req_o, + /// Read request valid + output logic r_valid_o, + /// Read request ready + input logic r_ready_i, + + /// Write request; contains datapath and meta information + output idma_w_req_t w_req_o, + /// Write request valid + output logic w_valid_o, + /// Write request ready + input logic w_ready_i, + + /// Invalidate the current burst transfer, stops emission of requests + input logic flush_i, + /// Kill the active 1D transfer; reload a new transfer + input logic kill_i, + + /// Read machine of the legalizer is busy + output logic r_busy_o, + /// Write machine of the legalizer is busy + output logic w_busy_o +); + function int unsigned max_size(input int unsigned a, b); + return a > b ? a : b; + endfunction + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + /// The size of a page in byte + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); + /// The width of page offset byte addresses + localparam int unsigned PageAddrWidth = $clog2(PageSize); + + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address type + typedef logic [ AddrWidth-1:0] addr_t; + /// Page address type + typedef logic [PageAddrWidth-1:0] page_addr_t; + /// Page length type + typedef logic [ PageAddrWidth:0] page_len_t; + + + // state: internally hold one transfer, this is mutated + idma_mut_tf_t r_tf_d, r_tf_q; + idma_mut_tf_t w_tf_d, w_tf_q; + idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + + // enable signals for next mutable transfer storage + logic r_tf_ena; + logic w_tf_ena; + + // page boundaries + page_len_t r_page_num_bytes_to_pb; + page_len_t r_num_bytes_to_pb; + page_len_t w_page_num_bytes_to_pb; + page_len_t w_num_bytes_to_pb; + page_len_t c_num_bytes_to_pb; + + // read process + page_len_t r_num_bytes_possible; + page_len_t r_num_bytes; + offset_t r_addr_offset; + logic r_done; + + // write process + page_len_t w_num_bytes_possible; + page_len_t w_num_bytes; + offset_t w_addr_offset; + logic w_done; + + + //-------------------------------------- + // read boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_read_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.src_reduce_len ), + .max_llen_i ( opt_tf_q.src_max_llen ), + + .addr_i ( r_tf_q.addr ), + .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) + ); + + always_comb begin : gen_read_num_bytes_to_pb_logic + case (opt_tf_q.src_protocol) + idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + default: r_num_bytes_to_pb = '0; + endcase + end + + //-------------------------------------- + // write boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_write_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.dst_reduce_len ), + .max_llen_i ( opt_tf_q.dst_max_llen ), + + .addr_i ( w_tf_q.addr ), + .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) + ); + + always_comb begin : gen_write_num_bytes_to_pb_logic + case (opt_tf_q.dst_protocol) + idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + idma_pkg::OBI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + default: w_num_bytes_to_pb = '0; + endcase + end + + //-------------------------------------- + // page boundary check + //-------------------------------------- + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; + + + //-------------------------------------- + // Synchronized R/W process + //-------------------------------------- + always_comb begin : proc_num_bytes_possible + // Default: Coupled + r_num_bytes_possible = c_num_bytes_to_pb; + w_num_bytes_possible = c_num_bytes_to_pb; + + if (opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; + end + end + + assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; + assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + + // legalization process -> read and write is coupled together + always_comb begin : proc_read_write_transaction + + // default: keep state + r_tf_d = r_tf_q; + w_tf_d = w_tf_q; + opt_tf_d = opt_tf_q; + + // default: not done + r_done = 1'b0; + w_done = 1'b0; + + //-------------------------------------- + // Legalize read transaction + //-------------------------------------- + // more bytes remaining than we can read + if (r_tf_q.length > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + r_tf_d.length = r_tf_q.length - r_num_bytes_possible; + // next address + r_tf_d.addr = r_tf_q.addr + r_num_bytes; + + // remaining bytes fit in one burst + end else begin + r_num_bytes = r_tf_q.length[PageAddrWidth:0]; + // finished + r_tf_d.valid = 1'b0; + r_done = 1'b1; + end + + //-------------------------------------- + // Legalize write transaction + //-------------------------------------- + // more bytes remaining than we can write + if (w_tf_q.length > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + w_tf_d.length = w_tf_q.length - w_num_bytes_possible; + // next address + w_tf_d.addr = w_tf_q.addr + w_num_bytes; + + // remaining bytes fit in one burst + end else begin + w_num_bytes = w_tf_q.length[PageAddrWidth:0]; + // finished + w_tf_d.valid = 1'b0; + w_done = 1'b1; + end + + //-------------------------------------- + // Kill + //-------------------------------------- + if (kill_i) begin + // kill the current state + r_tf_d = '0; + w_tf_d = '0; + r_done = 1'b1; + w_done = 1'b1; + end + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o & valid_i) begin + + // load all three mutable objects (source, destination, option) + // source or read + r_tf_d = '{ + length: req_i.length, + addr: req_i.src_addr, + valid: 1'b1, + base_addr: req_i.src_addr + }; + // destination or write + w_tf_d = '{ + length: req_i.length, + addr: req_i.dst_addr, + valid: 1'b1, + base_addr: req_i.dst_addr + }; + // options + opt_tf_d = '{ + src_protocol: req_i.opt.src_protocol, + dst_protocol: req_i.opt.dst_protocol, + read_shift: '0, + write_shift: '0, + decouple_rw: req_i.opt.beo.decouple_rw, + decouple_aw: req_i.opt.beo.decouple_aw, + src_max_llen: req_i.opt.beo.src_max_llen, + dst_max_llen: req_i.opt.beo.dst_max_llen, + src_reduce_len: req_i.opt.beo.src_reduce_len, + dst_reduce_len: req_i.opt.beo.dst_reduce_len, + axi_id: req_i.opt.axi_id, + src_axi_opt: req_i.opt.src, + dst_axi_opt: req_i.opt.dst, + super_last: req_i.opt.last + }; + // determine shift amount + if (CombinedShifter) begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = '0; + end else begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + end + end + end + + + //-------------------------------------- + // Connect outputs + //-------------------------------------- + + // Read meta channel + always_comb begin : gen_read_meta_channel + r_req_o.ar_req = '0; + case(opt_tf_q.src_protocol) + idma_pkg::AXI: begin + r_req_o.ar_req.axi.ar_chan = '{ + id: opt_tf_q.axi_id, + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 + }; + + end + idma_pkg::OBI: begin + r_req_o.ar_req.obi.a_chan = '{ + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '1, + we: 1'b0, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 + }; + + end + default: + r_req_o.ar_req = '0; + endcase + end + + // assign the signals needed to set-up the read data path + assign r_req_o.r_dp_req = '{ + src_protocol: opt_tf_q.src_protocol, + offset: r_addr_offset, + tailer: OffsetWidth'(r_num_bytes + r_addr_offset), + shift: opt_tf_q.read_shift, + decouple_aw: opt_tf_q.decouple_aw, + is_single: r_num_bytes <= StrbWidth + }; + + // Write meta channel and data path + always_comb begin : gen_write_meta_channel + w_req_o.aw_req = '0; + case(opt_tf_q.dst_protocol) + idma_pkg::AXI: begin + w_req_o.aw_req.axi.aw_chan = '{ + id: opt_tf_q.axi_id, + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.dst_axi_opt.burst, + lock: opt_tf_q.dst_axi_opt.lock, + cache: opt_tf_q.dst_axi_opt.cache, + prot: opt_tf_q.dst_axi_opt.prot, + qos: opt_tf_q.dst_axi_opt.qos, + region: opt_tf_q.dst_axi_opt.region, + user: '0, + atop: '0 + }; + + end + idma_pkg::OBI: begin + w_req_o.aw_req.obi.a_chan = '{ + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '0, + we: 1, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 + }; + + end + default: + w_req_o.aw_req = '0; + endcase + end + + // assign the signals needed to set-up the write data path + always_comb begin : gen_write_data_path + case (opt_tf_q.dst_protocol) + idma_pkg::AXI: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: w_req_o.aw_req.axi.aw_chan.len, + is_single: w_req_o.aw_req.axi.aw_chan.len == '0 + }; + + default: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: 'd0, + is_single: 1'b1 + }; + endcase + end + + + // last burst in generic 1D transfer? + assign w_req_o.last = w_done; + + // last burst indicated by midend + assign w_req_o.super_last = opt_tf_q.super_last; + + // assign aw decouple flag + assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + + // busy output + assign r_busy_o = r_tf_q.valid; + assign w_busy_o = w_tf_q.valid; + + + //-------------------------------------- + // Flow Control + //-------------------------------------- + // only advance to next state if: + // * rw_coupled: both machines advance + // * rw_decoupled: either machine advances + + always_comb begin : proc_legalizer_flow_control + if ( opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; + end else begin + r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end + end + + // load next idma request: if both machines are done! + assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; + + + //-------------------------------------- + // State + //-------------------------------------- + `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) + `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) + `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + + + //-------------------------------------- + // Assertions + //-------------------------------------- + // only support the decomposition of incremental bursts + `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & + req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & + req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "common_cells/registers.svh" +`include "common_cells/assertions.svh" +`include "idma/guard.svh" + +/// Legalizes a generic 1D transfer according to the rules given by the +/// used protocol. +module idma_legalizer_r_obi_rw_init_w_axi #( + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + parameter type idma_req_t = logic, + /// Read request type + parameter type idma_r_req_t = logic, + /// Write request type + parameter type idma_w_req_t = logic, + /// Mutable transfer type + parameter type idma_mut_tf_t = logic, + /// Mutable options type + parameter type idma_mut_tf_opt_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + /// 1D request + input idma_req_t req_i, + /// 1D request valid + input logic valid_i, + /// 1D request ready + output logic ready_o, + + /// Read request; contains datapath and meta information + output idma_r_req_t r_req_o, + /// Read request valid + output logic r_valid_o, + /// Read request ready + input logic r_ready_i, + + /// Write request; contains datapath and meta information + output idma_w_req_t w_req_o, + /// Write request valid + output logic w_valid_o, + /// Write request ready + input logic w_ready_i, + + /// Invalidate the current burst transfer, stops emission of requests + input logic flush_i, + /// Kill the active 1D transfer; reload a new transfer + input logic kill_i, + + /// Read machine of the legalizer is busy + output logic r_busy_o, + /// Write machine of the legalizer is busy + output logic w_busy_o +); + function int unsigned max_size(input int unsigned a, b); + return a > b ? a : b; + endfunction + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + /// The size of a page in byte + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, max_size(StrbWidth, StrbWidth)); + /// The width of page offset byte addresses + localparam int unsigned PageAddrWidth = $clog2(PageSize); + + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address type + typedef logic [ AddrWidth-1:0] addr_t; + /// Page address type + typedef logic [PageAddrWidth-1:0] page_addr_t; + /// Page length type + typedef logic [ PageAddrWidth:0] page_len_t; + + + // state: internally hold one transfer, this is mutated + idma_mut_tf_t r_tf_d, r_tf_q; + idma_mut_tf_t w_tf_d, w_tf_q; + idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + + // enable signals for next mutable transfer storage + logic r_tf_ena; + logic w_tf_ena; + + // page boundaries + page_len_t r_page_num_bytes_to_pb; + page_len_t r_num_bytes_to_pb; + page_len_t w_page_num_bytes_to_pb; + page_len_t w_num_bytes_to_pb; + page_len_t c_num_bytes_to_pb; + + // read process + page_len_t r_num_bytes_possible; + page_len_t r_num_bytes; + offset_t r_addr_offset; + logic r_done; + + // write process + page_len_t w_num_bytes_possible; + page_len_t w_num_bytes; + offset_t w_addr_offset; + logic w_done; + + + //-------------------------------------- + // read boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_read_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.src_reduce_len ), + .max_llen_i ( opt_tf_q.src_max_llen ), + + .addr_i ( r_tf_q.addr ), + .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) + ); + + always_comb begin : gen_read_num_bytes_to_pb_logic + case (opt_tf_q.src_protocol) + idma_pkg::INIT: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + default: r_num_bytes_to_pb = '0; + endcase + end + + //-------------------------------------- + // write boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_write_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.dst_reduce_len ), + .max_llen_i ( opt_tf_q.dst_max_llen ), + + .addr_i ( w_tf_q.addr ), + .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) + ); + + always_comb begin : gen_write_num_bytes_to_pb_logic + case (opt_tf_q.dst_protocol) + idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + idma_pkg::INIT: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + default: w_num_bytes_to_pb = '0; + endcase + end + + //-------------------------------------- + // page boundary check + //-------------------------------------- + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; + + + //-------------------------------------- + // Synchronized R/W process + //-------------------------------------- + always_comb begin : proc_num_bytes_possible + // Default: Coupled + r_num_bytes_possible = c_num_bytes_to_pb; + w_num_bytes_possible = c_num_bytes_to_pb; + + if (opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::INIT })) begin + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; + end + end + + assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; + assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + + // legalization process -> read and write is coupled together + always_comb begin : proc_read_write_transaction + + // default: keep state + r_tf_d = r_tf_q; + w_tf_d = w_tf_q; + opt_tf_d = opt_tf_q; + + // default: not done + r_done = 1'b0; + w_done = 1'b0; + + //-------------------------------------- + // Legalize read transaction + //-------------------------------------- + // more bytes remaining than we can read + if (r_tf_q.length > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + r_tf_d.length = r_tf_q.length - r_num_bytes_possible; + // next address + r_tf_d.addr = r_tf_q.addr + r_num_bytes; + + // remaining bytes fit in one burst + end else begin + r_num_bytes = r_tf_q.length[PageAddrWidth:0]; + // finished + r_tf_d.valid = 1'b0; + r_done = 1'b1; + end + + //-------------------------------------- + // Legalize write transaction + //-------------------------------------- + // more bytes remaining than we can write + if (w_tf_q.length > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + w_tf_d.length = w_tf_q.length - w_num_bytes_possible; + // next address + w_tf_d.addr = w_tf_q.addr + w_num_bytes; + + // remaining bytes fit in one burst + end else begin + w_num_bytes = w_tf_q.length[PageAddrWidth:0]; + // finished + w_tf_d.valid = 1'b0; + w_done = 1'b1; + end + + //-------------------------------------- + // Kill + //-------------------------------------- + if (kill_i) begin + // kill the current state + r_tf_d = '0; + w_tf_d = '0; + r_done = 1'b1; + w_done = 1'b1; + end + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o & valid_i) begin + + // load all three mutable objects (source, destination, option) + // source or read + r_tf_d = '{ + length: req_i.length, + addr: req_i.src_addr, + valid: 1'b1, + base_addr: req_i.src_addr + }; + // destination or write + w_tf_d = '{ + length: req_i.length, + addr: req_i.dst_addr, + valid: 1'b1, + base_addr: req_i.dst_addr + }; + // options + opt_tf_d = '{ + src_protocol: req_i.opt.src_protocol, + dst_protocol: req_i.opt.dst_protocol, + read_shift: '0, + write_shift: '0, + decouple_rw: req_i.opt.beo.decouple_rw, + decouple_aw: req_i.opt.beo.decouple_aw, + src_max_llen: req_i.opt.beo.src_max_llen, + dst_max_llen: req_i.opt.beo.dst_max_llen, + src_reduce_len: req_i.opt.beo.src_reduce_len, + dst_reduce_len: req_i.opt.beo.dst_reduce_len, + axi_id: req_i.opt.axi_id, + src_axi_opt: req_i.opt.src, + dst_axi_opt: req_i.opt.dst, + super_last: req_i.opt.last + }; + // determine shift amount + if (CombinedShifter) begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = '0; + end else begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + end + end + end + + + //-------------------------------------- + // Connect outputs + //-------------------------------------- + + // Read meta channel + always_comb begin : gen_read_meta_channel + r_req_o.ar_req = '0; + case(opt_tf_q.src_protocol) + idma_pkg::INIT: begin + r_req_o.ar_req.init.req_chan = '{ + cfg: r_tf_q.base_addr, + term: '0, + strb: '0, + id: opt_tf_d.axi_id + }; + + end + idma_pkg::OBI: begin + r_req_o.ar_req.obi.a_chan = '{ + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '1, + we: 1'b0, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 + }; + + end + default: + r_req_o.ar_req = '0; + endcase + end + + // assign the signals needed to set-up the read data path + assign r_req_o.r_dp_req = '{ + src_protocol: opt_tf_q.src_protocol, + offset: r_addr_offset, + tailer: OffsetWidth'(r_num_bytes + r_addr_offset), + shift: opt_tf_q.read_shift, + decouple_aw: opt_tf_q.decouple_aw, + is_single: r_num_bytes <= StrbWidth + }; + + // Write meta channel and data path + always_comb begin : gen_write_meta_channel + w_req_o.aw_req = '0; + case(opt_tf_q.dst_protocol) + idma_pkg::AXI: begin + w_req_o.aw_req.axi.aw_chan = '{ + id: opt_tf_q.axi_id, + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.dst_axi_opt.burst, + lock: opt_tf_q.dst_axi_opt.lock, + cache: opt_tf_q.dst_axi_opt.cache, + prot: opt_tf_q.dst_axi_opt.prot, + qos: opt_tf_q.dst_axi_opt.qos, + region: opt_tf_q.dst_axi_opt.region, + user: '0, + atop: '0 + }; + + end + idma_pkg::INIT: begin + w_req_o.aw_req.init.req_chan = '{ + cfg: w_tf_q.base_addr, + term: '0, + strb: '0, + id: opt_tf_d.axi_id + }; + + end + default: + w_req_o.aw_req = '0; + endcase + end + + // assign the signals needed to set-up the write data path + always_comb begin : gen_write_data_path + case (opt_tf_q.dst_protocol) + idma_pkg::AXI: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: w_req_o.aw_req.axi.aw_chan.len, + is_single: w_req_o.aw_req.axi.aw_chan.len == '0 + }; + + default: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: 'd0, + is_single: 1'b1 + }; + endcase + end + + + // last burst in generic 1D transfer? + assign w_req_o.last = w_done; + + // last burst indicated by midend + assign w_req_o.super_last = opt_tf_q.super_last; + + // assign aw decouple flag + assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + + // busy output + assign r_busy_o = r_tf_q.valid; + assign w_busy_o = w_tf_q.valid; + + + //-------------------------------------- + // Flow Control + //-------------------------------------- + // only advance to next state if: + // * rw_coupled: both machines advance + // * rw_decoupled: either machine advances + + always_comb begin : proc_legalizer_flow_control + if ( opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::INIT })) begin + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; + end else begin + r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end + end + + // load next idma request: if both machines are done! + assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; + + + //-------------------------------------- + // State + //-------------------------------------- + `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) + `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) + `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + + + //-------------------------------------- + // Assertions + //-------------------------------------- + // only support the decomposition of incremental bursts + `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & + req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & + req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "common_cells/registers.svh" +`include "common_cells/assertions.svh" +`include "idma/guard.svh" + +/// Legalizes a generic 1D transfer according to the rules given by the +/// used protocol. +module idma_legalizer_r_axi_rw_init_rw_obi #( + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + parameter type idma_req_t = logic, + /// Read request type + parameter type idma_r_req_t = logic, + /// Write request type + parameter type idma_w_req_t = logic, + /// Mutable transfer type + parameter type idma_mut_tf_t = logic, + /// Mutable options type + parameter type idma_mut_tf_opt_t = logic +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + + /// 1D request + input idma_req_t req_i, + /// 1D request valid + input logic valid_i, + /// 1D request ready + output logic ready_o, + + /// Read request; contains datapath and meta information + output idma_r_req_t r_req_o, + /// Read request valid + output logic r_valid_o, + /// Read request ready + input logic r_ready_i, + + /// Write request; contains datapath and meta information + output idma_w_req_t w_req_o, + /// Write request valid + output logic w_valid_o, + /// Write request ready + input logic w_ready_i, + + /// Invalidate the current burst transfer, stops emission of requests + input logic flush_i, + /// Kill the active 1D transfer; reload a new transfer + input logic kill_i, + + /// Read machine of the legalizer is busy + output logic r_busy_o, + /// Write machine of the legalizer is busy + output logic w_busy_o +); + function int unsigned max_size(input int unsigned a, b); + return a > b ? a : b; + endfunction + + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + /// The size of a page in byte + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, max_size(StrbWidth, StrbWidth)); + /// The width of page offset byte addresses + localparam int unsigned PageAddrWidth = $clog2(PageSize); + + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address type + typedef logic [ AddrWidth-1:0] addr_t; + /// Page address type + typedef logic [PageAddrWidth-1:0] page_addr_t; + /// Page length type + typedef logic [ PageAddrWidth:0] page_len_t; + + + // state: internally hold one transfer, this is mutated + idma_mut_tf_t r_tf_d, r_tf_q; + idma_mut_tf_t w_tf_d, w_tf_q; + idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + + // enable signals for next mutable transfer storage + logic r_tf_ena; + logic w_tf_ena; + + // page boundaries + page_len_t r_page_num_bytes_to_pb; + page_len_t r_num_bytes_to_pb; + page_len_t w_page_num_bytes_to_pb; + page_len_t w_num_bytes_to_pb; + page_len_t c_num_bytes_to_pb; + + // read process + page_len_t r_num_bytes_possible; + page_len_t r_num_bytes; + offset_t r_addr_offset; + logic r_done; + + // write process + page_len_t w_num_bytes_possible; + page_len_t w_num_bytes; + offset_t w_addr_offset; + logic w_done; + + + //-------------------------------------- + // read boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_read_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.src_reduce_len ), + .max_llen_i ( opt_tf_q.src_max_llen ), + + .addr_i ( r_tf_q.addr ), + .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) + ); + + always_comb begin : gen_read_num_bytes_to_pb_logic + case (opt_tf_q.src_protocol) + idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::INIT: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + default: r_num_bytes_to_pb = '0; + endcase + end + + //-------------------------------------- + // write boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_write_page_splitter ( + .not_bursting_i ( 1'b1 ), + + .reduce_len_i ( opt_tf_q.dst_reduce_len ), + .max_llen_i ( opt_tf_q.dst_max_llen ), + + .addr_i ( w_tf_q.addr ), + .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) + ); + + always_comb begin : gen_write_num_bytes_to_pb_logic + case (opt_tf_q.dst_protocol) + idma_pkg::INIT: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + idma_pkg::OBI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + default: w_num_bytes_to_pb = '0; + endcase + end + + //-------------------------------------- + // page boundary check + //-------------------------------------- + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; + + + //-------------------------------------- + // Synchronized R/W process + //-------------------------------------- + always_comb begin : proc_num_bytes_possible + // Default: Coupled + r_num_bytes_possible = c_num_bytes_to_pb; + w_num_bytes_possible = c_num_bytes_to_pb; + + if (opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI })) begin + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; + end + end + + assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; + assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + + // legalization process -> read and write is coupled together + always_comb begin : proc_read_write_transaction + + // default: keep state + r_tf_d = r_tf_q; + w_tf_d = w_tf_q; + opt_tf_d = opt_tf_q; + + // default: not done + r_done = 1'b0; + w_done = 1'b0; + + //-------------------------------------- + // Legalize read transaction + //-------------------------------------- + // more bytes remaining than we can read + if (r_tf_q.length > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + r_tf_d.length = r_tf_q.length - r_num_bytes_possible; + // next address + r_tf_d.addr = r_tf_q.addr + r_num_bytes; + + // remaining bytes fit in one burst + end else begin + r_num_bytes = r_tf_q.length[PageAddrWidth:0]; + // finished + r_tf_d.valid = 1'b0; + r_done = 1'b1; + end + + //-------------------------------------- + // Legalize write transaction + //-------------------------------------- + // more bytes remaining than we can write + if (w_tf_q.length > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + w_tf_d.length = w_tf_q.length - w_num_bytes_possible; + // next address + w_tf_d.addr = w_tf_q.addr + w_num_bytes; + + // remaining bytes fit in one burst + end else begin + w_num_bytes = w_tf_q.length[PageAddrWidth:0]; + // finished + w_tf_d.valid = 1'b0; + w_done = 1'b1; + end + + //-------------------------------------- + // Kill + //-------------------------------------- + if (kill_i) begin + // kill the current state + r_tf_d = '0; + w_tf_d = '0; + r_done = 1'b1; + w_done = 1'b1; + end + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o & valid_i) begin + + // load all three mutable objects (source, destination, option) + // source or read + r_tf_d = '{ + length: req_i.length, + addr: req_i.src_addr, + valid: 1'b1, + base_addr: req_i.src_addr + }; + // destination or write + w_tf_d = '{ + length: req_i.length, + addr: req_i.dst_addr, + valid: 1'b1, + base_addr: req_i.dst_addr + }; + // options + opt_tf_d = '{ + src_protocol: req_i.opt.src_protocol, + dst_protocol: req_i.opt.dst_protocol, + read_shift: '0, + write_shift: '0, + decouple_rw: req_i.opt.beo.decouple_rw, + decouple_aw: req_i.opt.beo.decouple_aw, + src_max_llen: req_i.opt.beo.src_max_llen, + dst_max_llen: req_i.opt.beo.dst_max_llen, + src_reduce_len: req_i.opt.beo.src_reduce_len, + dst_reduce_len: req_i.opt.beo.dst_reduce_len, + axi_id: req_i.opt.axi_id, + src_axi_opt: req_i.opt.src, + dst_axi_opt: req_i.opt.dst, + super_last: req_i.opt.last + }; + // determine shift amount + if (CombinedShifter) begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = '0; + end else begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + end + end + end + + + //-------------------------------------- + // Connect outputs + //-------------------------------------- + + // Read meta channel + always_comb begin : gen_read_meta_channel + r_req_o.ar_req = '0; + case(opt_tf_q.src_protocol) + idma_pkg::AXI: begin + r_req_o.ar_req.axi.ar_chan = '{ + id: opt_tf_q.axi_id, + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 + }; + + end + idma_pkg::INIT: begin + r_req_o.ar_req.init.req_chan = '{ + cfg: r_tf_q.base_addr, + term: '0, + strb: '0, + id: opt_tf_d.axi_id + }; + + end + idma_pkg::OBI: begin + r_req_o.ar_req.obi.a_chan = '{ + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '1, + we: 1'b0, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 + }; + + end + default: + r_req_o.ar_req = '0; + endcase + end + + // assign the signals needed to set-up the read data path + assign r_req_o.r_dp_req = '{ + src_protocol: opt_tf_q.src_protocol, + offset: r_addr_offset, + tailer: OffsetWidth'(r_num_bytes + r_addr_offset), + shift: opt_tf_q.read_shift, + decouple_aw: opt_tf_q.decouple_aw, + is_single: r_num_bytes <= StrbWidth + }; + + // Write meta channel and data path + always_comb begin : gen_write_meta_channel + w_req_o.aw_req = '0; + case(opt_tf_q.dst_protocol) + idma_pkg::INIT: begin + w_req_o.aw_req.init.req_chan = '{ + cfg: w_tf_q.base_addr, + term: '0, + strb: '0, + id: opt_tf_d.axi_id + }; + + end + idma_pkg::OBI: begin + w_req_o.aw_req.obi.a_chan = '{ + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '0, + we: 1, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 + }; + + end + default: + w_req_o.aw_req = '0; + endcase + end + + // assign the signals needed to set-up the write data path + always_comb begin : gen_write_data_path + case (opt_tf_q.dst_protocol) + default: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: 'd0, + is_single: 1'b1 + }; + endcase + end + + + // last burst in generic 1D transfer? + assign w_req_o.last = w_done; + + // last burst indicated by midend + assign w_req_o.super_last = opt_tf_q.super_last; + + // assign aw decouple flag + assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + + // busy output + assign r_busy_o = r_tf_q.valid; + assign w_busy_o = w_tf_q.valid; + + + //-------------------------------------- + // Flow Control + //-------------------------------------- + // only advance to next state if: + // * rw_coupled: both machines advance + // * rw_decoupled: either machine advances + + always_comb begin : proc_legalizer_flow_control + if ( opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI })) begin + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; + end else begin + r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + + r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end + end + + // load next idma request: if both machines are done! + assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; + + + //-------------------------------------- + // State + //-------------------------------------- + `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) + `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) + `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + + + //-------------------------------------- + // Assertions + //-------------------------------------- + // only support the decomposition of incremental bursts + `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & + req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & + req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "idma/guard.svh" + +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_rw_axi #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b1, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, + + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, + + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o +); + + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; + + /// Address type + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; + + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; + + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; + + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; + + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; + + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; + + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; + + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; + + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; + + + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; + + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; + + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; + + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; + + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; + + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; + + // Ax request from R-AW coupler to datapath + write_meta_channel_t aw_req_dp; + + // Ax request from the decoupling stage to the datapath + read_meta_channel_t ar_req_dp; + + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; + + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; + + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; + + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; + + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; + + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; + end + end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; + end + + + //-------------------------------------- + // Legalization + //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_rw_axi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); + + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); + + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); + + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; + + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; + + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; + + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; + + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; + + + //-------------------------------------- + // Error handler + //-------------------------------------- + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + idma_error_handler #( + .MetaFifoDepth ( MetaFifoDepth ), + .PrintFifoInfo ( PrintFifoInfo ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_eh_req_t ), + .addr_t ( addr_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ) + ) i_idma_error_handler ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid ), + .rsp_ready_i ( rsp_ready ), + .req_valid_i ( req_valid ), + .req_ready_i ( req_ready_o ), + .eh_i ( idma_eh_req_i ), + .eh_valid_i ( eh_req_valid_i ), + .eh_ready_o ( eh_req_ready_o ), + .r_addr_i ( r_req.ar_req.axi.ar_chan.addr ), + .w_addr_i ( w_req.aw_req.axi.aw_chan.addr ), + .r_consume_i ( r_valid & r_ready ), + .w_consume_i ( w_valid & w_ready ), + .legalizer_flush_o ( legalizer_flush ), + .legalizer_kill_o ( legalizer_kill ), + .dp_busy_i ( dp_busy ), + .dp_poison_o ( dp_poison ), + .r_dp_rsp_i ( r_dp_rsp ), + .r_dp_valid_i ( r_dp_rsp_valid ), + .r_dp_ready_o ( r_dp_rsp_ready ), + .w_dp_rsp_i ( w_dp_rsp ), + .w_dp_valid_i ( w_dp_rsp_valid ), + .w_dp_ready_o ( w_dp_rsp_ready ), + .w_last_burst_i ( w_last_burst ), + .w_super_last_i ( w_super_last ), + .fsm_busy_o ( busy_o.eh_fsm_busy ), + .cnt_busy_o ( busy_o.eh_cnt_busy ) + ); + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; + + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); + end + ) + end + + + //-------------------------------------- + // Datapath busy signal + //-------------------------------------- + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; + + + //-------------------------------------- + // Datapath decoupling + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + + fall_through_register #( + .T ( read_meta_channel_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_req.ar_req ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_rw_axi #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .axi_read_req_o ( axi_read_req_o ), + .axi_read_rsp_i ( axi_read_rsp_i ), + .axi_write_req_o ( axi_write_req_o ), + .axi_write_rsp_i ( axi_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + // instantiate the channel coupler + idma_channel_coupler #( + .NumAxInFlight ( NumAxInFlight ), + .AddrWidth ( AddrWidth ), + .UserWidth ( UserWidth ), + .AxiIdWidth ( AxiIdWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .axi_aw_chan_t ( write_meta_channel_t ) + ) i_idma_channel_coupler ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .r_rsp_valid_i ( r_chan_valid ), + .r_rsp_ready_i ( r_chan_ready ), + .r_rsp_first_i ( r_dp_rsp.first ), + .r_decouple_aw_i ( r_dp_req_out.decouple_aw ), + .aw_decouple_aw_i ( w_req.decouple_aw ), + .aw_req_i ( w_req.aw_req ), + .aw_valid_i ( w_valid ), + .aw_ready_o ( aw_ready ), + .aw_req_o ( aw_req_dp ), + .aw_valid_o ( aw_valid_dp ), + .aw_ready_i ( aw_ready_dp ), + .busy_o ( busy_o.raw_coupler_busy ) + ); + end else begin : gen_r_aw_bypass + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + fall_through_register #( + .T ( write_meta_channel_t ) + ) i_aw_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( w_valid ), + .ready_o ( aw_ready ), + .data_i ( w_req.aw_req ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp ), + .data_o ( aw_req_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end + + + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "idma/guard.svh" + +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_r_obi_w_axi #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, + + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, + + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, + + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o +); + + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; + + /// Address type + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; + + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; + + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; + + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; + + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; + + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; + + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; + + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; + + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; + + + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; + + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; + + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; + + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; + + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; + + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; + + // Ax request from R-AW coupler to datapath + write_meta_channel_t aw_req_dp; + + // Ax request from the decoupling stage to the datapath + read_meta_channel_t ar_req_dp; + + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; + + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; + + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; + + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; + + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; + + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; + end + end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; + end + + + //-------------------------------------- + // Legalization + //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_r_obi_w_axi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); + + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); + + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); + + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; + + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; + + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; + + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; + + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; + + + //-------------------------------------- + // Error handler + //-------------------------------------- + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); + end + ) + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; + + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); + end + ) + end + + + //-------------------------------------- + // Datapath busy signal + //-------------------------------------- + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; + + + //-------------------------------------- + // Datapath decoupling + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + + fall_through_register #( + .T ( read_meta_channel_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_req.ar_req ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_r_obi_w_axi #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .obi_read_req_o ( obi_read_req_o ), + .obi_read_rsp_i ( obi_read_rsp_i ), + .axi_write_req_o ( axi_write_req_o ), + .axi_write_rsp_i ( axi_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) + end else begin : gen_r_aw_bypass + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + fall_through_register #( + .T ( write_meta_channel_t ) + ) i_aw_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( w_valid ), + .ready_o ( aw_ready ), + .data_i ( w_req.aw_req ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp ), + .data_o ( aw_req_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end + + + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "idma/guard.svh" + +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_r_axi_w_obi #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, + + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, + + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o +); + + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; + + /// Address type + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; + + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; + + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; + + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; + + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; + + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; + + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; + + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; + + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; + + + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; + + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; + + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; + + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; + + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; + + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; + + // Ax request from R-AW coupler to datapath + write_meta_channel_t aw_req_dp; + + // Ax request from the decoupling stage to the datapath + read_meta_channel_t ar_req_dp; + + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; + + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; + + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; + + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; + + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; + + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; + end + end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; + end + + + //-------------------------------------- + // Legalization + //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_r_axi_w_obi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); + + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); + + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); + + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; + + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; + + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; + + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; + + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; + + + //-------------------------------------- + // Error handler + //-------------------------------------- + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); + end + ) + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; + + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); + end + ) + end + + + //-------------------------------------- + // Datapath busy signal + //-------------------------------------- + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; + + + //-------------------------------------- + // Datapath decoupling + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + + fall_through_register #( + .T ( read_meta_channel_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_req.ar_req ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_r_axi_w_obi #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .axi_read_req_o ( axi_read_req_o ), + .axi_read_rsp_i ( axi_read_rsp_i ), + .obi_write_req_o ( obi_write_req_o ), + .obi_write_rsp_i ( obi_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) + end else begin : gen_r_aw_bypass + // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests + // As a write could depend on up to two reads + stream_fifo_optimal_wrap #( + .Depth ( 2 ), + .type_t ( write_meta_channel_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.aw_req ), + .valid_i ( w_valid && aw_ready ), + .ready_o ( aw_ready ), + .data_o ( aw_req_dp ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp && aw_valid_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end + + + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "idma/guard.svh" + +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_rw_axi_rw_axis #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// AXI Stream Request and Response channel type + parameter type axis_req_t = logic, + parameter type axis_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, + + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, + + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// AXI Stream read request + input axis_req_t axis_read_req_i, + /// AXI Stream read response + output axis_rsp_t axis_read_rsp_o, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// AXI Stream write request + output axis_req_t axis_write_req_o, + /// AXI Stream write response + input axis_rsp_t axis_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o +); + + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; + + /// Address type + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; + + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; + + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; + + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; + + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; + + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; + typedef struct packed { + idma_pkg::protocol_e src_protocol; + read_meta_channel_t ar_req; + } read_meta_channel_tagged_t; + + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + write_meta_channel_t aw_req; + } write_meta_channel_tagged_t; + + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; + + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; + + + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; + + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + read_meta_channel_tagged_t r_meta_req_tagged; + write_meta_channel_tagged_t w_meta_req_tagged; + + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; + + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; + + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; + + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; + + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; + + // Ax request from R-AW coupler to datapath + write_meta_channel_tagged_t aw_req_dp; + + // Ax request from the decoupling stage to the datapath + read_meta_channel_tagged_t ar_req_dp; + + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; + + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; + + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; + + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; + + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; + + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; + end + end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; + end + + + //-------------------------------------- + // Legalization + //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_rw_axi_rw_axis #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); + + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); + + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); + + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; + + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; + + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; + + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; + + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; + + + //-------------------------------------- + // Error handler + //-------------------------------------- + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); + end + ) + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; + + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); + end + ) + end + + + //-------------------------------------- + // Datapath busy signal + //-------------------------------------- + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; + + + //-------------------------------------- + // Datapath decoupling + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + assign r_meta_req_tagged = '{ + src_protocol: r_req.r_dp_req.src_protocol, + ar_req: r_req.ar_req + }; + + fall_through_register #( + .T ( read_meta_channel_tagged_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_meta_req_tagged ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_rw_axi_rw_axis #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .axis_req_t ( axis_req_t ), + .axis_rsp_t ( axis_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .axi_read_req_o ( axi_read_req_o ), + .axi_read_rsp_i ( axi_read_rsp_i ), + .axis_read_req_i ( axis_read_req_i ), + .axis_read_rsp_o ( axis_read_rsp_o ), + .axi_write_req_o ( axi_write_req_o ), + .axi_write_rsp_i ( axi_write_rsp_i ), + .axis_write_req_o ( axis_write_req_o ), + .axis_write_rsp_i ( axis_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + assign w_meta_req_tagged = '{ + dst_protocol: w_req.w_dp_req.dst_protocol, + aw_req: w_req.aw_req + }; + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) + end else begin : gen_r_aw_bypass + // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests + // As a write could depend on up to two reads + stream_fifo_optimal_wrap #( + .Depth ( 2 ), + .type_t ( write_meta_channel_tagged_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_meta_req_tagged ), + .valid_i ( w_valid && aw_ready ), + .ready_o ( aw_ready ), + .data_o ( aw_req_dp ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp && aw_valid_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end + + + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "idma/guard.svh" + +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_rw_axi_rw_obi #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, + + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, + + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o +); + + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; + + /// Address type + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; + + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; + + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; + + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; + + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; + + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; + typedef struct packed { + idma_pkg::protocol_e src_protocol; + read_meta_channel_t ar_req; + } read_meta_channel_tagged_t; + + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + write_meta_channel_t aw_req; + } write_meta_channel_tagged_t; + + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; + + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; + + + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; + + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + read_meta_channel_tagged_t r_meta_req_tagged; + write_meta_channel_tagged_t w_meta_req_tagged; + + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; + + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; + + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; + + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; + + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; + + // Ax request from R-AW coupler to datapath + write_meta_channel_tagged_t aw_req_dp; + + // Ax request from the decoupling stage to the datapath + read_meta_channel_tagged_t ar_req_dp; + + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; + + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; + + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; + + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; + + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; + + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; + end + end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; + end + + + //-------------------------------------- + // Legalization + //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_rw_axi_rw_obi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); + + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); + + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); + + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; + + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; + + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; + + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; + + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; + + + //-------------------------------------- + // Error handler + //-------------------------------------- + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); + end + ) + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; + + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); + end + ) + end + + + //-------------------------------------- + // Datapath busy signal + //-------------------------------------- + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; + + + //-------------------------------------- + // Datapath decoupling + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + assign r_meta_req_tagged = '{ + src_protocol: r_req.r_dp_req.src_protocol, + ar_req: r_req.ar_req + }; + + fall_through_register #( + .T ( read_meta_channel_tagged_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_meta_req_tagged ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_rw_axi_rw_obi #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .axi_read_req_o ( axi_read_req_o ), + .axi_read_rsp_i ( axi_read_rsp_i ), + .obi_read_req_o ( obi_read_req_o ), + .obi_read_rsp_i ( obi_read_rsp_i ), + .axi_write_req_o ( axi_write_req_o ), + .axi_write_rsp_i ( axi_write_rsp_i ), + .obi_write_req_o ( obi_write_req_o ), + .obi_write_rsp_i ( obi_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + assign w_meta_req_tagged = '{ + dst_protocol: w_req.w_dp_req.dst_protocol, + aw_req: w_req.aw_req + }; + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) + end else begin : gen_r_aw_bypass + // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests + // As a write could depend on up to two reads + stream_fifo_optimal_wrap #( + .Depth ( 2 ), + .type_t ( write_meta_channel_tagged_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_meta_req_tagged ), + .valid_i ( w_valid && aw_ready ), + .ready_o ( aw_ready ), + .data_o ( aw_req_dp ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp && aw_valid_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end + + + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "idma/guard.svh" + +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_r_obi_rw_init_w_axi #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// Memory Init Request and Response channel type + parameter type init_req_t = logic, + parameter type init_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, + + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, + + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, + + /// Memory Init read request + output init_req_t init_read_req_o, + /// Memory Init read response + input init_rsp_t init_read_rsp_i, + + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// Memory Init write request + output init_req_t init_write_req_o, + /// Memory Init write response + input init_rsp_t init_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o +); + + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; + + /// Address type + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; + + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; + + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; + + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; + + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; + + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; + typedef struct packed { + idma_pkg::protocol_e src_protocol; + read_meta_channel_t ar_req; + } read_meta_channel_tagged_t; + + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + write_meta_channel_t aw_req; + } write_meta_channel_tagged_t; + + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; + + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; + + + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; + + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + read_meta_channel_tagged_t r_meta_req_tagged; + write_meta_channel_tagged_t w_meta_req_tagged; + + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; + + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; + + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; + + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; + + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; + + // Ax request from R-AW coupler to datapath + write_meta_channel_tagged_t aw_req_dp; + + // Ax request from the decoupling stage to the datapath + read_meta_channel_tagged_t ar_req_dp; + + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; + + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; + + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; + + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; + + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; + + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; + end + end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; + end + + + //-------------------------------------- + // Legalization + //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_r_obi_rw_init_w_axi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); + + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); + + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); + + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; + + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; + + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; + + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; + + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; + + + //-------------------------------------- + // Error handler + //-------------------------------------- + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); + end + ) + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; + + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); + end + ) + end + + + //-------------------------------------- + // Datapath busy signal + //-------------------------------------- + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; + + + //-------------------------------------- + // Datapath decoupling + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + assign r_meta_req_tagged = '{ + src_protocol: r_req.r_dp_req.src_protocol, + ar_req: r_req.ar_req + }; + + fall_through_register #( + .T ( read_meta_channel_tagged_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_meta_req_tagged ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_r_obi_rw_init_w_axi #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .init_req_t ( init_req_t ), + .init_rsp_t ( init_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .init_read_req_o ( init_read_req_o ), + .init_read_rsp_i ( init_read_rsp_i ), + .obi_read_req_o ( obi_read_req_o ), + .obi_read_rsp_i ( obi_read_rsp_i ), + .axi_write_req_o ( axi_write_req_o ), + .axi_write_rsp_i ( axi_write_rsp_i ), + .init_write_req_o ( init_write_req_o ), + .init_write_rsp_i ( init_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + assign w_meta_req_tagged = '{ + dst_protocol: w_req.w_dp_req.dst_protocol, + aw_req: w_req.aw_req + }; + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) + end else begin : gen_r_aw_bypass + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + fall_through_register #( + .T ( write_meta_channel_tagged_t ) + ) i_aw_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( w_valid ), + .ready_o ( aw_ready ), + .data_i ( w_meta_req_tagged ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp ), + .data_o ( aw_req_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end + + + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "idma/guard.svh" + +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_r_axi_rw_init_rw_obi #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// Memory Init Request and Response channel type + parameter type init_req_t = logic, + parameter type init_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) +)( + /// Clock + input logic clk_i, + /// Asynchronous reset, active low + input logic rst_ni, + /// Testmode in + input logic testmode_i, + + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, + + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, + + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, + + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// Memory Init read request + output init_req_t init_read_req_o, + /// Memory Init read response + input init_rsp_t init_read_rsp_i, + + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// Memory Init write request + output init_req_t init_write_req_o, + /// Memory Init write response + input init_rsp_t init_write_rsp_i, + + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o +); + + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; + + /// Address type + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; + + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; + + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; + + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; + + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; + + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; + typedef struct packed { + idma_pkg::protocol_e src_protocol; + read_meta_channel_t ar_req; + } read_meta_channel_tagged_t; + + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + write_meta_channel_t aw_req; + } write_meta_channel_tagged_t; + + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; + + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; + + + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; + + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + read_meta_channel_tagged_t r_meta_req_tagged; + write_meta_channel_tagged_t w_meta_req_tagged; + + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; + + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; + + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; + + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; + + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; + + // Ax request from R-AW coupler to datapath + write_meta_channel_tagged_t aw_req_dp; + + // Ax request from the decoupling stage to the datapath + read_meta_channel_tagged_t ar_req_dp; + + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; + + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; + + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; + + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; + + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; + + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; + + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; + end + end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; + end + + + //-------------------------------------- + // Legalization + //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_r_axi_rw_init_rw_obi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); + + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); + + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); + + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; + + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; + + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; + + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; + + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; + + + //-------------------------------------- + // Error handler + //-------------------------------------- + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); + end + ) + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; + + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); + end + ) + end + + + //-------------------------------------- + // Datapath busy signal + //-------------------------------------- + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; + + + //-------------------------------------- + // Datapath decoupling + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + assign r_meta_req_tagged = '{ + src_protocol: r_req.r_dp_req.src_protocol, + ar_req: r_req.ar_req + }; + + fall_through_register #( + .T ( read_meta_channel_tagged_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_meta_req_tagged ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_r_axi_rw_init_rw_obi #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .init_req_t ( init_req_t ), + .init_rsp_t ( init_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .axi_read_req_o ( axi_read_req_o ), + .axi_read_rsp_i ( axi_read_rsp_i ), + .init_read_req_o ( init_read_req_o ), + .init_read_rsp_i ( init_read_rsp_i ), + .obi_read_req_o ( obi_read_req_o ), + .obi_read_rsp_i ( obi_read_rsp_i ), + .init_write_req_o ( init_write_req_o ), + .init_write_rsp_i ( init_write_rsp_i ), + .obi_write_req_o ( obi_write_req_o ), + .obi_write_rsp_i ( obi_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + assign w_meta_req_tagged = '{ + dst_protocol: w_req.w_dp_req.dst_protocol, + aw_req: w_req.aw_req + }; + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) + end else begin : gen_r_aw_bypass + // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests + // As a write could depend on up to two reads + stream_fifo_optimal_wrap #( + .Depth ( 2 ), + .type_t ( write_meta_channel_tagged_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_meta_req_tagged ), + .valid_i ( w_valid && aw_ready ), + .ready_o ( aw_ready ), + .data_o ( aw_req_dp ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp && aw_valid_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end + + + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "axi_stream/typedef.svh" +`include "idma/typedef.svh" +`include "obi/typedef.svh" +`include "tilelink/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_backend_synth_rw_axi #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b1, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// User type (do not override!) + parameter type user_t = logic[UserWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input idma_pkg::protocol_e req_src_protocol_i, + input idma_pkg::protocol_e req_dst_protocol_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output id_t axi_ar_id_o, + output addr_t axi_ar_addr_o, + output axi_pkg::len_t axi_ar_len_o, + output axi_pkg::size_t axi_ar_size_o, + output axi_pkg::burst_t axi_ar_burst_o, + output logic axi_ar_lock_o, + output axi_pkg::cache_t axi_ar_cache_o, + output axi_pkg::prot_t axi_ar_prot_o, + output axi_pkg::qos_t axi_ar_qos_o, + output axi_pkg::region_t axi_ar_region_o, + output user_t axi_ar_user_o, + output logic axi_ar_valid_o, + input logic axi_ar_ready_i, + input id_t axi_r_id_i, + input data_t axi_r_data_i, + input axi_pkg::resp_t axi_r_resp_i, + input logic axi_r_last_i, + input user_t axi_r_user_i, + input logic axi_r_valid_i, + output logic axi_r_ready_o, + + + output id_t axi_aw_id_o, + output addr_t axi_aw_addr_o, + output axi_pkg::len_t axi_aw_len_o, + output axi_pkg::size_t axi_aw_size_o, + output axi_pkg::burst_t axi_aw_burst_o, + output logic axi_aw_lock_o, + output axi_pkg::cache_t axi_aw_cache_o, + output axi_pkg::prot_t axi_aw_prot_o, + output axi_pkg::qos_t axi_aw_qos_o, + output axi_pkg::region_t axi_aw_region_o, + output axi_pkg::atop_t axi_aw_atop_o, + output user_t axi_aw_user_o, + output logic axi_aw_valid_o, + input logic axi_aw_ready_i, + output data_t axi_w_data_o, + output strb_t axi_w_strb_o, + output logic axi_w_last_o, + output user_t axi_w_user_o, + output logic axi_w_valid_o, + input logic axi_w_ready_i, + input id_t axi_b_id_i, + input axi_pkg::resp_t axi_b_resp_i, + input user_t axi_b_user_i, + input logic axi_b_valid_i, + output logic axi_b_ready_o, + + + output idma_pkg::idma_busy_t idma_busy_o +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // AXI4+ATOP typedefs +`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) +`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + +`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + +`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) +`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + + // Meta Channel Widths + localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + + typedef struct packed { + axi_ar_chan_t ar_chan; + } axi_read_meta_channel_t; + + typedef struct packed { + axi_read_meta_channel_t axi; + } read_meta_channel_t; + + typedef struct packed { + axi_aw_chan_t aw_chan; + } axi_write_meta_channel_t; + + typedef struct packed { + axi_write_meta_channel_t axi; + } write_meta_channel_t; + + // local types + // AXI4+ATOP request and response + axi_req_t axi_read_req; + axi_rsp_t axi_read_rsp; + + axi_req_t axi_write_req; + axi_rsp_t axi_write_rsp; + + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + idma_backend_rw_axi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .axi_read_req_o ( axi_read_req ), + .axi_read_rsp_i ( axi_read_rsp ), + .axi_write_req_o ( axi_write_req ), + .axi_write_rsp_i ( axi_write_rsp ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.src_protocol = req_src_protocol_i; + assign idma_req.opt.dst_protocol = req_dst_protocol_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + + // AXI4+ATOP Read + assign axi_ar_id_o = axi_read_req.ar.id; + assign axi_ar_addr_o = axi_read_req.ar.addr; + assign axi_ar_len_o = axi_read_req.ar.len; + assign axi_ar_size_o = axi_read_req.ar.size; + assign axi_ar_burst_o = axi_read_req.ar.burst; + assign axi_ar_lock_o = axi_read_req.ar.lock; + assign axi_ar_cache_o = axi_read_req.ar.cache; + assign axi_ar_prot_o = axi_read_req.ar.prot; + assign axi_ar_qos_o = axi_read_req.ar.qos; + assign axi_ar_region_o = axi_read_req.ar.region; + assign axi_ar_user_o = axi_read_req.ar.user; + assign axi_ar_valid_o = axi_read_req.ar_valid; + assign axi_r_ready_o = axi_read_req.r_ready; + + assign axi_read_rsp.ar_ready = axi_ar_ready_i; + assign axi_read_rsp.r.id = axi_r_id_i; + assign axi_read_rsp.r.data = axi_r_data_i; + assign axi_read_rsp.r.resp = axi_r_resp_i; + assign axi_read_rsp.r.last = axi_r_last_i; + assign axi_read_rsp.r.user = axi_r_user_i; + assign axi_read_rsp.r_valid = axi_r_valid_i; + + + + // AXI4+ATOP Write + assign axi_aw_id_o = axi_write_req.aw.id; + assign axi_aw_addr_o = axi_write_req.aw.addr; + assign axi_aw_len_o = axi_write_req.aw.len; + assign axi_aw_size_o = axi_write_req.aw.size; + assign axi_aw_burst_o = axi_write_req.aw.burst; + assign axi_aw_lock_o = axi_write_req.aw.lock; + assign axi_aw_cache_o = axi_write_req.aw.cache; + assign axi_aw_prot_o = axi_write_req.aw.prot; + assign axi_aw_qos_o = axi_write_req.aw.qos; + assign axi_aw_region_o = axi_write_req.aw.region; + assign axi_aw_atop_o = axi_write_req.aw.atop; + assign axi_aw_user_o = axi_write_req.aw.user; + assign axi_aw_valid_o = axi_write_req.aw_valid; + assign axi_w_data_o = axi_write_req.w.data; + assign axi_w_strb_o = axi_write_req.w.strb; + assign axi_w_last_o = axi_write_req.w.last; + assign axi_w_user_o = axi_write_req.w.user; + assign axi_w_valid_o = axi_write_req.w_valid; + assign axi_b_ready_o = axi_write_req.b_ready; + + assign axi_write_rsp.aw_ready = axi_aw_ready_i; + assign axi_write_rsp.w_ready = axi_w_ready_i; + assign axi_write_rsp.b.id = axi_b_id_i; + assign axi_write_rsp.b.resp = axi_b_resp_i; + assign axi_write_rsp.b.user = axi_b_user_i; + assign axi_write_rsp.b_valid = axi_b_valid_i; + + + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "axi_stream/typedef.svh" +`include "idma/typedef.svh" +`include "obi/typedef.svh" +`include "tilelink/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_backend_synth_r_obi_w_axi #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 0, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b0, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// User type (do not override!) + parameter type user_t = logic[UserWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input idma_pkg::protocol_e req_src_protocol_i, + input idma_pkg::protocol_e req_dst_protocol_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output logic obi_read_req_a_req_o, + output addr_t obi_read_req_a_addr_o, + output logic obi_read_req_a_we_o, + output strb_t obi_read_req_a_be_o, + output data_t obi_read_req_a_wdata_o, + output logic obi_read_req_r_ready_o, + + input logic obi_read_rsp_a_gnt_i, + input logic obi_read_rsp_r_valid_i, + input data_t obi_read_rsp_r_rdata_i, + input id_t obi_read_rsp_r_rid_i, + input logic obi_read_rsp_r_err_i, + + + output id_t axi_aw_id_o, + output addr_t axi_aw_addr_o, + output axi_pkg::len_t axi_aw_len_o, + output axi_pkg::size_t axi_aw_size_o, + output axi_pkg::burst_t axi_aw_burst_o, + output logic axi_aw_lock_o, + output axi_pkg::cache_t axi_aw_cache_o, + output axi_pkg::prot_t axi_aw_prot_o, + output axi_pkg::qos_t axi_aw_qos_o, + output axi_pkg::region_t axi_aw_region_o, + output axi_pkg::atop_t axi_aw_atop_o, + output user_t axi_aw_user_o, + output logic axi_aw_valid_o, + input logic axi_aw_ready_i, + output data_t axi_w_data_o, + output strb_t axi_w_strb_o, + output logic axi_w_last_o, + output user_t axi_w_user_o, + output logic axi_w_valid_o, + input logic axi_w_ready_i, + input id_t axi_b_id_i, + input axi_pkg::resp_t axi_b_resp_i, + input user_t axi_b_user_i, + input logic axi_b_valid_i, + output logic axi_b_ready_o, + + + output idma_pkg::idma_busy_t idma_busy_o +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // AXI4+ATOP typedefs +`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) +`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + +`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + +`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) +`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + + // OBI typedefs +`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) +`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) + +`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) +`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + +`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) +`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) + + + // Meta Channel Widths + localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + + typedef struct packed { + obi_a_chan_t a_chan; + } obi_read_meta_channel_t; + + typedef struct packed { + obi_read_meta_channel_t obi; + } read_meta_channel_t; + + typedef struct packed { + axi_aw_chan_t aw_chan; + } axi_write_meta_channel_t; + + typedef struct packed { + axi_write_meta_channel_t axi; + } write_meta_channel_t; + + // local types + // AXI4+ATOP request and response + + axi_req_t axi_write_req; + axi_rsp_t axi_write_rsp; + + // OBI request and response + obi_req_t obi_read_req; + obi_rsp_t obi_read_rsp; + + + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + idma_backend_r_obi_w_axi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .obi_read_req_o ( obi_read_req ), + .obi_read_rsp_i ( obi_read_rsp ), + .axi_write_req_o ( axi_write_req ), + .axi_write_rsp_i ( axi_write_rsp ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.src_protocol = req_src_protocol_i; + assign idma_req.opt.dst_protocol = req_dst_protocol_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + + // OBI Read + assign obi_read_req_a_req_o = obi_read_req.req; + assign obi_read_req_a_addr_o = obi_read_req.a.addr; + assign obi_read_req_a_we_o = obi_read_req.a.we; + assign obi_read_req_a_be_o = obi_read_req.a.be; + assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; + assign obi_read_req_r_ready_o = obi_read_req.rready; + + assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; + assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; + assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; + assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; + assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; + + + + // AXI4+ATOP Write + assign axi_aw_id_o = axi_write_req.aw.id; + assign axi_aw_addr_o = axi_write_req.aw.addr; + assign axi_aw_len_o = axi_write_req.aw.len; + assign axi_aw_size_o = axi_write_req.aw.size; + assign axi_aw_burst_o = axi_write_req.aw.burst; + assign axi_aw_lock_o = axi_write_req.aw.lock; + assign axi_aw_cache_o = axi_write_req.aw.cache; + assign axi_aw_prot_o = axi_write_req.aw.prot; + assign axi_aw_qos_o = axi_write_req.aw.qos; + assign axi_aw_region_o = axi_write_req.aw.region; + assign axi_aw_atop_o = axi_write_req.aw.atop; + assign axi_aw_user_o = axi_write_req.aw.user; + assign axi_aw_valid_o = axi_write_req.aw_valid; + assign axi_w_data_o = axi_write_req.w.data; + assign axi_w_strb_o = axi_write_req.w.strb; + assign axi_w_last_o = axi_write_req.w.last; + assign axi_w_user_o = axi_write_req.w.user; + assign axi_w_valid_o = axi_write_req.w_valid; + assign axi_b_ready_o = axi_write_req.b_ready; + + assign axi_write_rsp.aw_ready = axi_aw_ready_i; + assign axi_write_rsp.w_ready = axi_w_ready_i; + assign axi_write_rsp.b.id = axi_b_id_i; + assign axi_write_rsp.b.resp = axi_b_resp_i; + assign axi_write_rsp.b.user = axi_b_user_i; + assign axi_write_rsp.b_valid = axi_b_valid_i; + + + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "axi_stream/typedef.svh" +`include "idma/typedef.svh" +`include "obi/typedef.svh" +`include "tilelink/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_backend_synth_r_axi_w_obi #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 0, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b0, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// User type (do not override!) + parameter type user_t = logic[UserWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input idma_pkg::protocol_e req_src_protocol_i, + input idma_pkg::protocol_e req_dst_protocol_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output id_t axi_ar_id_o, + output addr_t axi_ar_addr_o, + output axi_pkg::len_t axi_ar_len_o, + output axi_pkg::size_t axi_ar_size_o, + output axi_pkg::burst_t axi_ar_burst_o, + output logic axi_ar_lock_o, + output axi_pkg::cache_t axi_ar_cache_o, + output axi_pkg::prot_t axi_ar_prot_o, + output axi_pkg::qos_t axi_ar_qos_o, + output axi_pkg::region_t axi_ar_region_o, + output user_t axi_ar_user_o, + output logic axi_ar_valid_o, + input logic axi_ar_ready_i, + input id_t axi_r_id_i, + input data_t axi_r_data_i, + input axi_pkg::resp_t axi_r_resp_i, + input logic axi_r_last_i, + input user_t axi_r_user_i, + input logic axi_r_valid_i, + output logic axi_r_ready_o, + + + output logic obi_write_req_a_req_o, + output addr_t obi_write_req_a_addr_o, + output logic obi_write_req_a_we_o, + output strb_t obi_write_req_a_be_o, + output data_t obi_write_req_a_wdata_o, + output id_t obi_write_req_a_aid_o, + output logic obi_write_req_r_ready_o, + + input logic obi_write_rsp_a_gnt_i, + input logic obi_write_rsp_r_valid_i, + input data_t obi_write_rsp_r_rdata_i, + + + output idma_pkg::idma_busy_t idma_busy_o +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // AXI4+ATOP typedefs +`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) +`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + +`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + +`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) +`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + + // OBI typedefs +`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) +`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) + +`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) +`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + +`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) +`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) + + + // Meta Channel Widths + localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + + typedef struct packed { + axi_ar_chan_t ar_chan; + } axi_read_meta_channel_t; + + typedef struct packed { + axi_read_meta_channel_t axi; + } read_meta_channel_t; + + typedef struct packed { + obi_a_chan_t a_chan; + } obi_write_meta_channel_t; + + typedef struct packed { + obi_write_meta_channel_t obi; + } write_meta_channel_t; + + // local types + // AXI4+ATOP request and response + axi_req_t axi_read_req; + axi_rsp_t axi_read_rsp; + + + // OBI request and response + + obi_req_t obi_write_req; + obi_rsp_t obi_write_rsp; + + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + idma_backend_r_axi_w_obi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .axi_read_req_o ( axi_read_req ), + .axi_read_rsp_i ( axi_read_rsp ), + .obi_write_req_o ( obi_write_req ), + .obi_write_rsp_i ( obi_write_rsp ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.src_protocol = req_src_protocol_i; + assign idma_req.opt.dst_protocol = req_dst_protocol_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + + // AXI4+ATOP Read + assign axi_ar_id_o = axi_read_req.ar.id; + assign axi_ar_addr_o = axi_read_req.ar.addr; + assign axi_ar_len_o = axi_read_req.ar.len; + assign axi_ar_size_o = axi_read_req.ar.size; + assign axi_ar_burst_o = axi_read_req.ar.burst; + assign axi_ar_lock_o = axi_read_req.ar.lock; + assign axi_ar_cache_o = axi_read_req.ar.cache; + assign axi_ar_prot_o = axi_read_req.ar.prot; + assign axi_ar_qos_o = axi_read_req.ar.qos; + assign axi_ar_region_o = axi_read_req.ar.region; + assign axi_ar_user_o = axi_read_req.ar.user; + assign axi_ar_valid_o = axi_read_req.ar_valid; + assign axi_r_ready_o = axi_read_req.r_ready; + + assign axi_read_rsp.ar_ready = axi_ar_ready_i; + assign axi_read_rsp.r.id = axi_r_id_i; + assign axi_read_rsp.r.data = axi_r_data_i; + assign axi_read_rsp.r.resp = axi_r_resp_i; + assign axi_read_rsp.r.last = axi_r_last_i; + assign axi_read_rsp.r.user = axi_r_user_i; + assign axi_read_rsp.r_valid = axi_r_valid_i; + + + + // OBI Write + assign obi_write_req_a_req_o = obi_write_req.req; + assign obi_write_req_a_addr_o = obi_write_req.a.addr; + assign obi_write_req_a_we_o = obi_write_req.a.we; + assign obi_write_req_a_be_o = obi_write_req.a.be; + assign obi_write_req_a_wdata_o = obi_write_req.a.wdata; + assign obi_write_req_a_aid_o = obi_write_req.a.aid; + assign obi_write_req_r_ready_o = obi_write_req.rready; + + assign obi_write_rsp.gnt = obi_write_rsp_a_gnt_i; + assign obi_write_rsp.rvalid = obi_write_rsp_r_valid_i; + assign obi_write_rsp.r.rdata = obi_write_rsp_r_rdata_i; + + + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "axi_stream/typedef.svh" +`include "idma/typedef.svh" +`include "obi/typedef.svh" +`include "tilelink/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_backend_synth_rw_axi_rw_axis #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 0, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b0, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// User type (do not override!) + parameter type user_t = logic[UserWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input idma_pkg::protocol_e req_src_protocol_i, + input idma_pkg::protocol_e req_dst_protocol_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output id_t axi_ar_id_o, + output addr_t axi_ar_addr_o, + output axi_pkg::len_t axi_ar_len_o, + output axi_pkg::size_t axi_ar_size_o, + output axi_pkg::burst_t axi_ar_burst_o, + output logic axi_ar_lock_o, + output axi_pkg::cache_t axi_ar_cache_o, + output axi_pkg::prot_t axi_ar_prot_o, + output axi_pkg::qos_t axi_ar_qos_o, + output axi_pkg::region_t axi_ar_region_o, + output user_t axi_ar_user_o, + output logic axi_ar_valid_o, + input logic axi_ar_ready_i, + input id_t axi_r_id_i, + input data_t axi_r_data_i, + input axi_pkg::resp_t axi_r_resp_i, + input logic axi_r_last_i, + input user_t axi_r_user_i, + input logic axi_r_valid_i, + output logic axi_r_ready_o, + + + input data_t axis_read_data_i, + input strb_t axis_read_strb_i, + input strb_t axis_read_keep_i, + input logic axis_read_last_i, + input id_t axis_read_id_i, + input id_t axis_read_dest_i, + input user_t axis_read_user_i, + input logic axis_read_tvalid_i, + + output logic axis_read_tready_o, + + + output id_t axi_aw_id_o, + output addr_t axi_aw_addr_o, + output axi_pkg::len_t axi_aw_len_o, + output axi_pkg::size_t axi_aw_size_o, + output axi_pkg::burst_t axi_aw_burst_o, + output logic axi_aw_lock_o, + output axi_pkg::cache_t axi_aw_cache_o, + output axi_pkg::prot_t axi_aw_prot_o, + output axi_pkg::qos_t axi_aw_qos_o, + output axi_pkg::region_t axi_aw_region_o, + output axi_pkg::atop_t axi_aw_atop_o, + output user_t axi_aw_user_o, + output logic axi_aw_valid_o, + input logic axi_aw_ready_i, + output data_t axi_w_data_o, + output strb_t axi_w_strb_o, + output logic axi_w_last_o, + output user_t axi_w_user_o, + output logic axi_w_valid_o, + input logic axi_w_ready_i, + input id_t axi_b_id_i, + input axi_pkg::resp_t axi_b_resp_i, + input user_t axi_b_user_i, + input logic axi_b_valid_i, + output logic axi_b_ready_o, + + + output data_t axis_write_data_o, + output strb_t axis_write_strb_o, + output strb_t axis_write_keep_o, + output logic axis_write_last_o, + output id_t axis_write_id_o, + output id_t axis_write_dest_o, + output user_t axis_write_user_o, + output logic axis_write_tvalid_o, + + input logic axis_write_tready_i, + + + output idma_pkg::idma_busy_t idma_busy_o +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // AXI4+ATOP typedefs +`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) +`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + +`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + +`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) +`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + + // AXI Stream typedefs +`AXI_STREAM_TYPEDEF_S_CHAN_T(axis_t_chan_t, data_t, strb_t, strb_t, id_t, id_t, user_t) + +`AXI_STREAM_TYPEDEF_REQ_T(axis_req_t, axis_t_chan_t) +`AXI_STREAM_TYPEDEF_RSP_T(axis_rsp_t) + + + // Meta Channel Widths + localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned axis_t_chan_width = $bits(axis_t_chan_t); + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + function int unsigned max_width(input int unsigned a, b); + return (a > b) ? a : b; + endfunction + + typedef struct packed { + axi_ar_chan_t ar_chan; + logic[max_width(axi_ar_chan_width, axis_t_chan_width)-axi_ar_chan_width:0] padding; + } axi_read_ar_chan_padded_t; + + typedef struct packed { + axis_t_chan_t t_chan; + logic[max_width(axi_ar_chan_width, axis_t_chan_width)-axis_t_chan_width:0] padding; + } axis_read_t_chan_padded_t; + + typedef union packed { + axi_read_ar_chan_padded_t axi; + axis_read_t_chan_padded_t axis; + } read_meta_channel_t; + + typedef struct packed { + axi_aw_chan_t aw_chan; + logic[max_width(axi_aw_chan_width, axis_t_chan_width)-axi_aw_chan_width:0] padding; + } axi_write_aw_chan_padded_t; + + typedef struct packed { + axis_t_chan_t t_chan; + logic[max_width(axi_aw_chan_width, axis_t_chan_width)-axis_t_chan_width:0] padding; + } axis_write_t_chan_padded_t; + + typedef union packed { + axi_write_aw_chan_padded_t axi; + axis_write_t_chan_padded_t axis; + } write_meta_channel_t; + + // local types + // AXI4+ATOP request and response + axi_req_t axi_read_req; + axi_rsp_t axi_read_rsp; + + axi_req_t axi_write_req; + axi_rsp_t axi_write_rsp; + + // AXI Stream request and response + axis_req_t axis_read_req; + axis_rsp_t axis_read_rsp; + + axis_req_t axis_write_req; + axis_rsp_t axis_write_rsp; + + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + idma_backend_rw_axi_rw_axis #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .axis_req_t ( axis_req_t ), + .axis_rsp_t ( axis_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .axi_read_req_o ( axi_read_req ), + .axi_read_rsp_i ( axi_read_rsp ), + .axis_read_req_i ( axis_read_req ), + .axis_read_rsp_o ( axis_read_rsp ), + .axi_write_req_o ( axi_write_req ), + .axi_write_rsp_i ( axi_write_rsp ), + .axis_write_req_o ( axis_write_req ), + .axis_write_rsp_i ( axis_write_rsp ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.src_protocol = req_src_protocol_i; + assign idma_req.opt.dst_protocol = req_dst_protocol_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + + // AXI4+ATOP Read + assign axi_ar_id_o = axi_read_req.ar.id; + assign axi_ar_addr_o = axi_read_req.ar.addr; + assign axi_ar_len_o = axi_read_req.ar.len; + assign axi_ar_size_o = axi_read_req.ar.size; + assign axi_ar_burst_o = axi_read_req.ar.burst; + assign axi_ar_lock_o = axi_read_req.ar.lock; + assign axi_ar_cache_o = axi_read_req.ar.cache; + assign axi_ar_prot_o = axi_read_req.ar.prot; + assign axi_ar_qos_o = axi_read_req.ar.qos; + assign axi_ar_region_o = axi_read_req.ar.region; + assign axi_ar_user_o = axi_read_req.ar.user; + assign axi_ar_valid_o = axi_read_req.ar_valid; + assign axi_r_ready_o = axi_read_req.r_ready; + + assign axi_read_rsp.ar_ready = axi_ar_ready_i; + assign axi_read_rsp.r.id = axi_r_id_i; + assign axi_read_rsp.r.data = axi_r_data_i; + assign axi_read_rsp.r.resp = axi_r_resp_i; + assign axi_read_rsp.r.last = axi_r_last_i; + assign axi_read_rsp.r.user = axi_r_user_i; + assign axi_read_rsp.r_valid = axi_r_valid_i; + + + + // AXI Stream Read + assign axis_read_req.t.data = axis_read_data_i; + assign axis_read_req.t.strb = axis_read_strb_i; + assign axis_read_req.t.keep = axis_read_keep_i; + assign axis_read_req.t.last = axis_read_last_i; + assign axis_read_req.t.id = axis_read_id_i; + assign axis_read_req.t.dest = axis_read_dest_i; + assign axis_read_req.t.user = axis_read_user_i; + assign axis_read_req.tvalid = axis_read_tvalid_i; + + assign axis_read_tready_o = axis_read_rsp.tready; + + + + // AXI4+ATOP Write + assign axi_aw_id_o = axi_write_req.aw.id; + assign axi_aw_addr_o = axi_write_req.aw.addr; + assign axi_aw_len_o = axi_write_req.aw.len; + assign axi_aw_size_o = axi_write_req.aw.size; + assign axi_aw_burst_o = axi_write_req.aw.burst; + assign axi_aw_lock_o = axi_write_req.aw.lock; + assign axi_aw_cache_o = axi_write_req.aw.cache; + assign axi_aw_prot_o = axi_write_req.aw.prot; + assign axi_aw_qos_o = axi_write_req.aw.qos; + assign axi_aw_region_o = axi_write_req.aw.region; + assign axi_aw_atop_o = axi_write_req.aw.atop; + assign axi_aw_user_o = axi_write_req.aw.user; + assign axi_aw_valid_o = axi_write_req.aw_valid; + assign axi_w_data_o = axi_write_req.w.data; + assign axi_w_strb_o = axi_write_req.w.strb; + assign axi_w_last_o = axi_write_req.w.last; + assign axi_w_user_o = axi_write_req.w.user; + assign axi_w_valid_o = axi_write_req.w_valid; + assign axi_b_ready_o = axi_write_req.b_ready; + + assign axi_write_rsp.aw_ready = axi_aw_ready_i; + assign axi_write_rsp.w_ready = axi_w_ready_i; + assign axi_write_rsp.b.id = axi_b_id_i; + assign axi_write_rsp.b.resp = axi_b_resp_i; + assign axi_write_rsp.b.user = axi_b_user_i; + assign axi_write_rsp.b_valid = axi_b_valid_i; + + + + // AXI Stream Write + assign axis_write_data_o = axis_write_req.t.data; + assign axis_write_strb_o = axis_write_req.t.strb; + assign axis_write_keep_o = axis_write_req.t.keep; + assign axis_write_last_o = axis_write_req.t.last; + assign axis_write_id_o = axis_write_req.t.id; + assign axis_write_dest_o = axis_write_req.t.dest; + assign axis_write_user_o = axis_write_req.t.user; + assign axis_write_tvalid_o = axis_write_req.tvalid; + + assign axis_write_rsp.tready = axis_write_tready_i; + + + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "axi_stream/typedef.svh" +`include "idma/typedef.svh" +`include "obi/typedef.svh" +`include "tilelink/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_backend_synth_rw_axi_rw_obi #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 0, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b0, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// User type (do not override!) + parameter type user_t = logic[UserWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input idma_pkg::protocol_e req_src_protocol_i, + input idma_pkg::protocol_e req_dst_protocol_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output id_t axi_ar_id_o, + output addr_t axi_ar_addr_o, + output axi_pkg::len_t axi_ar_len_o, + output axi_pkg::size_t axi_ar_size_o, + output axi_pkg::burst_t axi_ar_burst_o, + output logic axi_ar_lock_o, + output axi_pkg::cache_t axi_ar_cache_o, + output axi_pkg::prot_t axi_ar_prot_o, + output axi_pkg::qos_t axi_ar_qos_o, + output axi_pkg::region_t axi_ar_region_o, + output user_t axi_ar_user_o, + output logic axi_ar_valid_o, + input logic axi_ar_ready_i, + input id_t axi_r_id_i, + input data_t axi_r_data_i, + input axi_pkg::resp_t axi_r_resp_i, + input logic axi_r_last_i, + input user_t axi_r_user_i, + input logic axi_r_valid_i, + output logic axi_r_ready_o, + + + output logic obi_read_req_a_req_o, + output addr_t obi_read_req_a_addr_o, + output logic obi_read_req_a_we_o, + output strb_t obi_read_req_a_be_o, + output data_t obi_read_req_a_wdata_o, + output logic obi_read_req_r_ready_o, + + input logic obi_read_rsp_a_gnt_i, + input logic obi_read_rsp_r_valid_i, + input data_t obi_read_rsp_r_rdata_i, + input id_t obi_read_rsp_r_rid_i, + input logic obi_read_rsp_r_err_i, + + + output id_t axi_aw_id_o, + output addr_t axi_aw_addr_o, + output axi_pkg::len_t axi_aw_len_o, + output axi_pkg::size_t axi_aw_size_o, + output axi_pkg::burst_t axi_aw_burst_o, + output logic axi_aw_lock_o, + output axi_pkg::cache_t axi_aw_cache_o, + output axi_pkg::prot_t axi_aw_prot_o, + output axi_pkg::qos_t axi_aw_qos_o, + output axi_pkg::region_t axi_aw_region_o, + output axi_pkg::atop_t axi_aw_atop_o, + output user_t axi_aw_user_o, + output logic axi_aw_valid_o, + input logic axi_aw_ready_i, + output data_t axi_w_data_o, + output strb_t axi_w_strb_o, + output logic axi_w_last_o, + output user_t axi_w_user_o, + output logic axi_w_valid_o, + input logic axi_w_ready_i, + input id_t axi_b_id_i, + input axi_pkg::resp_t axi_b_resp_i, + input user_t axi_b_user_i, + input logic axi_b_valid_i, + output logic axi_b_ready_o, + + + output logic obi_write_req_a_req_o, + output addr_t obi_write_req_a_addr_o, + output logic obi_write_req_a_we_o, + output strb_t obi_write_req_a_be_o, + output data_t obi_write_req_a_wdata_o, + output id_t obi_write_req_a_aid_o, + output logic obi_write_req_r_ready_o, + + input logic obi_write_rsp_a_gnt_i, + input logic obi_write_rsp_r_valid_i, + input data_t obi_write_rsp_r_rdata_i, + + + output idma_pkg::idma_busy_t idma_busy_o +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // AXI4+ATOP typedefs +`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) +`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + +`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + +`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) +`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + + // OBI typedefs +`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) +`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) + +`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) +`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + +`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) +`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) + + + // Meta Channel Widths + localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + function int unsigned max_width(input int unsigned a, b); + return (a > b) ? a : b; + endfunction + + typedef struct packed { + axi_ar_chan_t ar_chan; + logic[max_width(axi_ar_chan_width, obi_a_chan_width)-axi_ar_chan_width:0] padding; + } axi_read_ar_chan_padded_t; + + typedef struct packed { + obi_a_chan_t a_chan; + logic[max_width(axi_ar_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + } obi_read_a_chan_padded_t; + + typedef union packed { + axi_read_ar_chan_padded_t axi; + obi_read_a_chan_padded_t obi; + } read_meta_channel_t; + + typedef struct packed { + axi_aw_chan_t aw_chan; + logic[max_width(axi_aw_chan_width, obi_a_chan_width)-axi_aw_chan_width:0] padding; + } axi_write_aw_chan_padded_t; + + typedef struct packed { + obi_a_chan_t a_chan; + logic[max_width(axi_aw_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + } obi_write_a_chan_padded_t; + + typedef union packed { + axi_write_aw_chan_padded_t axi; + obi_write_a_chan_padded_t obi; + } write_meta_channel_t; + + // local types + // AXI4+ATOP request and response + axi_req_t axi_read_req; + axi_rsp_t axi_read_rsp; + + axi_req_t axi_write_req; + axi_rsp_t axi_write_rsp; + + // OBI request and response + obi_req_t obi_read_req; + obi_rsp_t obi_read_rsp; + + obi_req_t obi_write_req; + obi_rsp_t obi_write_rsp; + + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + idma_backend_rw_axi_rw_obi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .axi_read_req_o ( axi_read_req ), + .axi_read_rsp_i ( axi_read_rsp ), + .obi_read_req_o ( obi_read_req ), + .obi_read_rsp_i ( obi_read_rsp ), + .axi_write_req_o ( axi_write_req ), + .axi_write_rsp_i ( axi_write_rsp ), + .obi_write_req_o ( obi_write_req ), + .obi_write_rsp_i ( obi_write_rsp ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.src_protocol = req_src_protocol_i; + assign idma_req.opt.dst_protocol = req_dst_protocol_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + + // AXI4+ATOP Read + assign axi_ar_id_o = axi_read_req.ar.id; + assign axi_ar_addr_o = axi_read_req.ar.addr; + assign axi_ar_len_o = axi_read_req.ar.len; + assign axi_ar_size_o = axi_read_req.ar.size; + assign axi_ar_burst_o = axi_read_req.ar.burst; + assign axi_ar_lock_o = axi_read_req.ar.lock; + assign axi_ar_cache_o = axi_read_req.ar.cache; + assign axi_ar_prot_o = axi_read_req.ar.prot; + assign axi_ar_qos_o = axi_read_req.ar.qos; + assign axi_ar_region_o = axi_read_req.ar.region; + assign axi_ar_user_o = axi_read_req.ar.user; + assign axi_ar_valid_o = axi_read_req.ar_valid; + assign axi_r_ready_o = axi_read_req.r_ready; + + assign axi_read_rsp.ar_ready = axi_ar_ready_i; + assign axi_read_rsp.r.id = axi_r_id_i; + assign axi_read_rsp.r.data = axi_r_data_i; + assign axi_read_rsp.r.resp = axi_r_resp_i; + assign axi_read_rsp.r.last = axi_r_last_i; + assign axi_read_rsp.r.user = axi_r_user_i; + assign axi_read_rsp.r_valid = axi_r_valid_i; + + + + // OBI Read + assign obi_read_req_a_req_o = obi_read_req.req; + assign obi_read_req_a_addr_o = obi_read_req.a.addr; + assign obi_read_req_a_we_o = obi_read_req.a.we; + assign obi_read_req_a_be_o = obi_read_req.a.be; + assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; + assign obi_read_req_r_ready_o = obi_read_req.rready; + + assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; + assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; + assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; + assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; + assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; + + + + // AXI4+ATOP Write + assign axi_aw_id_o = axi_write_req.aw.id; + assign axi_aw_addr_o = axi_write_req.aw.addr; + assign axi_aw_len_o = axi_write_req.aw.len; + assign axi_aw_size_o = axi_write_req.aw.size; + assign axi_aw_burst_o = axi_write_req.aw.burst; + assign axi_aw_lock_o = axi_write_req.aw.lock; + assign axi_aw_cache_o = axi_write_req.aw.cache; + assign axi_aw_prot_o = axi_write_req.aw.prot; + assign axi_aw_qos_o = axi_write_req.aw.qos; + assign axi_aw_region_o = axi_write_req.aw.region; + assign axi_aw_atop_o = axi_write_req.aw.atop; + assign axi_aw_user_o = axi_write_req.aw.user; + assign axi_aw_valid_o = axi_write_req.aw_valid; + assign axi_w_data_o = axi_write_req.w.data; + assign axi_w_strb_o = axi_write_req.w.strb; + assign axi_w_last_o = axi_write_req.w.last; + assign axi_w_user_o = axi_write_req.w.user; + assign axi_w_valid_o = axi_write_req.w_valid; + assign axi_b_ready_o = axi_write_req.b_ready; + + assign axi_write_rsp.aw_ready = axi_aw_ready_i; + assign axi_write_rsp.w_ready = axi_w_ready_i; + assign axi_write_rsp.b.id = axi_b_id_i; + assign axi_write_rsp.b.resp = axi_b_resp_i; + assign axi_write_rsp.b.user = axi_b_user_i; + assign axi_write_rsp.b_valid = axi_b_valid_i; + + + + // OBI Write + assign obi_write_req_a_req_o = obi_write_req.req; + assign obi_write_req_a_addr_o = obi_write_req.a.addr; + assign obi_write_req_a_we_o = obi_write_req.a.we; + assign obi_write_req_a_be_o = obi_write_req.a.be; + assign obi_write_req_a_wdata_o = obi_write_req.a.wdata; + assign obi_write_req_a_aid_o = obi_write_req.a.aid; + assign obi_write_req_r_ready_o = obi_write_req.rready; + + assign obi_write_rsp.gnt = obi_write_rsp_a_gnt_i; + assign obi_write_rsp.rvalid = obi_write_rsp_r_valid_i; + assign obi_write_rsp.r.rdata = obi_write_rsp_r_rdata_i; + + + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "axi_stream/typedef.svh" +`include "idma/typedef.svh" +`include "obi/typedef.svh" +`include "tilelink/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_backend_synth_r_obi_rw_init_w_axi #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 0, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b0, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// User type (do not override!) + parameter type user_t = logic[UserWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input idma_pkg::protocol_e req_src_protocol_i, + input idma_pkg::protocol_e req_dst_protocol_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output logic init_read_req_valid_o, + output addr_t init_read_req_config_o, + input logic init_read_req_ready_i, + + input logic init_read_rsp_valid_i, + input data_t init_read_rsp_init_i, + output logic init_read_rsp_ready_o, + + + output logic obi_read_req_a_req_o, + output addr_t obi_read_req_a_addr_o, + output logic obi_read_req_a_we_o, + output strb_t obi_read_req_a_be_o, + output data_t obi_read_req_a_wdata_o, + output logic obi_read_req_r_ready_o, + + input logic obi_read_rsp_a_gnt_i, + input logic obi_read_rsp_r_valid_i, + input data_t obi_read_rsp_r_rdata_i, + input id_t obi_read_rsp_r_rid_i, + input logic obi_read_rsp_r_err_i, + + + output id_t axi_aw_id_o, + output addr_t axi_aw_addr_o, + output axi_pkg::len_t axi_aw_len_o, + output axi_pkg::size_t axi_aw_size_o, + output axi_pkg::burst_t axi_aw_burst_o, + output logic axi_aw_lock_o, + output axi_pkg::cache_t axi_aw_cache_o, + output axi_pkg::prot_t axi_aw_prot_o, + output axi_pkg::qos_t axi_aw_qos_o, + output axi_pkg::region_t axi_aw_region_o, + output axi_pkg::atop_t axi_aw_atop_o, + output user_t axi_aw_user_o, + output logic axi_aw_valid_o, + input logic axi_aw_ready_i, + output data_t axi_w_data_o, + output strb_t axi_w_strb_o, + output logic axi_w_last_o, + output user_t axi_w_user_o, + output logic axi_w_valid_o, + input logic axi_w_ready_i, + input id_t axi_b_id_i, + input axi_pkg::resp_t axi_b_resp_i, + input user_t axi_b_user_i, + input logic axi_b_valid_i, + output logic axi_b_ready_o, + + + output logic init_write_req_valid_o, + output addr_t init_write_req_cfg_o, + output data_t init_write_req_term_o, + output strb_t init_write_req_strb_o, + output id_t init_write_req_id_o, + input logic init_write_req_ready_i, + + input logic init_write_rsp_valid_i, + output logic init_write_rsp_ready_o, + + + output idma_pkg::idma_busy_t idma_busy_o +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // AXI4+ATOP typedefs +`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) +`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + +`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + +`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) +`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + + // Memory Init typedefs +/// init read request +typedef struct packed { + logic [AddrWidth-1:0] cfg; + logic [DataWidth-1:0] term; + logic [StrbWidth-1:0] strb; + logic [AxiIdWidth-1:0] id; +} init_req_chan_t; + +typedef struct packed { + init_req_chan_t req_chan; + logic req_valid; + logic rsp_ready; +} init_req_t; + +typedef struct packed { + logic [DataWidth-1:0] init; +} init_rsp_chan_t; + +typedef struct packed { + init_rsp_chan_t rsp_chan; + logic rsp_valid; + logic req_ready; +} init_rsp_t; + + + // OBI typedefs +`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) +`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) + +`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) +`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + +`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) +`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) + + + // Meta Channel Widths + localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); + localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + function int unsigned max_width(input int unsigned a, b); + return (a > b) ? a : b; + endfunction + + typedef struct packed { + init_req_chan_t req_chan; + logic[max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; + } init_read_req_chan_padded_t; + + typedef struct packed { + obi_a_chan_t a_chan; + logic[max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + } obi_read_a_chan_padded_t; + + typedef union packed { + init_read_req_chan_padded_t init; + obi_read_a_chan_padded_t obi; + } read_meta_channel_t; + + typedef struct packed { + axi_aw_chan_t aw_chan; + logic[max_width(axi_aw_chan_width, init_req_chan_width)-axi_aw_chan_width:0] padding; + } axi_write_aw_chan_padded_t; + + typedef struct packed { + init_req_chan_t req_chan; + logic[max_width(axi_aw_chan_width, init_req_chan_width)-init_req_chan_width:0] padding; + } init_write_req_chan_padded_t; + + typedef union packed { + axi_write_aw_chan_padded_t axi; + init_write_req_chan_padded_t init; + } write_meta_channel_t; + + // local types + // AXI4+ATOP request and response + + axi_req_t axi_write_req; + axi_rsp_t axi_write_rsp; + + // Memory Init request and response + init_req_t init_read_req; + init_rsp_t init_read_rsp; + + init_req_t init_write_req; + init_rsp_t init_write_rsp; + + // OBI request and response + obi_req_t obi_read_req; + obi_rsp_t obi_read_rsp; + + + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + idma_backend_r_obi_rw_init_w_axi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .init_req_t ( init_req_t ), + .init_rsp_t ( init_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .init_read_req_o ( init_read_req ), + .init_read_rsp_i ( init_read_rsp ), + .obi_read_req_o ( obi_read_req ), + .obi_read_rsp_i ( obi_read_rsp ), + .axi_write_req_o ( axi_write_req ), + .axi_write_rsp_i ( axi_write_rsp ), + .init_write_req_o ( init_write_req ), + .init_write_rsp_i ( init_write_rsp ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.src_protocol = req_src_protocol_i; + assign idma_req.opt.dst_protocol = req_dst_protocol_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + + // Memory Init Read + assign init_read_req_valid_o = init_read_req.req_valid; + assign init_read_req_config_o = init_read_req.req_chan.cfg; + assign init_read_rsp.req_ready = init_read_req_ready_i; + + assign init_read_rsp.rsp_valid = init_read_rsp_valid_i; + assign init_read_rsp.rsp_chan.init = init_read_rsp_init_i; + assign init_read_rsp_ready_o = init_read_req.rsp_ready; + + + + // OBI Read + assign obi_read_req_a_req_o = obi_read_req.req; + assign obi_read_req_a_addr_o = obi_read_req.a.addr; + assign obi_read_req_a_we_o = obi_read_req.a.we; + assign obi_read_req_a_be_o = obi_read_req.a.be; + assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; + assign obi_read_req_r_ready_o = obi_read_req.rready; + + assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; + assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; + assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; + assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; + assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; + + + + // AXI4+ATOP Write + assign axi_aw_id_o = axi_write_req.aw.id; + assign axi_aw_addr_o = axi_write_req.aw.addr; + assign axi_aw_len_o = axi_write_req.aw.len; + assign axi_aw_size_o = axi_write_req.aw.size; + assign axi_aw_burst_o = axi_write_req.aw.burst; + assign axi_aw_lock_o = axi_write_req.aw.lock; + assign axi_aw_cache_o = axi_write_req.aw.cache; + assign axi_aw_prot_o = axi_write_req.aw.prot; + assign axi_aw_qos_o = axi_write_req.aw.qos; + assign axi_aw_region_o = axi_write_req.aw.region; + assign axi_aw_atop_o = axi_write_req.aw.atop; + assign axi_aw_user_o = axi_write_req.aw.user; + assign axi_aw_valid_o = axi_write_req.aw_valid; + assign axi_w_data_o = axi_write_req.w.data; + assign axi_w_strb_o = axi_write_req.w.strb; + assign axi_w_last_o = axi_write_req.w.last; + assign axi_w_user_o = axi_write_req.w.user; + assign axi_w_valid_o = axi_write_req.w_valid; + assign axi_b_ready_o = axi_write_req.b_ready; + + assign axi_write_rsp.aw_ready = axi_aw_ready_i; + assign axi_write_rsp.w_ready = axi_w_ready_i; + assign axi_write_rsp.b.id = axi_b_id_i; + assign axi_write_rsp.b.resp = axi_b_resp_i; + assign axi_write_rsp.b.user = axi_b_user_i; + assign axi_write_rsp.b_valid = axi_b_valid_i; + + + + // Memory Init Write + assign init_write_req_valid_o = init_write_req.req_valid; + assign init_write_req_cfg_o = init_write_req.req_chan.cfg; + assign init_write_req_term_o = init_write_req.req_chan.term; + assign init_write_req_strb_o = init_write_req.req_chan.strb; + assign init_write_req_id_o = init_write_req.req_chan.id; + assign init_write_rsp.req_ready = init_write_req_ready_i; + + assign init_write_rsp.rsp_valid = init_write_rsp_valid_i; + assign init_write_rsp_ready_o = init_write_req.rsp_ready; + + + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti + +`include "axi/typedef.svh" +`include "axi_stream/typedef.svh" +`include "idma/typedef.svh" +`include "obi/typedef.svh" +`include "tilelink/typedef.svh" + +/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors +module idma_backend_synth_r_axi_rw_init_rw_obi #( + /// Data width + parameter int unsigned DataWidth = 32'd32, + /// Address width + parameter int unsigned AddrWidth = 32'd32, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd3, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd3, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd32, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 0, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter bit ErrorHandling = 1'b0, + // Dependent parameters; do not override! + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth), + /// Address type (do not override!) + parameter type addr_t = logic[AddrWidth-1:0], + /// Data type (do not override!) + parameter type data_t = logic[DataWidth-1:0], + /// Strobe type (do not override!) + parameter type strb_t = logic[StrbWidth-1:0], + /// User type (do not override!) + parameter type user_t = logic[UserWidth-1:0], + /// ID type (do not override!) + parameter type id_t = logic[AxiIdWidth-1:0], + /// Transfer length type (do not override!) + parameter type tf_len_t = logic[TFLenWidth-1:0], + /// Offset type (do not override!) + parameter type offset_t = logic[OffsetWidth-1:0] +)( + input logic clk_i, + input logic rst_ni, + input logic test_i, + + input logic req_valid_i, + output logic req_ready_o, + + input tf_len_t req_length_i, + input addr_t req_src_addr_i, + input addr_t req_dst_addr_i, + input idma_pkg::protocol_e req_src_protocol_i, + input idma_pkg::protocol_e req_dst_protocol_i, + input id_t req_axi_id_i, + input axi_pkg::burst_t req_src_burst_i, + input axi_pkg::cache_t req_src_cache_i, + input logic req_src_lock_i, + input axi_pkg::prot_t req_src_prot_i, + input axi_pkg::qos_t req_src_qos_i, + input axi_pkg::region_t req_src_region_i, + input axi_pkg::burst_t req_dst_burst_i, + input axi_pkg::cache_t req_dst_cache_i, + input logic req_dst_lock_i, + input axi_pkg::prot_t req_dst_prot_i, + input axi_pkg::qos_t req_dst_qos_i, + input axi_pkg::region_t req_dst_region_i, + input logic req_decouple_aw_i, + input logic req_decouple_rw_i, + input logic [2:0] req_src_max_llen_i, + input logic [2:0] req_dst_max_llen_i, + input logic req_src_reduce_len_i, + input logic req_dst_reduce_len_i, + input logic req_last_i, + + output logic rsp_valid_o, + input logic rsp_ready_i, + + output axi_pkg::resp_t rsp_cause_o, + output idma_pkg::err_type_t rsp_err_type_o, + output addr_t rsp_burst_addr_o, + output logic rsp_error_o, + output logic rsp_last_o, + + input logic eh_req_valid_i, + output logic eh_req_ready_o, + input idma_pkg::idma_eh_req_t eh_req_i, + + output id_t axi_ar_id_o, + output addr_t axi_ar_addr_o, + output axi_pkg::len_t axi_ar_len_o, + output axi_pkg::size_t axi_ar_size_o, + output axi_pkg::burst_t axi_ar_burst_o, + output logic axi_ar_lock_o, + output axi_pkg::cache_t axi_ar_cache_o, + output axi_pkg::prot_t axi_ar_prot_o, + output axi_pkg::qos_t axi_ar_qos_o, + output axi_pkg::region_t axi_ar_region_o, + output user_t axi_ar_user_o, + output logic axi_ar_valid_o, + input logic axi_ar_ready_i, + input id_t axi_r_id_i, + input data_t axi_r_data_i, + input axi_pkg::resp_t axi_r_resp_i, + input logic axi_r_last_i, + input user_t axi_r_user_i, + input logic axi_r_valid_i, + output logic axi_r_ready_o, + + + output logic init_read_req_valid_o, + output addr_t init_read_req_config_o, + input logic init_read_req_ready_i, + + input logic init_read_rsp_valid_i, + input data_t init_read_rsp_init_i, + output logic init_read_rsp_ready_o, + + + output logic obi_read_req_a_req_o, + output addr_t obi_read_req_a_addr_o, + output logic obi_read_req_a_we_o, + output strb_t obi_read_req_a_be_o, + output data_t obi_read_req_a_wdata_o, + output logic obi_read_req_r_ready_o, + + input logic obi_read_rsp_a_gnt_i, + input logic obi_read_rsp_r_valid_i, + input data_t obi_read_rsp_r_rdata_i, + input id_t obi_read_rsp_r_rid_i, + input logic obi_read_rsp_r_err_i, + + + output logic init_write_req_valid_o, + output addr_t init_write_req_cfg_o, + output data_t init_write_req_term_o, + output strb_t init_write_req_strb_o, + output id_t init_write_req_id_o, + input logic init_write_req_ready_i, + + input logic init_write_rsp_valid_i, + output logic init_write_rsp_ready_o, + + + output logic obi_write_req_a_req_o, + output addr_t obi_write_req_a_addr_o, + output logic obi_write_req_a_we_o, + output strb_t obi_write_req_a_be_o, + output data_t obi_write_req_a_wdata_o, + output id_t obi_write_req_a_aid_o, + output logic obi_write_req_r_ready_o, + + input logic obi_write_rsp_a_gnt_i, + input logic obi_write_rsp_r_valid_i, + input data_t obi_write_rsp_r_rdata_i, + + + output idma_pkg::idma_busy_t idma_busy_o +); + + /// Define the error handling capability + localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : + idma_pkg::NO_ERROR_HANDLING; + + // AXI4+ATOP typedefs +`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) +`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + +`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) +`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) + +`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) +`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) + + + // Memory Init typedefs +/// init read request +typedef struct packed { + logic [AddrWidth-1:0] cfg; + logic [DataWidth-1:0] term; + logic [StrbWidth-1:0] strb; + logic [AxiIdWidth-1:0] id; +} init_req_chan_t; + +typedef struct packed { + init_req_chan_t req_chan; + logic req_valid; + logic rsp_ready; +} init_req_t; + +typedef struct packed { + logic [DataWidth-1:0] init; +} init_rsp_chan_t; + +typedef struct packed { + init_rsp_chan_t rsp_chan; + logic rsp_valid; + logic req_ready; +} init_rsp_t; + + + // OBI typedefs +`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) +`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) + +`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) +`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + +`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) +`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) + + + // Meta Channel Widths + localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); + localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + + /// Option struct: AXI4 id as well as AXI and backend options + /// - `last`: a flag can be set if this transfer is the last of a set of transfers + `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) + + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) + + /// 1D iDMA response payload: + /// - `cause`: the AXI response + /// - `err_type`: type of the error: read, write, internal, ... + /// - `burst_addr`: the burst address where the issue error occurred + `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) + + /// 1D iDMA response type: + /// - `last`: the response of the request that was marked with the `opt.last` flag + /// - `error`: 1 if an error occurred + /// - `pld`: the error payload + `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) + + function int unsigned max_width(input int unsigned a, b); + return (a > b) ? a : b; + endfunction + + typedef struct packed { + axi_ar_chan_t ar_chan; + logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-axi_ar_chan_width:0] padding; + } axi_read_ar_chan_padded_t; + + typedef struct packed { + init_req_chan_t req_chan; + logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-init_req_chan_width:0] padding; + } init_read_req_chan_padded_t; + + typedef struct packed { + obi_a_chan_t a_chan; + logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-obi_a_chan_width:0] padding; + } obi_read_a_chan_padded_t; + + typedef union packed { + axi_read_ar_chan_padded_t axi; + init_read_req_chan_padded_t init; + obi_read_a_chan_padded_t obi; + } read_meta_channel_t; + + typedef struct packed { + init_req_chan_t req_chan; + logic[max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; + } init_write_req_chan_padded_t; + + typedef struct packed { + obi_a_chan_t a_chan; + logic[max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + } obi_write_a_chan_padded_t; + + typedef union packed { + init_write_req_chan_padded_t init; + obi_write_a_chan_padded_t obi; + } write_meta_channel_t; + + // local types + // AXI4+ATOP request and response + axi_req_t axi_read_req; + axi_rsp_t axi_read_rsp; + + + // Memory Init request and response + init_req_t init_read_req; + init_rsp_t init_read_rsp; + + init_req_t init_write_req; + init_rsp_t init_write_rsp; + + // OBI request and response + obi_req_t obi_read_req; + obi_rsp_t obi_read_rsp; + + obi_req_t obi_write_req; + obi_rsp_t obi_write_rsp; + + idma_req_t idma_req; + idma_rsp_t idma_rsp; + + idma_backend_r_axi_rw_init_rw_obi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .AxiIdWidth ( AxiIdWidth ), + .UserWidth ( UserWidth ), + .TFLenWidth ( TFLenWidth ), + .MaskInvalidData ( MaskInvalidData ), + .BufferDepth ( BufferDepth ), + .NumAxInFlight ( NumAxInFlight ), + .MemSysDepth ( MemSysDepth ), + .RAWCouplingAvail ( RAWCouplingAvail ), + .HardwareLegalizer ( HardwareLegalizer ), + .RejectZeroTransfers ( RejectZeroTransfers ), + .ErrorCap ( ErrorCap ), + .idma_req_t ( idma_req_t ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), + .idma_busy_t ( idma_pkg::idma_busy_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .init_req_t ( init_req_t ), + .init_rsp_t ( init_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ) + ) i_idma_backend ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( test_i ), + .idma_req_i ( idma_req ), + .req_valid_i ( req_valid_i ), + .req_ready_o ( req_ready_o ), + .idma_rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid_o ), + .rsp_ready_i ( rsp_ready_i ), + .idma_eh_req_i ( eh_req_i ), + .eh_req_valid_i ( eh_req_valid_i ), + .eh_req_ready_o ( eh_req_ready_o ), + .axi_read_req_o ( axi_read_req ), + .axi_read_rsp_i ( axi_read_rsp ), + .init_read_req_o ( init_read_req ), + .init_read_rsp_i ( init_read_rsp ), + .obi_read_req_o ( obi_read_req ), + .obi_read_rsp_i ( obi_read_rsp ), + .init_write_req_o ( init_write_req ), + .init_write_rsp_i ( init_write_rsp ), + .obi_write_req_o ( obi_write_req ), + .obi_write_rsp_i ( obi_write_rsp ), + .busy_o ( idma_busy_o ) + ); + + // flatten structs + assign idma_req.dst_addr = req_dst_addr_i; + assign idma_req.src_addr = req_src_addr_i; + assign idma_req.length = req_length_i; + assign idma_req.opt.src_protocol = req_src_protocol_i; + assign idma_req.opt.dst_protocol = req_dst_protocol_i; + assign idma_req.opt.axi_id = req_axi_id_i; + assign idma_req.opt.dst.cache = req_dst_cache_i; + assign idma_req.opt.dst.burst = req_dst_burst_i; + assign idma_req.opt.dst.qos = req_dst_qos_i; + assign idma_req.opt.dst.lock = req_dst_lock_i; + assign idma_req.opt.dst.prot = req_dst_prot_i; + assign idma_req.opt.dst.region = req_dst_region_i; + assign idma_req.opt.src.cache = req_src_cache_i; + assign idma_req.opt.src.burst = req_src_burst_i; + assign idma_req.opt.src.qos = req_src_qos_i; + assign idma_req.opt.src.lock = req_src_lock_i; + assign idma_req.opt.src.prot = req_src_prot_i; + assign idma_req.opt.src.region = req_src_region_i; + assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; + assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; + assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; + assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; + assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; + assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; + assign idma_req.opt.last = req_last_i; + + assign rsp_cause_o = idma_rsp.pld.cause; + assign rsp_err_type_o = idma_rsp.pld.err_type; + assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; + assign rsp_error_o = idma_rsp.error; + assign rsp_last_o = idma_rsp.last; + + + // AXI4+ATOP Read + assign axi_ar_id_o = axi_read_req.ar.id; + assign axi_ar_addr_o = axi_read_req.ar.addr; + assign axi_ar_len_o = axi_read_req.ar.len; + assign axi_ar_size_o = axi_read_req.ar.size; + assign axi_ar_burst_o = axi_read_req.ar.burst; + assign axi_ar_lock_o = axi_read_req.ar.lock; + assign axi_ar_cache_o = axi_read_req.ar.cache; + assign axi_ar_prot_o = axi_read_req.ar.prot; + assign axi_ar_qos_o = axi_read_req.ar.qos; + assign axi_ar_region_o = axi_read_req.ar.region; + assign axi_ar_user_o = axi_read_req.ar.user; + assign axi_ar_valid_o = axi_read_req.ar_valid; + assign axi_r_ready_o = axi_read_req.r_ready; + + assign axi_read_rsp.ar_ready = axi_ar_ready_i; + assign axi_read_rsp.r.id = axi_r_id_i; + assign axi_read_rsp.r.data = axi_r_data_i; + assign axi_read_rsp.r.resp = axi_r_resp_i; + assign axi_read_rsp.r.last = axi_r_last_i; + assign axi_read_rsp.r.user = axi_r_user_i; + assign axi_read_rsp.r_valid = axi_r_valid_i; + + + + // Memory Init Read + assign init_read_req_valid_o = init_read_req.req_valid; + assign init_read_req_config_o = init_read_req.req_chan.cfg; + assign init_read_rsp.req_ready = init_read_req_ready_i; + + assign init_read_rsp.rsp_valid = init_read_rsp_valid_i; + assign init_read_rsp.rsp_chan.init = init_read_rsp_init_i; + assign init_read_rsp_ready_o = init_read_req.rsp_ready; + + + + // OBI Read + assign obi_read_req_a_req_o = obi_read_req.req; + assign obi_read_req_a_addr_o = obi_read_req.a.addr; + assign obi_read_req_a_we_o = obi_read_req.a.we; + assign obi_read_req_a_be_o = obi_read_req.a.be; + assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; + assign obi_read_req_r_ready_o = obi_read_req.rready; + + assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; + assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; + assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; + assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; + assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; + + + + // Memory Init Write + assign init_write_req_valid_o = init_write_req.req_valid; + assign init_write_req_cfg_o = init_write_req.req_chan.cfg; + assign init_write_req_term_o = init_write_req.req_chan.term; + assign init_write_req_strb_o = init_write_req.req_chan.strb; + assign init_write_req_id_o = init_write_req.req_chan.id; + assign init_write_rsp.req_ready = init_write_req_ready_i; + + assign init_write_rsp.rsp_valid = init_write_rsp_valid_i; + assign init_write_rsp_ready_o = init_write_req.rsp_ready; + + + + // OBI Write + assign obi_write_req_a_req_o = obi_write_req.req; + assign obi_write_req_a_addr_o = obi_write_req.a.addr; + assign obi_write_req_a_we_o = obi_write_req.a.we; + assign obi_write_req_a_be_o = obi_write_req.a.be; + assign obi_write_req_a_wdata_o = obi_write_req.a.wdata; + assign obi_write_req_a_aid_o = obi_write_req.a.aid; + assign obi_write_req_r_ready_o = obi_write_req.rready; + + assign obi_write_rsp.gnt = obi_write_rsp_a_gnt_i; + assign obi_write_rsp.rvalid = obi_write_rsp_r_valid_i; + assign obi_write_rsp.r.rdata = obi_write_rsp_r_rdata_i; + + + +endmodule + +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package idma_desc64_reg_pkg; + + // Address widths within the block + parameter int BlockAw = 4; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + logic [63:0] q; + logic qe; + } idma_desc64_reg2hw_desc_addr_reg_t; + + typedef struct packed { + struct packed { + logic d; + logic de; + } busy; + struct packed { + logic d; + logic de; + } fifo_full; + } idma_desc64_hw2reg_status_reg_t; + + // Register -> HW type + typedef struct packed { + idma_desc64_reg2hw_desc_addr_reg_t desc_addr; // [64:0] + } idma_desc64_reg2hw_t; + + // HW -> register type + typedef struct packed { + idma_desc64_hw2reg_status_reg_t status; // [3:0] + } idma_desc64_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] IDMA_DESC64_DESC_ADDR_OFFSET = 4'h 0; + parameter logic [BlockAw-1:0] IDMA_DESC64_STATUS_OFFSET = 4'h 8; + + // Register index + typedef enum int { + IDMA_DESC64_DESC_ADDR, + IDMA_DESC64_STATUS + } idma_desc64_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] IDMA_DESC64_PERMIT [2] = '{ + 4'b 1111, // index[0] IDMA_DESC64_DESC_ADDR + 4'b 0001 // index[1] IDMA_DESC64_STATUS + }; + +endpackage + +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package idma_reg32_3d_reg_pkg; + + // Param list + parameter int num_dims = 3; + + // Address widths within the block + parameter int BlockAw = 9; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + struct packed { + logic q; + } decouple_aw; + struct packed { + logic q; + } decouple_rw; + struct packed { + logic q; + } src_reduce_len; + struct packed { + logic q; + } dst_reduce_len; + struct packed { + logic [2:0] q; + } src_max_llen; + struct packed { + logic [2:0] q; + } dst_max_llen; + struct packed { + logic [1:0] q; + } enable_nd; + struct packed { + logic [2:0] q; + } src_protocol; + struct packed { + logic [2:0] q; + } dst_protocol; + } idma_reg32_3d_reg2hw_conf_reg_t; + + typedef struct packed { + logic [31:0] q; + logic re; + } idma_reg32_3d_reg2hw_next_id_mreg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_dst_addr_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_src_addr_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_length_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_dst_stride_2_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_src_stride_2_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_reps_2_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_dst_stride_3_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_src_stride_3_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg32_3d_reg2hw_reps_3_low_reg_t; + + typedef struct packed { + logic [9:0] d; + } idma_reg32_3d_hw2reg_status_mreg_t; + + typedef struct packed { + logic [31:0] d; + } idma_reg32_3d_hw2reg_next_id_mreg_t; + + typedef struct packed { + logic [31:0] d; + } idma_reg32_3d_hw2reg_done_id_mreg_t; + + // Register -> HW type + typedef struct packed { + idma_reg32_3d_reg2hw_conf_reg_t conf; // [833:816] + idma_reg32_3d_reg2hw_next_id_mreg_t [15:0] next_id; // [815:288] + idma_reg32_3d_reg2hw_dst_addr_low_reg_t dst_addr_low; // [287:256] + idma_reg32_3d_reg2hw_src_addr_low_reg_t src_addr_low; // [255:224] + idma_reg32_3d_reg2hw_length_low_reg_t length_low; // [223:192] + idma_reg32_3d_reg2hw_dst_stride_2_low_reg_t dst_stride_2_low; // [191:160] + idma_reg32_3d_reg2hw_src_stride_2_low_reg_t src_stride_2_low; // [159:128] + idma_reg32_3d_reg2hw_reps_2_low_reg_t reps_2_low; // [127:96] + idma_reg32_3d_reg2hw_dst_stride_3_low_reg_t dst_stride_3_low; // [95:64] + idma_reg32_3d_reg2hw_src_stride_3_low_reg_t src_stride_3_low; // [63:32] + idma_reg32_3d_reg2hw_reps_3_low_reg_t reps_3_low; // [31:0] + } idma_reg32_3d_reg2hw_t; + + // HW -> register type + typedef struct packed { + idma_reg32_3d_hw2reg_status_mreg_t [15:0] status; // [1183:1024] + idma_reg32_3d_hw2reg_next_id_mreg_t [15:0] next_id; // [1023:512] + idma_reg32_3d_hw2reg_done_id_mreg_t [15:0] done_id; // [511:0] + } idma_reg32_3d_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] IDMA_REG32_3D_CONF_OFFSET = 9'h 0; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_0_OFFSET = 9'h 4; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_1_OFFSET = 9'h 8; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_2_OFFSET = 9'h c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_3_OFFSET = 9'h 10; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_4_OFFSET = 9'h 14; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_5_OFFSET = 9'h 18; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_6_OFFSET = 9'h 1c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_7_OFFSET = 9'h 20; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_8_OFFSET = 9'h 24; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_9_OFFSET = 9'h 28; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_10_OFFSET = 9'h 2c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_11_OFFSET = 9'h 30; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_12_OFFSET = 9'h 34; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_13_OFFSET = 9'h 38; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_14_OFFSET = 9'h 3c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_15_OFFSET = 9'h 40; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_0_OFFSET = 9'h 44; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_1_OFFSET = 9'h 48; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_2_OFFSET = 9'h 4c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_3_OFFSET = 9'h 50; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_4_OFFSET = 9'h 54; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_5_OFFSET = 9'h 58; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_6_OFFSET = 9'h 5c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_7_OFFSET = 9'h 60; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_8_OFFSET = 9'h 64; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_9_OFFSET = 9'h 68; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_10_OFFSET = 9'h 6c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_11_OFFSET = 9'h 70; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_12_OFFSET = 9'h 74; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_13_OFFSET = 9'h 78; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_14_OFFSET = 9'h 7c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_15_OFFSET = 9'h 80; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_0_OFFSET = 9'h 84; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_1_OFFSET = 9'h 88; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_2_OFFSET = 9'h 8c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_3_OFFSET = 9'h 90; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_4_OFFSET = 9'h 94; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_5_OFFSET = 9'h 98; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_6_OFFSET = 9'h 9c; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_7_OFFSET = 9'h a0; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_8_OFFSET = 9'h a4; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_9_OFFSET = 9'h a8; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_10_OFFSET = 9'h ac; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_11_OFFSET = 9'h b0; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_12_OFFSET = 9'h b4; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_13_OFFSET = 9'h b8; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_14_OFFSET = 9'h bc; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_15_OFFSET = 9'h c0; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DST_ADDR_LOW_OFFSET = 9'h d0; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_SRC_ADDR_LOW_OFFSET = 9'h d8; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_LENGTH_LOW_OFFSET = 9'h e0; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DST_STRIDE_2_LOW_OFFSET = 9'h e8; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_SRC_STRIDE_2_LOW_OFFSET = 9'h f0; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_REPS_2_LOW_OFFSET = 9'h f8; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_DST_STRIDE_3_LOW_OFFSET = 9'h 100; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_SRC_STRIDE_3_LOW_OFFSET = 9'h 108; + parameter logic [BlockAw-1:0] IDMA_REG32_3D_REPS_3_LOW_OFFSET = 9'h 110; + + // Reset values for hwext registers and their fields + parameter logic [9:0] IDMA_REG32_3D_STATUS_0_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_1_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_2_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_3_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_4_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_5_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_6_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_7_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_8_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_9_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_10_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_11_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_12_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_13_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_14_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG32_3D_STATUS_15_RESVAL = 10'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_0_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_1_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_2_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_3_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_4_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_5_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_6_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_7_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_8_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_9_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_10_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_11_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_12_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_13_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_14_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_15_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_0_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_1_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_2_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_3_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_4_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_5_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_6_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_7_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_8_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_9_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_10_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_11_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_12_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_13_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_14_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG32_3D_DONE_ID_15_RESVAL = 32'h 0; + + // Register index + typedef enum int { + IDMA_REG32_3D_CONF, + IDMA_REG32_3D_STATUS_0, + IDMA_REG32_3D_STATUS_1, + IDMA_REG32_3D_STATUS_2, + IDMA_REG32_3D_STATUS_3, + IDMA_REG32_3D_STATUS_4, + IDMA_REG32_3D_STATUS_5, + IDMA_REG32_3D_STATUS_6, + IDMA_REG32_3D_STATUS_7, + IDMA_REG32_3D_STATUS_8, + IDMA_REG32_3D_STATUS_9, + IDMA_REG32_3D_STATUS_10, + IDMA_REG32_3D_STATUS_11, + IDMA_REG32_3D_STATUS_12, + IDMA_REG32_3D_STATUS_13, + IDMA_REG32_3D_STATUS_14, + IDMA_REG32_3D_STATUS_15, + IDMA_REG32_3D_NEXT_ID_0, + IDMA_REG32_3D_NEXT_ID_1, + IDMA_REG32_3D_NEXT_ID_2, + IDMA_REG32_3D_NEXT_ID_3, + IDMA_REG32_3D_NEXT_ID_4, + IDMA_REG32_3D_NEXT_ID_5, + IDMA_REG32_3D_NEXT_ID_6, + IDMA_REG32_3D_NEXT_ID_7, + IDMA_REG32_3D_NEXT_ID_8, + IDMA_REG32_3D_NEXT_ID_9, + IDMA_REG32_3D_NEXT_ID_10, + IDMA_REG32_3D_NEXT_ID_11, + IDMA_REG32_3D_NEXT_ID_12, + IDMA_REG32_3D_NEXT_ID_13, + IDMA_REG32_3D_NEXT_ID_14, + IDMA_REG32_3D_NEXT_ID_15, + IDMA_REG32_3D_DONE_ID_0, + IDMA_REG32_3D_DONE_ID_1, + IDMA_REG32_3D_DONE_ID_2, + IDMA_REG32_3D_DONE_ID_3, + IDMA_REG32_3D_DONE_ID_4, + IDMA_REG32_3D_DONE_ID_5, + IDMA_REG32_3D_DONE_ID_6, + IDMA_REG32_3D_DONE_ID_7, + IDMA_REG32_3D_DONE_ID_8, + IDMA_REG32_3D_DONE_ID_9, + IDMA_REG32_3D_DONE_ID_10, + IDMA_REG32_3D_DONE_ID_11, + IDMA_REG32_3D_DONE_ID_12, + IDMA_REG32_3D_DONE_ID_13, + IDMA_REG32_3D_DONE_ID_14, + IDMA_REG32_3D_DONE_ID_15, + IDMA_REG32_3D_DST_ADDR_LOW, + IDMA_REG32_3D_SRC_ADDR_LOW, + IDMA_REG32_3D_LENGTH_LOW, + IDMA_REG32_3D_DST_STRIDE_2_LOW, + IDMA_REG32_3D_SRC_STRIDE_2_LOW, + IDMA_REG32_3D_REPS_2_LOW, + IDMA_REG32_3D_DST_STRIDE_3_LOW, + IDMA_REG32_3D_SRC_STRIDE_3_LOW, + IDMA_REG32_3D_REPS_3_LOW + } idma_reg32_3d_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] IDMA_REG32_3D_PERMIT [58] = '{ + 4'b 0011, // index[ 0] IDMA_REG32_3D_CONF + 4'b 0011, // index[ 1] IDMA_REG32_3D_STATUS_0 + 4'b 0011, // index[ 2] IDMA_REG32_3D_STATUS_1 + 4'b 0011, // index[ 3] IDMA_REG32_3D_STATUS_2 + 4'b 0011, // index[ 4] IDMA_REG32_3D_STATUS_3 + 4'b 0011, // index[ 5] IDMA_REG32_3D_STATUS_4 + 4'b 0011, // index[ 6] IDMA_REG32_3D_STATUS_5 + 4'b 0011, // index[ 7] IDMA_REG32_3D_STATUS_6 + 4'b 0011, // index[ 8] IDMA_REG32_3D_STATUS_7 + 4'b 0011, // index[ 9] IDMA_REG32_3D_STATUS_8 + 4'b 0011, // index[10] IDMA_REG32_3D_STATUS_9 + 4'b 0011, // index[11] IDMA_REG32_3D_STATUS_10 + 4'b 0011, // index[12] IDMA_REG32_3D_STATUS_11 + 4'b 0011, // index[13] IDMA_REG32_3D_STATUS_12 + 4'b 0011, // index[14] IDMA_REG32_3D_STATUS_13 + 4'b 0011, // index[15] IDMA_REG32_3D_STATUS_14 + 4'b 0011, // index[16] IDMA_REG32_3D_STATUS_15 + 4'b 1111, // index[17] IDMA_REG32_3D_NEXT_ID_0 + 4'b 1111, // index[18] IDMA_REG32_3D_NEXT_ID_1 + 4'b 1111, // index[19] IDMA_REG32_3D_NEXT_ID_2 + 4'b 1111, // index[20] IDMA_REG32_3D_NEXT_ID_3 + 4'b 1111, // index[21] IDMA_REG32_3D_NEXT_ID_4 + 4'b 1111, // index[22] IDMA_REG32_3D_NEXT_ID_5 + 4'b 1111, // index[23] IDMA_REG32_3D_NEXT_ID_6 + 4'b 1111, // index[24] IDMA_REG32_3D_NEXT_ID_7 + 4'b 1111, // index[25] IDMA_REG32_3D_NEXT_ID_8 + 4'b 1111, // index[26] IDMA_REG32_3D_NEXT_ID_9 + 4'b 1111, // index[27] IDMA_REG32_3D_NEXT_ID_10 + 4'b 1111, // index[28] IDMA_REG32_3D_NEXT_ID_11 + 4'b 1111, // index[29] IDMA_REG32_3D_NEXT_ID_12 + 4'b 1111, // index[30] IDMA_REG32_3D_NEXT_ID_13 + 4'b 1111, // index[31] IDMA_REG32_3D_NEXT_ID_14 + 4'b 1111, // index[32] IDMA_REG32_3D_NEXT_ID_15 + 4'b 1111, // index[33] IDMA_REG32_3D_DONE_ID_0 + 4'b 1111, // index[34] IDMA_REG32_3D_DONE_ID_1 + 4'b 1111, // index[35] IDMA_REG32_3D_DONE_ID_2 + 4'b 1111, // index[36] IDMA_REG32_3D_DONE_ID_3 + 4'b 1111, // index[37] IDMA_REG32_3D_DONE_ID_4 + 4'b 1111, // index[38] IDMA_REG32_3D_DONE_ID_5 + 4'b 1111, // index[39] IDMA_REG32_3D_DONE_ID_6 + 4'b 1111, // index[40] IDMA_REG32_3D_DONE_ID_7 + 4'b 1111, // index[41] IDMA_REG32_3D_DONE_ID_8 + 4'b 1111, // index[42] IDMA_REG32_3D_DONE_ID_9 + 4'b 1111, // index[43] IDMA_REG32_3D_DONE_ID_10 + 4'b 1111, // index[44] IDMA_REG32_3D_DONE_ID_11 + 4'b 1111, // index[45] IDMA_REG32_3D_DONE_ID_12 + 4'b 1111, // index[46] IDMA_REG32_3D_DONE_ID_13 + 4'b 1111, // index[47] IDMA_REG32_3D_DONE_ID_14 + 4'b 1111, // index[48] IDMA_REG32_3D_DONE_ID_15 + 4'b 1111, // index[49] IDMA_REG32_3D_DST_ADDR_LOW + 4'b 1111, // index[50] IDMA_REG32_3D_SRC_ADDR_LOW + 4'b 1111, // index[51] IDMA_REG32_3D_LENGTH_LOW + 4'b 1111, // index[52] IDMA_REG32_3D_DST_STRIDE_2_LOW + 4'b 1111, // index[53] IDMA_REG32_3D_SRC_STRIDE_2_LOW + 4'b 1111, // index[54] IDMA_REG32_3D_REPS_2_LOW + 4'b 1111, // index[55] IDMA_REG32_3D_DST_STRIDE_3_LOW + 4'b 1111, // index[56] IDMA_REG32_3D_SRC_STRIDE_3_LOW + 4'b 1111 // index[57] IDMA_REG32_3D_REPS_3_LOW + }; + +endpackage + +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package idma_reg64_2d_reg_pkg; + + // Param list + parameter int num_dims = 2; + + // Address widths within the block + parameter int BlockAw = 8; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + struct packed { + logic q; + } decouple_aw; + struct packed { + logic q; + } decouple_rw; + struct packed { + logic q; + } src_reduce_len; + struct packed { + logic q; + } dst_reduce_len; + struct packed { + logic [2:0] q; + } src_max_llen; + struct packed { + logic [2:0] q; + } dst_max_llen; + struct packed { + logic q; + } enable_nd; + struct packed { + logic [2:0] q; + } src_protocol; + struct packed { + logic [2:0] q; + } dst_protocol; + } idma_reg64_2d_reg2hw_conf_reg_t; + + typedef struct packed { + logic [31:0] q; + logic re; + } idma_reg64_2d_reg2hw_next_id_mreg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_dst_addr_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_dst_addr_high_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_src_addr_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_src_addr_high_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_length_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_length_high_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_dst_stride_2_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_dst_stride_2_high_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_src_stride_2_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_src_stride_2_high_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_reps_2_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_2d_reg2hw_reps_2_high_reg_t; + + typedef struct packed { + logic [9:0] d; + } idma_reg64_2d_hw2reg_status_mreg_t; + + typedef struct packed { + logic [31:0] d; + } idma_reg64_2d_hw2reg_next_id_mreg_t; + + typedef struct packed { + logic [31:0] d; + } idma_reg64_2d_hw2reg_done_id_mreg_t; + + // Register -> HW type + typedef struct packed { + idma_reg64_2d_reg2hw_conf_reg_t conf; // [928:912] + idma_reg64_2d_reg2hw_next_id_mreg_t [15:0] next_id; // [911:384] + idma_reg64_2d_reg2hw_dst_addr_low_reg_t dst_addr_low; // [383:352] + idma_reg64_2d_reg2hw_dst_addr_high_reg_t dst_addr_high; // [351:320] + idma_reg64_2d_reg2hw_src_addr_low_reg_t src_addr_low; // [319:288] + idma_reg64_2d_reg2hw_src_addr_high_reg_t src_addr_high; // [287:256] + idma_reg64_2d_reg2hw_length_low_reg_t length_low; // [255:224] + idma_reg64_2d_reg2hw_length_high_reg_t length_high; // [223:192] + idma_reg64_2d_reg2hw_dst_stride_2_low_reg_t dst_stride_2_low; // [191:160] + idma_reg64_2d_reg2hw_dst_stride_2_high_reg_t dst_stride_2_high; // [159:128] + idma_reg64_2d_reg2hw_src_stride_2_low_reg_t src_stride_2_low; // [127:96] + idma_reg64_2d_reg2hw_src_stride_2_high_reg_t src_stride_2_high; // [95:64] + idma_reg64_2d_reg2hw_reps_2_low_reg_t reps_2_low; // [63:32] + idma_reg64_2d_reg2hw_reps_2_high_reg_t reps_2_high; // [31:0] + } idma_reg64_2d_reg2hw_t; + + // HW -> register type + typedef struct packed { + idma_reg64_2d_hw2reg_status_mreg_t [15:0] status; // [1183:1024] + idma_reg64_2d_hw2reg_next_id_mreg_t [15:0] next_id; // [1023:512] + idma_reg64_2d_hw2reg_done_id_mreg_t [15:0] done_id; // [511:0] + } idma_reg64_2d_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] IDMA_REG64_2D_CONF_OFFSET = 8'h 0; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_0_OFFSET = 8'h 4; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_1_OFFSET = 8'h 8; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_2_OFFSET = 8'h c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_3_OFFSET = 8'h 10; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_4_OFFSET = 8'h 14; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_5_OFFSET = 8'h 18; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_6_OFFSET = 8'h 1c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_7_OFFSET = 8'h 20; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_8_OFFSET = 8'h 24; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_9_OFFSET = 8'h 28; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_10_OFFSET = 8'h 2c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_11_OFFSET = 8'h 30; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_12_OFFSET = 8'h 34; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_13_OFFSET = 8'h 38; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_14_OFFSET = 8'h 3c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_15_OFFSET = 8'h 40; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_0_OFFSET = 8'h 44; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_1_OFFSET = 8'h 48; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_2_OFFSET = 8'h 4c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_3_OFFSET = 8'h 50; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_4_OFFSET = 8'h 54; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_5_OFFSET = 8'h 58; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_6_OFFSET = 8'h 5c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_7_OFFSET = 8'h 60; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_8_OFFSET = 8'h 64; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_9_OFFSET = 8'h 68; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_10_OFFSET = 8'h 6c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_11_OFFSET = 8'h 70; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_12_OFFSET = 8'h 74; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_13_OFFSET = 8'h 78; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_14_OFFSET = 8'h 7c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_15_OFFSET = 8'h 80; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_0_OFFSET = 8'h 84; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_1_OFFSET = 8'h 88; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_2_OFFSET = 8'h 8c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_3_OFFSET = 8'h 90; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_4_OFFSET = 8'h 94; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_5_OFFSET = 8'h 98; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_6_OFFSET = 8'h 9c; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_7_OFFSET = 8'h a0; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_8_OFFSET = 8'h a4; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_9_OFFSET = 8'h a8; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_10_OFFSET = 8'h ac; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_11_OFFSET = 8'h b0; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_12_OFFSET = 8'h b4; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_13_OFFSET = 8'h b8; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_14_OFFSET = 8'h bc; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_15_OFFSET = 8'h c0; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DST_ADDR_LOW_OFFSET = 8'h d0; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DST_ADDR_HIGH_OFFSET = 8'h d4; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_SRC_ADDR_LOW_OFFSET = 8'h d8; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_SRC_ADDR_HIGH_OFFSET = 8'h dc; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_LENGTH_LOW_OFFSET = 8'h e0; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_LENGTH_HIGH_OFFSET = 8'h e4; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DST_STRIDE_2_LOW_OFFSET = 8'h e8; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_DST_STRIDE_2_HIGH_OFFSET = 8'h ec; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_SRC_STRIDE_2_LOW_OFFSET = 8'h f0; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_SRC_STRIDE_2_HIGH_OFFSET = 8'h f4; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_REPS_2_LOW_OFFSET = 8'h f8; + parameter logic [BlockAw-1:0] IDMA_REG64_2D_REPS_2_HIGH_OFFSET = 8'h fc; + + // Reset values for hwext registers and their fields + parameter logic [9:0] IDMA_REG64_2D_STATUS_0_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_1_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_2_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_3_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_4_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_5_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_6_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_7_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_8_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_9_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_10_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_11_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_12_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_13_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_14_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_2D_STATUS_15_RESVAL = 10'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_0_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_1_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_2_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_3_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_4_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_5_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_6_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_7_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_8_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_9_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_10_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_11_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_12_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_13_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_14_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_15_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_0_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_1_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_2_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_3_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_4_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_5_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_6_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_7_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_8_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_9_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_10_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_11_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_12_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_13_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_14_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_2D_DONE_ID_15_RESVAL = 32'h 0; + + // Register index + typedef enum int { + IDMA_REG64_2D_CONF, + IDMA_REG64_2D_STATUS_0, + IDMA_REG64_2D_STATUS_1, + IDMA_REG64_2D_STATUS_2, + IDMA_REG64_2D_STATUS_3, + IDMA_REG64_2D_STATUS_4, + IDMA_REG64_2D_STATUS_5, + IDMA_REG64_2D_STATUS_6, + IDMA_REG64_2D_STATUS_7, + IDMA_REG64_2D_STATUS_8, + IDMA_REG64_2D_STATUS_9, + IDMA_REG64_2D_STATUS_10, + IDMA_REG64_2D_STATUS_11, + IDMA_REG64_2D_STATUS_12, + IDMA_REG64_2D_STATUS_13, + IDMA_REG64_2D_STATUS_14, + IDMA_REG64_2D_STATUS_15, + IDMA_REG64_2D_NEXT_ID_0, + IDMA_REG64_2D_NEXT_ID_1, + IDMA_REG64_2D_NEXT_ID_2, + IDMA_REG64_2D_NEXT_ID_3, + IDMA_REG64_2D_NEXT_ID_4, + IDMA_REG64_2D_NEXT_ID_5, + IDMA_REG64_2D_NEXT_ID_6, + IDMA_REG64_2D_NEXT_ID_7, + IDMA_REG64_2D_NEXT_ID_8, + IDMA_REG64_2D_NEXT_ID_9, + IDMA_REG64_2D_NEXT_ID_10, + IDMA_REG64_2D_NEXT_ID_11, + IDMA_REG64_2D_NEXT_ID_12, + IDMA_REG64_2D_NEXT_ID_13, + IDMA_REG64_2D_NEXT_ID_14, + IDMA_REG64_2D_NEXT_ID_15, + IDMA_REG64_2D_DONE_ID_0, + IDMA_REG64_2D_DONE_ID_1, + IDMA_REG64_2D_DONE_ID_2, + IDMA_REG64_2D_DONE_ID_3, + IDMA_REG64_2D_DONE_ID_4, + IDMA_REG64_2D_DONE_ID_5, + IDMA_REG64_2D_DONE_ID_6, + IDMA_REG64_2D_DONE_ID_7, + IDMA_REG64_2D_DONE_ID_8, + IDMA_REG64_2D_DONE_ID_9, + IDMA_REG64_2D_DONE_ID_10, + IDMA_REG64_2D_DONE_ID_11, + IDMA_REG64_2D_DONE_ID_12, + IDMA_REG64_2D_DONE_ID_13, + IDMA_REG64_2D_DONE_ID_14, + IDMA_REG64_2D_DONE_ID_15, + IDMA_REG64_2D_DST_ADDR_LOW, + IDMA_REG64_2D_DST_ADDR_HIGH, + IDMA_REG64_2D_SRC_ADDR_LOW, + IDMA_REG64_2D_SRC_ADDR_HIGH, + IDMA_REG64_2D_LENGTH_LOW, + IDMA_REG64_2D_LENGTH_HIGH, + IDMA_REG64_2D_DST_STRIDE_2_LOW, + IDMA_REG64_2D_DST_STRIDE_2_HIGH, + IDMA_REG64_2D_SRC_STRIDE_2_LOW, + IDMA_REG64_2D_SRC_STRIDE_2_HIGH, + IDMA_REG64_2D_REPS_2_LOW, + IDMA_REG64_2D_REPS_2_HIGH + } idma_reg64_2d_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] IDMA_REG64_2D_PERMIT [61] = '{ + 4'b 0011, // index[ 0] IDMA_REG64_2D_CONF + 4'b 0011, // index[ 1] IDMA_REG64_2D_STATUS_0 + 4'b 0011, // index[ 2] IDMA_REG64_2D_STATUS_1 + 4'b 0011, // index[ 3] IDMA_REG64_2D_STATUS_2 + 4'b 0011, // index[ 4] IDMA_REG64_2D_STATUS_3 + 4'b 0011, // index[ 5] IDMA_REG64_2D_STATUS_4 + 4'b 0011, // index[ 6] IDMA_REG64_2D_STATUS_5 + 4'b 0011, // index[ 7] IDMA_REG64_2D_STATUS_6 + 4'b 0011, // index[ 8] IDMA_REG64_2D_STATUS_7 + 4'b 0011, // index[ 9] IDMA_REG64_2D_STATUS_8 + 4'b 0011, // index[10] IDMA_REG64_2D_STATUS_9 + 4'b 0011, // index[11] IDMA_REG64_2D_STATUS_10 + 4'b 0011, // index[12] IDMA_REG64_2D_STATUS_11 + 4'b 0011, // index[13] IDMA_REG64_2D_STATUS_12 + 4'b 0011, // index[14] IDMA_REG64_2D_STATUS_13 + 4'b 0011, // index[15] IDMA_REG64_2D_STATUS_14 + 4'b 0011, // index[16] IDMA_REG64_2D_STATUS_15 + 4'b 1111, // index[17] IDMA_REG64_2D_NEXT_ID_0 + 4'b 1111, // index[18] IDMA_REG64_2D_NEXT_ID_1 + 4'b 1111, // index[19] IDMA_REG64_2D_NEXT_ID_2 + 4'b 1111, // index[20] IDMA_REG64_2D_NEXT_ID_3 + 4'b 1111, // index[21] IDMA_REG64_2D_NEXT_ID_4 + 4'b 1111, // index[22] IDMA_REG64_2D_NEXT_ID_5 + 4'b 1111, // index[23] IDMA_REG64_2D_NEXT_ID_6 + 4'b 1111, // index[24] IDMA_REG64_2D_NEXT_ID_7 + 4'b 1111, // index[25] IDMA_REG64_2D_NEXT_ID_8 + 4'b 1111, // index[26] IDMA_REG64_2D_NEXT_ID_9 + 4'b 1111, // index[27] IDMA_REG64_2D_NEXT_ID_10 + 4'b 1111, // index[28] IDMA_REG64_2D_NEXT_ID_11 + 4'b 1111, // index[29] IDMA_REG64_2D_NEXT_ID_12 + 4'b 1111, // index[30] IDMA_REG64_2D_NEXT_ID_13 + 4'b 1111, // index[31] IDMA_REG64_2D_NEXT_ID_14 + 4'b 1111, // index[32] IDMA_REG64_2D_NEXT_ID_15 + 4'b 1111, // index[33] IDMA_REG64_2D_DONE_ID_0 + 4'b 1111, // index[34] IDMA_REG64_2D_DONE_ID_1 + 4'b 1111, // index[35] IDMA_REG64_2D_DONE_ID_2 + 4'b 1111, // index[36] IDMA_REG64_2D_DONE_ID_3 + 4'b 1111, // index[37] IDMA_REG64_2D_DONE_ID_4 + 4'b 1111, // index[38] IDMA_REG64_2D_DONE_ID_5 + 4'b 1111, // index[39] IDMA_REG64_2D_DONE_ID_6 + 4'b 1111, // index[40] IDMA_REG64_2D_DONE_ID_7 + 4'b 1111, // index[41] IDMA_REG64_2D_DONE_ID_8 + 4'b 1111, // index[42] IDMA_REG64_2D_DONE_ID_9 + 4'b 1111, // index[43] IDMA_REG64_2D_DONE_ID_10 + 4'b 1111, // index[44] IDMA_REG64_2D_DONE_ID_11 + 4'b 1111, // index[45] IDMA_REG64_2D_DONE_ID_12 + 4'b 1111, // index[46] IDMA_REG64_2D_DONE_ID_13 + 4'b 1111, // index[47] IDMA_REG64_2D_DONE_ID_14 + 4'b 1111, // index[48] IDMA_REG64_2D_DONE_ID_15 + 4'b 1111, // index[49] IDMA_REG64_2D_DST_ADDR_LOW + 4'b 1111, // index[50] IDMA_REG64_2D_DST_ADDR_HIGH + 4'b 1111, // index[51] IDMA_REG64_2D_SRC_ADDR_LOW + 4'b 1111, // index[52] IDMA_REG64_2D_SRC_ADDR_HIGH + 4'b 1111, // index[53] IDMA_REG64_2D_LENGTH_LOW + 4'b 1111, // index[54] IDMA_REG64_2D_LENGTH_HIGH + 4'b 1111, // index[55] IDMA_REG64_2D_DST_STRIDE_2_LOW + 4'b 1111, // index[56] IDMA_REG64_2D_DST_STRIDE_2_HIGH + 4'b 1111, // index[57] IDMA_REG64_2D_SRC_STRIDE_2_LOW + 4'b 1111, // index[58] IDMA_REG64_2D_SRC_STRIDE_2_HIGH + 4'b 1111, // index[59] IDMA_REG64_2D_REPS_2_LOW + 4'b 1111 // index[60] IDMA_REG64_2D_REPS_2_HIGH + }; + +endpackage + +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package idma_reg64_1d_reg_pkg; + + // Param list + parameter int num_dims = 1; + + // Address widths within the block + parameter int BlockAw = 8; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + struct packed { + logic q; + } decouple_aw; + struct packed { + logic q; + } decouple_rw; + struct packed { + logic q; + } src_reduce_len; + struct packed { + logic q; + } dst_reduce_len; + struct packed { + logic [2:0] q; + } src_max_llen; + struct packed { + logic [2:0] q; + } dst_max_llen; + struct packed { + logic q; + } enable_nd; + struct packed { + logic [2:0] q; + } src_protocol; + struct packed { + logic [2:0] q; + } dst_protocol; + } idma_reg64_1d_reg2hw_conf_reg_t; + + typedef struct packed { + logic [31:0] q; + logic re; + } idma_reg64_1d_reg2hw_next_id_mreg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_1d_reg2hw_dst_addr_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_1d_reg2hw_dst_addr_high_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_1d_reg2hw_src_addr_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_1d_reg2hw_src_addr_high_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_1d_reg2hw_length_low_reg_t; + + typedef struct packed { + logic [31:0] q; + } idma_reg64_1d_reg2hw_length_high_reg_t; + + typedef struct packed { + logic [9:0] d; + } idma_reg64_1d_hw2reg_status_mreg_t; + + typedef struct packed { + logic [31:0] d; + } idma_reg64_1d_hw2reg_next_id_mreg_t; + + typedef struct packed { + logic [31:0] d; + } idma_reg64_1d_hw2reg_done_id_mreg_t; + + // Register -> HW type + typedef struct packed { + idma_reg64_1d_reg2hw_conf_reg_t conf; // [736:720] + idma_reg64_1d_reg2hw_next_id_mreg_t [15:0] next_id; // [719:192] + idma_reg64_1d_reg2hw_dst_addr_low_reg_t dst_addr_low; // [191:160] + idma_reg64_1d_reg2hw_dst_addr_high_reg_t dst_addr_high; // [159:128] + idma_reg64_1d_reg2hw_src_addr_low_reg_t src_addr_low; // [127:96] + idma_reg64_1d_reg2hw_src_addr_high_reg_t src_addr_high; // [95:64] + idma_reg64_1d_reg2hw_length_low_reg_t length_low; // [63:32] + idma_reg64_1d_reg2hw_length_high_reg_t length_high; // [31:0] + } idma_reg64_1d_reg2hw_t; + + // HW -> register type + typedef struct packed { + idma_reg64_1d_hw2reg_status_mreg_t [15:0] status; // [1183:1024] + idma_reg64_1d_hw2reg_next_id_mreg_t [15:0] next_id; // [1023:512] + idma_reg64_1d_hw2reg_done_id_mreg_t [15:0] done_id; // [511:0] + } idma_reg64_1d_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] IDMA_REG64_1D_CONF_OFFSET = 8'h 0; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_0_OFFSET = 8'h 4; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_1_OFFSET = 8'h 8; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_2_OFFSET = 8'h c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_3_OFFSET = 8'h 10; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_4_OFFSET = 8'h 14; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_5_OFFSET = 8'h 18; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_6_OFFSET = 8'h 1c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_7_OFFSET = 8'h 20; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_8_OFFSET = 8'h 24; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_9_OFFSET = 8'h 28; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_10_OFFSET = 8'h 2c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_11_OFFSET = 8'h 30; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_12_OFFSET = 8'h 34; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_13_OFFSET = 8'h 38; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_14_OFFSET = 8'h 3c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_15_OFFSET = 8'h 40; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_0_OFFSET = 8'h 44; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_1_OFFSET = 8'h 48; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_2_OFFSET = 8'h 4c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_3_OFFSET = 8'h 50; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_4_OFFSET = 8'h 54; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_5_OFFSET = 8'h 58; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_6_OFFSET = 8'h 5c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_7_OFFSET = 8'h 60; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_8_OFFSET = 8'h 64; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_9_OFFSET = 8'h 68; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_10_OFFSET = 8'h 6c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_11_OFFSET = 8'h 70; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_12_OFFSET = 8'h 74; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_13_OFFSET = 8'h 78; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_14_OFFSET = 8'h 7c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_15_OFFSET = 8'h 80; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_0_OFFSET = 8'h 84; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_1_OFFSET = 8'h 88; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_2_OFFSET = 8'h 8c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_3_OFFSET = 8'h 90; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_4_OFFSET = 8'h 94; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_5_OFFSET = 8'h 98; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_6_OFFSET = 8'h 9c; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_7_OFFSET = 8'h a0; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_8_OFFSET = 8'h a4; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_9_OFFSET = 8'h a8; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_10_OFFSET = 8'h ac; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_11_OFFSET = 8'h b0; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_12_OFFSET = 8'h b4; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_13_OFFSET = 8'h b8; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_14_OFFSET = 8'h bc; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_15_OFFSET = 8'h c0; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DST_ADDR_LOW_OFFSET = 8'h d0; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_DST_ADDR_HIGH_OFFSET = 8'h d4; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_SRC_ADDR_LOW_OFFSET = 8'h d8; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_SRC_ADDR_HIGH_OFFSET = 8'h dc; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_LENGTH_LOW_OFFSET = 8'h e0; + parameter logic [BlockAw-1:0] IDMA_REG64_1D_LENGTH_HIGH_OFFSET = 8'h e4; + + // Reset values for hwext registers and their fields + parameter logic [9:0] IDMA_REG64_1D_STATUS_0_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_1_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_2_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_3_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_4_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_5_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_6_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_7_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_8_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_9_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_10_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_11_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_12_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_13_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_14_RESVAL = 10'h 0; + parameter logic [9:0] IDMA_REG64_1D_STATUS_15_RESVAL = 10'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_0_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_1_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_2_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_3_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_4_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_5_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_6_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_7_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_8_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_9_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_10_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_11_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_12_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_13_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_14_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_15_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_0_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_1_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_2_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_3_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_4_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_5_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_6_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_7_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_8_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_9_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_10_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_11_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_12_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_13_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_14_RESVAL = 32'h 0; + parameter logic [31:0] IDMA_REG64_1D_DONE_ID_15_RESVAL = 32'h 0; + + // Register index + typedef enum int { + IDMA_REG64_1D_CONF, + IDMA_REG64_1D_STATUS_0, + IDMA_REG64_1D_STATUS_1, + IDMA_REG64_1D_STATUS_2, + IDMA_REG64_1D_STATUS_3, + IDMA_REG64_1D_STATUS_4, + IDMA_REG64_1D_STATUS_5, + IDMA_REG64_1D_STATUS_6, + IDMA_REG64_1D_STATUS_7, + IDMA_REG64_1D_STATUS_8, + IDMA_REG64_1D_STATUS_9, + IDMA_REG64_1D_STATUS_10, + IDMA_REG64_1D_STATUS_11, + IDMA_REG64_1D_STATUS_12, + IDMA_REG64_1D_STATUS_13, + IDMA_REG64_1D_STATUS_14, + IDMA_REG64_1D_STATUS_15, + IDMA_REG64_1D_NEXT_ID_0, + IDMA_REG64_1D_NEXT_ID_1, + IDMA_REG64_1D_NEXT_ID_2, + IDMA_REG64_1D_NEXT_ID_3, + IDMA_REG64_1D_NEXT_ID_4, + IDMA_REG64_1D_NEXT_ID_5, + IDMA_REG64_1D_NEXT_ID_6, + IDMA_REG64_1D_NEXT_ID_7, + IDMA_REG64_1D_NEXT_ID_8, + IDMA_REG64_1D_NEXT_ID_9, + IDMA_REG64_1D_NEXT_ID_10, + IDMA_REG64_1D_NEXT_ID_11, + IDMA_REG64_1D_NEXT_ID_12, + IDMA_REG64_1D_NEXT_ID_13, + IDMA_REG64_1D_NEXT_ID_14, + IDMA_REG64_1D_NEXT_ID_15, + IDMA_REG64_1D_DONE_ID_0, + IDMA_REG64_1D_DONE_ID_1, + IDMA_REG64_1D_DONE_ID_2, + IDMA_REG64_1D_DONE_ID_3, + IDMA_REG64_1D_DONE_ID_4, + IDMA_REG64_1D_DONE_ID_5, + IDMA_REG64_1D_DONE_ID_6, + IDMA_REG64_1D_DONE_ID_7, + IDMA_REG64_1D_DONE_ID_8, + IDMA_REG64_1D_DONE_ID_9, + IDMA_REG64_1D_DONE_ID_10, + IDMA_REG64_1D_DONE_ID_11, + IDMA_REG64_1D_DONE_ID_12, + IDMA_REG64_1D_DONE_ID_13, + IDMA_REG64_1D_DONE_ID_14, + IDMA_REG64_1D_DONE_ID_15, + IDMA_REG64_1D_DST_ADDR_LOW, + IDMA_REG64_1D_DST_ADDR_HIGH, + IDMA_REG64_1D_SRC_ADDR_LOW, + IDMA_REG64_1D_SRC_ADDR_HIGH, + IDMA_REG64_1D_LENGTH_LOW, + IDMA_REG64_1D_LENGTH_HIGH + } idma_reg64_1d_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] IDMA_REG64_1D_PERMIT [55] = '{ + 4'b 0011, // index[ 0] IDMA_REG64_1D_CONF + 4'b 0011, // index[ 1] IDMA_REG64_1D_STATUS_0 + 4'b 0011, // index[ 2] IDMA_REG64_1D_STATUS_1 + 4'b 0011, // index[ 3] IDMA_REG64_1D_STATUS_2 + 4'b 0011, // index[ 4] IDMA_REG64_1D_STATUS_3 + 4'b 0011, // index[ 5] IDMA_REG64_1D_STATUS_4 + 4'b 0011, // index[ 6] IDMA_REG64_1D_STATUS_5 + 4'b 0011, // index[ 7] IDMA_REG64_1D_STATUS_6 + 4'b 0011, // index[ 8] IDMA_REG64_1D_STATUS_7 + 4'b 0011, // index[ 9] IDMA_REG64_1D_STATUS_8 + 4'b 0011, // index[10] IDMA_REG64_1D_STATUS_9 + 4'b 0011, // index[11] IDMA_REG64_1D_STATUS_10 + 4'b 0011, // index[12] IDMA_REG64_1D_STATUS_11 + 4'b 0011, // index[13] IDMA_REG64_1D_STATUS_12 + 4'b 0011, // index[14] IDMA_REG64_1D_STATUS_13 + 4'b 0011, // index[15] IDMA_REG64_1D_STATUS_14 + 4'b 0011, // index[16] IDMA_REG64_1D_STATUS_15 + 4'b 1111, // index[17] IDMA_REG64_1D_NEXT_ID_0 + 4'b 1111, // index[18] IDMA_REG64_1D_NEXT_ID_1 + 4'b 1111, // index[19] IDMA_REG64_1D_NEXT_ID_2 + 4'b 1111, // index[20] IDMA_REG64_1D_NEXT_ID_3 + 4'b 1111, // index[21] IDMA_REG64_1D_NEXT_ID_4 + 4'b 1111, // index[22] IDMA_REG64_1D_NEXT_ID_5 + 4'b 1111, // index[23] IDMA_REG64_1D_NEXT_ID_6 + 4'b 1111, // index[24] IDMA_REG64_1D_NEXT_ID_7 + 4'b 1111, // index[25] IDMA_REG64_1D_NEXT_ID_8 + 4'b 1111, // index[26] IDMA_REG64_1D_NEXT_ID_9 + 4'b 1111, // index[27] IDMA_REG64_1D_NEXT_ID_10 + 4'b 1111, // index[28] IDMA_REG64_1D_NEXT_ID_11 + 4'b 1111, // index[29] IDMA_REG64_1D_NEXT_ID_12 + 4'b 1111, // index[30] IDMA_REG64_1D_NEXT_ID_13 + 4'b 1111, // index[31] IDMA_REG64_1D_NEXT_ID_14 + 4'b 1111, // index[32] IDMA_REG64_1D_NEXT_ID_15 + 4'b 1111, // index[33] IDMA_REG64_1D_DONE_ID_0 + 4'b 1111, // index[34] IDMA_REG64_1D_DONE_ID_1 + 4'b 1111, // index[35] IDMA_REG64_1D_DONE_ID_2 + 4'b 1111, // index[36] IDMA_REG64_1D_DONE_ID_3 + 4'b 1111, // index[37] IDMA_REG64_1D_DONE_ID_4 + 4'b 1111, // index[38] IDMA_REG64_1D_DONE_ID_5 + 4'b 1111, // index[39] IDMA_REG64_1D_DONE_ID_6 + 4'b 1111, // index[40] IDMA_REG64_1D_DONE_ID_7 + 4'b 1111, // index[41] IDMA_REG64_1D_DONE_ID_8 + 4'b 1111, // index[42] IDMA_REG64_1D_DONE_ID_9 + 4'b 1111, // index[43] IDMA_REG64_1D_DONE_ID_10 + 4'b 1111, // index[44] IDMA_REG64_1D_DONE_ID_11 + 4'b 1111, // index[45] IDMA_REG64_1D_DONE_ID_12 + 4'b 1111, // index[46] IDMA_REG64_1D_DONE_ID_13 + 4'b 1111, // index[47] IDMA_REG64_1D_DONE_ID_14 + 4'b 1111, // index[48] IDMA_REG64_1D_DONE_ID_15 + 4'b 1111, // index[49] IDMA_REG64_1D_DST_ADDR_LOW + 4'b 1111, // index[50] IDMA_REG64_1D_DST_ADDR_HIGH + 4'b 1111, // index[51] IDMA_REG64_1D_SRC_ADDR_LOW + 4'b 1111, // index[52] IDMA_REG64_1D_SRC_ADDR_HIGH + 4'b 1111, // index[53] IDMA_REG64_1D_LENGTH_LOW + 4'b 1111 // index[54] IDMA_REG64_1D_LENGTH_HIGH + }; + +endpackage + +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module idma_desc64_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 4 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output idma_desc64_reg_pkg::idma_desc64_reg2hw_t reg2hw, // Write + input idma_desc64_reg_pkg::idma_desc64_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import idma_desc64_reg_pkg::* ; + + localparam int DW = 64; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [BlockAw-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next ; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic [63:0] desc_addr_wd; + logic desc_addr_we; + logic status_busy_qs; + logic status_fifo_full_qs; + + // Register instances + // R[desc_addr]: V(False) + + prim_subreg #( + .DW (64), + .SWACCESS("WO"), + .RESVAL (64'hffffffffffffffff) + ) u_desc_addr ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (desc_addr_we), + .wd (desc_addr_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (reg2hw.desc_addr.qe), + .q (reg2hw.desc_addr.q ), + + .qs () + ); + + + // R[status]: V(False) + + // F[busy]: 0:0 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_busy ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + .we (1'b0), + .wd ('0 ), + + // from internal hardware + .de (hw2reg.status.busy.de), + .d (hw2reg.status.busy.d ), + + // to internal hardware + .qe (), + .q (), + + // to register interface (read) + .qs (status_busy_qs) + ); + + + // F[fifo_full]: 1:1 + prim_subreg #( + .DW (1), + .SWACCESS("RO"), + .RESVAL (1'h0) + ) u_status_fifo_full ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + .we (1'b0), + .wd ('0 ), + + // from internal hardware + .de (hw2reg.status.fifo_full.de), + .d (hw2reg.status.fifo_full.d ), + + // to internal hardware + .qe (), + .q (), + + // to register interface (read) + .qs (status_fifo_full_qs) + ); + + + + + logic [1:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[0] = (reg_addr == IDMA_DESC64_DESC_ADDR_OFFSET); + addr_hit[1] = (reg_addr == IDMA_DESC64_STATUS_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[0] & (|(IDMA_DESC64_PERMIT[0] & ~reg_be))) | + (addr_hit[1] & (|(IDMA_DESC64_PERMIT[1] & ~reg_be))))); + end + + assign desc_addr_we = addr_hit[0] & reg_we & !reg_error; + assign desc_addr_wd = reg_wdata[63:0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[63:0] = '0; + end + + addr_hit[1]: begin + reg_rdata_next[0] = status_busy_qs; + reg_rdata_next[1] = status_fifo_full_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module idma_desc64_reg_top_intf +#( + parameter int AW = 4, + localparam int DW = 64 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output idma_desc64_reg_pkg::idma_desc64_reg2hw_t reg2hw, // Write + input idma_desc64_reg_pkg::idma_desc64_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW/8; + +`include "register_interface/typedef.svh" +`include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + idma_desc64_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module idma_reg32_3d_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 9 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output idma_reg32_3d_reg_pkg::idma_reg32_3d_reg2hw_t reg2hw, // Write + input idma_reg32_3d_reg_pkg::idma_reg32_3d_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import idma_reg32_3d_reg_pkg::* ; + + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [BlockAw-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next ; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic conf_decouple_aw_qs; + logic conf_decouple_aw_wd; + logic conf_decouple_aw_we; + logic conf_decouple_rw_qs; + logic conf_decouple_rw_wd; + logic conf_decouple_rw_we; + logic conf_src_reduce_len_qs; + logic conf_src_reduce_len_wd; + logic conf_src_reduce_len_we; + logic conf_dst_reduce_len_qs; + logic conf_dst_reduce_len_wd; + logic conf_dst_reduce_len_we; + logic [2:0] conf_src_max_llen_qs; + logic [2:0] conf_src_max_llen_wd; + logic conf_src_max_llen_we; + logic [2:0] conf_dst_max_llen_qs; + logic [2:0] conf_dst_max_llen_wd; + logic conf_dst_max_llen_we; + logic [1:0] conf_enable_nd_qs; + logic [1:0] conf_enable_nd_wd; + logic conf_enable_nd_we; + logic [2:0] conf_src_protocol_qs; + logic [2:0] conf_src_protocol_wd; + logic conf_src_protocol_we; + logic [2:0] conf_dst_protocol_qs; + logic [2:0] conf_dst_protocol_wd; + logic conf_dst_protocol_we; + logic [9:0] status_0_qs; + logic status_0_re; + logic [9:0] status_1_qs; + logic status_1_re; + logic [9:0] status_2_qs; + logic status_2_re; + logic [9:0] status_3_qs; + logic status_3_re; + logic [9:0] status_4_qs; + logic status_4_re; + logic [9:0] status_5_qs; + logic status_5_re; + logic [9:0] status_6_qs; + logic status_6_re; + logic [9:0] status_7_qs; + logic status_7_re; + logic [9:0] status_8_qs; + logic status_8_re; + logic [9:0] status_9_qs; + logic status_9_re; + logic [9:0] status_10_qs; + logic status_10_re; + logic [9:0] status_11_qs; + logic status_11_re; + logic [9:0] status_12_qs; + logic status_12_re; + logic [9:0] status_13_qs; + logic status_13_re; + logic [9:0] status_14_qs; + logic status_14_re; + logic [9:0] status_15_qs; + logic status_15_re; + logic [31:0] next_id_0_qs; + logic next_id_0_re; + logic [31:0] next_id_1_qs; + logic next_id_1_re; + logic [31:0] next_id_2_qs; + logic next_id_2_re; + logic [31:0] next_id_3_qs; + logic next_id_3_re; + logic [31:0] next_id_4_qs; + logic next_id_4_re; + logic [31:0] next_id_5_qs; + logic next_id_5_re; + logic [31:0] next_id_6_qs; + logic next_id_6_re; + logic [31:0] next_id_7_qs; + logic next_id_7_re; + logic [31:0] next_id_8_qs; + logic next_id_8_re; + logic [31:0] next_id_9_qs; + logic next_id_9_re; + logic [31:0] next_id_10_qs; + logic next_id_10_re; + logic [31:0] next_id_11_qs; + logic next_id_11_re; + logic [31:0] next_id_12_qs; + logic next_id_12_re; + logic [31:0] next_id_13_qs; + logic next_id_13_re; + logic [31:0] next_id_14_qs; + logic next_id_14_re; + logic [31:0] next_id_15_qs; + logic next_id_15_re; + logic [31:0] done_id_0_qs; + logic done_id_0_re; + logic [31:0] done_id_1_qs; + logic done_id_1_re; + logic [31:0] done_id_2_qs; + logic done_id_2_re; + logic [31:0] done_id_3_qs; + logic done_id_3_re; + logic [31:0] done_id_4_qs; + logic done_id_4_re; + logic [31:0] done_id_5_qs; + logic done_id_5_re; + logic [31:0] done_id_6_qs; + logic done_id_6_re; + logic [31:0] done_id_7_qs; + logic done_id_7_re; + logic [31:0] done_id_8_qs; + logic done_id_8_re; + logic [31:0] done_id_9_qs; + logic done_id_9_re; + logic [31:0] done_id_10_qs; + logic done_id_10_re; + logic [31:0] done_id_11_qs; + logic done_id_11_re; + logic [31:0] done_id_12_qs; + logic done_id_12_re; + logic [31:0] done_id_13_qs; + logic done_id_13_re; + logic [31:0] done_id_14_qs; + logic done_id_14_re; + logic [31:0] done_id_15_qs; + logic done_id_15_re; + logic [31:0] dst_addr_low_qs; + logic [31:0] dst_addr_low_wd; + logic dst_addr_low_we; + logic [31:0] src_addr_low_qs; + logic [31:0] src_addr_low_wd; + logic src_addr_low_we; + logic [31:0] length_low_qs; + logic [31:0] length_low_wd; + logic length_low_we; + logic [31:0] dst_stride_2_low_qs; + logic [31:0] dst_stride_2_low_wd; + logic dst_stride_2_low_we; + logic [31:0] src_stride_2_low_qs; + logic [31:0] src_stride_2_low_wd; + logic src_stride_2_low_we; + logic [31:0] reps_2_low_qs; + logic [31:0] reps_2_low_wd; + logic reps_2_low_we; + logic [31:0] dst_stride_3_low_qs; + logic [31:0] dst_stride_3_low_wd; + logic dst_stride_3_low_we; + logic [31:0] src_stride_3_low_qs; + logic [31:0] src_stride_3_low_wd; + logic src_stride_3_low_we; + logic [31:0] reps_3_low_qs; + logic [31:0] reps_3_low_wd; + logic reps_3_low_we; + + // Register instances + // R[conf]: V(False) + + // F[decouple_aw]: 0:0 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_decouple_aw ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_decouple_aw_we), + .wd (conf_decouple_aw_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.decouple_aw.q ), + + // to register interface (read) + .qs (conf_decouple_aw_qs) + ); + + + // F[decouple_rw]: 1:1 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_decouple_rw ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_decouple_rw_we), + .wd (conf_decouple_rw_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.decouple_rw.q ), + + // to register interface (read) + .qs (conf_decouple_rw_qs) + ); + + + // F[src_reduce_len]: 2:2 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_src_reduce_len ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_reduce_len_we), + .wd (conf_src_reduce_len_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_reduce_len.q ), + + // to register interface (read) + .qs (conf_src_reduce_len_qs) + ); + + + // F[dst_reduce_len]: 3:3 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_dst_reduce_len ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_reduce_len_we), + .wd (conf_dst_reduce_len_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_reduce_len.q ), + + // to register interface (read) + .qs (conf_dst_reduce_len_qs) + ); + + + // F[src_max_llen]: 6:4 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_src_max_llen ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_max_llen_we), + .wd (conf_src_max_llen_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_max_llen.q ), + + // to register interface (read) + .qs (conf_src_max_llen_qs) + ); + + + // F[dst_max_llen]: 9:7 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_dst_max_llen ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_max_llen_we), + .wd (conf_dst_max_llen_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_max_llen.q ), + + // to register interface (read) + .qs (conf_dst_max_llen_qs) + ); + + + // F[enable_nd]: 11:10 + prim_subreg #( + .DW (2), + .SWACCESS("RW"), + .RESVAL (2'h0) + ) u_conf_enable_nd ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_enable_nd_we), + .wd (conf_enable_nd_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.enable_nd.q ), + + // to register interface (read) + .qs (conf_enable_nd_qs) + ); + + + // F[src_protocol]: 13:11 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_src_protocol ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_protocol_we), + .wd (conf_src_protocol_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_protocol.q ), + + // to register interface (read) + .qs (conf_src_protocol_qs) + ); + + + // F[dst_protocol]: 15:13 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_dst_protocol ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_protocol_we), + .wd (conf_dst_protocol_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_protocol.q ), + + // to register interface (read) + .qs (conf_dst_protocol_qs) + ); + + + + // Subregister 0 of Multireg status + // R[status_0]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_0 ( + .re (status_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[0].d), + .qre (), + .qe (), + .q (), + .qs (status_0_qs) + ); + + // Subregister 1 of Multireg status + // R[status_1]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_1 ( + .re (status_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[1].d), + .qre (), + .qe (), + .q (), + .qs (status_1_qs) + ); + + // Subregister 2 of Multireg status + // R[status_2]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_2 ( + .re (status_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[2].d), + .qre (), + .qe (), + .q (), + .qs (status_2_qs) + ); + + // Subregister 3 of Multireg status + // R[status_3]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_3 ( + .re (status_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[3].d), + .qre (), + .qe (), + .q (), + .qs (status_3_qs) + ); + + // Subregister 4 of Multireg status + // R[status_4]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_4 ( + .re (status_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[4].d), + .qre (), + .qe (), + .q (), + .qs (status_4_qs) + ); + + // Subregister 5 of Multireg status + // R[status_5]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_5 ( + .re (status_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[5].d), + .qre (), + .qe (), + .q (), + .qs (status_5_qs) + ); + + // Subregister 6 of Multireg status + // R[status_6]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_6 ( + .re (status_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[6].d), + .qre (), + .qe (), + .q (), + .qs (status_6_qs) + ); + + // Subregister 7 of Multireg status + // R[status_7]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_7 ( + .re (status_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[7].d), + .qre (), + .qe (), + .q (), + .qs (status_7_qs) + ); + + // Subregister 8 of Multireg status + // R[status_8]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_8 ( + .re (status_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[8].d), + .qre (), + .qe (), + .q (), + .qs (status_8_qs) + ); + + // Subregister 9 of Multireg status + // R[status_9]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_9 ( + .re (status_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[9].d), + .qre (), + .qe (), + .q (), + .qs (status_9_qs) + ); + + // Subregister 10 of Multireg status + // R[status_10]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_10 ( + .re (status_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[10].d), + .qre (), + .qe (), + .q (), + .qs (status_10_qs) + ); + + // Subregister 11 of Multireg status + // R[status_11]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_11 ( + .re (status_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[11].d), + .qre (), + .qe (), + .q (), + .qs (status_11_qs) + ); + + // Subregister 12 of Multireg status + // R[status_12]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_12 ( + .re (status_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[12].d), + .qre (), + .qe (), + .q (), + .qs (status_12_qs) + ); + + // Subregister 13 of Multireg status + // R[status_13]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_13 ( + .re (status_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[13].d), + .qre (), + .qe (), + .q (), + .qs (status_13_qs) + ); + + // Subregister 14 of Multireg status + // R[status_14]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_14 ( + .re (status_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[14].d), + .qre (), + .qe (), + .q (), + .qs (status_14_qs) + ); + + // Subregister 15 of Multireg status + // R[status_15]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_15 ( + .re (status_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[15].d), + .qre (), + .qe (), + .q (), + .qs (status_15_qs) + ); + + + + // Subregister 0 of Multireg next_id + // R[next_id_0]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_0 ( + .re (next_id_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[0].d), + .qre (reg2hw.next_id[0].re), + .qe (), + .q (reg2hw.next_id[0].q ), + .qs (next_id_0_qs) + ); + + // Subregister 1 of Multireg next_id + // R[next_id_1]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_1 ( + .re (next_id_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[1].d), + .qre (reg2hw.next_id[1].re), + .qe (), + .q (reg2hw.next_id[1].q ), + .qs (next_id_1_qs) + ); + + // Subregister 2 of Multireg next_id + // R[next_id_2]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_2 ( + .re (next_id_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[2].d), + .qre (reg2hw.next_id[2].re), + .qe (), + .q (reg2hw.next_id[2].q ), + .qs (next_id_2_qs) + ); + + // Subregister 3 of Multireg next_id + // R[next_id_3]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_3 ( + .re (next_id_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[3].d), + .qre (reg2hw.next_id[3].re), + .qe (), + .q (reg2hw.next_id[3].q ), + .qs (next_id_3_qs) + ); + + // Subregister 4 of Multireg next_id + // R[next_id_4]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_4 ( + .re (next_id_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[4].d), + .qre (reg2hw.next_id[4].re), + .qe (), + .q (reg2hw.next_id[4].q ), + .qs (next_id_4_qs) + ); + + // Subregister 5 of Multireg next_id + // R[next_id_5]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_5 ( + .re (next_id_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[5].d), + .qre (reg2hw.next_id[5].re), + .qe (), + .q (reg2hw.next_id[5].q ), + .qs (next_id_5_qs) + ); + + // Subregister 6 of Multireg next_id + // R[next_id_6]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_6 ( + .re (next_id_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[6].d), + .qre (reg2hw.next_id[6].re), + .qe (), + .q (reg2hw.next_id[6].q ), + .qs (next_id_6_qs) + ); + + // Subregister 7 of Multireg next_id + // R[next_id_7]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_7 ( + .re (next_id_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[7].d), + .qre (reg2hw.next_id[7].re), + .qe (), + .q (reg2hw.next_id[7].q ), + .qs (next_id_7_qs) + ); + + // Subregister 8 of Multireg next_id + // R[next_id_8]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_8 ( + .re (next_id_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[8].d), + .qre (reg2hw.next_id[8].re), + .qe (), + .q (reg2hw.next_id[8].q ), + .qs (next_id_8_qs) + ); + + // Subregister 9 of Multireg next_id + // R[next_id_9]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_9 ( + .re (next_id_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[9].d), + .qre (reg2hw.next_id[9].re), + .qe (), + .q (reg2hw.next_id[9].q ), + .qs (next_id_9_qs) + ); + + // Subregister 10 of Multireg next_id + // R[next_id_10]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_10 ( + .re (next_id_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[10].d), + .qre (reg2hw.next_id[10].re), + .qe (), + .q (reg2hw.next_id[10].q ), + .qs (next_id_10_qs) + ); + + // Subregister 11 of Multireg next_id + // R[next_id_11]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_11 ( + .re (next_id_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[11].d), + .qre (reg2hw.next_id[11].re), + .qe (), + .q (reg2hw.next_id[11].q ), + .qs (next_id_11_qs) + ); + + // Subregister 12 of Multireg next_id + // R[next_id_12]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_12 ( + .re (next_id_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[12].d), + .qre (reg2hw.next_id[12].re), + .qe (), + .q (reg2hw.next_id[12].q ), + .qs (next_id_12_qs) + ); + + // Subregister 13 of Multireg next_id + // R[next_id_13]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_13 ( + .re (next_id_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[13].d), + .qre (reg2hw.next_id[13].re), + .qe (), + .q (reg2hw.next_id[13].q ), + .qs (next_id_13_qs) + ); + + // Subregister 14 of Multireg next_id + // R[next_id_14]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_14 ( + .re (next_id_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[14].d), + .qre (reg2hw.next_id[14].re), + .qe (), + .q (reg2hw.next_id[14].q ), + .qs (next_id_14_qs) + ); + + // Subregister 15 of Multireg next_id + // R[next_id_15]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_15 ( + .re (next_id_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[15].d), + .qre (reg2hw.next_id[15].re), + .qe (), + .q (reg2hw.next_id[15].q ), + .qs (next_id_15_qs) + ); + + + + // Subregister 0 of Multireg done_id + // R[done_id_0]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_0 ( + .re (done_id_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[0].d), + .qre (), + .qe (), + .q (), + .qs (done_id_0_qs) + ); + + // Subregister 1 of Multireg done_id + // R[done_id_1]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_1 ( + .re (done_id_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[1].d), + .qre (), + .qe (), + .q (), + .qs (done_id_1_qs) + ); + + // Subregister 2 of Multireg done_id + // R[done_id_2]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_2 ( + .re (done_id_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[2].d), + .qre (), + .qe (), + .q (), + .qs (done_id_2_qs) + ); + + // Subregister 3 of Multireg done_id + // R[done_id_3]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_3 ( + .re (done_id_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[3].d), + .qre (), + .qe (), + .q (), + .qs (done_id_3_qs) + ); + + // Subregister 4 of Multireg done_id + // R[done_id_4]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_4 ( + .re (done_id_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[4].d), + .qre (), + .qe (), + .q (), + .qs (done_id_4_qs) + ); + + // Subregister 5 of Multireg done_id + // R[done_id_5]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_5 ( + .re (done_id_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[5].d), + .qre (), + .qe (), + .q (), + .qs (done_id_5_qs) + ); + + // Subregister 6 of Multireg done_id + // R[done_id_6]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_6 ( + .re (done_id_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[6].d), + .qre (), + .qe (), + .q (), + .qs (done_id_6_qs) + ); + + // Subregister 7 of Multireg done_id + // R[done_id_7]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_7 ( + .re (done_id_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[7].d), + .qre (), + .qe (), + .q (), + .qs (done_id_7_qs) + ); + + // Subregister 8 of Multireg done_id + // R[done_id_8]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_8 ( + .re (done_id_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[8].d), + .qre (), + .qe (), + .q (), + .qs (done_id_8_qs) + ); + + // Subregister 9 of Multireg done_id + // R[done_id_9]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_9 ( + .re (done_id_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[9].d), + .qre (), + .qe (), + .q (), + .qs (done_id_9_qs) + ); + + // Subregister 10 of Multireg done_id + // R[done_id_10]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_10 ( + .re (done_id_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[10].d), + .qre (), + .qe (), + .q (), + .qs (done_id_10_qs) + ); + + // Subregister 11 of Multireg done_id + // R[done_id_11]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_11 ( + .re (done_id_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[11].d), + .qre (), + .qe (), + .q (), + .qs (done_id_11_qs) + ); + + // Subregister 12 of Multireg done_id + // R[done_id_12]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_12 ( + .re (done_id_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[12].d), + .qre (), + .qe (), + .q (), + .qs (done_id_12_qs) + ); + + // Subregister 13 of Multireg done_id + // R[done_id_13]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_13 ( + .re (done_id_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[13].d), + .qre (), + .qe (), + .q (), + .qs (done_id_13_qs) + ); + + // Subregister 14 of Multireg done_id + // R[done_id_14]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_14 ( + .re (done_id_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[14].d), + .qre (), + .qe (), + .q (), + .qs (done_id_14_qs) + ); + + // Subregister 15 of Multireg done_id + // R[done_id_15]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_15 ( + .re (done_id_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[15].d), + .qre (), + .qe (), + .q (), + .qs (done_id_15_qs) + ); + + + // R[dst_addr_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_addr_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_addr_low_we), + .wd (dst_addr_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_addr_low.q ), + + // to register interface (read) + .qs (dst_addr_low_qs) + ); + + + // R[src_addr_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_addr_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_addr_low_we), + .wd (src_addr_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_addr_low.q ), + + // to register interface (read) + .qs (src_addr_low_qs) + ); + + + // R[length_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_length_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (length_low_we), + .wd (length_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.length_low.q ), + + // to register interface (read) + .qs (length_low_qs) + ); + + + // R[dst_stride_2_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_stride_2_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_stride_2_low_we), + .wd (dst_stride_2_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_stride_2_low.q ), + + // to register interface (read) + .qs (dst_stride_2_low_qs) + ); + + + // R[src_stride_2_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_stride_2_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_stride_2_low_we), + .wd (src_stride_2_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_stride_2_low.q ), + + // to register interface (read) + .qs (src_stride_2_low_qs) + ); + + + // R[reps_2_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_reps_2_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (reps_2_low_we), + .wd (reps_2_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.reps_2_low.q ), + + // to register interface (read) + .qs (reps_2_low_qs) + ); + + + // R[dst_stride_3_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_stride_3_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_stride_3_low_we), + .wd (dst_stride_3_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_stride_3_low.q ), + + // to register interface (read) + .qs (dst_stride_3_low_qs) + ); + + + // R[src_stride_3_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_stride_3_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_stride_3_low_we), + .wd (src_stride_3_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_stride_3_low.q ), + + // to register interface (read) + .qs (src_stride_3_low_qs) + ); + + + // R[reps_3_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_reps_3_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (reps_3_low_we), + .wd (reps_3_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.reps_3_low.q ), + + // to register interface (read) + .qs (reps_3_low_qs) + ); + + + + + logic [57:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[ 0] = (reg_addr == IDMA_REG32_3D_CONF_OFFSET); + addr_hit[ 1] = (reg_addr == IDMA_REG32_3D_STATUS_0_OFFSET); + addr_hit[ 2] = (reg_addr == IDMA_REG32_3D_STATUS_1_OFFSET); + addr_hit[ 3] = (reg_addr == IDMA_REG32_3D_STATUS_2_OFFSET); + addr_hit[ 4] = (reg_addr == IDMA_REG32_3D_STATUS_3_OFFSET); + addr_hit[ 5] = (reg_addr == IDMA_REG32_3D_STATUS_4_OFFSET); + addr_hit[ 6] = (reg_addr == IDMA_REG32_3D_STATUS_5_OFFSET); + addr_hit[ 7] = (reg_addr == IDMA_REG32_3D_STATUS_6_OFFSET); + addr_hit[ 8] = (reg_addr == IDMA_REG32_3D_STATUS_7_OFFSET); + addr_hit[ 9] = (reg_addr == IDMA_REG32_3D_STATUS_8_OFFSET); + addr_hit[10] = (reg_addr == IDMA_REG32_3D_STATUS_9_OFFSET); + addr_hit[11] = (reg_addr == IDMA_REG32_3D_STATUS_10_OFFSET); + addr_hit[12] = (reg_addr == IDMA_REG32_3D_STATUS_11_OFFSET); + addr_hit[13] = (reg_addr == IDMA_REG32_3D_STATUS_12_OFFSET); + addr_hit[14] = (reg_addr == IDMA_REG32_3D_STATUS_13_OFFSET); + addr_hit[15] = (reg_addr == IDMA_REG32_3D_STATUS_14_OFFSET); + addr_hit[16] = (reg_addr == IDMA_REG32_3D_STATUS_15_OFFSET); + addr_hit[17] = (reg_addr == IDMA_REG32_3D_NEXT_ID_0_OFFSET); + addr_hit[18] = (reg_addr == IDMA_REG32_3D_NEXT_ID_1_OFFSET); + addr_hit[19] = (reg_addr == IDMA_REG32_3D_NEXT_ID_2_OFFSET); + addr_hit[20] = (reg_addr == IDMA_REG32_3D_NEXT_ID_3_OFFSET); + addr_hit[21] = (reg_addr == IDMA_REG32_3D_NEXT_ID_4_OFFSET); + addr_hit[22] = (reg_addr == IDMA_REG32_3D_NEXT_ID_5_OFFSET); + addr_hit[23] = (reg_addr == IDMA_REG32_3D_NEXT_ID_6_OFFSET); + addr_hit[24] = (reg_addr == IDMA_REG32_3D_NEXT_ID_7_OFFSET); + addr_hit[25] = (reg_addr == IDMA_REG32_3D_NEXT_ID_8_OFFSET); + addr_hit[26] = (reg_addr == IDMA_REG32_3D_NEXT_ID_9_OFFSET); + addr_hit[27] = (reg_addr == IDMA_REG32_3D_NEXT_ID_10_OFFSET); + addr_hit[28] = (reg_addr == IDMA_REG32_3D_NEXT_ID_11_OFFSET); + addr_hit[29] = (reg_addr == IDMA_REG32_3D_NEXT_ID_12_OFFSET); + addr_hit[30] = (reg_addr == IDMA_REG32_3D_NEXT_ID_13_OFFSET); + addr_hit[31] = (reg_addr == IDMA_REG32_3D_NEXT_ID_14_OFFSET); + addr_hit[32] = (reg_addr == IDMA_REG32_3D_NEXT_ID_15_OFFSET); + addr_hit[33] = (reg_addr == IDMA_REG32_3D_DONE_ID_0_OFFSET); + addr_hit[34] = (reg_addr == IDMA_REG32_3D_DONE_ID_1_OFFSET); + addr_hit[35] = (reg_addr == IDMA_REG32_3D_DONE_ID_2_OFFSET); + addr_hit[36] = (reg_addr == IDMA_REG32_3D_DONE_ID_3_OFFSET); + addr_hit[37] = (reg_addr == IDMA_REG32_3D_DONE_ID_4_OFFSET); + addr_hit[38] = (reg_addr == IDMA_REG32_3D_DONE_ID_5_OFFSET); + addr_hit[39] = (reg_addr == IDMA_REG32_3D_DONE_ID_6_OFFSET); + addr_hit[40] = (reg_addr == IDMA_REG32_3D_DONE_ID_7_OFFSET); + addr_hit[41] = (reg_addr == IDMA_REG32_3D_DONE_ID_8_OFFSET); + addr_hit[42] = (reg_addr == IDMA_REG32_3D_DONE_ID_9_OFFSET); + addr_hit[43] = (reg_addr == IDMA_REG32_3D_DONE_ID_10_OFFSET); + addr_hit[44] = (reg_addr == IDMA_REG32_3D_DONE_ID_11_OFFSET); + addr_hit[45] = (reg_addr == IDMA_REG32_3D_DONE_ID_12_OFFSET); + addr_hit[46] = (reg_addr == IDMA_REG32_3D_DONE_ID_13_OFFSET); + addr_hit[47] = (reg_addr == IDMA_REG32_3D_DONE_ID_14_OFFSET); + addr_hit[48] = (reg_addr == IDMA_REG32_3D_DONE_ID_15_OFFSET); + addr_hit[49] = (reg_addr == IDMA_REG32_3D_DST_ADDR_LOW_OFFSET); + addr_hit[50] = (reg_addr == IDMA_REG32_3D_SRC_ADDR_LOW_OFFSET); + addr_hit[51] = (reg_addr == IDMA_REG32_3D_LENGTH_LOW_OFFSET); + addr_hit[52] = (reg_addr == IDMA_REG32_3D_DST_STRIDE_2_LOW_OFFSET); + addr_hit[53] = (reg_addr == IDMA_REG32_3D_SRC_STRIDE_2_LOW_OFFSET); + addr_hit[54] = (reg_addr == IDMA_REG32_3D_REPS_2_LOW_OFFSET); + addr_hit[55] = (reg_addr == IDMA_REG32_3D_DST_STRIDE_3_LOW_OFFSET); + addr_hit[56] = (reg_addr == IDMA_REG32_3D_SRC_STRIDE_3_LOW_OFFSET); + addr_hit[57] = (reg_addr == IDMA_REG32_3D_REPS_3_LOW_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[ 0] & (|(IDMA_REG32_3D_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(IDMA_REG32_3D_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(IDMA_REG32_3D_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(IDMA_REG32_3D_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(IDMA_REG32_3D_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(IDMA_REG32_3D_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(IDMA_REG32_3D_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(IDMA_REG32_3D_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(IDMA_REG32_3D_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(IDMA_REG32_3D_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(IDMA_REG32_3D_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(IDMA_REG32_3D_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(IDMA_REG32_3D_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(IDMA_REG32_3D_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(IDMA_REG32_3D_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(IDMA_REG32_3D_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(IDMA_REG32_3D_PERMIT[16] & ~reg_be))) | + (addr_hit[17] & (|(IDMA_REG32_3D_PERMIT[17] & ~reg_be))) | + (addr_hit[18] & (|(IDMA_REG32_3D_PERMIT[18] & ~reg_be))) | + (addr_hit[19] & (|(IDMA_REG32_3D_PERMIT[19] & ~reg_be))) | + (addr_hit[20] & (|(IDMA_REG32_3D_PERMIT[20] & ~reg_be))) | + (addr_hit[21] & (|(IDMA_REG32_3D_PERMIT[21] & ~reg_be))) | + (addr_hit[22] & (|(IDMA_REG32_3D_PERMIT[22] & ~reg_be))) | + (addr_hit[23] & (|(IDMA_REG32_3D_PERMIT[23] & ~reg_be))) | + (addr_hit[24] & (|(IDMA_REG32_3D_PERMIT[24] & ~reg_be))) | + (addr_hit[25] & (|(IDMA_REG32_3D_PERMIT[25] & ~reg_be))) | + (addr_hit[26] & (|(IDMA_REG32_3D_PERMIT[26] & ~reg_be))) | + (addr_hit[27] & (|(IDMA_REG32_3D_PERMIT[27] & ~reg_be))) | + (addr_hit[28] & (|(IDMA_REG32_3D_PERMIT[28] & ~reg_be))) | + (addr_hit[29] & (|(IDMA_REG32_3D_PERMIT[29] & ~reg_be))) | + (addr_hit[30] & (|(IDMA_REG32_3D_PERMIT[30] & ~reg_be))) | + (addr_hit[31] & (|(IDMA_REG32_3D_PERMIT[31] & ~reg_be))) | + (addr_hit[32] & (|(IDMA_REG32_3D_PERMIT[32] & ~reg_be))) | + (addr_hit[33] & (|(IDMA_REG32_3D_PERMIT[33] & ~reg_be))) | + (addr_hit[34] & (|(IDMA_REG32_3D_PERMIT[34] & ~reg_be))) | + (addr_hit[35] & (|(IDMA_REG32_3D_PERMIT[35] & ~reg_be))) | + (addr_hit[36] & (|(IDMA_REG32_3D_PERMIT[36] & ~reg_be))) | + (addr_hit[37] & (|(IDMA_REG32_3D_PERMIT[37] & ~reg_be))) | + (addr_hit[38] & (|(IDMA_REG32_3D_PERMIT[38] & ~reg_be))) | + (addr_hit[39] & (|(IDMA_REG32_3D_PERMIT[39] & ~reg_be))) | + (addr_hit[40] & (|(IDMA_REG32_3D_PERMIT[40] & ~reg_be))) | + (addr_hit[41] & (|(IDMA_REG32_3D_PERMIT[41] & ~reg_be))) | + (addr_hit[42] & (|(IDMA_REG32_3D_PERMIT[42] & ~reg_be))) | + (addr_hit[43] & (|(IDMA_REG32_3D_PERMIT[43] & ~reg_be))) | + (addr_hit[44] & (|(IDMA_REG32_3D_PERMIT[44] & ~reg_be))) | + (addr_hit[45] & (|(IDMA_REG32_3D_PERMIT[45] & ~reg_be))) | + (addr_hit[46] & (|(IDMA_REG32_3D_PERMIT[46] & ~reg_be))) | + (addr_hit[47] & (|(IDMA_REG32_3D_PERMIT[47] & ~reg_be))) | + (addr_hit[48] & (|(IDMA_REG32_3D_PERMIT[48] & ~reg_be))) | + (addr_hit[49] & (|(IDMA_REG32_3D_PERMIT[49] & ~reg_be))) | + (addr_hit[50] & (|(IDMA_REG32_3D_PERMIT[50] & ~reg_be))) | + (addr_hit[51] & (|(IDMA_REG32_3D_PERMIT[51] & ~reg_be))) | + (addr_hit[52] & (|(IDMA_REG32_3D_PERMIT[52] & ~reg_be))) | + (addr_hit[53] & (|(IDMA_REG32_3D_PERMIT[53] & ~reg_be))) | + (addr_hit[54] & (|(IDMA_REG32_3D_PERMIT[54] & ~reg_be))) | + (addr_hit[55] & (|(IDMA_REG32_3D_PERMIT[55] & ~reg_be))) | + (addr_hit[56] & (|(IDMA_REG32_3D_PERMIT[56] & ~reg_be))) | + (addr_hit[57] & (|(IDMA_REG32_3D_PERMIT[57] & ~reg_be))))); + end + + assign conf_decouple_aw_we = addr_hit[0] & reg_we & !reg_error; + assign conf_decouple_aw_wd = reg_wdata[0]; + + assign conf_decouple_rw_we = addr_hit[0] & reg_we & !reg_error; + assign conf_decouple_rw_wd = reg_wdata[1]; + + assign conf_src_reduce_len_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_reduce_len_wd = reg_wdata[2]; + + assign conf_dst_reduce_len_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_reduce_len_wd = reg_wdata[3]; + + assign conf_src_max_llen_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_max_llen_wd = reg_wdata[6:4]; + + assign conf_dst_max_llen_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_max_llen_wd = reg_wdata[9:7]; + + assign conf_enable_nd_we = addr_hit[0] & reg_we & !reg_error; + assign conf_enable_nd_wd = reg_wdata[11:10]; + + assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_protocol_wd = reg_wdata[13:11]; + + assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_protocol_wd = reg_wdata[15:13]; + + assign status_0_re = addr_hit[1] & reg_re & !reg_error; + + assign status_1_re = addr_hit[2] & reg_re & !reg_error; + + assign status_2_re = addr_hit[3] & reg_re & !reg_error; + + assign status_3_re = addr_hit[4] & reg_re & !reg_error; + + assign status_4_re = addr_hit[5] & reg_re & !reg_error; + + assign status_5_re = addr_hit[6] & reg_re & !reg_error; + + assign status_6_re = addr_hit[7] & reg_re & !reg_error; + + assign status_7_re = addr_hit[8] & reg_re & !reg_error; + + assign status_8_re = addr_hit[9] & reg_re & !reg_error; + + assign status_9_re = addr_hit[10] & reg_re & !reg_error; + + assign status_10_re = addr_hit[11] & reg_re & !reg_error; + + assign status_11_re = addr_hit[12] & reg_re & !reg_error; + + assign status_12_re = addr_hit[13] & reg_re & !reg_error; + + assign status_13_re = addr_hit[14] & reg_re & !reg_error; + + assign status_14_re = addr_hit[15] & reg_re & !reg_error; + + assign status_15_re = addr_hit[16] & reg_re & !reg_error; + + assign next_id_0_re = addr_hit[17] & reg_re & !reg_error; + + assign next_id_1_re = addr_hit[18] & reg_re & !reg_error; + + assign next_id_2_re = addr_hit[19] & reg_re & !reg_error; + + assign next_id_3_re = addr_hit[20] & reg_re & !reg_error; + + assign next_id_4_re = addr_hit[21] & reg_re & !reg_error; + + assign next_id_5_re = addr_hit[22] & reg_re & !reg_error; + + assign next_id_6_re = addr_hit[23] & reg_re & !reg_error; + + assign next_id_7_re = addr_hit[24] & reg_re & !reg_error; + + assign next_id_8_re = addr_hit[25] & reg_re & !reg_error; + + assign next_id_9_re = addr_hit[26] & reg_re & !reg_error; + + assign next_id_10_re = addr_hit[27] & reg_re & !reg_error; + + assign next_id_11_re = addr_hit[28] & reg_re & !reg_error; + + assign next_id_12_re = addr_hit[29] & reg_re & !reg_error; + + assign next_id_13_re = addr_hit[30] & reg_re & !reg_error; + + assign next_id_14_re = addr_hit[31] & reg_re & !reg_error; + + assign next_id_15_re = addr_hit[32] & reg_re & !reg_error; + + assign done_id_0_re = addr_hit[33] & reg_re & !reg_error; + + assign done_id_1_re = addr_hit[34] & reg_re & !reg_error; + + assign done_id_2_re = addr_hit[35] & reg_re & !reg_error; + + assign done_id_3_re = addr_hit[36] & reg_re & !reg_error; + + assign done_id_4_re = addr_hit[37] & reg_re & !reg_error; + + assign done_id_5_re = addr_hit[38] & reg_re & !reg_error; + + assign done_id_6_re = addr_hit[39] & reg_re & !reg_error; + + assign done_id_7_re = addr_hit[40] & reg_re & !reg_error; + + assign done_id_8_re = addr_hit[41] & reg_re & !reg_error; + + assign done_id_9_re = addr_hit[42] & reg_re & !reg_error; + + assign done_id_10_re = addr_hit[43] & reg_re & !reg_error; + + assign done_id_11_re = addr_hit[44] & reg_re & !reg_error; + + assign done_id_12_re = addr_hit[45] & reg_re & !reg_error; + + assign done_id_13_re = addr_hit[46] & reg_re & !reg_error; + + assign done_id_14_re = addr_hit[47] & reg_re & !reg_error; + + assign done_id_15_re = addr_hit[48] & reg_re & !reg_error; + + assign dst_addr_low_we = addr_hit[49] & reg_we & !reg_error; + assign dst_addr_low_wd = reg_wdata[31:0]; + + assign src_addr_low_we = addr_hit[50] & reg_we & !reg_error; + assign src_addr_low_wd = reg_wdata[31:0]; + + assign length_low_we = addr_hit[51] & reg_we & !reg_error; + assign length_low_wd = reg_wdata[31:0]; + + assign dst_stride_2_low_we = addr_hit[52] & reg_we & !reg_error; + assign dst_stride_2_low_wd = reg_wdata[31:0]; + + assign src_stride_2_low_we = addr_hit[53] & reg_we & !reg_error; + assign src_stride_2_low_wd = reg_wdata[31:0]; + + assign reps_2_low_we = addr_hit[54] & reg_we & !reg_error; + assign reps_2_low_wd = reg_wdata[31:0]; + + assign dst_stride_3_low_we = addr_hit[55] & reg_we & !reg_error; + assign dst_stride_3_low_wd = reg_wdata[31:0]; + + assign src_stride_3_low_we = addr_hit[56] & reg_we & !reg_error; + assign src_stride_3_low_wd = reg_wdata[31:0]; + + assign reps_3_low_we = addr_hit[57] & reg_we & !reg_error; + assign reps_3_low_wd = reg_wdata[31:0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[0] = conf_decouple_aw_qs; + reg_rdata_next[1] = conf_decouple_rw_qs; + reg_rdata_next[2] = conf_src_reduce_len_qs; + reg_rdata_next[3] = conf_dst_reduce_len_qs; + reg_rdata_next[6:4] = conf_src_max_llen_qs; + reg_rdata_next[9:7] = conf_dst_max_llen_qs; + reg_rdata_next[11:10] = conf_enable_nd_qs; + reg_rdata_next[13:11] = conf_src_protocol_qs; + reg_rdata_next[15:13] = conf_dst_protocol_qs; + end + + addr_hit[1]: begin + reg_rdata_next[9:0] = status_0_qs; + end + + addr_hit[2]: begin + reg_rdata_next[9:0] = status_1_qs; + end + + addr_hit[3]: begin + reg_rdata_next[9:0] = status_2_qs; + end + + addr_hit[4]: begin + reg_rdata_next[9:0] = status_3_qs; + end + + addr_hit[5]: begin + reg_rdata_next[9:0] = status_4_qs; + end + + addr_hit[6]: begin + reg_rdata_next[9:0] = status_5_qs; + end + + addr_hit[7]: begin + reg_rdata_next[9:0] = status_6_qs; + end + + addr_hit[8]: begin + reg_rdata_next[9:0] = status_7_qs; + end + + addr_hit[9]: begin + reg_rdata_next[9:0] = status_8_qs; + end + + addr_hit[10]: begin + reg_rdata_next[9:0] = status_9_qs; + end + + addr_hit[11]: begin + reg_rdata_next[9:0] = status_10_qs; + end + + addr_hit[12]: begin + reg_rdata_next[9:0] = status_11_qs; + end + + addr_hit[13]: begin + reg_rdata_next[9:0] = status_12_qs; + end + + addr_hit[14]: begin + reg_rdata_next[9:0] = status_13_qs; + end + + addr_hit[15]: begin + reg_rdata_next[9:0] = status_14_qs; + end + + addr_hit[16]: begin + reg_rdata_next[9:0] = status_15_qs; + end + + addr_hit[17]: begin + reg_rdata_next[31:0] = next_id_0_qs; + end + + addr_hit[18]: begin + reg_rdata_next[31:0] = next_id_1_qs; + end + + addr_hit[19]: begin + reg_rdata_next[31:0] = next_id_2_qs; + end + + addr_hit[20]: begin + reg_rdata_next[31:0] = next_id_3_qs; + end + + addr_hit[21]: begin + reg_rdata_next[31:0] = next_id_4_qs; + end + + addr_hit[22]: begin + reg_rdata_next[31:0] = next_id_5_qs; + end + + addr_hit[23]: begin + reg_rdata_next[31:0] = next_id_6_qs; + end + + addr_hit[24]: begin + reg_rdata_next[31:0] = next_id_7_qs; + end + + addr_hit[25]: begin + reg_rdata_next[31:0] = next_id_8_qs; + end + + addr_hit[26]: begin + reg_rdata_next[31:0] = next_id_9_qs; + end + + addr_hit[27]: begin + reg_rdata_next[31:0] = next_id_10_qs; + end + + addr_hit[28]: begin + reg_rdata_next[31:0] = next_id_11_qs; + end + + addr_hit[29]: begin + reg_rdata_next[31:0] = next_id_12_qs; + end + + addr_hit[30]: begin + reg_rdata_next[31:0] = next_id_13_qs; + end + + addr_hit[31]: begin + reg_rdata_next[31:0] = next_id_14_qs; + end + + addr_hit[32]: begin + reg_rdata_next[31:0] = next_id_15_qs; + end + + addr_hit[33]: begin + reg_rdata_next[31:0] = done_id_0_qs; + end + + addr_hit[34]: begin + reg_rdata_next[31:0] = done_id_1_qs; + end + + addr_hit[35]: begin + reg_rdata_next[31:0] = done_id_2_qs; + end + + addr_hit[36]: begin + reg_rdata_next[31:0] = done_id_3_qs; + end + + addr_hit[37]: begin + reg_rdata_next[31:0] = done_id_4_qs; + end + + addr_hit[38]: begin + reg_rdata_next[31:0] = done_id_5_qs; + end + + addr_hit[39]: begin + reg_rdata_next[31:0] = done_id_6_qs; + end + + addr_hit[40]: begin + reg_rdata_next[31:0] = done_id_7_qs; + end + + addr_hit[41]: begin + reg_rdata_next[31:0] = done_id_8_qs; + end + + addr_hit[42]: begin + reg_rdata_next[31:0] = done_id_9_qs; + end + + addr_hit[43]: begin + reg_rdata_next[31:0] = done_id_10_qs; + end + + addr_hit[44]: begin + reg_rdata_next[31:0] = done_id_11_qs; + end + + addr_hit[45]: begin + reg_rdata_next[31:0] = done_id_12_qs; + end + + addr_hit[46]: begin + reg_rdata_next[31:0] = done_id_13_qs; + end + + addr_hit[47]: begin + reg_rdata_next[31:0] = done_id_14_qs; + end + + addr_hit[48]: begin + reg_rdata_next[31:0] = done_id_15_qs; + end + + addr_hit[49]: begin + reg_rdata_next[31:0] = dst_addr_low_qs; + end + + addr_hit[50]: begin + reg_rdata_next[31:0] = src_addr_low_qs; + end + + addr_hit[51]: begin + reg_rdata_next[31:0] = length_low_qs; + end + + addr_hit[52]: begin + reg_rdata_next[31:0] = dst_stride_2_low_qs; + end + + addr_hit[53]: begin + reg_rdata_next[31:0] = src_stride_2_low_qs; + end + + addr_hit[54]: begin + reg_rdata_next[31:0] = reps_2_low_qs; + end + + addr_hit[55]: begin + reg_rdata_next[31:0] = dst_stride_3_low_qs; + end + + addr_hit[56]: begin + reg_rdata_next[31:0] = src_stride_3_low_qs; + end + + addr_hit[57]: begin + reg_rdata_next[31:0] = reps_3_low_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module idma_reg32_3d_reg_top_intf +#( + parameter int AW = 9, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output idma_reg32_3d_reg_pkg::idma_reg32_3d_reg2hw_t reg2hw, // Write + input idma_reg32_3d_reg_pkg::idma_reg32_3d_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW/8; + +`include "register_interface/typedef.svh" +`include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + idma_reg32_3d_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module idma_reg64_2d_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 8 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output idma_reg64_2d_reg_pkg::idma_reg64_2d_reg2hw_t reg2hw, // Write + input idma_reg64_2d_reg_pkg::idma_reg64_2d_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import idma_reg64_2d_reg_pkg::* ; + + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [BlockAw-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next ; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic conf_decouple_aw_qs; + logic conf_decouple_aw_wd; + logic conf_decouple_aw_we; + logic conf_decouple_rw_qs; + logic conf_decouple_rw_wd; + logic conf_decouple_rw_we; + logic conf_src_reduce_len_qs; + logic conf_src_reduce_len_wd; + logic conf_src_reduce_len_we; + logic conf_dst_reduce_len_qs; + logic conf_dst_reduce_len_wd; + logic conf_dst_reduce_len_we; + logic [2:0] conf_src_max_llen_qs; + logic [2:0] conf_src_max_llen_wd; + logic conf_src_max_llen_we; + logic [2:0] conf_dst_max_llen_qs; + logic [2:0] conf_dst_max_llen_wd; + logic conf_dst_max_llen_we; + logic conf_enable_nd_qs; + logic conf_enable_nd_wd; + logic conf_enable_nd_we; + logic [2:0] conf_src_protocol_qs; + logic [2:0] conf_src_protocol_wd; + logic conf_src_protocol_we; + logic [2:0] conf_dst_protocol_qs; + logic [2:0] conf_dst_protocol_wd; + logic conf_dst_protocol_we; + logic [9:0] status_0_qs; + logic status_0_re; + logic [9:0] status_1_qs; + logic status_1_re; + logic [9:0] status_2_qs; + logic status_2_re; + logic [9:0] status_3_qs; + logic status_3_re; + logic [9:0] status_4_qs; + logic status_4_re; + logic [9:0] status_5_qs; + logic status_5_re; + logic [9:0] status_6_qs; + logic status_6_re; + logic [9:0] status_7_qs; + logic status_7_re; + logic [9:0] status_8_qs; + logic status_8_re; + logic [9:0] status_9_qs; + logic status_9_re; + logic [9:0] status_10_qs; + logic status_10_re; + logic [9:0] status_11_qs; + logic status_11_re; + logic [9:0] status_12_qs; + logic status_12_re; + logic [9:0] status_13_qs; + logic status_13_re; + logic [9:0] status_14_qs; + logic status_14_re; + logic [9:0] status_15_qs; + logic status_15_re; + logic [31:0] next_id_0_qs; + logic next_id_0_re; + logic [31:0] next_id_1_qs; + logic next_id_1_re; + logic [31:0] next_id_2_qs; + logic next_id_2_re; + logic [31:0] next_id_3_qs; + logic next_id_3_re; + logic [31:0] next_id_4_qs; + logic next_id_4_re; + logic [31:0] next_id_5_qs; + logic next_id_5_re; + logic [31:0] next_id_6_qs; + logic next_id_6_re; + logic [31:0] next_id_7_qs; + logic next_id_7_re; + logic [31:0] next_id_8_qs; + logic next_id_8_re; + logic [31:0] next_id_9_qs; + logic next_id_9_re; + logic [31:0] next_id_10_qs; + logic next_id_10_re; + logic [31:0] next_id_11_qs; + logic next_id_11_re; + logic [31:0] next_id_12_qs; + logic next_id_12_re; + logic [31:0] next_id_13_qs; + logic next_id_13_re; + logic [31:0] next_id_14_qs; + logic next_id_14_re; + logic [31:0] next_id_15_qs; + logic next_id_15_re; + logic [31:0] done_id_0_qs; + logic done_id_0_re; + logic [31:0] done_id_1_qs; + logic done_id_1_re; + logic [31:0] done_id_2_qs; + logic done_id_2_re; + logic [31:0] done_id_3_qs; + logic done_id_3_re; + logic [31:0] done_id_4_qs; + logic done_id_4_re; + logic [31:0] done_id_5_qs; + logic done_id_5_re; + logic [31:0] done_id_6_qs; + logic done_id_6_re; + logic [31:0] done_id_7_qs; + logic done_id_7_re; + logic [31:0] done_id_8_qs; + logic done_id_8_re; + logic [31:0] done_id_9_qs; + logic done_id_9_re; + logic [31:0] done_id_10_qs; + logic done_id_10_re; + logic [31:0] done_id_11_qs; + logic done_id_11_re; + logic [31:0] done_id_12_qs; + logic done_id_12_re; + logic [31:0] done_id_13_qs; + logic done_id_13_re; + logic [31:0] done_id_14_qs; + logic done_id_14_re; + logic [31:0] done_id_15_qs; + logic done_id_15_re; + logic [31:0] dst_addr_low_qs; + logic [31:0] dst_addr_low_wd; + logic dst_addr_low_we; + logic [31:0] dst_addr_high_qs; + logic [31:0] dst_addr_high_wd; + logic dst_addr_high_we; + logic [31:0] src_addr_low_qs; + logic [31:0] src_addr_low_wd; + logic src_addr_low_we; + logic [31:0] src_addr_high_qs; + logic [31:0] src_addr_high_wd; + logic src_addr_high_we; + logic [31:0] length_low_qs; + logic [31:0] length_low_wd; + logic length_low_we; + logic [31:0] length_high_qs; + logic [31:0] length_high_wd; + logic length_high_we; + logic [31:0] dst_stride_2_low_qs; + logic [31:0] dst_stride_2_low_wd; + logic dst_stride_2_low_we; + logic [31:0] dst_stride_2_high_qs; + logic [31:0] dst_stride_2_high_wd; + logic dst_stride_2_high_we; + logic [31:0] src_stride_2_low_qs; + logic [31:0] src_stride_2_low_wd; + logic src_stride_2_low_we; + logic [31:0] src_stride_2_high_qs; + logic [31:0] src_stride_2_high_wd; + logic src_stride_2_high_we; + logic [31:0] reps_2_low_qs; + logic [31:0] reps_2_low_wd; + logic reps_2_low_we; + logic [31:0] reps_2_high_qs; + logic [31:0] reps_2_high_wd; + logic reps_2_high_we; + + // Register instances + // R[conf]: V(False) + + // F[decouple_aw]: 0:0 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_decouple_aw ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_decouple_aw_we), + .wd (conf_decouple_aw_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.decouple_aw.q ), + + // to register interface (read) + .qs (conf_decouple_aw_qs) + ); + + + // F[decouple_rw]: 1:1 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_decouple_rw ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_decouple_rw_we), + .wd (conf_decouple_rw_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.decouple_rw.q ), + + // to register interface (read) + .qs (conf_decouple_rw_qs) + ); + + + // F[src_reduce_len]: 2:2 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_src_reduce_len ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_reduce_len_we), + .wd (conf_src_reduce_len_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_reduce_len.q ), + + // to register interface (read) + .qs (conf_src_reduce_len_qs) + ); + + + // F[dst_reduce_len]: 3:3 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_dst_reduce_len ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_reduce_len_we), + .wd (conf_dst_reduce_len_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_reduce_len.q ), + + // to register interface (read) + .qs (conf_dst_reduce_len_qs) + ); + + + // F[src_max_llen]: 6:4 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_src_max_llen ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_max_llen_we), + .wd (conf_src_max_llen_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_max_llen.q ), + + // to register interface (read) + .qs (conf_src_max_llen_qs) + ); + + + // F[dst_max_llen]: 9:7 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_dst_max_llen ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_max_llen_we), + .wd (conf_dst_max_llen_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_max_llen.q ), + + // to register interface (read) + .qs (conf_dst_max_llen_qs) + ); + + + // F[enable_nd]: 10:10 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_enable_nd ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_enable_nd_we), + .wd (conf_enable_nd_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.enable_nd.q ), + + // to register interface (read) + .qs (conf_enable_nd_qs) + ); + + + // F[src_protocol]: 12:10 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_src_protocol ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_protocol_we), + .wd (conf_src_protocol_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_protocol.q ), + + // to register interface (read) + .qs (conf_src_protocol_qs) + ); + + + // F[dst_protocol]: 14:12 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_dst_protocol ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_protocol_we), + .wd (conf_dst_protocol_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_protocol.q ), + + // to register interface (read) + .qs (conf_dst_protocol_qs) + ); + + + + // Subregister 0 of Multireg status + // R[status_0]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_0 ( + .re (status_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[0].d), + .qre (), + .qe (), + .q (), + .qs (status_0_qs) + ); + + // Subregister 1 of Multireg status + // R[status_1]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_1 ( + .re (status_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[1].d), + .qre (), + .qe (), + .q (), + .qs (status_1_qs) + ); + + // Subregister 2 of Multireg status + // R[status_2]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_2 ( + .re (status_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[2].d), + .qre (), + .qe (), + .q (), + .qs (status_2_qs) + ); + + // Subregister 3 of Multireg status + // R[status_3]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_3 ( + .re (status_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[3].d), + .qre (), + .qe (), + .q (), + .qs (status_3_qs) + ); + + // Subregister 4 of Multireg status + // R[status_4]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_4 ( + .re (status_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[4].d), + .qre (), + .qe (), + .q (), + .qs (status_4_qs) + ); + + // Subregister 5 of Multireg status + // R[status_5]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_5 ( + .re (status_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[5].d), + .qre (), + .qe (), + .q (), + .qs (status_5_qs) + ); + + // Subregister 6 of Multireg status + // R[status_6]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_6 ( + .re (status_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[6].d), + .qre (), + .qe (), + .q (), + .qs (status_6_qs) + ); + + // Subregister 7 of Multireg status + // R[status_7]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_7 ( + .re (status_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[7].d), + .qre (), + .qe (), + .q (), + .qs (status_7_qs) + ); + + // Subregister 8 of Multireg status + // R[status_8]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_8 ( + .re (status_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[8].d), + .qre (), + .qe (), + .q (), + .qs (status_8_qs) + ); + + // Subregister 9 of Multireg status + // R[status_9]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_9 ( + .re (status_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[9].d), + .qre (), + .qe (), + .q (), + .qs (status_9_qs) + ); + + // Subregister 10 of Multireg status + // R[status_10]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_10 ( + .re (status_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[10].d), + .qre (), + .qe (), + .q (), + .qs (status_10_qs) + ); + + // Subregister 11 of Multireg status + // R[status_11]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_11 ( + .re (status_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[11].d), + .qre (), + .qe (), + .q (), + .qs (status_11_qs) + ); + + // Subregister 12 of Multireg status + // R[status_12]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_12 ( + .re (status_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[12].d), + .qre (), + .qe (), + .q (), + .qs (status_12_qs) + ); + + // Subregister 13 of Multireg status + // R[status_13]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_13 ( + .re (status_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[13].d), + .qre (), + .qe (), + .q (), + .qs (status_13_qs) + ); + + // Subregister 14 of Multireg status + // R[status_14]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_14 ( + .re (status_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[14].d), + .qre (), + .qe (), + .q (), + .qs (status_14_qs) + ); + + // Subregister 15 of Multireg status + // R[status_15]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_15 ( + .re (status_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[15].d), + .qre (), + .qe (), + .q (), + .qs (status_15_qs) + ); + + + + // Subregister 0 of Multireg next_id + // R[next_id_0]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_0 ( + .re (next_id_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[0].d), + .qre (reg2hw.next_id[0].re), + .qe (), + .q (reg2hw.next_id[0].q ), + .qs (next_id_0_qs) + ); + + // Subregister 1 of Multireg next_id + // R[next_id_1]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_1 ( + .re (next_id_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[1].d), + .qre (reg2hw.next_id[1].re), + .qe (), + .q (reg2hw.next_id[1].q ), + .qs (next_id_1_qs) + ); + + // Subregister 2 of Multireg next_id + // R[next_id_2]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_2 ( + .re (next_id_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[2].d), + .qre (reg2hw.next_id[2].re), + .qe (), + .q (reg2hw.next_id[2].q ), + .qs (next_id_2_qs) + ); + + // Subregister 3 of Multireg next_id + // R[next_id_3]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_3 ( + .re (next_id_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[3].d), + .qre (reg2hw.next_id[3].re), + .qe (), + .q (reg2hw.next_id[3].q ), + .qs (next_id_3_qs) + ); + + // Subregister 4 of Multireg next_id + // R[next_id_4]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_4 ( + .re (next_id_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[4].d), + .qre (reg2hw.next_id[4].re), + .qe (), + .q (reg2hw.next_id[4].q ), + .qs (next_id_4_qs) + ); + + // Subregister 5 of Multireg next_id + // R[next_id_5]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_5 ( + .re (next_id_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[5].d), + .qre (reg2hw.next_id[5].re), + .qe (), + .q (reg2hw.next_id[5].q ), + .qs (next_id_5_qs) + ); + + // Subregister 6 of Multireg next_id + // R[next_id_6]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_6 ( + .re (next_id_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[6].d), + .qre (reg2hw.next_id[6].re), + .qe (), + .q (reg2hw.next_id[6].q ), + .qs (next_id_6_qs) + ); + + // Subregister 7 of Multireg next_id + // R[next_id_7]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_7 ( + .re (next_id_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[7].d), + .qre (reg2hw.next_id[7].re), + .qe (), + .q (reg2hw.next_id[7].q ), + .qs (next_id_7_qs) + ); + + // Subregister 8 of Multireg next_id + // R[next_id_8]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_8 ( + .re (next_id_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[8].d), + .qre (reg2hw.next_id[8].re), + .qe (), + .q (reg2hw.next_id[8].q ), + .qs (next_id_8_qs) + ); + + // Subregister 9 of Multireg next_id + // R[next_id_9]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_9 ( + .re (next_id_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[9].d), + .qre (reg2hw.next_id[9].re), + .qe (), + .q (reg2hw.next_id[9].q ), + .qs (next_id_9_qs) + ); + + // Subregister 10 of Multireg next_id + // R[next_id_10]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_10 ( + .re (next_id_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[10].d), + .qre (reg2hw.next_id[10].re), + .qe (), + .q (reg2hw.next_id[10].q ), + .qs (next_id_10_qs) + ); + + // Subregister 11 of Multireg next_id + // R[next_id_11]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_11 ( + .re (next_id_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[11].d), + .qre (reg2hw.next_id[11].re), + .qe (), + .q (reg2hw.next_id[11].q ), + .qs (next_id_11_qs) + ); + + // Subregister 12 of Multireg next_id + // R[next_id_12]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_12 ( + .re (next_id_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[12].d), + .qre (reg2hw.next_id[12].re), + .qe (), + .q (reg2hw.next_id[12].q ), + .qs (next_id_12_qs) + ); + + // Subregister 13 of Multireg next_id + // R[next_id_13]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_13 ( + .re (next_id_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[13].d), + .qre (reg2hw.next_id[13].re), + .qe (), + .q (reg2hw.next_id[13].q ), + .qs (next_id_13_qs) + ); + + // Subregister 14 of Multireg next_id + // R[next_id_14]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_14 ( + .re (next_id_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[14].d), + .qre (reg2hw.next_id[14].re), + .qe (), + .q (reg2hw.next_id[14].q ), + .qs (next_id_14_qs) + ); + + // Subregister 15 of Multireg next_id + // R[next_id_15]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_15 ( + .re (next_id_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[15].d), + .qre (reg2hw.next_id[15].re), + .qe (), + .q (reg2hw.next_id[15].q ), + .qs (next_id_15_qs) + ); + + + + // Subregister 0 of Multireg done_id + // R[done_id_0]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_0 ( + .re (done_id_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[0].d), + .qre (), + .qe (), + .q (), + .qs (done_id_0_qs) + ); + + // Subregister 1 of Multireg done_id + // R[done_id_1]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_1 ( + .re (done_id_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[1].d), + .qre (), + .qe (), + .q (), + .qs (done_id_1_qs) + ); + + // Subregister 2 of Multireg done_id + // R[done_id_2]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_2 ( + .re (done_id_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[2].d), + .qre (), + .qe (), + .q (), + .qs (done_id_2_qs) + ); + + // Subregister 3 of Multireg done_id + // R[done_id_3]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_3 ( + .re (done_id_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[3].d), + .qre (), + .qe (), + .q (), + .qs (done_id_3_qs) + ); + + // Subregister 4 of Multireg done_id + // R[done_id_4]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_4 ( + .re (done_id_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[4].d), + .qre (), + .qe (), + .q (), + .qs (done_id_4_qs) + ); + + // Subregister 5 of Multireg done_id + // R[done_id_5]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_5 ( + .re (done_id_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[5].d), + .qre (), + .qe (), + .q (), + .qs (done_id_5_qs) + ); + + // Subregister 6 of Multireg done_id + // R[done_id_6]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_6 ( + .re (done_id_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[6].d), + .qre (), + .qe (), + .q (), + .qs (done_id_6_qs) + ); + + // Subregister 7 of Multireg done_id + // R[done_id_7]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_7 ( + .re (done_id_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[7].d), + .qre (), + .qe (), + .q (), + .qs (done_id_7_qs) + ); + + // Subregister 8 of Multireg done_id + // R[done_id_8]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_8 ( + .re (done_id_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[8].d), + .qre (), + .qe (), + .q (), + .qs (done_id_8_qs) + ); + + // Subregister 9 of Multireg done_id + // R[done_id_9]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_9 ( + .re (done_id_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[9].d), + .qre (), + .qe (), + .q (), + .qs (done_id_9_qs) + ); + + // Subregister 10 of Multireg done_id + // R[done_id_10]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_10 ( + .re (done_id_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[10].d), + .qre (), + .qe (), + .q (), + .qs (done_id_10_qs) + ); + + // Subregister 11 of Multireg done_id + // R[done_id_11]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_11 ( + .re (done_id_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[11].d), + .qre (), + .qe (), + .q (), + .qs (done_id_11_qs) + ); + + // Subregister 12 of Multireg done_id + // R[done_id_12]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_12 ( + .re (done_id_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[12].d), + .qre (), + .qe (), + .q (), + .qs (done_id_12_qs) + ); + + // Subregister 13 of Multireg done_id + // R[done_id_13]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_13 ( + .re (done_id_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[13].d), + .qre (), + .qe (), + .q (), + .qs (done_id_13_qs) + ); + + // Subregister 14 of Multireg done_id + // R[done_id_14]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_14 ( + .re (done_id_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[14].d), + .qre (), + .qe (), + .q (), + .qs (done_id_14_qs) + ); + + // Subregister 15 of Multireg done_id + // R[done_id_15]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_15 ( + .re (done_id_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[15].d), + .qre (), + .qe (), + .q (), + .qs (done_id_15_qs) + ); + + + // R[dst_addr_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_addr_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_addr_low_we), + .wd (dst_addr_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_addr_low.q ), + + // to register interface (read) + .qs (dst_addr_low_qs) + ); + + + // R[dst_addr_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_addr_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_addr_high_we), + .wd (dst_addr_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_addr_high.q ), + + // to register interface (read) + .qs (dst_addr_high_qs) + ); + + + // R[src_addr_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_addr_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_addr_low_we), + .wd (src_addr_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_addr_low.q ), + + // to register interface (read) + .qs (src_addr_low_qs) + ); + + + // R[src_addr_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_addr_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_addr_high_we), + .wd (src_addr_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_addr_high.q ), + + // to register interface (read) + .qs (src_addr_high_qs) + ); + + + // R[length_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_length_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (length_low_we), + .wd (length_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.length_low.q ), + + // to register interface (read) + .qs (length_low_qs) + ); + + + // R[length_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_length_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (length_high_we), + .wd (length_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.length_high.q ), + + // to register interface (read) + .qs (length_high_qs) + ); + + + // R[dst_stride_2_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_stride_2_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_stride_2_low_we), + .wd (dst_stride_2_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_stride_2_low.q ), + + // to register interface (read) + .qs (dst_stride_2_low_qs) + ); + + + // R[dst_stride_2_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_stride_2_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_stride_2_high_we), + .wd (dst_stride_2_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_stride_2_high.q ), + + // to register interface (read) + .qs (dst_stride_2_high_qs) + ); + + + // R[src_stride_2_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_stride_2_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_stride_2_low_we), + .wd (src_stride_2_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_stride_2_low.q ), + + // to register interface (read) + .qs (src_stride_2_low_qs) + ); + + + // R[src_stride_2_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_stride_2_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_stride_2_high_we), + .wd (src_stride_2_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_stride_2_high.q ), + + // to register interface (read) + .qs (src_stride_2_high_qs) + ); + + + // R[reps_2_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_reps_2_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (reps_2_low_we), + .wd (reps_2_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.reps_2_low.q ), + + // to register interface (read) + .qs (reps_2_low_qs) + ); + + + // R[reps_2_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_reps_2_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (reps_2_high_we), + .wd (reps_2_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.reps_2_high.q ), + + // to register interface (read) + .qs (reps_2_high_qs) + ); + + + + + logic [60:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[ 0] = (reg_addr == IDMA_REG64_2D_CONF_OFFSET); + addr_hit[ 1] = (reg_addr == IDMA_REG64_2D_STATUS_0_OFFSET); + addr_hit[ 2] = (reg_addr == IDMA_REG64_2D_STATUS_1_OFFSET); + addr_hit[ 3] = (reg_addr == IDMA_REG64_2D_STATUS_2_OFFSET); + addr_hit[ 4] = (reg_addr == IDMA_REG64_2D_STATUS_3_OFFSET); + addr_hit[ 5] = (reg_addr == IDMA_REG64_2D_STATUS_4_OFFSET); + addr_hit[ 6] = (reg_addr == IDMA_REG64_2D_STATUS_5_OFFSET); + addr_hit[ 7] = (reg_addr == IDMA_REG64_2D_STATUS_6_OFFSET); + addr_hit[ 8] = (reg_addr == IDMA_REG64_2D_STATUS_7_OFFSET); + addr_hit[ 9] = (reg_addr == IDMA_REG64_2D_STATUS_8_OFFSET); + addr_hit[10] = (reg_addr == IDMA_REG64_2D_STATUS_9_OFFSET); + addr_hit[11] = (reg_addr == IDMA_REG64_2D_STATUS_10_OFFSET); + addr_hit[12] = (reg_addr == IDMA_REG64_2D_STATUS_11_OFFSET); + addr_hit[13] = (reg_addr == IDMA_REG64_2D_STATUS_12_OFFSET); + addr_hit[14] = (reg_addr == IDMA_REG64_2D_STATUS_13_OFFSET); + addr_hit[15] = (reg_addr == IDMA_REG64_2D_STATUS_14_OFFSET); + addr_hit[16] = (reg_addr == IDMA_REG64_2D_STATUS_15_OFFSET); + addr_hit[17] = (reg_addr == IDMA_REG64_2D_NEXT_ID_0_OFFSET); + addr_hit[18] = (reg_addr == IDMA_REG64_2D_NEXT_ID_1_OFFSET); + addr_hit[19] = (reg_addr == IDMA_REG64_2D_NEXT_ID_2_OFFSET); + addr_hit[20] = (reg_addr == IDMA_REG64_2D_NEXT_ID_3_OFFSET); + addr_hit[21] = (reg_addr == IDMA_REG64_2D_NEXT_ID_4_OFFSET); + addr_hit[22] = (reg_addr == IDMA_REG64_2D_NEXT_ID_5_OFFSET); + addr_hit[23] = (reg_addr == IDMA_REG64_2D_NEXT_ID_6_OFFSET); + addr_hit[24] = (reg_addr == IDMA_REG64_2D_NEXT_ID_7_OFFSET); + addr_hit[25] = (reg_addr == IDMA_REG64_2D_NEXT_ID_8_OFFSET); + addr_hit[26] = (reg_addr == IDMA_REG64_2D_NEXT_ID_9_OFFSET); + addr_hit[27] = (reg_addr == IDMA_REG64_2D_NEXT_ID_10_OFFSET); + addr_hit[28] = (reg_addr == IDMA_REG64_2D_NEXT_ID_11_OFFSET); + addr_hit[29] = (reg_addr == IDMA_REG64_2D_NEXT_ID_12_OFFSET); + addr_hit[30] = (reg_addr == IDMA_REG64_2D_NEXT_ID_13_OFFSET); + addr_hit[31] = (reg_addr == IDMA_REG64_2D_NEXT_ID_14_OFFSET); + addr_hit[32] = (reg_addr == IDMA_REG64_2D_NEXT_ID_15_OFFSET); + addr_hit[33] = (reg_addr == IDMA_REG64_2D_DONE_ID_0_OFFSET); + addr_hit[34] = (reg_addr == IDMA_REG64_2D_DONE_ID_1_OFFSET); + addr_hit[35] = (reg_addr == IDMA_REG64_2D_DONE_ID_2_OFFSET); + addr_hit[36] = (reg_addr == IDMA_REG64_2D_DONE_ID_3_OFFSET); + addr_hit[37] = (reg_addr == IDMA_REG64_2D_DONE_ID_4_OFFSET); + addr_hit[38] = (reg_addr == IDMA_REG64_2D_DONE_ID_5_OFFSET); + addr_hit[39] = (reg_addr == IDMA_REG64_2D_DONE_ID_6_OFFSET); + addr_hit[40] = (reg_addr == IDMA_REG64_2D_DONE_ID_7_OFFSET); + addr_hit[41] = (reg_addr == IDMA_REG64_2D_DONE_ID_8_OFFSET); + addr_hit[42] = (reg_addr == IDMA_REG64_2D_DONE_ID_9_OFFSET); + addr_hit[43] = (reg_addr == IDMA_REG64_2D_DONE_ID_10_OFFSET); + addr_hit[44] = (reg_addr == IDMA_REG64_2D_DONE_ID_11_OFFSET); + addr_hit[45] = (reg_addr == IDMA_REG64_2D_DONE_ID_12_OFFSET); + addr_hit[46] = (reg_addr == IDMA_REG64_2D_DONE_ID_13_OFFSET); + addr_hit[47] = (reg_addr == IDMA_REG64_2D_DONE_ID_14_OFFSET); + addr_hit[48] = (reg_addr == IDMA_REG64_2D_DONE_ID_15_OFFSET); + addr_hit[49] = (reg_addr == IDMA_REG64_2D_DST_ADDR_LOW_OFFSET); + addr_hit[50] = (reg_addr == IDMA_REG64_2D_DST_ADDR_HIGH_OFFSET); + addr_hit[51] = (reg_addr == IDMA_REG64_2D_SRC_ADDR_LOW_OFFSET); + addr_hit[52] = (reg_addr == IDMA_REG64_2D_SRC_ADDR_HIGH_OFFSET); + addr_hit[53] = (reg_addr == IDMA_REG64_2D_LENGTH_LOW_OFFSET); + addr_hit[54] = (reg_addr == IDMA_REG64_2D_LENGTH_HIGH_OFFSET); + addr_hit[55] = (reg_addr == IDMA_REG64_2D_DST_STRIDE_2_LOW_OFFSET); + addr_hit[56] = (reg_addr == IDMA_REG64_2D_DST_STRIDE_2_HIGH_OFFSET); + addr_hit[57] = (reg_addr == IDMA_REG64_2D_SRC_STRIDE_2_LOW_OFFSET); + addr_hit[58] = (reg_addr == IDMA_REG64_2D_SRC_STRIDE_2_HIGH_OFFSET); + addr_hit[59] = (reg_addr == IDMA_REG64_2D_REPS_2_LOW_OFFSET); + addr_hit[60] = (reg_addr == IDMA_REG64_2D_REPS_2_HIGH_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[ 0] & (|(IDMA_REG64_2D_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(IDMA_REG64_2D_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(IDMA_REG64_2D_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(IDMA_REG64_2D_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(IDMA_REG64_2D_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(IDMA_REG64_2D_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(IDMA_REG64_2D_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(IDMA_REG64_2D_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(IDMA_REG64_2D_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(IDMA_REG64_2D_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(IDMA_REG64_2D_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(IDMA_REG64_2D_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(IDMA_REG64_2D_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(IDMA_REG64_2D_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(IDMA_REG64_2D_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(IDMA_REG64_2D_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(IDMA_REG64_2D_PERMIT[16] & ~reg_be))) | + (addr_hit[17] & (|(IDMA_REG64_2D_PERMIT[17] & ~reg_be))) | + (addr_hit[18] & (|(IDMA_REG64_2D_PERMIT[18] & ~reg_be))) | + (addr_hit[19] & (|(IDMA_REG64_2D_PERMIT[19] & ~reg_be))) | + (addr_hit[20] & (|(IDMA_REG64_2D_PERMIT[20] & ~reg_be))) | + (addr_hit[21] & (|(IDMA_REG64_2D_PERMIT[21] & ~reg_be))) | + (addr_hit[22] & (|(IDMA_REG64_2D_PERMIT[22] & ~reg_be))) | + (addr_hit[23] & (|(IDMA_REG64_2D_PERMIT[23] & ~reg_be))) | + (addr_hit[24] & (|(IDMA_REG64_2D_PERMIT[24] & ~reg_be))) | + (addr_hit[25] & (|(IDMA_REG64_2D_PERMIT[25] & ~reg_be))) | + (addr_hit[26] & (|(IDMA_REG64_2D_PERMIT[26] & ~reg_be))) | + (addr_hit[27] & (|(IDMA_REG64_2D_PERMIT[27] & ~reg_be))) | + (addr_hit[28] & (|(IDMA_REG64_2D_PERMIT[28] & ~reg_be))) | + (addr_hit[29] & (|(IDMA_REG64_2D_PERMIT[29] & ~reg_be))) | + (addr_hit[30] & (|(IDMA_REG64_2D_PERMIT[30] & ~reg_be))) | + (addr_hit[31] & (|(IDMA_REG64_2D_PERMIT[31] & ~reg_be))) | + (addr_hit[32] & (|(IDMA_REG64_2D_PERMIT[32] & ~reg_be))) | + (addr_hit[33] & (|(IDMA_REG64_2D_PERMIT[33] & ~reg_be))) | + (addr_hit[34] & (|(IDMA_REG64_2D_PERMIT[34] & ~reg_be))) | + (addr_hit[35] & (|(IDMA_REG64_2D_PERMIT[35] & ~reg_be))) | + (addr_hit[36] & (|(IDMA_REG64_2D_PERMIT[36] & ~reg_be))) | + (addr_hit[37] & (|(IDMA_REG64_2D_PERMIT[37] & ~reg_be))) | + (addr_hit[38] & (|(IDMA_REG64_2D_PERMIT[38] & ~reg_be))) | + (addr_hit[39] & (|(IDMA_REG64_2D_PERMIT[39] & ~reg_be))) | + (addr_hit[40] & (|(IDMA_REG64_2D_PERMIT[40] & ~reg_be))) | + (addr_hit[41] & (|(IDMA_REG64_2D_PERMIT[41] & ~reg_be))) | + (addr_hit[42] & (|(IDMA_REG64_2D_PERMIT[42] & ~reg_be))) | + (addr_hit[43] & (|(IDMA_REG64_2D_PERMIT[43] & ~reg_be))) | + (addr_hit[44] & (|(IDMA_REG64_2D_PERMIT[44] & ~reg_be))) | + (addr_hit[45] & (|(IDMA_REG64_2D_PERMIT[45] & ~reg_be))) | + (addr_hit[46] & (|(IDMA_REG64_2D_PERMIT[46] & ~reg_be))) | + (addr_hit[47] & (|(IDMA_REG64_2D_PERMIT[47] & ~reg_be))) | + (addr_hit[48] & (|(IDMA_REG64_2D_PERMIT[48] & ~reg_be))) | + (addr_hit[49] & (|(IDMA_REG64_2D_PERMIT[49] & ~reg_be))) | + (addr_hit[50] & (|(IDMA_REG64_2D_PERMIT[50] & ~reg_be))) | + (addr_hit[51] & (|(IDMA_REG64_2D_PERMIT[51] & ~reg_be))) | + (addr_hit[52] & (|(IDMA_REG64_2D_PERMIT[52] & ~reg_be))) | + (addr_hit[53] & (|(IDMA_REG64_2D_PERMIT[53] & ~reg_be))) | + (addr_hit[54] & (|(IDMA_REG64_2D_PERMIT[54] & ~reg_be))) | + (addr_hit[55] & (|(IDMA_REG64_2D_PERMIT[55] & ~reg_be))) | + (addr_hit[56] & (|(IDMA_REG64_2D_PERMIT[56] & ~reg_be))) | + (addr_hit[57] & (|(IDMA_REG64_2D_PERMIT[57] & ~reg_be))) | + (addr_hit[58] & (|(IDMA_REG64_2D_PERMIT[58] & ~reg_be))) | + (addr_hit[59] & (|(IDMA_REG64_2D_PERMIT[59] & ~reg_be))) | + (addr_hit[60] & (|(IDMA_REG64_2D_PERMIT[60] & ~reg_be))))); + end + + assign conf_decouple_aw_we = addr_hit[0] & reg_we & !reg_error; + assign conf_decouple_aw_wd = reg_wdata[0]; + + assign conf_decouple_rw_we = addr_hit[0] & reg_we & !reg_error; + assign conf_decouple_rw_wd = reg_wdata[1]; + + assign conf_src_reduce_len_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_reduce_len_wd = reg_wdata[2]; + + assign conf_dst_reduce_len_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_reduce_len_wd = reg_wdata[3]; + + assign conf_src_max_llen_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_max_llen_wd = reg_wdata[6:4]; + + assign conf_dst_max_llen_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_max_llen_wd = reg_wdata[9:7]; + + assign conf_enable_nd_we = addr_hit[0] & reg_we & !reg_error; + assign conf_enable_nd_wd = reg_wdata[10]; + + assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_protocol_wd = reg_wdata[12:10]; + + assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_protocol_wd = reg_wdata[14:12]; + + assign status_0_re = addr_hit[1] & reg_re & !reg_error; + + assign status_1_re = addr_hit[2] & reg_re & !reg_error; + + assign status_2_re = addr_hit[3] & reg_re & !reg_error; + + assign status_3_re = addr_hit[4] & reg_re & !reg_error; + + assign status_4_re = addr_hit[5] & reg_re & !reg_error; + + assign status_5_re = addr_hit[6] & reg_re & !reg_error; + + assign status_6_re = addr_hit[7] & reg_re & !reg_error; + + assign status_7_re = addr_hit[8] & reg_re & !reg_error; + + assign status_8_re = addr_hit[9] & reg_re & !reg_error; + + assign status_9_re = addr_hit[10] & reg_re & !reg_error; + + assign status_10_re = addr_hit[11] & reg_re & !reg_error; + + assign status_11_re = addr_hit[12] & reg_re & !reg_error; + + assign status_12_re = addr_hit[13] & reg_re & !reg_error; + + assign status_13_re = addr_hit[14] & reg_re & !reg_error; + + assign status_14_re = addr_hit[15] & reg_re & !reg_error; + + assign status_15_re = addr_hit[16] & reg_re & !reg_error; + + assign next_id_0_re = addr_hit[17] & reg_re & !reg_error; + + assign next_id_1_re = addr_hit[18] & reg_re & !reg_error; + + assign next_id_2_re = addr_hit[19] & reg_re & !reg_error; + + assign next_id_3_re = addr_hit[20] & reg_re & !reg_error; + + assign next_id_4_re = addr_hit[21] & reg_re & !reg_error; + + assign next_id_5_re = addr_hit[22] & reg_re & !reg_error; + + assign next_id_6_re = addr_hit[23] & reg_re & !reg_error; + + assign next_id_7_re = addr_hit[24] & reg_re & !reg_error; + + assign next_id_8_re = addr_hit[25] & reg_re & !reg_error; + + assign next_id_9_re = addr_hit[26] & reg_re & !reg_error; + + assign next_id_10_re = addr_hit[27] & reg_re & !reg_error; + + assign next_id_11_re = addr_hit[28] & reg_re & !reg_error; + + assign next_id_12_re = addr_hit[29] & reg_re & !reg_error; + + assign next_id_13_re = addr_hit[30] & reg_re & !reg_error; + + assign next_id_14_re = addr_hit[31] & reg_re & !reg_error; + + assign next_id_15_re = addr_hit[32] & reg_re & !reg_error; + + assign done_id_0_re = addr_hit[33] & reg_re & !reg_error; + + assign done_id_1_re = addr_hit[34] & reg_re & !reg_error; + + assign done_id_2_re = addr_hit[35] & reg_re & !reg_error; + + assign done_id_3_re = addr_hit[36] & reg_re & !reg_error; + + assign done_id_4_re = addr_hit[37] & reg_re & !reg_error; + + assign done_id_5_re = addr_hit[38] & reg_re & !reg_error; + + assign done_id_6_re = addr_hit[39] & reg_re & !reg_error; + + assign done_id_7_re = addr_hit[40] & reg_re & !reg_error; + + assign done_id_8_re = addr_hit[41] & reg_re & !reg_error; + + assign done_id_9_re = addr_hit[42] & reg_re & !reg_error; + + assign done_id_10_re = addr_hit[43] & reg_re & !reg_error; + + assign done_id_11_re = addr_hit[44] & reg_re & !reg_error; + + assign done_id_12_re = addr_hit[45] & reg_re & !reg_error; + + assign done_id_13_re = addr_hit[46] & reg_re & !reg_error; + + assign done_id_14_re = addr_hit[47] & reg_re & !reg_error; + + assign done_id_15_re = addr_hit[48] & reg_re & !reg_error; + + assign dst_addr_low_we = addr_hit[49] & reg_we & !reg_error; + assign dst_addr_low_wd = reg_wdata[31:0]; + + assign dst_addr_high_we = addr_hit[50] & reg_we & !reg_error; + assign dst_addr_high_wd = reg_wdata[31:0]; + + assign src_addr_low_we = addr_hit[51] & reg_we & !reg_error; + assign src_addr_low_wd = reg_wdata[31:0]; + + assign src_addr_high_we = addr_hit[52] & reg_we & !reg_error; + assign src_addr_high_wd = reg_wdata[31:0]; + + assign length_low_we = addr_hit[53] & reg_we & !reg_error; + assign length_low_wd = reg_wdata[31:0]; + + assign length_high_we = addr_hit[54] & reg_we & !reg_error; + assign length_high_wd = reg_wdata[31:0]; + + assign dst_stride_2_low_we = addr_hit[55] & reg_we & !reg_error; + assign dst_stride_2_low_wd = reg_wdata[31:0]; + + assign dst_stride_2_high_we = addr_hit[56] & reg_we & !reg_error; + assign dst_stride_2_high_wd = reg_wdata[31:0]; + + assign src_stride_2_low_we = addr_hit[57] & reg_we & !reg_error; + assign src_stride_2_low_wd = reg_wdata[31:0]; + + assign src_stride_2_high_we = addr_hit[58] & reg_we & !reg_error; + assign src_stride_2_high_wd = reg_wdata[31:0]; + + assign reps_2_low_we = addr_hit[59] & reg_we & !reg_error; + assign reps_2_low_wd = reg_wdata[31:0]; + + assign reps_2_high_we = addr_hit[60] & reg_we & !reg_error; + assign reps_2_high_wd = reg_wdata[31:0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[0] = conf_decouple_aw_qs; + reg_rdata_next[1] = conf_decouple_rw_qs; + reg_rdata_next[2] = conf_src_reduce_len_qs; + reg_rdata_next[3] = conf_dst_reduce_len_qs; + reg_rdata_next[6:4] = conf_src_max_llen_qs; + reg_rdata_next[9:7] = conf_dst_max_llen_qs; + reg_rdata_next[10] = conf_enable_nd_qs; + reg_rdata_next[12:10] = conf_src_protocol_qs; + reg_rdata_next[14:12] = conf_dst_protocol_qs; + end + + addr_hit[1]: begin + reg_rdata_next[9:0] = status_0_qs; + end + + addr_hit[2]: begin + reg_rdata_next[9:0] = status_1_qs; + end + + addr_hit[3]: begin + reg_rdata_next[9:0] = status_2_qs; + end + + addr_hit[4]: begin + reg_rdata_next[9:0] = status_3_qs; + end + + addr_hit[5]: begin + reg_rdata_next[9:0] = status_4_qs; + end + + addr_hit[6]: begin + reg_rdata_next[9:0] = status_5_qs; + end + + addr_hit[7]: begin + reg_rdata_next[9:0] = status_6_qs; + end + + addr_hit[8]: begin + reg_rdata_next[9:0] = status_7_qs; + end + + addr_hit[9]: begin + reg_rdata_next[9:0] = status_8_qs; + end + + addr_hit[10]: begin + reg_rdata_next[9:0] = status_9_qs; + end + + addr_hit[11]: begin + reg_rdata_next[9:0] = status_10_qs; + end + + addr_hit[12]: begin + reg_rdata_next[9:0] = status_11_qs; + end + + addr_hit[13]: begin + reg_rdata_next[9:0] = status_12_qs; + end + + addr_hit[14]: begin + reg_rdata_next[9:0] = status_13_qs; + end + + addr_hit[15]: begin + reg_rdata_next[9:0] = status_14_qs; + end + + addr_hit[16]: begin + reg_rdata_next[9:0] = status_15_qs; + end + + addr_hit[17]: begin + reg_rdata_next[31:0] = next_id_0_qs; + end + + addr_hit[18]: begin + reg_rdata_next[31:0] = next_id_1_qs; + end + + addr_hit[19]: begin + reg_rdata_next[31:0] = next_id_2_qs; + end + + addr_hit[20]: begin + reg_rdata_next[31:0] = next_id_3_qs; + end + + addr_hit[21]: begin + reg_rdata_next[31:0] = next_id_4_qs; + end + + addr_hit[22]: begin + reg_rdata_next[31:0] = next_id_5_qs; + end + + addr_hit[23]: begin + reg_rdata_next[31:0] = next_id_6_qs; + end + + addr_hit[24]: begin + reg_rdata_next[31:0] = next_id_7_qs; + end + + addr_hit[25]: begin + reg_rdata_next[31:0] = next_id_8_qs; + end + + addr_hit[26]: begin + reg_rdata_next[31:0] = next_id_9_qs; + end + + addr_hit[27]: begin + reg_rdata_next[31:0] = next_id_10_qs; + end + + addr_hit[28]: begin + reg_rdata_next[31:0] = next_id_11_qs; + end + + addr_hit[29]: begin + reg_rdata_next[31:0] = next_id_12_qs; + end + + addr_hit[30]: begin + reg_rdata_next[31:0] = next_id_13_qs; + end + + addr_hit[31]: begin + reg_rdata_next[31:0] = next_id_14_qs; + end + + addr_hit[32]: begin + reg_rdata_next[31:0] = next_id_15_qs; + end + + addr_hit[33]: begin + reg_rdata_next[31:0] = done_id_0_qs; + end + + addr_hit[34]: begin + reg_rdata_next[31:0] = done_id_1_qs; + end + + addr_hit[35]: begin + reg_rdata_next[31:0] = done_id_2_qs; + end + + addr_hit[36]: begin + reg_rdata_next[31:0] = done_id_3_qs; + end + + addr_hit[37]: begin + reg_rdata_next[31:0] = done_id_4_qs; + end + + addr_hit[38]: begin + reg_rdata_next[31:0] = done_id_5_qs; + end + + addr_hit[39]: begin + reg_rdata_next[31:0] = done_id_6_qs; + end + + addr_hit[40]: begin + reg_rdata_next[31:0] = done_id_7_qs; + end + + addr_hit[41]: begin + reg_rdata_next[31:0] = done_id_8_qs; + end + + addr_hit[42]: begin + reg_rdata_next[31:0] = done_id_9_qs; + end + + addr_hit[43]: begin + reg_rdata_next[31:0] = done_id_10_qs; + end + + addr_hit[44]: begin + reg_rdata_next[31:0] = done_id_11_qs; + end + + addr_hit[45]: begin + reg_rdata_next[31:0] = done_id_12_qs; + end + + addr_hit[46]: begin + reg_rdata_next[31:0] = done_id_13_qs; + end + + addr_hit[47]: begin + reg_rdata_next[31:0] = done_id_14_qs; + end + + addr_hit[48]: begin + reg_rdata_next[31:0] = done_id_15_qs; + end + + addr_hit[49]: begin + reg_rdata_next[31:0] = dst_addr_low_qs; + end + + addr_hit[50]: begin + reg_rdata_next[31:0] = dst_addr_high_qs; + end + + addr_hit[51]: begin + reg_rdata_next[31:0] = src_addr_low_qs; + end + + addr_hit[52]: begin + reg_rdata_next[31:0] = src_addr_high_qs; + end + + addr_hit[53]: begin + reg_rdata_next[31:0] = length_low_qs; + end + + addr_hit[54]: begin + reg_rdata_next[31:0] = length_high_qs; + end + + addr_hit[55]: begin + reg_rdata_next[31:0] = dst_stride_2_low_qs; + end + + addr_hit[56]: begin + reg_rdata_next[31:0] = dst_stride_2_high_qs; + end + + addr_hit[57]: begin + reg_rdata_next[31:0] = src_stride_2_low_qs; + end + + addr_hit[58]: begin + reg_rdata_next[31:0] = src_stride_2_high_qs; + end + + addr_hit[59]: begin + reg_rdata_next[31:0] = reps_2_low_qs; + end + + addr_hit[60]: begin + reg_rdata_next[31:0] = reps_2_high_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module idma_reg64_2d_reg_top_intf +#( + parameter int AW = 8, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output idma_reg64_2d_reg_pkg::idma_reg64_2d_reg2hw_t reg2hw, // Write + input idma_reg64_2d_reg_pkg::idma_reg64_2d_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW/8; + +`include "register_interface/typedef.svh" +`include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + idma_reg64_2d_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module idma_reg64_1d_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 8 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output idma_reg64_1d_reg_pkg::idma_reg64_1d_reg2hw_t reg2hw, // Write + input idma_reg64_1d_reg_pkg::idma_reg64_1d_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import idma_reg64_1d_reg_pkg::* ; + + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [BlockAw-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next ; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic conf_decouple_aw_qs; + logic conf_decouple_aw_wd; + logic conf_decouple_aw_we; + logic conf_decouple_rw_qs; + logic conf_decouple_rw_wd; + logic conf_decouple_rw_we; + logic conf_src_reduce_len_qs; + logic conf_src_reduce_len_wd; + logic conf_src_reduce_len_we; + logic conf_dst_reduce_len_qs; + logic conf_dst_reduce_len_wd; + logic conf_dst_reduce_len_we; + logic [2:0] conf_src_max_llen_qs; + logic [2:0] conf_src_max_llen_wd; + logic conf_src_max_llen_we; + logic [2:0] conf_dst_max_llen_qs; + logic [2:0] conf_dst_max_llen_wd; + logic conf_dst_max_llen_we; + logic conf_enable_nd_qs; + logic conf_enable_nd_wd; + logic conf_enable_nd_we; + logic [2:0] conf_src_protocol_qs; + logic [2:0] conf_src_protocol_wd; + logic conf_src_protocol_we; + logic [2:0] conf_dst_protocol_qs; + logic [2:0] conf_dst_protocol_wd; + logic conf_dst_protocol_we; + logic [9:0] status_0_qs; + logic status_0_re; + logic [9:0] status_1_qs; + logic status_1_re; + logic [9:0] status_2_qs; + logic status_2_re; + logic [9:0] status_3_qs; + logic status_3_re; + logic [9:0] status_4_qs; + logic status_4_re; + logic [9:0] status_5_qs; + logic status_5_re; + logic [9:0] status_6_qs; + logic status_6_re; + logic [9:0] status_7_qs; + logic status_7_re; + logic [9:0] status_8_qs; + logic status_8_re; + logic [9:0] status_9_qs; + logic status_9_re; + logic [9:0] status_10_qs; + logic status_10_re; + logic [9:0] status_11_qs; + logic status_11_re; + logic [9:0] status_12_qs; + logic status_12_re; + logic [9:0] status_13_qs; + logic status_13_re; + logic [9:0] status_14_qs; + logic status_14_re; + logic [9:0] status_15_qs; + logic status_15_re; + logic [31:0] next_id_0_qs; + logic next_id_0_re; + logic [31:0] next_id_1_qs; + logic next_id_1_re; + logic [31:0] next_id_2_qs; + logic next_id_2_re; + logic [31:0] next_id_3_qs; + logic next_id_3_re; + logic [31:0] next_id_4_qs; + logic next_id_4_re; + logic [31:0] next_id_5_qs; + logic next_id_5_re; + logic [31:0] next_id_6_qs; + logic next_id_6_re; + logic [31:0] next_id_7_qs; + logic next_id_7_re; + logic [31:0] next_id_8_qs; + logic next_id_8_re; + logic [31:0] next_id_9_qs; + logic next_id_9_re; + logic [31:0] next_id_10_qs; + logic next_id_10_re; + logic [31:0] next_id_11_qs; + logic next_id_11_re; + logic [31:0] next_id_12_qs; + logic next_id_12_re; + logic [31:0] next_id_13_qs; + logic next_id_13_re; + logic [31:0] next_id_14_qs; + logic next_id_14_re; + logic [31:0] next_id_15_qs; + logic next_id_15_re; + logic [31:0] done_id_0_qs; + logic done_id_0_re; + logic [31:0] done_id_1_qs; + logic done_id_1_re; + logic [31:0] done_id_2_qs; + logic done_id_2_re; + logic [31:0] done_id_3_qs; + logic done_id_3_re; + logic [31:0] done_id_4_qs; + logic done_id_4_re; + logic [31:0] done_id_5_qs; + logic done_id_5_re; + logic [31:0] done_id_6_qs; + logic done_id_6_re; + logic [31:0] done_id_7_qs; + logic done_id_7_re; + logic [31:0] done_id_8_qs; + logic done_id_8_re; + logic [31:0] done_id_9_qs; + logic done_id_9_re; + logic [31:0] done_id_10_qs; + logic done_id_10_re; + logic [31:0] done_id_11_qs; + logic done_id_11_re; + logic [31:0] done_id_12_qs; + logic done_id_12_re; + logic [31:0] done_id_13_qs; + logic done_id_13_re; + logic [31:0] done_id_14_qs; + logic done_id_14_re; + logic [31:0] done_id_15_qs; + logic done_id_15_re; + logic [31:0] dst_addr_low_qs; + logic [31:0] dst_addr_low_wd; + logic dst_addr_low_we; + logic [31:0] dst_addr_high_qs; + logic [31:0] dst_addr_high_wd; + logic dst_addr_high_we; + logic [31:0] src_addr_low_qs; + logic [31:0] src_addr_low_wd; + logic src_addr_low_we; + logic [31:0] src_addr_high_qs; + logic [31:0] src_addr_high_wd; + logic src_addr_high_we; + logic [31:0] length_low_qs; + logic [31:0] length_low_wd; + logic length_low_we; + logic [31:0] length_high_qs; + logic [31:0] length_high_wd; + logic length_high_we; + + // Register instances + // R[conf]: V(False) + + // F[decouple_aw]: 0:0 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_decouple_aw ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_decouple_aw_we), + .wd (conf_decouple_aw_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.decouple_aw.q ), + + // to register interface (read) + .qs (conf_decouple_aw_qs) + ); + + + // F[decouple_rw]: 1:1 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_decouple_rw ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_decouple_rw_we), + .wd (conf_decouple_rw_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.decouple_rw.q ), + + // to register interface (read) + .qs (conf_decouple_rw_qs) + ); + + + // F[src_reduce_len]: 2:2 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_src_reduce_len ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_reduce_len_we), + .wd (conf_src_reduce_len_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_reduce_len.q ), + + // to register interface (read) + .qs (conf_src_reduce_len_qs) + ); + + + // F[dst_reduce_len]: 3:3 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_dst_reduce_len ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_reduce_len_we), + .wd (conf_dst_reduce_len_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_reduce_len.q ), + + // to register interface (read) + .qs (conf_dst_reduce_len_qs) + ); + + + // F[src_max_llen]: 6:4 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_src_max_llen ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_max_llen_we), + .wd (conf_src_max_llen_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_max_llen.q ), + + // to register interface (read) + .qs (conf_src_max_llen_qs) + ); + + + // F[dst_max_llen]: 9:7 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_dst_max_llen ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_max_llen_we), + .wd (conf_dst_max_llen_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_max_llen.q ), + + // to register interface (read) + .qs (conf_dst_max_llen_qs) + ); + + + // F[enable_nd]: 10:10 + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h0) + ) u_conf_enable_nd ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_enable_nd_we), + .wd (conf_enable_nd_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.enable_nd.q ), + + // to register interface (read) + .qs (conf_enable_nd_qs) + ); + + + // F[src_protocol]: 12:10 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_src_protocol ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_src_protocol_we), + .wd (conf_src_protocol_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.src_protocol.q ), + + // to register interface (read) + .qs (conf_src_protocol_qs) + ); + + + // F[dst_protocol]: 14:12 + prim_subreg #( + .DW (3), + .SWACCESS("RW"), + .RESVAL (3'h0) + ) u_conf_dst_protocol ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (conf_dst_protocol_we), + .wd (conf_dst_protocol_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.conf.dst_protocol.q ), + + // to register interface (read) + .qs (conf_dst_protocol_qs) + ); + + + + // Subregister 0 of Multireg status + // R[status_0]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_0 ( + .re (status_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[0].d), + .qre (), + .qe (), + .q (), + .qs (status_0_qs) + ); + + // Subregister 1 of Multireg status + // R[status_1]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_1 ( + .re (status_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[1].d), + .qre (), + .qe (), + .q (), + .qs (status_1_qs) + ); + + // Subregister 2 of Multireg status + // R[status_2]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_2 ( + .re (status_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[2].d), + .qre (), + .qe (), + .q (), + .qs (status_2_qs) + ); + + // Subregister 3 of Multireg status + // R[status_3]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_3 ( + .re (status_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[3].d), + .qre (), + .qe (), + .q (), + .qs (status_3_qs) + ); + + // Subregister 4 of Multireg status + // R[status_4]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_4 ( + .re (status_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[4].d), + .qre (), + .qe (), + .q (), + .qs (status_4_qs) + ); + + // Subregister 5 of Multireg status + // R[status_5]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_5 ( + .re (status_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[5].d), + .qre (), + .qe (), + .q (), + .qs (status_5_qs) + ); + + // Subregister 6 of Multireg status + // R[status_6]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_6 ( + .re (status_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[6].d), + .qre (), + .qe (), + .q (), + .qs (status_6_qs) + ); + + // Subregister 7 of Multireg status + // R[status_7]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_7 ( + .re (status_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[7].d), + .qre (), + .qe (), + .q (), + .qs (status_7_qs) + ); + + // Subregister 8 of Multireg status + // R[status_8]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_8 ( + .re (status_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[8].d), + .qre (), + .qe (), + .q (), + .qs (status_8_qs) + ); + + // Subregister 9 of Multireg status + // R[status_9]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_9 ( + .re (status_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[9].d), + .qre (), + .qe (), + .q (), + .qs (status_9_qs) + ); + + // Subregister 10 of Multireg status + // R[status_10]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_10 ( + .re (status_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[10].d), + .qre (), + .qe (), + .q (), + .qs (status_10_qs) + ); + + // Subregister 11 of Multireg status + // R[status_11]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_11 ( + .re (status_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[11].d), + .qre (), + .qe (), + .q (), + .qs (status_11_qs) + ); + + // Subregister 12 of Multireg status + // R[status_12]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_12 ( + .re (status_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[12].d), + .qre (), + .qe (), + .q (), + .qs (status_12_qs) + ); + + // Subregister 13 of Multireg status + // R[status_13]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_13 ( + .re (status_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[13].d), + .qre (), + .qe (), + .q (), + .qs (status_13_qs) + ); + + // Subregister 14 of Multireg status + // R[status_14]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_14 ( + .re (status_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[14].d), + .qre (), + .qe (), + .q (), + .qs (status_14_qs) + ); + + // Subregister 15 of Multireg status + // R[status_15]: V(True) + + prim_subreg_ext #( + .DW (10) + ) u_status_15 ( + .re (status_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.status[15].d), + .qre (), + .qe (), + .q (), + .qs (status_15_qs) + ); + + + + // Subregister 0 of Multireg next_id + // R[next_id_0]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_0 ( + .re (next_id_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[0].d), + .qre (reg2hw.next_id[0].re), + .qe (), + .q (reg2hw.next_id[0].q ), + .qs (next_id_0_qs) + ); + + // Subregister 1 of Multireg next_id + // R[next_id_1]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_1 ( + .re (next_id_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[1].d), + .qre (reg2hw.next_id[1].re), + .qe (), + .q (reg2hw.next_id[1].q ), + .qs (next_id_1_qs) + ); + + // Subregister 2 of Multireg next_id + // R[next_id_2]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_2 ( + .re (next_id_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[2].d), + .qre (reg2hw.next_id[2].re), + .qe (), + .q (reg2hw.next_id[2].q ), + .qs (next_id_2_qs) + ); + + // Subregister 3 of Multireg next_id + // R[next_id_3]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_3 ( + .re (next_id_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[3].d), + .qre (reg2hw.next_id[3].re), + .qe (), + .q (reg2hw.next_id[3].q ), + .qs (next_id_3_qs) + ); + + // Subregister 4 of Multireg next_id + // R[next_id_4]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_4 ( + .re (next_id_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[4].d), + .qre (reg2hw.next_id[4].re), + .qe (), + .q (reg2hw.next_id[4].q ), + .qs (next_id_4_qs) + ); + + // Subregister 5 of Multireg next_id + // R[next_id_5]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_5 ( + .re (next_id_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[5].d), + .qre (reg2hw.next_id[5].re), + .qe (), + .q (reg2hw.next_id[5].q ), + .qs (next_id_5_qs) + ); + + // Subregister 6 of Multireg next_id + // R[next_id_6]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_6 ( + .re (next_id_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[6].d), + .qre (reg2hw.next_id[6].re), + .qe (), + .q (reg2hw.next_id[6].q ), + .qs (next_id_6_qs) + ); + + // Subregister 7 of Multireg next_id + // R[next_id_7]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_7 ( + .re (next_id_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[7].d), + .qre (reg2hw.next_id[7].re), + .qe (), + .q (reg2hw.next_id[7].q ), + .qs (next_id_7_qs) + ); + + // Subregister 8 of Multireg next_id + // R[next_id_8]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_8 ( + .re (next_id_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[8].d), + .qre (reg2hw.next_id[8].re), + .qe (), + .q (reg2hw.next_id[8].q ), + .qs (next_id_8_qs) + ); + + // Subregister 9 of Multireg next_id + // R[next_id_9]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_9 ( + .re (next_id_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[9].d), + .qre (reg2hw.next_id[9].re), + .qe (), + .q (reg2hw.next_id[9].q ), + .qs (next_id_9_qs) + ); + + // Subregister 10 of Multireg next_id + // R[next_id_10]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_10 ( + .re (next_id_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[10].d), + .qre (reg2hw.next_id[10].re), + .qe (), + .q (reg2hw.next_id[10].q ), + .qs (next_id_10_qs) + ); + + // Subregister 11 of Multireg next_id + // R[next_id_11]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_11 ( + .re (next_id_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[11].d), + .qre (reg2hw.next_id[11].re), + .qe (), + .q (reg2hw.next_id[11].q ), + .qs (next_id_11_qs) + ); + + // Subregister 12 of Multireg next_id + // R[next_id_12]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_12 ( + .re (next_id_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[12].d), + .qre (reg2hw.next_id[12].re), + .qe (), + .q (reg2hw.next_id[12].q ), + .qs (next_id_12_qs) + ); + + // Subregister 13 of Multireg next_id + // R[next_id_13]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_13 ( + .re (next_id_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[13].d), + .qre (reg2hw.next_id[13].re), + .qe (), + .q (reg2hw.next_id[13].q ), + .qs (next_id_13_qs) + ); + + // Subregister 14 of Multireg next_id + // R[next_id_14]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_14 ( + .re (next_id_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[14].d), + .qre (reg2hw.next_id[14].re), + .qe (), + .q (reg2hw.next_id[14].q ), + .qs (next_id_14_qs) + ); + + // Subregister 15 of Multireg next_id + // R[next_id_15]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_next_id_15 ( + .re (next_id_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.next_id[15].d), + .qre (reg2hw.next_id[15].re), + .qe (), + .q (reg2hw.next_id[15].q ), + .qs (next_id_15_qs) + ); + + + + // Subregister 0 of Multireg done_id + // R[done_id_0]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_0 ( + .re (done_id_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[0].d), + .qre (), + .qe (), + .q (), + .qs (done_id_0_qs) + ); + + // Subregister 1 of Multireg done_id + // R[done_id_1]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_1 ( + .re (done_id_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[1].d), + .qre (), + .qe (), + .q (), + .qs (done_id_1_qs) + ); + + // Subregister 2 of Multireg done_id + // R[done_id_2]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_2 ( + .re (done_id_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[2].d), + .qre (), + .qe (), + .q (), + .qs (done_id_2_qs) + ); + + // Subregister 3 of Multireg done_id + // R[done_id_3]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_3 ( + .re (done_id_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[3].d), + .qre (), + .qe (), + .q (), + .qs (done_id_3_qs) + ); + + // Subregister 4 of Multireg done_id + // R[done_id_4]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_4 ( + .re (done_id_4_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[4].d), + .qre (), + .qe (), + .q (), + .qs (done_id_4_qs) + ); + + // Subregister 5 of Multireg done_id + // R[done_id_5]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_5 ( + .re (done_id_5_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[5].d), + .qre (), + .qe (), + .q (), + .qs (done_id_5_qs) + ); + + // Subregister 6 of Multireg done_id + // R[done_id_6]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_6 ( + .re (done_id_6_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[6].d), + .qre (), + .qe (), + .q (), + .qs (done_id_6_qs) + ); + + // Subregister 7 of Multireg done_id + // R[done_id_7]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_7 ( + .re (done_id_7_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[7].d), + .qre (), + .qe (), + .q (), + .qs (done_id_7_qs) + ); + + // Subregister 8 of Multireg done_id + // R[done_id_8]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_8 ( + .re (done_id_8_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[8].d), + .qre (), + .qe (), + .q (), + .qs (done_id_8_qs) + ); + + // Subregister 9 of Multireg done_id + // R[done_id_9]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_9 ( + .re (done_id_9_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[9].d), + .qre (), + .qe (), + .q (), + .qs (done_id_9_qs) + ); + + // Subregister 10 of Multireg done_id + // R[done_id_10]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_10 ( + .re (done_id_10_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[10].d), + .qre (), + .qe (), + .q (), + .qs (done_id_10_qs) + ); + + // Subregister 11 of Multireg done_id + // R[done_id_11]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_11 ( + .re (done_id_11_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[11].d), + .qre (), + .qe (), + .q (), + .qs (done_id_11_qs) + ); + + // Subregister 12 of Multireg done_id + // R[done_id_12]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_12 ( + .re (done_id_12_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[12].d), + .qre (), + .qe (), + .q (), + .qs (done_id_12_qs) + ); + + // Subregister 13 of Multireg done_id + // R[done_id_13]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_13 ( + .re (done_id_13_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[13].d), + .qre (), + .qe (), + .q (), + .qs (done_id_13_qs) + ); + + // Subregister 14 of Multireg done_id + // R[done_id_14]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_14 ( + .re (done_id_14_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[14].d), + .qre (), + .qe (), + .q (), + .qs (done_id_14_qs) + ); + + // Subregister 15 of Multireg done_id + // R[done_id_15]: V(True) + + prim_subreg_ext #( + .DW (32) + ) u_done_id_15 ( + .re (done_id_15_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.done_id[15].d), + .qre (), + .qe (), + .q (), + .qs (done_id_15_qs) + ); + + + // R[dst_addr_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_addr_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_addr_low_we), + .wd (dst_addr_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_addr_low.q ), + + // to register interface (read) + .qs (dst_addr_low_qs) + ); + + + // R[dst_addr_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_dst_addr_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (dst_addr_high_we), + .wd (dst_addr_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.dst_addr_high.q ), + + // to register interface (read) + .qs (dst_addr_high_qs) + ); + + + // R[src_addr_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_addr_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_addr_low_we), + .wd (src_addr_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_addr_low.q ), + + // to register interface (read) + .qs (src_addr_low_qs) + ); + + + // R[src_addr_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_src_addr_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (src_addr_high_we), + .wd (src_addr_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.src_addr_high.q ), + + // to register interface (read) + .qs (src_addr_high_qs) + ); + + + // R[length_low]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_length_low ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (length_low_we), + .wd (length_low_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.length_low.q ), + + // to register interface (read) + .qs (length_low_qs) + ); + + + // R[length_high]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("RW"), + .RESVAL (32'h0) + ) u_length_high ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (length_high_we), + .wd (length_high_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.length_high.q ), + + // to register interface (read) + .qs (length_high_qs) + ); + + + + + logic [54:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[ 0] = (reg_addr == IDMA_REG64_1D_CONF_OFFSET); + addr_hit[ 1] = (reg_addr == IDMA_REG64_1D_STATUS_0_OFFSET); + addr_hit[ 2] = (reg_addr == IDMA_REG64_1D_STATUS_1_OFFSET); + addr_hit[ 3] = (reg_addr == IDMA_REG64_1D_STATUS_2_OFFSET); + addr_hit[ 4] = (reg_addr == IDMA_REG64_1D_STATUS_3_OFFSET); + addr_hit[ 5] = (reg_addr == IDMA_REG64_1D_STATUS_4_OFFSET); + addr_hit[ 6] = (reg_addr == IDMA_REG64_1D_STATUS_5_OFFSET); + addr_hit[ 7] = (reg_addr == IDMA_REG64_1D_STATUS_6_OFFSET); + addr_hit[ 8] = (reg_addr == IDMA_REG64_1D_STATUS_7_OFFSET); + addr_hit[ 9] = (reg_addr == IDMA_REG64_1D_STATUS_8_OFFSET); + addr_hit[10] = (reg_addr == IDMA_REG64_1D_STATUS_9_OFFSET); + addr_hit[11] = (reg_addr == IDMA_REG64_1D_STATUS_10_OFFSET); + addr_hit[12] = (reg_addr == IDMA_REG64_1D_STATUS_11_OFFSET); + addr_hit[13] = (reg_addr == IDMA_REG64_1D_STATUS_12_OFFSET); + addr_hit[14] = (reg_addr == IDMA_REG64_1D_STATUS_13_OFFSET); + addr_hit[15] = (reg_addr == IDMA_REG64_1D_STATUS_14_OFFSET); + addr_hit[16] = (reg_addr == IDMA_REG64_1D_STATUS_15_OFFSET); + addr_hit[17] = (reg_addr == IDMA_REG64_1D_NEXT_ID_0_OFFSET); + addr_hit[18] = (reg_addr == IDMA_REG64_1D_NEXT_ID_1_OFFSET); + addr_hit[19] = (reg_addr == IDMA_REG64_1D_NEXT_ID_2_OFFSET); + addr_hit[20] = (reg_addr == IDMA_REG64_1D_NEXT_ID_3_OFFSET); + addr_hit[21] = (reg_addr == IDMA_REG64_1D_NEXT_ID_4_OFFSET); + addr_hit[22] = (reg_addr == IDMA_REG64_1D_NEXT_ID_5_OFFSET); + addr_hit[23] = (reg_addr == IDMA_REG64_1D_NEXT_ID_6_OFFSET); + addr_hit[24] = (reg_addr == IDMA_REG64_1D_NEXT_ID_7_OFFSET); + addr_hit[25] = (reg_addr == IDMA_REG64_1D_NEXT_ID_8_OFFSET); + addr_hit[26] = (reg_addr == IDMA_REG64_1D_NEXT_ID_9_OFFSET); + addr_hit[27] = (reg_addr == IDMA_REG64_1D_NEXT_ID_10_OFFSET); + addr_hit[28] = (reg_addr == IDMA_REG64_1D_NEXT_ID_11_OFFSET); + addr_hit[29] = (reg_addr == IDMA_REG64_1D_NEXT_ID_12_OFFSET); + addr_hit[30] = (reg_addr == IDMA_REG64_1D_NEXT_ID_13_OFFSET); + addr_hit[31] = (reg_addr == IDMA_REG64_1D_NEXT_ID_14_OFFSET); + addr_hit[32] = (reg_addr == IDMA_REG64_1D_NEXT_ID_15_OFFSET); + addr_hit[33] = (reg_addr == IDMA_REG64_1D_DONE_ID_0_OFFSET); + addr_hit[34] = (reg_addr == IDMA_REG64_1D_DONE_ID_1_OFFSET); + addr_hit[35] = (reg_addr == IDMA_REG64_1D_DONE_ID_2_OFFSET); + addr_hit[36] = (reg_addr == IDMA_REG64_1D_DONE_ID_3_OFFSET); + addr_hit[37] = (reg_addr == IDMA_REG64_1D_DONE_ID_4_OFFSET); + addr_hit[38] = (reg_addr == IDMA_REG64_1D_DONE_ID_5_OFFSET); + addr_hit[39] = (reg_addr == IDMA_REG64_1D_DONE_ID_6_OFFSET); + addr_hit[40] = (reg_addr == IDMA_REG64_1D_DONE_ID_7_OFFSET); + addr_hit[41] = (reg_addr == IDMA_REG64_1D_DONE_ID_8_OFFSET); + addr_hit[42] = (reg_addr == IDMA_REG64_1D_DONE_ID_9_OFFSET); + addr_hit[43] = (reg_addr == IDMA_REG64_1D_DONE_ID_10_OFFSET); + addr_hit[44] = (reg_addr == IDMA_REG64_1D_DONE_ID_11_OFFSET); + addr_hit[45] = (reg_addr == IDMA_REG64_1D_DONE_ID_12_OFFSET); + addr_hit[46] = (reg_addr == IDMA_REG64_1D_DONE_ID_13_OFFSET); + addr_hit[47] = (reg_addr == IDMA_REG64_1D_DONE_ID_14_OFFSET); + addr_hit[48] = (reg_addr == IDMA_REG64_1D_DONE_ID_15_OFFSET); + addr_hit[49] = (reg_addr == IDMA_REG64_1D_DST_ADDR_LOW_OFFSET); + addr_hit[50] = (reg_addr == IDMA_REG64_1D_DST_ADDR_HIGH_OFFSET); + addr_hit[51] = (reg_addr == IDMA_REG64_1D_SRC_ADDR_LOW_OFFSET); + addr_hit[52] = (reg_addr == IDMA_REG64_1D_SRC_ADDR_HIGH_OFFSET); + addr_hit[53] = (reg_addr == IDMA_REG64_1D_LENGTH_LOW_OFFSET); + addr_hit[54] = (reg_addr == IDMA_REG64_1D_LENGTH_HIGH_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[ 0] & (|(IDMA_REG64_1D_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(IDMA_REG64_1D_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(IDMA_REG64_1D_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(IDMA_REG64_1D_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(IDMA_REG64_1D_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(IDMA_REG64_1D_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(IDMA_REG64_1D_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(IDMA_REG64_1D_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(IDMA_REG64_1D_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(IDMA_REG64_1D_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(IDMA_REG64_1D_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(IDMA_REG64_1D_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(IDMA_REG64_1D_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(IDMA_REG64_1D_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(IDMA_REG64_1D_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(IDMA_REG64_1D_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(IDMA_REG64_1D_PERMIT[16] & ~reg_be))) | + (addr_hit[17] & (|(IDMA_REG64_1D_PERMIT[17] & ~reg_be))) | + (addr_hit[18] & (|(IDMA_REG64_1D_PERMIT[18] & ~reg_be))) | + (addr_hit[19] & (|(IDMA_REG64_1D_PERMIT[19] & ~reg_be))) | + (addr_hit[20] & (|(IDMA_REG64_1D_PERMIT[20] & ~reg_be))) | + (addr_hit[21] & (|(IDMA_REG64_1D_PERMIT[21] & ~reg_be))) | + (addr_hit[22] & (|(IDMA_REG64_1D_PERMIT[22] & ~reg_be))) | + (addr_hit[23] & (|(IDMA_REG64_1D_PERMIT[23] & ~reg_be))) | + (addr_hit[24] & (|(IDMA_REG64_1D_PERMIT[24] & ~reg_be))) | + (addr_hit[25] & (|(IDMA_REG64_1D_PERMIT[25] & ~reg_be))) | + (addr_hit[26] & (|(IDMA_REG64_1D_PERMIT[26] & ~reg_be))) | + (addr_hit[27] & (|(IDMA_REG64_1D_PERMIT[27] & ~reg_be))) | + (addr_hit[28] & (|(IDMA_REG64_1D_PERMIT[28] & ~reg_be))) | + (addr_hit[29] & (|(IDMA_REG64_1D_PERMIT[29] & ~reg_be))) | + (addr_hit[30] & (|(IDMA_REG64_1D_PERMIT[30] & ~reg_be))) | + (addr_hit[31] & (|(IDMA_REG64_1D_PERMIT[31] & ~reg_be))) | + (addr_hit[32] & (|(IDMA_REG64_1D_PERMIT[32] & ~reg_be))) | + (addr_hit[33] & (|(IDMA_REG64_1D_PERMIT[33] & ~reg_be))) | + (addr_hit[34] & (|(IDMA_REG64_1D_PERMIT[34] & ~reg_be))) | + (addr_hit[35] & (|(IDMA_REG64_1D_PERMIT[35] & ~reg_be))) | + (addr_hit[36] & (|(IDMA_REG64_1D_PERMIT[36] & ~reg_be))) | + (addr_hit[37] & (|(IDMA_REG64_1D_PERMIT[37] & ~reg_be))) | + (addr_hit[38] & (|(IDMA_REG64_1D_PERMIT[38] & ~reg_be))) | + (addr_hit[39] & (|(IDMA_REG64_1D_PERMIT[39] & ~reg_be))) | + (addr_hit[40] & (|(IDMA_REG64_1D_PERMIT[40] & ~reg_be))) | + (addr_hit[41] & (|(IDMA_REG64_1D_PERMIT[41] & ~reg_be))) | + (addr_hit[42] & (|(IDMA_REG64_1D_PERMIT[42] & ~reg_be))) | + (addr_hit[43] & (|(IDMA_REG64_1D_PERMIT[43] & ~reg_be))) | + (addr_hit[44] & (|(IDMA_REG64_1D_PERMIT[44] & ~reg_be))) | + (addr_hit[45] & (|(IDMA_REG64_1D_PERMIT[45] & ~reg_be))) | + (addr_hit[46] & (|(IDMA_REG64_1D_PERMIT[46] & ~reg_be))) | + (addr_hit[47] & (|(IDMA_REG64_1D_PERMIT[47] & ~reg_be))) | + (addr_hit[48] & (|(IDMA_REG64_1D_PERMIT[48] & ~reg_be))) | + (addr_hit[49] & (|(IDMA_REG64_1D_PERMIT[49] & ~reg_be))) | + (addr_hit[50] & (|(IDMA_REG64_1D_PERMIT[50] & ~reg_be))) | + (addr_hit[51] & (|(IDMA_REG64_1D_PERMIT[51] & ~reg_be))) | + (addr_hit[52] & (|(IDMA_REG64_1D_PERMIT[52] & ~reg_be))) | + (addr_hit[53] & (|(IDMA_REG64_1D_PERMIT[53] & ~reg_be))) | + (addr_hit[54] & (|(IDMA_REG64_1D_PERMIT[54] & ~reg_be))))); + end + + assign conf_decouple_aw_we = addr_hit[0] & reg_we & !reg_error; + assign conf_decouple_aw_wd = reg_wdata[0]; + + assign conf_decouple_rw_we = addr_hit[0] & reg_we & !reg_error; + assign conf_decouple_rw_wd = reg_wdata[1]; + + assign conf_src_reduce_len_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_reduce_len_wd = reg_wdata[2]; + + assign conf_dst_reduce_len_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_reduce_len_wd = reg_wdata[3]; + + assign conf_src_max_llen_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_max_llen_wd = reg_wdata[6:4]; + + assign conf_dst_max_llen_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_max_llen_wd = reg_wdata[9:7]; + + assign conf_enable_nd_we = addr_hit[0] & reg_we & !reg_error; + assign conf_enable_nd_wd = reg_wdata[10]; + + assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; + assign conf_src_protocol_wd = reg_wdata[12:10]; + + assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; + assign conf_dst_protocol_wd = reg_wdata[14:12]; + + assign status_0_re = addr_hit[1] & reg_re & !reg_error; + + assign status_1_re = addr_hit[2] & reg_re & !reg_error; + + assign status_2_re = addr_hit[3] & reg_re & !reg_error; + + assign status_3_re = addr_hit[4] & reg_re & !reg_error; + + assign status_4_re = addr_hit[5] & reg_re & !reg_error; + + assign status_5_re = addr_hit[6] & reg_re & !reg_error; + + assign status_6_re = addr_hit[7] & reg_re & !reg_error; + + assign status_7_re = addr_hit[8] & reg_re & !reg_error; + + assign status_8_re = addr_hit[9] & reg_re & !reg_error; + + assign status_9_re = addr_hit[10] & reg_re & !reg_error; + + assign status_10_re = addr_hit[11] & reg_re & !reg_error; + + assign status_11_re = addr_hit[12] & reg_re & !reg_error; + + assign status_12_re = addr_hit[13] & reg_re & !reg_error; + + assign status_13_re = addr_hit[14] & reg_re & !reg_error; + + assign status_14_re = addr_hit[15] & reg_re & !reg_error; + + assign status_15_re = addr_hit[16] & reg_re & !reg_error; + + assign next_id_0_re = addr_hit[17] & reg_re & !reg_error; + + assign next_id_1_re = addr_hit[18] & reg_re & !reg_error; + + assign next_id_2_re = addr_hit[19] & reg_re & !reg_error; + + assign next_id_3_re = addr_hit[20] & reg_re & !reg_error; + + assign next_id_4_re = addr_hit[21] & reg_re & !reg_error; + + assign next_id_5_re = addr_hit[22] & reg_re & !reg_error; + + assign next_id_6_re = addr_hit[23] & reg_re & !reg_error; + + assign next_id_7_re = addr_hit[24] & reg_re & !reg_error; + + assign next_id_8_re = addr_hit[25] & reg_re & !reg_error; + + assign next_id_9_re = addr_hit[26] & reg_re & !reg_error; + + assign next_id_10_re = addr_hit[27] & reg_re & !reg_error; + + assign next_id_11_re = addr_hit[28] & reg_re & !reg_error; + + assign next_id_12_re = addr_hit[29] & reg_re & !reg_error; + + assign next_id_13_re = addr_hit[30] & reg_re & !reg_error; + + assign next_id_14_re = addr_hit[31] & reg_re & !reg_error; + + assign next_id_15_re = addr_hit[32] & reg_re & !reg_error; + + assign done_id_0_re = addr_hit[33] & reg_re & !reg_error; + + assign done_id_1_re = addr_hit[34] & reg_re & !reg_error; + + assign done_id_2_re = addr_hit[35] & reg_re & !reg_error; + + assign done_id_3_re = addr_hit[36] & reg_re & !reg_error; + + assign done_id_4_re = addr_hit[37] & reg_re & !reg_error; + + assign done_id_5_re = addr_hit[38] & reg_re & !reg_error; + + assign done_id_6_re = addr_hit[39] & reg_re & !reg_error; + + assign done_id_7_re = addr_hit[40] & reg_re & !reg_error; + + assign done_id_8_re = addr_hit[41] & reg_re & !reg_error; + + assign done_id_9_re = addr_hit[42] & reg_re & !reg_error; + + assign done_id_10_re = addr_hit[43] & reg_re & !reg_error; + + assign done_id_11_re = addr_hit[44] & reg_re & !reg_error; + + assign done_id_12_re = addr_hit[45] & reg_re & !reg_error; + + assign done_id_13_re = addr_hit[46] & reg_re & !reg_error; + + assign done_id_14_re = addr_hit[47] & reg_re & !reg_error; + + assign done_id_15_re = addr_hit[48] & reg_re & !reg_error; + + assign dst_addr_low_we = addr_hit[49] & reg_we & !reg_error; + assign dst_addr_low_wd = reg_wdata[31:0]; + + assign dst_addr_high_we = addr_hit[50] & reg_we & !reg_error; + assign dst_addr_high_wd = reg_wdata[31:0]; + + assign src_addr_low_we = addr_hit[51] & reg_we & !reg_error; + assign src_addr_low_wd = reg_wdata[31:0]; + + assign src_addr_high_we = addr_hit[52] & reg_we & !reg_error; + assign src_addr_high_wd = reg_wdata[31:0]; + + assign length_low_we = addr_hit[53] & reg_we & !reg_error; + assign length_low_wd = reg_wdata[31:0]; + + assign length_high_we = addr_hit[54] & reg_we & !reg_error; + assign length_high_wd = reg_wdata[31:0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[0] = conf_decouple_aw_qs; + reg_rdata_next[1] = conf_decouple_rw_qs; + reg_rdata_next[2] = conf_src_reduce_len_qs; + reg_rdata_next[3] = conf_dst_reduce_len_qs; + reg_rdata_next[6:4] = conf_src_max_llen_qs; + reg_rdata_next[9:7] = conf_dst_max_llen_qs; + reg_rdata_next[10] = conf_enable_nd_qs; + reg_rdata_next[12:10] = conf_src_protocol_qs; + reg_rdata_next[14:12] = conf_dst_protocol_qs; + end + + addr_hit[1]: begin + reg_rdata_next[9:0] = status_0_qs; + end + + addr_hit[2]: begin + reg_rdata_next[9:0] = status_1_qs; + end + + addr_hit[3]: begin + reg_rdata_next[9:0] = status_2_qs; + end + + addr_hit[4]: begin + reg_rdata_next[9:0] = status_3_qs; + end + + addr_hit[5]: begin + reg_rdata_next[9:0] = status_4_qs; + end + + addr_hit[6]: begin + reg_rdata_next[9:0] = status_5_qs; + end + + addr_hit[7]: begin + reg_rdata_next[9:0] = status_6_qs; + end + + addr_hit[8]: begin + reg_rdata_next[9:0] = status_7_qs; + end + + addr_hit[9]: begin + reg_rdata_next[9:0] = status_8_qs; + end + + addr_hit[10]: begin + reg_rdata_next[9:0] = status_9_qs; + end + + addr_hit[11]: begin + reg_rdata_next[9:0] = status_10_qs; + end + + addr_hit[12]: begin + reg_rdata_next[9:0] = status_11_qs; + end + + addr_hit[13]: begin + reg_rdata_next[9:0] = status_12_qs; + end + + addr_hit[14]: begin + reg_rdata_next[9:0] = status_13_qs; + end + + addr_hit[15]: begin + reg_rdata_next[9:0] = status_14_qs; + end + + addr_hit[16]: begin + reg_rdata_next[9:0] = status_15_qs; + end + + addr_hit[17]: begin + reg_rdata_next[31:0] = next_id_0_qs; + end + + addr_hit[18]: begin + reg_rdata_next[31:0] = next_id_1_qs; + end + + addr_hit[19]: begin + reg_rdata_next[31:0] = next_id_2_qs; + end + + addr_hit[20]: begin + reg_rdata_next[31:0] = next_id_3_qs; + end + + addr_hit[21]: begin + reg_rdata_next[31:0] = next_id_4_qs; + end + + addr_hit[22]: begin + reg_rdata_next[31:0] = next_id_5_qs; + end + + addr_hit[23]: begin + reg_rdata_next[31:0] = next_id_6_qs; + end + + addr_hit[24]: begin + reg_rdata_next[31:0] = next_id_7_qs; + end + + addr_hit[25]: begin + reg_rdata_next[31:0] = next_id_8_qs; + end + + addr_hit[26]: begin + reg_rdata_next[31:0] = next_id_9_qs; + end + + addr_hit[27]: begin + reg_rdata_next[31:0] = next_id_10_qs; + end + + addr_hit[28]: begin + reg_rdata_next[31:0] = next_id_11_qs; + end + + addr_hit[29]: begin + reg_rdata_next[31:0] = next_id_12_qs; + end + + addr_hit[30]: begin + reg_rdata_next[31:0] = next_id_13_qs; + end + + addr_hit[31]: begin + reg_rdata_next[31:0] = next_id_14_qs; + end + + addr_hit[32]: begin + reg_rdata_next[31:0] = next_id_15_qs; + end + + addr_hit[33]: begin + reg_rdata_next[31:0] = done_id_0_qs; + end + + addr_hit[34]: begin + reg_rdata_next[31:0] = done_id_1_qs; + end + + addr_hit[35]: begin + reg_rdata_next[31:0] = done_id_2_qs; + end + + addr_hit[36]: begin + reg_rdata_next[31:0] = done_id_3_qs; + end + + addr_hit[37]: begin + reg_rdata_next[31:0] = done_id_4_qs; + end + + addr_hit[38]: begin + reg_rdata_next[31:0] = done_id_5_qs; + end + + addr_hit[39]: begin + reg_rdata_next[31:0] = done_id_6_qs; + end + + addr_hit[40]: begin + reg_rdata_next[31:0] = done_id_7_qs; + end + + addr_hit[41]: begin + reg_rdata_next[31:0] = done_id_8_qs; + end + + addr_hit[42]: begin + reg_rdata_next[31:0] = done_id_9_qs; + end + + addr_hit[43]: begin + reg_rdata_next[31:0] = done_id_10_qs; + end + + addr_hit[44]: begin + reg_rdata_next[31:0] = done_id_11_qs; + end + + addr_hit[45]: begin + reg_rdata_next[31:0] = done_id_12_qs; + end + + addr_hit[46]: begin + reg_rdata_next[31:0] = done_id_13_qs; + end + + addr_hit[47]: begin + reg_rdata_next[31:0] = done_id_14_qs; + end + + addr_hit[48]: begin + reg_rdata_next[31:0] = done_id_15_qs; + end + + addr_hit[49]: begin + reg_rdata_next[31:0] = dst_addr_low_qs; + end + + addr_hit[50]: begin + reg_rdata_next[31:0] = dst_addr_high_qs; + end + + addr_hit[51]: begin + reg_rdata_next[31:0] = src_addr_low_qs; + end + + addr_hit[52]: begin + reg_rdata_next[31:0] = src_addr_high_qs; + end + + addr_hit[53]: begin + reg_rdata_next[31:0] = length_low_qs; + end + + addr_hit[54]: begin + reg_rdata_next[31:0] = length_high_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module idma_reg64_1d_reg_top_intf +#( + parameter int AW = 8, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output idma_reg64_1d_reg_pkg::idma_reg64_1d_reg2hw_t reg2hw, // Write + input idma_reg64_1d_reg_pkg::idma_reg64_1d_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW/8; + +`include "register_interface/typedef.svh" +`include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + idma_reg64_1d_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Michael Rogenmoser +// - Thomas Benz + +/// Description: Register-based front-end for iDMA +module idma_reg32_3d #( + /// Number of configuration register ports + parameter int unsigned NumRegs = 32'd1, + /// Number of streams (max 16) + parameter int unsigned NumStreams = 32'd1, + /// Width of the transfer id (max 32-bit) + parameter int unsigned IdCounterWidth = 32'd32, + /// Dependent parameter: Stream Idx + parameter int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams), + /// Register_interface request type + parameter type reg_req_t = logic, + /// Register_interface response type + parameter type reg_rsp_t = logic, + /// DMA 1d or ND burst request type + parameter type dma_req_t = logic, + /// Dependent type for IdCounterWidth + parameter type cnt_width_t = logic [IdCounterWidth-1:0], + /// Dependent type for StreamWidth + parameter type stream_t = logic [StreamWidth-1:0] +) ( + input logic clk_i, + input logic rst_ni, + /// Register interface control slave + input reg_req_t [NumRegs-1:0] dma_ctrl_req_i, + output reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, + /// Request signals + output dma_req_t dma_req_o, + output logic req_valid_o, + input logic req_ready_i, + input cnt_width_t next_id_i, + output stream_t stream_idx_o, + /// Status signals + input cnt_width_t [NumStreams-1:0] done_id_i, + input idma_pkg::idma_busy_t [NumStreams-1:0] busy_i, + input logic [NumStreams-1:0] midend_busy_i +); + + /// Maximum number of streams is set to 16. It can be enlarged, but the register file + /// needs to be adapted too. + localparam int unsigned MaxNumStreams = 32'd16; + + // register connections + idma_reg32_3d_reg_pkg::idma_reg32_3d_reg2hw_t [NumRegs-1:0] dma_reg2hw; + idma_reg32_3d_reg_pkg::idma_reg32_3d_hw2reg_t [NumRegs-1:0] dma_hw2reg; + + // arbitration output + dma_req_t [NumRegs-1:0] arb_dma_req; + logic [NumRegs-1:0] arb_valid; + logic [NumRegs-1:0] arb_ready; + + // register signals + reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; + + // generate the registers + for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs + + idma_reg32_3d_reg_top #( + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ) + ) i_idma_reg32_3d_reg_top ( + .clk_i, + .rst_ni, + .reg_req_i ( dma_ctrl_req_i [i] ), + .reg_rsp_o ( dma_ctrl_rsp [i] ), + .reg2hw ( dma_reg2hw [i] ), + .hw2reg ( dma_hw2reg [i] ), + .devmode_i ( 1'b1 ) + ); + + // DMA backpressure + always_comb begin : proc_dma_backpressure + // ready signal + dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; + dma_ctrl_rsp_o[i].ready = arb_ready[i]; + end + + // valid signals + logic read_happens; + always_comb begin : proc_launch + read_happens = 1'b0; + stream_idx_o = '0; + for (int c = 0; c < NumStreams; c++) begin + read_happens |= dma_reg2hw[i].next_id[c].re; + if (dma_reg2hw[i].next_id[c].re) begin + stream_idx_o = c; + end + end + arb_valid[i] = read_happens; + end + + // assign request struct + always_comb begin : proc_hw_req_conv + // all fields are zero per default + arb_dma_req[i] = '0; + + // address and length + arb_dma_req[i].burst_req.length = dma_reg2hw[i].length_low.q; + arb_dma_req[i].burst_req.src_addr = dma_reg2hw[i].src_addr_low.q; + arb_dma_req[i].burst_req.dst_addr = dma_reg2hw[i].dst_addr_low.q; + + // Protocols + arb_dma_req[i].burst_req.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); + arb_dma_req[i].burst_req.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); + + // Current backend only supports incremental burst + arb_dma_req[i].burst_req.opt.src.burst = axi_pkg::BURST_INCR; + arb_dma_req[i].burst_req.opt.dst.burst = axi_pkg::BURST_INCR; + // this frontend currently does not support cache variations + arb_dma_req[i].burst_req.opt.src.cache = axi_pkg::CACHE_MODIFIABLE; + arb_dma_req[i].burst_req.opt.dst.cache = axi_pkg::CACHE_MODIFIABLE; + + // Backend options + arb_dma_req[i].burst_req.opt.beo.decouple_aw = dma_reg2hw[i].conf.decouple_aw.q; + arb_dma_req[i].burst_req.opt.beo.decouple_rw = dma_reg2hw[i].conf.decouple_rw.q; + arb_dma_req[i].burst_req.opt.beo.src_max_llen = dma_reg2hw[i].conf.src_max_llen.q; + arb_dma_req[i].burst_req.opt.beo.dst_max_llen = dma_reg2hw[i].conf.dst_max_llen.q; + arb_dma_req[i].burst_req.opt.beo.src_reduce_len = dma_reg2hw[i].conf.src_reduce_len.q; + arb_dma_req[i].burst_req.opt.beo.dst_reduce_len = dma_reg2hw[i].conf.dst_reduce_len.q; + + // ND connections + arb_dma_req[i].d_req[0].reps = dma_reg2hw[i].reps_2_low.q; + arb_dma_req[i].d_req[0].src_strides = dma_reg2hw[i].src_stride_2_low.q; + arb_dma_req[i].d_req[0].dst_strides = dma_reg2hw[i].dst_stride_2_low.q; + arb_dma_req[i].d_req[1].reps = dma_reg2hw[i].reps_3_low.q; + arb_dma_req[i].d_req[1].src_strides = dma_reg2hw[i].src_stride_3_low.q; + arb_dma_req[i].d_req[1].dst_strides = dma_reg2hw[i].dst_stride_3_low.q; + + // Disable higher dimensions + if ( dma_reg2hw[i].conf.enable_nd.q == 0) begin + arb_dma_req[i].d_req[0].reps = '0; + arb_dma_req[i].d_req[1].reps = '0; + end + else if ( dma_reg2hw[i].conf.enable_nd.q == 1) begin + arb_dma_req[i].d_req[1].reps = '0; + end + end + + // observational registers + for (genvar c = 0; c < NumStreams; c++) begin + assign dma_hw2reg[i].status[c] = {midend_busy_i[c], busy_i[c]}; + assign dma_hw2reg[i].next_id[c] = next_id_i; + assign dma_hw2reg[i].done_id[c] = done_id_i[c]; + end + + // tie-off unused channels + for (genvar c = NumStreams; c < MaxNumStreams; c++) begin + assign dma_hw2reg[i].status[c] = '0; + assign dma_hw2reg[i].next_id[c] = '0; + assign dma_hw2reg[i].done_id[c] = '0; + end + + end + + // arbitration + rr_arb_tree #( + .NumIn ( NumRegs ), + .DataType ( dma_req_t ), + .ExtPrio ( 0 ), + .AxiVldRdy ( 1 ), + .LockIn ( 1 ) + ) i_rr_arb_tree ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .rr_i ( '0 ), + .req_i ( arb_valid ), + .gnt_o ( arb_ready ), + .data_i ( arb_dma_req ), + .gnt_i ( req_ready_i ), + .req_o ( req_valid_o ), + .data_o ( dma_req_o ), + .idx_o ( /* NC */ ) + ); + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Michael Rogenmoser +// - Thomas Benz + +/// Description: Register-based front-end for iDMA +module idma_reg64_2d #( + /// Number of configuration register ports + parameter int unsigned NumRegs = 32'd1, + /// Number of streams (max 16) + parameter int unsigned NumStreams = 32'd1, + /// Width of the transfer id (max 32-bit) + parameter int unsigned IdCounterWidth = 32'd32, + /// Dependent parameter: Stream Idx + parameter int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams), + /// Register_interface request type + parameter type reg_req_t = logic, + /// Register_interface response type + parameter type reg_rsp_t = logic, + /// DMA 1d or ND burst request type + parameter type dma_req_t = logic, + /// Dependent type for IdCounterWidth + parameter type cnt_width_t = logic [IdCounterWidth-1:0], + /// Dependent type for StreamWidth + parameter type stream_t = logic [StreamWidth-1:0] +) ( + input logic clk_i, + input logic rst_ni, + /// Register interface control slave + input reg_req_t [NumRegs-1:0] dma_ctrl_req_i, + output reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, + /// Request signals + output dma_req_t dma_req_o, + output logic req_valid_o, + input logic req_ready_i, + input cnt_width_t next_id_i, + output stream_t stream_idx_o, + /// Status signals + input cnt_width_t [NumStreams-1:0] done_id_i, + input idma_pkg::idma_busy_t [NumStreams-1:0] busy_i, + input logic [NumStreams-1:0] midend_busy_i +); + + /// Maximum number of streams is set to 16. It can be enlarged, but the register file + /// needs to be adapted too. + localparam int unsigned MaxNumStreams = 32'd16; + + // register connections + idma_reg64_2d_reg_pkg::idma_reg64_2d_reg2hw_t [NumRegs-1:0] dma_reg2hw; + idma_reg64_2d_reg_pkg::idma_reg64_2d_hw2reg_t [NumRegs-1:0] dma_hw2reg; + + // arbitration output + dma_req_t [NumRegs-1:0] arb_dma_req; + logic [NumRegs-1:0] arb_valid; + logic [NumRegs-1:0] arb_ready; + + // register signals + reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; + + // generate the registers + for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs + + idma_reg64_2d_reg_top #( + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ) + ) i_idma_reg64_2d_reg_top ( + .clk_i, + .rst_ni, + .reg_req_i ( dma_ctrl_req_i [i] ), + .reg_rsp_o ( dma_ctrl_rsp [i] ), + .reg2hw ( dma_reg2hw [i] ), + .hw2reg ( dma_hw2reg [i] ), + .devmode_i ( 1'b1 ) + ); + + // DMA backpressure + always_comb begin : proc_dma_backpressure + // ready signal + dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; + dma_ctrl_rsp_o[i].ready = arb_ready[i]; + end + + // valid signals + logic read_happens; + always_comb begin : proc_launch + read_happens = 1'b0; + stream_idx_o = '0; + for (int c = 0; c < NumStreams; c++) begin + read_happens |= dma_reg2hw[i].next_id[c].re; + if (dma_reg2hw[i].next_id[c].re) begin + stream_idx_o = c; + end + end + arb_valid[i] = read_happens; + end + + // assign request struct + always_comb begin : proc_hw_req_conv + // all fields are zero per default + arb_dma_req[i] = '0; + + // address and length + arb_dma_req[i].burst_req.length = {dma_reg2hw[i].length_high.q, dma_reg2hw[i].length_low.q}; + arb_dma_req[i].burst_req.src_addr = {dma_reg2hw[i].src_addr_high.q, dma_reg2hw[i].src_addr_low.q}; + arb_dma_req[i].burst_req.dst_addr = {dma_reg2hw[i].dst_addr_high.q, dma_reg2hw[i].dst_addr_low.q}; + + // Protocols + arb_dma_req[i].burst_req.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); + arb_dma_req[i].burst_req.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); + + // Current backend only supports incremental burst + arb_dma_req[i].burst_req.opt.src.burst = axi_pkg::BURST_INCR; + arb_dma_req[i].burst_req.opt.dst.burst = axi_pkg::BURST_INCR; + // this frontend currently does not support cache variations + arb_dma_req[i].burst_req.opt.src.cache = axi_pkg::CACHE_MODIFIABLE; + arb_dma_req[i].burst_req.opt.dst.cache = axi_pkg::CACHE_MODIFIABLE; + + // Backend options + arb_dma_req[i].burst_req.opt.beo.decouple_aw = dma_reg2hw[i].conf.decouple_aw.q; + arb_dma_req[i].burst_req.opt.beo.decouple_rw = dma_reg2hw[i].conf.decouple_rw.q; + arb_dma_req[i].burst_req.opt.beo.src_max_llen = dma_reg2hw[i].conf.src_max_llen.q; + arb_dma_req[i].burst_req.opt.beo.dst_max_llen = dma_reg2hw[i].conf.dst_max_llen.q; + arb_dma_req[i].burst_req.opt.beo.src_reduce_len = dma_reg2hw[i].conf.src_reduce_len.q; + arb_dma_req[i].burst_req.opt.beo.dst_reduce_len = dma_reg2hw[i].conf.dst_reduce_len.q; + + // ND connections + arb_dma_req[i].d_req[0].reps = {dma_reg2hw[i].reps_2_high.q, + dma_reg2hw[i].reps_2_low.q }; + arb_dma_req[i].d_req[0].src_strides = {dma_reg2hw[i].src_stride_2_high.q, + dma_reg2hw[i].src_stride_2_low.q}; + arb_dma_req[i].d_req[0].dst_strides = {dma_reg2hw[i].dst_stride_2_high.q, + dma_reg2hw[i].dst_stride_2_low.q}; + + // Disable higher dimensions + if ( dma_reg2hw[i].conf.enable_nd.q == 0) begin + arb_dma_req[i].d_req[0].reps = '0; + end + end + + // observational registers + for (genvar c = 0; c < NumStreams; c++) begin + assign dma_hw2reg[i].status[c] = {midend_busy_i[c], busy_i[c]}; + assign dma_hw2reg[i].next_id[c] = next_id_i; + assign dma_hw2reg[i].done_id[c] = done_id_i[c]; + end + + // tie-off unused channels + for (genvar c = NumStreams; c < MaxNumStreams; c++) begin + assign dma_hw2reg[i].status[c] = '0; + assign dma_hw2reg[i].next_id[c] = '0; + assign dma_hw2reg[i].done_id[c] = '0; + end + + end + + // arbitration + rr_arb_tree #( + .NumIn ( NumRegs ), + .DataType ( dma_req_t ), + .ExtPrio ( 0 ), + .AxiVldRdy ( 1 ), + .LockIn ( 1 ) + ) i_rr_arb_tree ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .rr_i ( '0 ), + .req_i ( arb_valid ), + .gnt_o ( arb_ready ), + .data_i ( arb_dma_req ), + .gnt_i ( req_ready_i ), + .req_o ( req_valid_o ), + .data_o ( dma_req_o ), + .idx_o ( /* NC */ ) + ); + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Michael Rogenmoser +// - Thomas Benz + +/// Description: Register-based front-end for iDMA +module idma_reg64_1d #( + /// Number of configuration register ports + parameter int unsigned NumRegs = 32'd1, + /// Number of streams (max 16) + parameter int unsigned NumStreams = 32'd1, + /// Width of the transfer id (max 32-bit) + parameter int unsigned IdCounterWidth = 32'd32, + /// Dependent parameter: Stream Idx + parameter int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams), + /// Register_interface request type + parameter type reg_req_t = logic, + /// Register_interface response type + parameter type reg_rsp_t = logic, + /// DMA 1d or ND burst request type + parameter type dma_req_t = logic, + /// Dependent type for IdCounterWidth + parameter type cnt_width_t = logic [IdCounterWidth-1:0], + /// Dependent type for StreamWidth + parameter type stream_t = logic [StreamWidth-1:0] +) ( + input logic clk_i, + input logic rst_ni, + /// Register interface control slave + input reg_req_t [NumRegs-1:0] dma_ctrl_req_i, + output reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, + /// Request signals + output dma_req_t dma_req_o, + output logic req_valid_o, + input logic req_ready_i, + input cnt_width_t next_id_i, + output stream_t stream_idx_o, + /// Status signals + input cnt_width_t [NumStreams-1:0] done_id_i, + input idma_pkg::idma_busy_t [NumStreams-1:0] busy_i, + input logic [NumStreams-1:0] midend_busy_i +); + + /// Maximum number of streams is set to 16. It can be enlarged, but the register file + /// needs to be adapted too. + localparam int unsigned MaxNumStreams = 32'd16; + + // register connections + idma_reg64_1d_reg_pkg::idma_reg64_1d_reg2hw_t [NumRegs-1:0] dma_reg2hw; + idma_reg64_1d_reg_pkg::idma_reg64_1d_hw2reg_t [NumRegs-1:0] dma_hw2reg; + + // arbitration output + dma_req_t [NumRegs-1:0] arb_dma_req; + logic [NumRegs-1:0] arb_valid; + logic [NumRegs-1:0] arb_ready; + + // register signals + reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; + + // generate the registers + for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs + + idma_reg64_1d_reg_top #( + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ) + ) i_idma_reg64_1d_reg_top ( + .clk_i, + .rst_ni, + .reg_req_i ( dma_ctrl_req_i [i] ), + .reg_rsp_o ( dma_ctrl_rsp [i] ), + .reg2hw ( dma_reg2hw [i] ), + .hw2reg ( dma_hw2reg [i] ), + .devmode_i ( 1'b1 ) + ); + + // DMA backpressure + always_comb begin : proc_dma_backpressure + // ready signal + dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; + dma_ctrl_rsp_o[i].ready = arb_ready[i]; + end + + // valid signals + logic read_happens; + always_comb begin : proc_launch + read_happens = 1'b0; + stream_idx_o = '0; + for (int c = 0; c < NumStreams; c++) begin + read_happens |= dma_reg2hw[i].next_id[c].re; + if (dma_reg2hw[i].next_id[c].re) begin + stream_idx_o = c; + end + end + arb_valid[i] = read_happens; + end + + // assign request struct + always_comb begin : proc_hw_req_conv + // all fields are zero per default + arb_dma_req[i] = '0; + + // address and length + arb_dma_req[i].length = {dma_reg2hw[i].length_high.q, dma_reg2hw[i].length_low.q}; + arb_dma_req[i].src_addr = {dma_reg2hw[i].src_addr_high.q, dma_reg2hw[i].src_addr_low.q}; + arb_dma_req[i].dst_addr = {dma_reg2hw[i].dst_addr_high.q, dma_reg2hw[i].dst_addr_low.q}; + + // Protocols + arb_dma_req[i].src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); + arb_dma_req[i].dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); + + // Current backend only supports incremental burst + arb_dma_req[i].opt.src.burst = axi_pkg::BURST_INCR; + arb_dma_req[i].opt.dst.burst = axi_pkg::BURST_INCR; + // this frontend currently does not support cache variations + arb_dma_req[i].opt.src.cache = axi_pkg::CACHE_MODIFIABLE; + arb_dma_req[i].opt.dst.cache = axi_pkg::CACHE_MODIFIABLE; + + // Backend options + arb_dma_req[i].opt.beo.decouple_aw = dma_reg2hw[i].conf.decouple_aw.q; + arb_dma_req[i].opt.beo.decouple_rw = dma_reg2hw[i].conf.decouple_rw.q; + arb_dma_req[i].opt.beo.src_max_llen = dma_reg2hw[i].conf.src_max_llen.q; + arb_dma_req[i].opt.beo.dst_max_llen = dma_reg2hw[i].conf.dst_max_llen.q; + arb_dma_req[i].opt.beo.src_reduce_len = dma_reg2hw[i].conf.src_reduce_len.q; + arb_dma_req[i].opt.beo.dst_reduce_len = dma_reg2hw[i].conf.dst_reduce_len.q; + + end + + // observational registers + for (genvar c = 0; c < NumStreams; c++) begin + assign dma_hw2reg[i].status[c] = {midend_busy_i[c], busy_i[c]}; + assign dma_hw2reg[i].next_id[c] = next_id_i; + assign dma_hw2reg[i].done_id[c] = done_id_i[c]; + end + + // tie-off unused channels + for (genvar c = NumStreams; c < MaxNumStreams; c++) begin + assign dma_hw2reg[i].status[c] = '0; + assign dma_hw2reg[i].next_id[c] = '0; + assign dma_hw2reg[i].done_id[c] = '0; + end + + end + + // arbitration + rr_arb_tree #( + .NumIn ( NumRegs ), + .DataType ( dma_req_t ), + .ExtPrio ( 0 ), + .AxiVldRdy ( 1 ), + .LockIn ( 1 ) + ) i_rr_arb_tree ( + .clk_i, + .rst_ni, + .flush_i ( 1'b0 ), + .rr_i ( '0 ), + .req_i ( arb_valid ), + .gnt_o ( arb_ready ), + .data_i ( arb_dma_req ), + .gnt_i ( req_ready_i ), + .req_o ( req_valid_o ), + .data_o ( dma_req_o ), + .idx_o ( /* NC */ ) + ); + +endmodule + From 3d018f067a7e0c2c7293cd972d1d361efe1a6d8a Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Fri, 21 Jun 2024 18:06:59 +0200 Subject: [PATCH 05/13] [WIP] change inst64_snitch_pkg bender target to only `rtl` --- Bender.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bender.yml b/Bender.yml index adc686f1..8fa92168 100644 --- a/Bender.yml +++ b/Bender.yml @@ -68,7 +68,7 @@ sources: - src/midend/idma_rt_midend.sv # RISC-V opcode package for ooc use of inst64 - - target: all(rtl,snitch_cluster) + - target: rtl files: # Level 0 - src/frontend/inst64/idma_inst64_snitch_pkg.sv From 187b18ee2356208d0aaebd4aa747bc7a86638551 Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Fri, 21 Jun 2024 18:34:01 +0200 Subject: [PATCH 06/13] [WIP] fix compilation errors in pulp_idma_wrap --- src/pulp_idma_wrap.sv | 59 ++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/src/pulp_idma_wrap.sv b/src/pulp_idma_wrap.sv index 412eb7fa..a2be55f5 100644 --- a/src/pulp_idma_wrap.sv +++ b/src/pulp_idma_wrap.sv @@ -18,34 +18,34 @@ `include "register_interface/typedef.svh" module pulp_idma_wrap #( - parameter int unsigned NB_CORES = 4, - parameter int unsigned AXI_ADDR_WIDTH = 32, - parameter int unsigned AXI_DATA_WIDTH = 64, - parameter int unsigned AXI_USER_WIDTH = 6, - parameter int unsigned AXI_ID_WIDTH = 4, - parameter int unsigned PE_ID_WIDTH = 1, - parameter int unsigned NB_PE_PORTS = 1, - parameter int unsigned DATA_WIDTH = 32, - parameter int unsigned ADDR_WIDTH = 32, - parameter int unsigned BE_WIDTH = DATA_WIDTH / 8, - parameter type axi_req_t = logic, - parameter type axi_resp_t = logic, + parameter int unsigned NB_CORES = 4, + parameter int unsigned AXI_ADDR_WIDTH = 32, + parameter int unsigned AXI_DATA_WIDTH = 64, + parameter int unsigned AXI_USER_WIDTH = 6, + parameter int unsigned AXI_ID_WIDTH = 4, + parameter int unsigned PE_ID_WIDTH = 1, + parameter int unsigned NB_PE_PORTS = 1, + parameter int unsigned DATA_WIDTH = 32, + parameter int unsigned ADDR_WIDTH = 32, + parameter int unsigned BE_WIDTH = DATA_WIDTH / 8, + parameter type axi_req_t = logic, + parameter type axi_resp_t = logic, // bidirectional streams: range 1 to 8 - parameter int unsigned NUM_BIDIR_STREAMS = 1, - parameter int unsigned NB_OUTSND_BURSTS = 8, + parameter int unsigned NUM_BIDIR_STREAMS = 1, + parameter int unsigned NB_OUTSND_BURSTS = 8, // queue depth per stream - parameter int unsigned GLOBAL_QUEUE_DEPTH = 2, + parameter int unsigned GLOBAL_QUEUE_DEPTH = 2, // mux read ports between tcdm-tcdm and tcdm-axi? - parameter bit MUX_READ = 1'b0, + parameter bit MUX_READ = 1'b0, // 4 ports per stream if read ports muxed, otherwise 6 - localparam int unsigned NB_TCDM_PORTS_PER_STRM = 4 + (~MUX_READ) * 2 + parameter int unsigned NB_TCDM_PORTS_PER_STRM = 4 + (~MUX_READ) * 2 ) ( // verilog_format: off // verible does not manage to align this :( input logic clk_i, input logic rst_ni, input logic test_mode_i, - XBAR_PERIPH_BUS.Slave pe_ctrl_slave[NB_PE_PORTS-1:0], - XBAR_TCDM_BUS.Slave ctrl_slave[NB_CORES-1:0], - hci_core_intf.master tcdm_master[NB_TCDM_PORTS_PER_STRM*NUM_BIDIR_STREAMS-1:0], + XBAR_PERIPH_BUS.Slave pe_ctrl_slave[NB_PE_PORTS-1:0], + XBAR_TCDM_BUS.Slave ctrl_slave[NB_CORES-1:0], + hci_core_intf.master tcdm_master[NB_TCDM_PORTS_PER_STRM*NUM_BIDIR_STREAMS-1:0], output axi_req_t [NUM_BIDIR_STREAMS-1:0] ext_master_req_o, input axi_resp_t [NUM_BIDIR_STREAMS-1:0] ext_master_rsp_i, output logic [NB_CORES-1:0] term_event_o, @@ -114,10 +114,10 @@ module pulp_idma_wrap #( // Memory Init typedefs /// init read request typedef struct packed { - logic [AXI_ADDR_WIDTH-1:0] cfg; - logic [AXI_DATA_WIDTH-1:0] term; - logic [AXI_STRB_WIDTH-1:0] strb; - logic [AXI_ID_WIDTH-1:0] id; + logic [AXI_ADDR_WIDTH-1:0] cfg; + logic [AXI_DATA_WIDTH-1:0] term; + logic [AXI_DATA_WIDTH/8-1:0] strb; + logic [AXI_ID_WIDTH-1:0] id; } init_req_chan_t; typedef struct packed { @@ -157,13 +157,10 @@ module pulp_idma_wrap #( // interface to structs for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin : gen_connect_interface - // `AXI_ASSIGN_FROM_REQ(ext_master[s], soc_req[s]) - // `AXI_ASSIGN_TO_RESP(soc_rsp[s], ext_master[s]) assign ext_master_req_o[s] = soc_req[s]; assign soc_rsp[s] = ext_master_resp_i[s]; end - // connect RW axi buses for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin : gen_rw_axi_connection axi_rw_join #( @@ -198,7 +195,7 @@ module pulp_idma_wrap #( typedef logic [StrideWidth-1:0] strides_t; // iDMA request / response types - `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, slv_id_t, addr_t, tf_len_t) + `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, id_t, addr_t, tf_len_t) `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, addr_t) // iDMA ND request @@ -656,7 +653,7 @@ axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) .atop_i('0), .we_i(obi_read_req_muxed[s].a.we), .rvalid_o(obi_read_rsp_to_mux[s].rvalid), - .rdata_o(obi_read_rsp_to_mux[s].r.data), + .rdata_o(obi_read_rsp_to_mux[s].r.rdata), .bank_req_o({ tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].req }), @@ -714,7 +711,7 @@ axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) .atop_i('0), .we_i(obi_reorg_req[s].a.we), .rvalid_o(obi_reorg_rsp[s].rvalid), - .rdata_o(obi_reorg_rsp[s].r.data), + .rdata_o(obi_reorg_rsp[s].r.rdata), .bank_req_o({ tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].req }), @@ -770,7 +767,7 @@ axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) .atop_i('0), .we_i(obi_write_req[s].a.we), .rvalid_o(obi_write_rsp[s].rvalid), - .rdata_o(obi_write_rsp[s].r.data), + .rdata_o(obi_write_rsp[s].r.rdata), .bank_req_o({ tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].req }), From e7b61b22614d57e3277e1075207150c7f9c3ce5c Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Mon, 24 Jun 2024 13:44:05 +0200 Subject: [PATCH 07/13] [WIP] Fix compilation & optimization of PULP iDMA wrap, register FE --- Bender.yml | 2 + src/frontend/reg/tpl/idma_reg.sv.tpl | 19 +- src/pulp_idma_wrap.sv | 53 +- target/rtl/idma_generated.sv | 7198 +++++++++----------------- 4 files changed, 2558 insertions(+), 4714 deletions(-) diff --git a/Bender.yml b/Bender.yml index 8fa92168..404a0137 100644 --- a/Bender.yml +++ b/Bender.yml @@ -52,6 +52,8 @@ sources: - src/backend/idma_obi_write.sv - src/backend/idma_tilelink_read.sv - src/backend/idma_tilelink_write.sv + # Level 2 + - src/pulp_idma_wrap.sv # Generated content - target: rtl diff --git a/src/frontend/reg/tpl/idma_reg.sv.tpl b/src/frontend/reg/tpl/idma_reg.sv.tpl index 1183d9f1..40ae8fb7 100644 --- a/src/frontend/reg/tpl/idma_reg.sv.tpl +++ b/src/frontend/reg/tpl/idma_reg.sv.tpl @@ -60,6 +60,17 @@ module idma_${identifier} #( // register signals reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; + always_comb begin + stream_idx_o = '0; + for (int r = 0; r < NumRegs; r++) begin + for (int c = 0; c < NumStreams; c++) begin + if (dma_reg2hw[r].next_id[c].re) begin + stream_idx_o = c; + end + end + end + end + // generate the registers for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs @@ -87,12 +98,8 @@ module idma_${identifier} #( logic read_happens; always_comb begin : proc_launch read_happens = 1'b0; - stream_idx_o = '0; for (int c = 0; c < NumStreams; c++) begin read_happens |= dma_reg2hw[i].next_id[c].re; - if (dma_reg2hw[i].next_id[c].re) begin - stream_idx_o = c; - end end arb_valid[i] = read_happens; end @@ -114,8 +121,8 @@ module idma_${identifier} #( % endif // Protocols - arb_dma_req[i]${sep}src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); - arb_dma_req[i]${sep}dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); + arb_dma_req[i]${sep}opt.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); + arb_dma_req[i]${sep}opt.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); // Current backend only supports incremental burst arb_dma_req[i]${sep}opt.src.burst = axi_pkg::BURST_INCR; diff --git a/src/pulp_idma_wrap.sv b/src/pulp_idma_wrap.sv index a2be55f5..1e7ad6ee 100644 --- a/src/pulp_idma_wrap.sv +++ b/src/pulp_idma_wrap.sv @@ -17,6 +17,8 @@ `include "idma/typedef.svh" `include "register_interface/typedef.svh" +`define MY_MAX(a,b) (a > b ? a : b) + module pulp_idma_wrap #( parameter int unsigned NB_CORES = 4, parameter int unsigned AXI_ADDR_WIDTH = 32, @@ -38,7 +40,7 @@ module pulp_idma_wrap #( // mux read ports between tcdm-tcdm and tcdm-axi? parameter bit MUX_READ = 1'b0, // 4 ports per stream if read ports muxed, otherwise 6 - parameter int unsigned NB_TCDM_PORTS_PER_STRM = 4 + (~MUX_READ) * 2 + localparam int unsigned NB_TCDM_PORTS_PER_STRM = 4 + (!MUX_READ) * 2 ) ( // verilog_format: off // verible does not manage to align this :( input logic clk_i, input logic rst_ni, @@ -47,7 +49,7 @@ module pulp_idma_wrap #( XBAR_TCDM_BUS.Slave ctrl_slave[NB_CORES-1:0], hci_core_intf.master tcdm_master[NB_TCDM_PORTS_PER_STRM*NUM_BIDIR_STREAMS-1:0], output axi_req_t [NUM_BIDIR_STREAMS-1:0] ext_master_req_o, - input axi_resp_t [NUM_BIDIR_STREAMS-1:0] ext_master_rsp_i, + input axi_resp_t [NUM_BIDIR_STREAMS-1:0] ext_master_resp_i, output logic [NB_CORES-1:0] term_event_o, output logic [NB_CORES-1:0] term_irq_o, output logic [NB_PE_PORTS-1:0] term_event_pe_o, @@ -109,8 +111,12 @@ module pulp_idma_wrap #( typedef logic [AXI_USER_WIDTH-1:0] user_t; // // AXI4+ATOP channels typedefs - `AXI_TYPEDEF_ALL(axi, addr_t, id_t, data_t, strb_t, user_t) - + //`AXI_TYPEDEF_ALL(axi_int, addr_t, id_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) + `AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) + `AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) + `AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) // Memory Init typedefs /// init read request typedef struct packed { @@ -360,18 +366,15 @@ module pulp_idma_wrap #( localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); - function int unsigned max_width(input int unsigned a, b); - return (a > b) ? a : b; - endfunction typedef struct packed { init_req_chan_t req_chan; - logic [max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; + logic [`MY_MAX(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; } init_read_req_chan_padded_t; typedef struct packed { obi_a_chan_t a_chan; - logic [max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + logic [`MY_MAX(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; } obi_read_a_chan_padded_t; typedef union packed { @@ -381,12 +384,12 @@ module pulp_idma_wrap #( typedef struct packed { axi_aw_chan_t aw_chan; - logic [max_width(axi_aw_chan_width, init_req_chan_width)-axi_aw_chan_width:0] padding; + logic [`MY_MAX(axi_aw_chan_width, init_req_chan_width)-axi_aw_chan_width:0] padding; } axi_write_aw_chan_padded_t; typedef struct packed { init_req_chan_t req_chan; - logic [max_width(axi_aw_chan_width, init_req_chan_width)-init_req_chan_width:0] padding; + logic [`MY_MAX(axi_aw_chan_width, init_req_chan_width)-init_req_chan_width:0] padding; } init_write_req_chan_padded_t; typedef union packed { @@ -417,7 +420,7 @@ module pulp_idma_wrap #( .idma_eh_req_t (idma_pkg::idma_eh_req_t), .idma_busy_t (idma_pkg::idma_busy_t), .axi_req_t (axi_req_t), - .axi_rsp_t (axi_rsp_t), + .axi_rsp_t (axi_resp_t), .init_req_t (init_req_t), .init_rsp_t (init_rsp_t), .obi_req_t (obi_req_t), @@ -475,23 +478,19 @@ module pulp_idma_wrap #( typedef struct packed { axi_ar_chan_t ar_chan; - logic [max_width( -axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) + logic [`MY_MAX( +axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) )-axi_ar_chan_width:0] padding; } axi_read_ar_chan_padded_t; typedef struct packed { init_req_chan_t req_chan; - logic [max_width( -axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) -)-init_req_chan_width:0] padding; + logic [`MY_MAX(axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width))-init_req_chan_width:0] padding; } init_read_req_chan_padded_t; typedef struct packed { obi_a_chan_t a_chan; - logic [max_width( -axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) -)-obi_a_chan_width:0] padding; + logic [`MY_MAX(axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width))-obi_a_chan_width:0] padding; } obi_read_a_chan_padded_t; typedef union packed { @@ -502,12 +501,12 @@ axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) typedef struct packed { init_req_chan_t req_chan; - logic [max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; + logic [`MY_MAX(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; } init_write_req_chan_padded_t; typedef struct packed { obi_a_chan_t a_chan; - logic [max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; + logic [`MY_MAX(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; } obi_write_a_chan_padded_t; typedef union packed { @@ -538,7 +537,7 @@ axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) .idma_eh_req_t (idma_pkg::idma_eh_req_t), .idma_busy_t (idma_pkg::idma_busy_t), .axi_req_t (axi_req_t), - .axi_rsp_t (axi_rsp_t), + .axi_rsp_t (axi_resp_t), .init_req_t (init_req_t), .init_rsp_t (init_rsp_t), .obi_req_t (obi_req_t), @@ -580,8 +579,8 @@ axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) assign init_write_rsp.rsp_chan.init = '0; assign init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register assign init_write_rsp.req_ready = 1'b1; - end // block: gen_cpy_in - end // block: gen_streams + end : gen_cpy_in + end : gen_streams // ------------------------------------------------------ @@ -589,8 +588,7 @@ axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) // ------------------------------------------------------ for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin if (MUX_READ) begin - obi_pkg::obi_cfg_t sbr_obi_cfg; - assign sbr_obi_cfg = obi_pkg::obi_default_cfg( + localparam obi_pkg::obi_cfg_t sbr_obi_cfg = obi_pkg::obi_default_cfg( AXI_ADDR_WIDTH, AXI_DATA_WIDTH, 0, obi_pkg::ObiMinimalOptionalConfig ); @@ -805,3 +803,4 @@ axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width) end endmodule +`undef MY_MAX diff --git a/target/rtl/idma_generated.sv b/target/rtl/idma_generated.sv index 13c47c20..4603c5bd 100644 --- a/target/rtl/idma_generated.sv +++ b/target/rtl/idma_generated.sv @@ -1305,7 +1305,7 @@ endmodule `include "common_cells/registers.svh" /// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_rw_axi_rw_obi #( +module idma_transport_layer_r_obi_rw_init_w_axi #( /// Number of transaction that can be in-flight concurrently parameter int unsigned NumAxInFlight = 32'd2, /// Data width @@ -1335,6 +1335,9 @@ module idma_transport_layer_rw_axi_rw_obi #( /// AXI4+ATOP Request and Response channel type parameter type axi_req_t = logic, parameter type axi_rsp_t = logic, + /// Memory Init Request and Response channel type + parameter type init_req_t = logic, + parameter type init_rsp_t = logic, /// OBI Request and Response channel type parameter type obi_req_t = logic, parameter type obi_rsp_t = logic @@ -1346,10 +1349,10 @@ module idma_transport_layer_rw_axi_rw_obi #( /// Testmode in input logic testmode_i, - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, + /// Memory Init read request + output init_req_t init_read_req_o, + /// Memory Init read response + input init_rsp_t init_read_rsp_i, /// OBI read request output obi_req_t obi_read_req_o, @@ -1361,10 +1364,10 @@ module idma_transport_layer_rw_axi_rw_obi #( /// AXI4+ATOP write response input axi_rsp_t axi_write_rsp_i, - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, + /// Memory Init write request + output init_req_t init_write_req_o, + /// Memory Init write response + input init_rsp_t init_write_rsp_i, /// Read datapath request input r_dp_req_t r_dp_req_i, @@ -1434,36 +1437,36 @@ module idma_transport_layer_rw_axi_rw_obi #( typedef logic [7:0] byte_t; // inbound control signals to the read buffer: controlled by the read process - strb_t axi_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; + strb_t init_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; strb_t buffer_in_ready; // outbound control signals of the buffer: controlled by the write process strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t axi_buffer_out_ready, obi_buffer_out_ready, + strb_t axi_buffer_out_ready, init_buffer_out_ready, buffer_out_ready, buffer_out_ready_shifted; // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] axi_buffer_in, obi_buffer_in, + byte_t [StrbWidth-1:0] init_buffer_in, obi_buffer_in, buffer_in, buffer_in_shifted; // aligned and coalesced data leaving the buffer byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; // Read multiplexed signals - logic axi_r_chan_valid, obi_r_chan_valid; - logic axi_r_chan_ready, obi_r_chan_ready; - logic axi_r_dp_valid, obi_r_dp_valid; - logic axi_r_dp_ready, obi_r_dp_ready; - r_dp_rsp_t axi_r_dp_rsp, obi_r_dp_rsp; + logic init_r_chan_valid, obi_r_chan_valid; + logic init_r_chan_ready, obi_r_chan_ready; + logic init_r_dp_valid, obi_r_dp_valid; + logic init_r_dp_ready, obi_r_dp_ready; + r_dp_rsp_t init_r_dp_rsp, obi_r_dp_rsp; - logic axi_ar_ready, obi_ar_ready; + logic init_ar_ready, obi_ar_ready; // Write multiplexed signals - logic axi_w_dp_rsp_valid, obi_w_dp_rsp_valid; - logic axi_w_dp_rsp_ready, obi_w_dp_rsp_ready; - logic axi_w_dp_ready, obi_w_dp_ready; - w_dp_rsp_t axi_w_dp_rsp, obi_w_dp_rsp; + logic axi_w_dp_rsp_valid, init_w_dp_rsp_valid; + logic axi_w_dp_rsp_ready, init_w_dp_rsp_ready; + logic axi_w_dp_ready, init_w_dp_ready; + w_dp_rsp_t axi_w_dp_rsp, init_w_dp_rsp; - logic axi_aw_ready, obi_aw_ready; + logic axi_aw_ready, init_aw_ready; logic w_dp_req_valid, w_dp_req_ready; logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; logic w_dp_rsp_valid, w_dp_rsp_ready; @@ -1478,33 +1481,31 @@ module idma_transport_layer_rw_axi_rw_obi #( // Read Ports //-------------------------------------- - idma_axi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .ar_chan_t ( read_meta_channel_t ), - .read_req_t ( axi_req_t ), - .read_rsp_t ( axi_rsp_t ) - ) i_idma_axi_read ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), + idma_init_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .read_meta_chan_t ( read_meta_channel_t ), + .read_req_t ( init_req_t ), + .read_rsp_t ( init_rsp_t ) + ) i_idma_init_read ( .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_valid_i ), - .r_dp_ready_o ( axi_r_dp_ready ), - .r_dp_rsp_o ( axi_r_dp_rsp ), - .r_dp_valid_o ( axi_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_ready_i ), - .ar_req_i ( ar_req_i.ar_req ), - .ar_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI) & ar_valid_i ), - .ar_ready_o ( axi_ar_ready ), - .read_req_o ( axi_read_req_o ), - .read_rsp_i ( axi_read_rsp_i ), - .r_chan_valid_o ( axi_r_chan_valid ), - .r_chan_ready_o ( axi_r_chan_ready ), - .buffer_in_o ( axi_buffer_in ), - .buffer_in_valid_o ( axi_buffer_in_valid ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_valid_i ), + .r_dp_ready_o ( init_r_dp_ready ), + .r_dp_rsp_o ( init_r_dp_rsp ), + .r_dp_valid_o ( init_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_ready_i ), + .read_meta_req_i ( ar_req_i.ar_req ), + .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::INIT) & ar_valid_i ), + .read_meta_ready_o ( init_ar_ready ), + .read_req_o ( init_read_req_o ), + .read_rsp_i ( init_read_rsp_i ), + .r_chan_valid_o ( init_r_chan_valid ), + .r_chan_ready_o ( init_r_chan_ready ), + .buffer_in_o ( init_buffer_in ), + .buffer_in_valid_o ( init_buffer_in_valid ), .buffer_in_ready_i ( buffer_in_ready ) ); @@ -1542,7 +1543,7 @@ module idma_transport_layer_rw_axi_rw_obi #( always_comb begin : gen_read_meta_channel_multiplexer case(ar_req_i.src_protocol) - idma_pkg::AXI: ar_ready_o = axi_ar_ready; + idma_pkg::INIT: ar_ready_o = init_ar_ready; idma_pkg::OBI: ar_ready_o = obi_ar_ready; default: ar_ready_o = 1'b0; endcase @@ -1550,16 +1551,16 @@ module idma_transport_layer_rw_axi_rw_obi #( always_comb begin : gen_read_multiplexer case(r_dp_req_i.src_protocol) - idma_pkg::AXI: begin - r_chan_valid_o = axi_r_chan_valid; - r_chan_ready_o = axi_r_chan_ready; + idma_pkg::INIT: begin + r_chan_valid_o = init_r_chan_valid; + r_chan_ready_o = init_r_chan_ready; - r_dp_ready_o = axi_r_dp_ready; - r_dp_rsp_o = axi_r_dp_rsp; - r_dp_valid_o = axi_r_dp_valid; + r_dp_ready_o = init_r_dp_ready; + r_dp_rsp_o = init_r_dp_rsp; + r_dp_valid_o = init_r_dp_valid; - buffer_in = axi_buffer_in; - buffer_in_valid = axi_buffer_in_valid; + buffer_in = init_buffer_in; + buffer_in_valid = init_buffer_in_valid; end idma_pkg::OBI: begin r_chan_valid_o = obi_r_chan_valid; @@ -1645,9 +1646,9 @@ module idma_transport_layer_rw_axi_rw_obi #( w_dp_req_ready = axi_w_dp_ready; buffer_out_ready = axi_buffer_out_ready; end - idma_pkg::OBI: begin - w_dp_req_ready = obi_w_dp_ready; - buffer_out_ready = obi_buffer_out_ready; + idma_pkg::INIT: begin + w_dp_req_ready = init_w_dp_ready; + buffer_out_ready = init_buffer_out_ready; end default: begin w_dp_req_ready = 1'b0; @@ -1660,7 +1661,7 @@ module idma_transport_layer_rw_axi_rw_obi #( always_comb begin : gen_write_meta_channel_multiplexer case(aw_req_i.dst_protocol) idma_pkg::AXI: aw_ready_o = axi_aw_ready; - idma_pkg::OBI: aw_ready_o = obi_aw_ready; + idma_pkg::INIT: aw_ready_o = init_aw_ready; default: aw_ready_o = 1'b0; endcase end @@ -1700,33 +1701,32 @@ module idma_transport_layer_rw_axi_rw_obi #( .buffer_out_ready_o ( axi_buffer_out_ready ) ); - idma_obi_write #( + idma_init_write #( .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), .byte_t ( byte_t ), .data_t ( data_t ), .strb_t ( strb_t ), .w_dp_req_t ( w_dp_req_t ), .w_dp_rsp_t ( w_dp_rsp_t ), .write_meta_channel_t ( write_meta_channel_t ), - .write_req_t ( obi_req_t ), - .write_rsp_t ( obi_rsp_t ) - ) i_idma_obi_write ( + .write_req_t ( init_req_t ), + .write_rsp_t ( init_rsp_t ) + ) i_idma_init_write ( .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::OBI) & w_dp_req_valid ), - .w_dp_ready_o ( obi_w_dp_ready ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::INIT) & w_dp_req_valid ), + .w_dp_ready_o ( init_w_dp_ready ), .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( obi_w_dp_rsp ), - .w_dp_valid_o ( obi_w_dp_rsp_valid ), - .w_dp_ready_i ( obi_w_dp_rsp_ready ), - .aw_req_i ( aw_req_i.aw_req ), - .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::OBI) & aw_valid_i ), - .aw_ready_o ( obi_aw_ready ), - .write_req_o ( obi_write_req_o ), - .write_rsp_i ( obi_write_rsp_i ), + .w_dp_rsp_o ( init_w_dp_rsp ), + .w_dp_valid_o ( init_w_dp_rsp_valid ), + .w_dp_ready_i ( init_w_dp_rsp_ready ), + .write_meta_req_i ( aw_req_i.aw_req ), + .write_meta_valid_i ( (aw_req_i.dst_protocol == idma_pkg::INIT) & aw_valid_i ), + .write_meta_ready_o ( init_aw_ready ), + .write_req_o ( init_write_req_o ), + .write_rsp_i ( init_write_rsp_i ), .buffer_out_i ( buffer_out_shifted ), .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( obi_buffer_out_ready ) + .buffer_out_ready_o ( init_buffer_out_ready ) ); //-------------------------------------- @@ -1763,7 +1763,7 @@ module idma_transport_layer_rw_axi_rw_obi #( w_dp_rsp_mux = '0; w_dp_rsp_mux_valid = 1'b0; axi_w_dp_rsp_ready = 1'b0; - obi_w_dp_rsp_ready = 1'b0; + init_w_dp_rsp_ready = 1'b0; if ( w_resp_fifo_out_valid ) begin case(w_resp_fifo_out_protocol) idma_pkg::AXI: begin @@ -1771,10 +1771,10 @@ module idma_transport_layer_rw_axi_rw_obi #( w_dp_rsp_mux = axi_w_dp_rsp; axi_w_dp_rsp_ready = w_dp_rsp_mux_ready; end - idma_pkg::OBI: begin - w_dp_rsp_mux_valid = obi_w_dp_rsp_valid; - w_dp_rsp_mux = obi_w_dp_rsp; - obi_w_dp_rsp_ready = w_dp_rsp_mux_ready; + idma_pkg::INIT: begin + w_dp_rsp_mux_valid = init_w_dp_rsp_valid; + w_dp_rsp_mux = init_w_dp_rsp; + init_w_dp_rsp_ready = w_dp_rsp_mux_ready; end default: begin w_dp_rsp_mux_valid = 1'b0; @@ -1834,7 +1834,7 @@ endmodule `include "common_cells/registers.svh" /// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_r_obi_rw_init_w_axi #( +module idma_transport_layer_r_axi_rw_init_rw_obi #( /// Number of transaction that can be in-flight concurrently parameter int unsigned NumAxInFlight = 32'd2, /// Data width @@ -1878,6 +1878,11 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( /// Testmode in input logic testmode_i, + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + /// Memory Init read request output init_req_t init_read_req_o, /// Memory Init read response @@ -1888,16 +1893,16 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( /// OBI read response input obi_rsp_t obi_read_rsp_i, - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - /// Memory Init write request output init_req_t init_write_req_o, /// Memory Init write response input init_rsp_t init_write_rsp_i, + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, + /// Read datapath request input r_dp_req_t r_dp_req_i, /// Read datapath request valid @@ -1966,36 +1971,36 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( typedef logic [7:0] byte_t; // inbound control signals to the read buffer: controlled by the read process - strb_t init_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; + strb_t axi_buffer_in_valid, init_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; strb_t buffer_in_ready; // outbound control signals of the buffer: controlled by the write process strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t axi_buffer_out_ready, init_buffer_out_ready, + strb_t init_buffer_out_ready, obi_buffer_out_ready, buffer_out_ready, buffer_out_ready_shifted; // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] init_buffer_in, obi_buffer_in, + byte_t [StrbWidth-1:0] axi_buffer_in, init_buffer_in, obi_buffer_in, buffer_in, buffer_in_shifted; // aligned and coalesced data leaving the buffer byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; // Read multiplexed signals - logic init_r_chan_valid, obi_r_chan_valid; - logic init_r_chan_ready, obi_r_chan_ready; - logic init_r_dp_valid, obi_r_dp_valid; - logic init_r_dp_ready, obi_r_dp_ready; - r_dp_rsp_t init_r_dp_rsp, obi_r_dp_rsp; + logic axi_r_chan_valid, init_r_chan_valid, obi_r_chan_valid; + logic axi_r_chan_ready, init_r_chan_ready, obi_r_chan_ready; + logic axi_r_dp_valid, init_r_dp_valid, obi_r_dp_valid; + logic axi_r_dp_ready, init_r_dp_ready, obi_r_dp_ready; + r_dp_rsp_t axi_r_dp_rsp, init_r_dp_rsp, obi_r_dp_rsp; - logic init_ar_ready, obi_ar_ready; + logic axi_ar_ready, init_ar_ready, obi_ar_ready; // Write multiplexed signals - logic axi_w_dp_rsp_valid, init_w_dp_rsp_valid; - logic axi_w_dp_rsp_ready, init_w_dp_rsp_ready; - logic axi_w_dp_ready, init_w_dp_ready; - w_dp_rsp_t axi_w_dp_rsp, init_w_dp_rsp; + logic init_w_dp_rsp_valid, obi_w_dp_rsp_valid; + logic init_w_dp_rsp_ready, obi_w_dp_rsp_ready; + logic init_w_dp_ready, obi_w_dp_ready; + w_dp_rsp_t init_w_dp_rsp, obi_w_dp_rsp; - logic axi_aw_ready, init_aw_ready; + logic init_aw_ready, obi_aw_ready; logic w_dp_req_valid, w_dp_req_ready; logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; logic w_dp_rsp_valid, w_dp_rsp_ready; @@ -2010,6 +2015,36 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( // Read Ports //-------------------------------------- + idma_axi_read #( + .StrbWidth ( StrbWidth ), + .byte_t ( byte_t ), + .strb_t ( strb_t ), + .r_dp_req_t ( r_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .ar_chan_t ( read_meta_channel_t ), + .read_req_t ( axi_req_t ), + .read_rsp_t ( axi_rsp_t ) + ) i_idma_axi_read ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .r_dp_req_i ( r_dp_req_i ), + .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_valid_i ), + .r_dp_ready_o ( axi_r_dp_ready ), + .r_dp_rsp_o ( axi_r_dp_rsp ), + .r_dp_valid_o ( axi_r_dp_valid ), + .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_ready_i ), + .ar_req_i ( ar_req_i.ar_req ), + .ar_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI) & ar_valid_i ), + .ar_ready_o ( axi_ar_ready ), + .read_req_o ( axi_read_req_o ), + .read_rsp_i ( axi_read_rsp_i ), + .r_chan_valid_o ( axi_r_chan_valid ), + .r_chan_ready_o ( axi_r_chan_ready ), + .buffer_in_o ( axi_buffer_in ), + .buffer_in_valid_o ( axi_buffer_in_valid ), + .buffer_in_ready_i ( buffer_in_ready ) + ); + idma_init_read #( .StrbWidth ( StrbWidth ), .byte_t ( byte_t ), @@ -2072,6 +2107,7 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( always_comb begin : gen_read_meta_channel_multiplexer case(ar_req_i.src_protocol) + idma_pkg::AXI: ar_ready_o = axi_ar_ready; idma_pkg::INIT: ar_ready_o = init_ar_ready; idma_pkg::OBI: ar_ready_o = obi_ar_ready; default: ar_ready_o = 1'b0; @@ -2080,6 +2116,17 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( always_comb begin : gen_read_multiplexer case(r_dp_req_i.src_protocol) + idma_pkg::AXI: begin + r_chan_valid_o = axi_r_chan_valid; + r_chan_ready_o = axi_r_chan_ready; + + r_dp_ready_o = axi_r_dp_ready; + r_dp_rsp_o = axi_r_dp_rsp; + r_dp_valid_o = axi_r_dp_valid; + + buffer_in = axi_buffer_in; + buffer_in_valid = axi_buffer_in_valid; + end idma_pkg::INIT: begin r_chan_valid_o = init_r_chan_valid; r_chan_ready_o = init_r_chan_ready; @@ -2171,14 +2218,14 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( // Demux write request to correct write port always_comb begin : gen_write_multiplexer case(w_dp_req_i.dst_protocol) - idma_pkg::AXI: begin - w_dp_req_ready = axi_w_dp_ready; - buffer_out_ready = axi_buffer_out_ready; - end idma_pkg::INIT: begin w_dp_req_ready = init_w_dp_ready; buffer_out_ready = init_buffer_out_ready; end + idma_pkg::OBI: begin + w_dp_req_ready = obi_w_dp_ready; + buffer_out_ready = obi_buffer_out_ready; + end default: begin w_dp_req_ready = 1'b0; buffer_out_ready = '0; @@ -2189,8 +2236,8 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( // Demux write meta channel to correct write port always_comb begin : gen_write_meta_channel_multiplexer case(aw_req_i.dst_protocol) - idma_pkg::AXI: aw_ready_o = axi_aw_ready; idma_pkg::INIT: aw_ready_o = init_aw_ready; + idma_pkg::OBI: aw_ready_o = obi_aw_ready; default: aw_ready_o = 1'b0; endcase end @@ -2199,37 +2246,6 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( // Write Ports //-------------------------------------- - idma_axi_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .aw_chan_t ( write_meta_channel_t ), - .write_req_t ( axi_req_t ), - .write_rsp_t ( axi_rsp_t ) - ) i_idma_axi_write ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::AXI) & w_dp_req_valid ), - .w_dp_ready_o ( axi_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( axi_w_dp_rsp ), - .w_dp_valid_o ( axi_w_dp_rsp_valid ), - .w_dp_ready_i ( axi_w_dp_rsp_ready ), - .aw_req_i ( aw_req_i.aw_req ), - .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::AXI) & aw_valid_i ), - .aw_ready_o ( axi_aw_ready ), - .write_req_o ( axi_write_req_o ), - .write_rsp_i ( axi_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( axi_buffer_out_ready ) - ); - idma_init_write #( .StrbWidth ( StrbWidth ), .byte_t ( byte_t ), @@ -2258,6 +2274,35 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( .buffer_out_ready_o ( init_buffer_out_ready ) ); + idma_obi_write #( + .StrbWidth ( StrbWidth ), + .MaskInvalidData ( MaskInvalidData ), + .byte_t ( byte_t ), + .data_t ( data_t ), + .strb_t ( strb_t ), + .w_dp_req_t ( w_dp_req_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .write_req_t ( obi_req_t ), + .write_rsp_t ( obi_rsp_t ) + ) i_idma_obi_write ( + .w_dp_req_i ( w_dp_req_i ), + .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::OBI) & w_dp_req_valid ), + .w_dp_ready_o ( obi_w_dp_ready ), + .dp_poison_i ( dp_poison_i ), + .w_dp_rsp_o ( obi_w_dp_rsp ), + .w_dp_valid_o ( obi_w_dp_rsp_valid ), + .w_dp_ready_i ( obi_w_dp_rsp_ready ), + .aw_req_i ( aw_req_i.aw_req ), + .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::OBI) & aw_valid_i ), + .aw_ready_o ( obi_aw_ready ), + .write_req_o ( obi_write_req_o ), + .write_rsp_i ( obi_write_rsp_i ), + .buffer_out_i ( buffer_out_shifted ), + .buffer_out_valid_i ( buffer_out_valid_shifted ), + .buffer_out_ready_o ( obi_buffer_out_ready ) + ); + //-------------------------------------- // Write Response FIFO //-------------------------------------- @@ -2291,20 +2336,20 @@ module idma_transport_layer_r_obi_rw_init_w_axi #( always_comb begin : gen_write_reponse_multiplexer w_dp_rsp_mux = '0; w_dp_rsp_mux_valid = 1'b0; - axi_w_dp_rsp_ready = 1'b0; init_w_dp_rsp_ready = 1'b0; + obi_w_dp_rsp_ready = 1'b0; if ( w_resp_fifo_out_valid ) begin case(w_resp_fifo_out_protocol) - idma_pkg::AXI: begin - w_dp_rsp_mux_valid = axi_w_dp_rsp_valid; - w_dp_rsp_mux = axi_w_dp_rsp; - axi_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end idma_pkg::INIT: begin w_dp_rsp_mux_valid = init_w_dp_rsp_valid; w_dp_rsp_mux = init_w_dp_rsp; init_w_dp_rsp_ready = w_dp_rsp_mux_ready; end + idma_pkg::OBI: begin + w_dp_rsp_mux_valid = obi_w_dp_rsp_valid; + w_dp_rsp_mux = obi_w_dp_rsp; + obi_w_dp_rsp_ready = w_dp_rsp_mux_ready; + end default: begin w_dp_rsp_mux_valid = 1'b0; w_dp_rsp_mux = '0; @@ -2359,569 +2404,415 @@ endmodule // - Thomas Benz // - Tobias Senti -`include "idma/guard.svh" `include "common_cells/registers.svh" +`include "common_cells/assertions.svh" +`include "idma/guard.svh" -/// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_r_axi_rw_init_rw_obi #( - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, +/// Legalizes a generic 1D transfer according to the rules given by the +/// used protocol. +module idma_legalizer_rw_axi #( + /// Should both data shifts be done before the dataflow element? + /// If this is enabled, then the data inserted into the dataflow element + /// will no longer be word aligned, but only a single shifter is needed + parameter bit CombinedShifter = 1'b0, /// Data width - parameter int unsigned DataWidth = 32'd16, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// `r_dp_req_t` type: - parameter type r_dp_req_t = logic, - /// `w_dp_req_t` type: - parameter type w_dp_req_t = logic, - /// `r_dp_rsp_t` type: - parameter type r_dp_rsp_t = logic, - /// `w_dp_rsp_t` type: - parameter type w_dp_rsp_t = logic, - /// Write Meta channel type - parameter type write_meta_channel_t = logic, - parameter type write_meta_channel_tagged_t = logic, - /// Read Meta channel type - parameter type read_meta_channel_t = logic, - parameter type read_meta_channel_tagged_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// Memory Init Request and Response channel type - parameter type init_req_t = logic, - parameter type init_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// 1D iDMA request type: + /// - `length`: the length of the transfer in bytes + /// - `*_addr`: the source / target byte addresses of the transfer + /// - `opt`: the options field + parameter type idma_req_t = logic, + /// Read request type + parameter type idma_r_req_t = logic, + /// Write request type + parameter type idma_w_req_t = logic, + /// Mutable transfer type + parameter type idma_mut_tf_t = logic, + /// Mutable options type + parameter type idma_mut_tf_opt_t = logic )( /// Clock input logic clk_i, /// Asynchronous reset, active low input logic rst_ni, - /// Testmode in - input logic testmode_i, - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, + /// 1D request + input idma_req_t req_i, + /// 1D request valid + input logic valid_i, + /// 1D request ready + output logic ready_o, - /// Memory Init read request - output init_req_t init_read_req_o, - /// Memory Init read response - input init_rsp_t init_read_rsp_i, + /// Read request; contains datapath and meta information + output idma_r_req_t r_req_o, + /// Read request valid + output logic r_valid_o, + /// Read request ready + input logic r_ready_i, - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, + /// Write request; contains datapath and meta information + output idma_w_req_t w_req_o, + /// Write request valid + output logic w_valid_o, + /// Write request ready + input logic w_ready_i, - /// Memory Init write request - output init_req_t init_write_req_o, - /// Memory Init write response - input init_rsp_t init_write_rsp_i, + /// Invalidate the current burst transfer, stops emission of requests + input logic flush_i, + /// Kill the active 1D transfer; reload a new transfer + input logic kill_i, - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, + /// Read machine of the legalizer is busy + output logic r_busy_o, + /// Write machine of the legalizer is busy + output logic w_busy_o +); + /// Stobe width + localparam int unsigned StrbWidth = DataWidth / 8; + /// Offset width + localparam int unsigned OffsetWidth = $clog2(StrbWidth); + /// The size of a page in byte + localparam int unsigned PageSize = 256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth; + /// The width of page offset byte addresses + localparam int unsigned PageAddrWidth = $clog2(PageSize); - /// Read datapath request - input r_dp_req_t r_dp_req_i, - /// Read datapath request valid - input logic r_dp_valid_i, - /// Read datapath request ready - output logic r_dp_ready_o, + /// Offset type + typedef logic [ OffsetWidth-1:0] offset_t; + /// Address type + typedef logic [ AddrWidth-1:0] addr_t; + /// Page address type + typedef logic [PageAddrWidth-1:0] page_addr_t; + /// Page length type + typedef logic [ PageAddrWidth:0] page_len_t; - /// Read datapath response - output r_dp_rsp_t r_dp_rsp_o, - /// Read datapath response valid - output logic r_dp_valid_o, - /// Read datapath response valid - input logic r_dp_ready_i, - /// Write datapath request - input w_dp_req_t w_dp_req_i, - /// Write datapath request valid - input logic w_dp_valid_i, - /// Write datapath request ready - output logic w_dp_ready_o, + // state: internally hold one transfer, this is mutated + idma_mut_tf_t r_tf_d, r_tf_q; + idma_mut_tf_t w_tf_d, w_tf_q; + idma_mut_tf_opt_t opt_tf_d, opt_tf_q; - /// Write datapath response - output w_dp_rsp_t w_dp_rsp_o, - /// Write datapath response valid - output logic w_dp_valid_o, - /// Write datapath response valid - input logic w_dp_ready_i, + // enable signals for next mutable transfer storage + logic r_tf_ena; + logic w_tf_ena; - /// Read meta request - input read_meta_channel_tagged_t ar_req_i, - /// Read meta request valid - input logic ar_valid_i, - /// Read meta request ready - output logic ar_ready_o, + // page boundaries + page_len_t r_page_num_bytes_to_pb; + page_len_t r_num_bytes_to_pb; + page_len_t w_page_num_bytes_to_pb; + page_len_t w_num_bytes_to_pb; + page_len_t c_num_bytes_to_pb; - /// Write meta request - input write_meta_channel_tagged_t aw_req_i, - /// Write meta request valid - input logic aw_valid_i, - /// Write meta request ready - output logic aw_ready_o, + // read process + page_len_t r_num_bytes_possible; + page_len_t r_num_bytes; + offset_t r_addr_offset; + logic r_done; - /// Datapath poison signal - input logic dp_poison_i, + // write process + page_len_t w_num_bytes_possible; + page_len_t w_num_bytes; + offset_t w_addr_offset; + logic w_done; - /// Response channel valid and ready - output logic r_chan_ready_o, - output logic r_chan_valid_o, - /// Read part of the datapath is busy - output logic r_dp_busy_o, - /// Write part of the datapath is busy - output logic w_dp_busy_o, - /// Buffer is busy - output logic buffer_busy_o -); - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - - /// Data type - typedef logic [DataWidth-1:0] data_t; - /// Offset type - typedef logic [StrbWidth-1:0] strb_t; - /// Byte type - typedef logic [7:0] byte_t; - - // inbound control signals to the read buffer: controlled by the read process - strb_t axi_buffer_in_valid, init_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; - - strb_t buffer_in_ready; - // outbound control signals of the buffer: controlled by the write process - strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t init_buffer_out_ready, obi_buffer_out_ready, - buffer_out_ready, buffer_out_ready_shifted; - - // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] axi_buffer_in, init_buffer_in, obi_buffer_in, - buffer_in, buffer_in_shifted; - // aligned and coalesced data leaving the buffer - byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; - - // Read multiplexed signals - logic axi_r_chan_valid, init_r_chan_valid, obi_r_chan_valid; - logic axi_r_chan_ready, init_r_chan_ready, obi_r_chan_ready; - logic axi_r_dp_valid, init_r_dp_valid, obi_r_dp_valid; - logic axi_r_dp_ready, init_r_dp_ready, obi_r_dp_ready; - r_dp_rsp_t axi_r_dp_rsp, init_r_dp_rsp, obi_r_dp_rsp; - - logic axi_ar_ready, init_ar_ready, obi_ar_ready; - - // Write multiplexed signals - logic init_w_dp_rsp_valid, obi_w_dp_rsp_valid; - logic init_w_dp_rsp_ready, obi_w_dp_rsp_ready; - logic init_w_dp_ready, obi_w_dp_ready; - w_dp_rsp_t init_w_dp_rsp, obi_w_dp_rsp; + //-------------------------------------- + // read boundary check + //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_read_page_splitter ( + .not_bursting_i ( 1'b0 ), - logic init_aw_ready, obi_aw_ready; - logic w_dp_req_valid, w_dp_req_ready; - logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; - logic w_dp_rsp_valid, w_dp_rsp_ready; - w_dp_rsp_t w_dp_rsp_mux; + .reduce_len_i ( opt_tf_q.src_reduce_len ), + .max_llen_i ( opt_tf_q.src_max_llen ), + + .addr_i ( r_tf_q.addr ), + .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) + ); - // Write Response FIFO signals - logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; - idma_pkg::protocol_e w_resp_fifo_out_protocol; - logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; + assign r_num_bytes_to_pb = r_page_num_bytes_to_pb; //-------------------------------------- - // Read Ports + // write boundary check //-------------------------------------- + idma_legalizer_page_splitter #( + .OffsetWidth ( OffsetWidth ), + .PageAddrWidth ( PageSize ), + .addr_t ( addr_t ), + .page_len_t ( page_len_t ), + .page_addr_t ( page_addr_t ) + ) i_write_page_splitter ( + .not_bursting_i ( 1'b0 ), - idma_axi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .ar_chan_t ( read_meta_channel_t ), - .read_req_t ( axi_req_t ), - .read_rsp_t ( axi_rsp_t ) - ) i_idma_axi_read ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_valid_i ), - .r_dp_ready_o ( axi_r_dp_ready ), - .r_dp_rsp_o ( axi_r_dp_rsp ), - .r_dp_valid_o ( axi_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_ready_i ), - .ar_req_i ( ar_req_i.ar_req ), - .ar_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI) & ar_valid_i ), - .ar_ready_o ( axi_ar_ready ), - .read_req_o ( axi_read_req_o ), - .read_rsp_i ( axi_read_rsp_i ), - .r_chan_valid_o ( axi_r_chan_valid ), - .r_chan_ready_o ( axi_r_chan_ready ), - .buffer_in_o ( axi_buffer_in ), - .buffer_in_valid_o ( axi_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) + .reduce_len_i ( opt_tf_q.dst_reduce_len ), + .max_llen_i ( opt_tf_q.dst_max_llen ), + + .addr_i ( w_tf_q.addr ), + .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) ); - idma_init_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .read_meta_chan_t ( read_meta_channel_t ), - .read_req_t ( init_req_t ), - .read_rsp_t ( init_rsp_t ) - ) i_idma_init_read ( - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_valid_i ), - .r_dp_ready_o ( init_r_dp_ready ), - .r_dp_rsp_o ( init_r_dp_rsp ), - .r_dp_valid_o ( init_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_ready_i ), - .read_meta_req_i ( ar_req_i.ar_req ), - .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::INIT) & ar_valid_i ), - .read_meta_ready_o ( init_ar_ready ), - .read_req_o ( init_read_req_o ), - .read_rsp_i ( init_read_rsp_i ), - .r_chan_valid_o ( init_r_chan_valid ), - .r_chan_ready_o ( init_r_chan_ready ), - .buffer_in_o ( init_buffer_in ), - .buffer_in_valid_o ( init_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); + assign w_num_bytes_to_pb = w_page_num_bytes_to_pb; + + //-------------------------------------- + // page boundary check + //-------------------------------------- + // how many transfers are remaining when concerning both r/w pages? + // take the boundary that is closer + assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? + w_num_bytes_to_pb : r_num_bytes_to_pb; - idma_obi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .read_meta_chan_t ( read_meta_channel_t ), - .read_req_t ( obi_req_t ), - .read_rsp_t ( obi_rsp_t ) - ) i_idma_obi_read ( - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_valid_i ), - .r_dp_ready_o ( obi_r_dp_ready ), - .r_dp_rsp_o ( obi_r_dp_rsp ), - .r_dp_valid_o ( obi_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_ready_i ), - .read_meta_req_i ( ar_req_i.ar_req ), - .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::OBI) & ar_valid_i ), - .read_meta_ready_o ( obi_ar_ready ), - .read_req_o ( obi_read_req_o ), - .read_rsp_i ( obi_read_rsp_i ), - .r_chan_valid_o ( obi_r_chan_valid ), - .r_chan_ready_o ( obi_r_chan_ready ), - .buffer_in_o ( obi_buffer_in ), - .buffer_in_valid_o ( obi_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); //-------------------------------------- - // Read Multiplexers + // Synchronized R/W process //-------------------------------------- + always_comb begin : proc_num_bytes_possible + // Default: Coupled + r_num_bytes_possible = c_num_bytes_to_pb; + w_num_bytes_possible = c_num_bytes_to_pb; - always_comb begin : gen_read_meta_channel_multiplexer - case(ar_req_i.src_protocol) - idma_pkg::AXI: ar_ready_o = axi_ar_ready; - idma_pkg::INIT: ar_ready_o = init_ar_ready; - idma_pkg::OBI: ar_ready_o = obi_ar_ready; - default: ar_ready_o = 1'b0; - endcase + if (opt_tf_q.decouple_rw) begin + r_num_bytes_possible = r_num_bytes_to_pb; + w_num_bytes_possible = w_num_bytes_to_pb; + end end - always_comb begin : gen_read_multiplexer - case(r_dp_req_i.src_protocol) - idma_pkg::AXI: begin - r_chan_valid_o = axi_r_chan_valid; - r_chan_ready_o = axi_r_chan_ready; - - r_dp_ready_o = axi_r_dp_ready; - r_dp_rsp_o = axi_r_dp_rsp; - r_dp_valid_o = axi_r_dp_valid; + assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; + assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; - buffer_in = axi_buffer_in; - buffer_in_valid = axi_buffer_in_valid; - end - idma_pkg::INIT: begin - r_chan_valid_o = init_r_chan_valid; - r_chan_ready_o = init_r_chan_ready; + // legalization process -> read and write is coupled together + always_comb begin : proc_read_write_transaction - r_dp_ready_o = init_r_dp_ready; - r_dp_rsp_o = init_r_dp_rsp; - r_dp_valid_o = init_r_dp_valid; + // default: keep state + r_tf_d = r_tf_q; + w_tf_d = w_tf_q; + opt_tf_d = opt_tf_q; - buffer_in = init_buffer_in; - buffer_in_valid = init_buffer_in_valid; - end - idma_pkg::OBI: begin - r_chan_valid_o = obi_r_chan_valid; - r_chan_ready_o = obi_r_chan_ready; + // default: not done + r_done = 1'b0; + w_done = 1'b0; - r_dp_ready_o = obi_r_dp_ready; - r_dp_rsp_o = obi_r_dp_rsp; - r_dp_valid_o = obi_r_dp_valid; + //-------------------------------------- + // Legalize read transaction + //-------------------------------------- + // more bytes remaining than we can read + if (r_tf_q.length > r_num_bytes_possible) begin + r_num_bytes = r_num_bytes_possible; + // calculate remainder + r_tf_d.length = r_tf_q.length - r_num_bytes_possible; + // next address + r_tf_d.addr = r_tf_q.addr + r_num_bytes; - buffer_in = obi_buffer_in; - buffer_in_valid = obi_buffer_in_valid; + // remaining bytes fit in one burst + end else begin + r_num_bytes = r_tf_q.length[PageAddrWidth:0]; + // finished + r_tf_d.valid = 1'b0; + r_done = 1'b1; end - default: begin - r_chan_valid_o = 1'b0; - r_chan_ready_o = 1'b0; - r_dp_ready_o = 1'b0; - r_dp_rsp_o = '0; - r_dp_valid_o = 1'b0; + //-------------------------------------- + // Legalize write transaction + //-------------------------------------- + // more bytes remaining than we can write + if (w_tf_q.length > w_num_bytes_possible) begin + w_num_bytes = w_num_bytes_possible; + // calculate remainder + w_tf_d.length = w_tf_q.length - w_num_bytes_possible; + // next address + w_tf_d.addr = w_tf_q.addr + w_num_bytes; - buffer_in = '0; - buffer_in_valid = '0; + // remaining bytes fit in one burst + end else begin + w_num_bytes = w_tf_q.length[PageAddrWidth:0]; + // finished + w_tf_d.valid = 1'b0; + w_done = 1'b1; + end + + //-------------------------------------- + // Kill + //-------------------------------------- + if (kill_i) begin + // kill the current state + r_tf_d = '0; + w_tf_d = '0; + r_done = 1'b1; + w_done = 1'b1; + end + + //-------------------------------------- + // Refill + //-------------------------------------- + // new request is taken in if both r and w machines are ready. + if (ready_o & valid_i) begin + + // load all three mutable objects (source, destination, option) + // source or read + r_tf_d = '{ + length: req_i.length, + addr: req_i.src_addr, + valid: 1'b1, + base_addr: req_i.src_addr + }; + // destination or write + w_tf_d = '{ + length: req_i.length, + addr: req_i.dst_addr, + valid: 1'b1, + base_addr: req_i.dst_addr + }; + // options + opt_tf_d = '{ + src_protocol: req_i.opt.src_protocol, + dst_protocol: req_i.opt.dst_protocol, + read_shift: '0, + write_shift: '0, + decouple_rw: req_i.opt.beo.decouple_rw, + decouple_aw: req_i.opt.beo.decouple_aw, + src_max_llen: req_i.opt.beo.src_max_llen, + dst_max_llen: req_i.opt.beo.dst_max_llen, + src_reduce_len: req_i.opt.beo.src_reduce_len, + dst_reduce_len: req_i.opt.beo.dst_reduce_len, + axi_id: req_i.opt.axi_id, + src_axi_opt: req_i.opt.src, + dst_axi_opt: req_i.opt.dst, + super_last: req_i.opt.last + }; + // determine shift amount + if (CombinedShifter) begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = '0; + end else begin + opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; + opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + end end - endcase end + //-------------------------------------- - // Read Barrel shifter + // Connect outputs //-------------------------------------- - assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); + // Read meta channel + always_comb begin + r_req_o.ar_req.axi.ar_chan = '{ + id: opt_tf_q.axi_id, + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 + }; + + end - //-------------------------------------- - // Buffer - //-------------------------------------- + // assign the signals needed to set-up the read data path + assign r_req_o.r_dp_req = '{ + src_protocol: opt_tf_q.src_protocol, + offset: r_addr_offset, + tailer: OffsetWidth'(r_num_bytes + r_addr_offset), + shift: opt_tf_q.read_shift, + decouple_aw: opt_tf_q.decouple_aw, + is_single: r_num_bytes <= StrbWidth + }; - idma_dataflow_element #( - .BufferDepth ( BufferDepth ), - .StrbWidth ( StrbWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .strb_t ( strb_t ), - .byte_t ( byte_t ) - ) i_dataflow_element ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .data_i ( buffer_in_shifted ), - .valid_i ( buffer_in_valid ), - .ready_o ( buffer_in_ready ), - .data_o ( buffer_out ), - .valid_o ( buffer_out_valid ), - .ready_i ( buffer_out_ready_shifted ) - ); + // Write meta channel and data path + always_comb begin + w_req_o.aw_req.axi.aw_chan = '{ + id: opt_tf_q.axi_id, + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.dst_axi_opt.burst, + lock: opt_tf_q.dst_axi_opt.lock, + cache: opt_tf_q.dst_axi_opt.cache, + prot: opt_tf_q.dst_axi_opt.prot, + qos: opt_tf_q.dst_axi_opt.qos, + region: opt_tf_q.dst_axi_opt.region, + user: '0, + atop: '0 + }; + + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: w_req_o.aw_req.axi.aw_chan.len, + is_single: w_req_o.aw_req.axi.aw_chan.len == '0 + }; + + end - //-------------------------------------- - // Write Barrel shifter - //-------------------------------------- + // last burst in generic 1D transfer? + assign w_req_o.last = w_done; + + // last burst indicated by midend + assign w_req_o.super_last = opt_tf_q.super_last; + + // assign aw decouple flag + assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + + // busy output + assign r_busy_o = r_tf_q.valid; + assign w_busy_o = w_tf_q.valid; - assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); - assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; - assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; //-------------------------------------- - // Write Request Demultiplexer + // Flow Control //-------------------------------------- + // only advance to next state if: + // * rw_coupled: both machines advance + // * rw_decoupled: either machine advances + + always_comb begin : proc_legalizer_flow_control + if ( opt_tf_q.decouple_rw) begin + r_tf_ena = (r_ready_i & !flush_i) | kill_i; + w_tf_ena = (w_ready_i & !flush_i) | kill_i; - // Split write request to write response fifo and write ports - stream_fork #( - .N_OUP ( 2 ) - ) i_write_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( w_dp_valid_i ), - .ready_o ( w_dp_ready_o ), - .valid_o ( { w_resp_fifo_in_valid, w_dp_req_valid } ), - .ready_i ( { w_resp_fifo_in_ready, w_dp_req_ready } ) - ); + r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; + end else begin + r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - // Demux write request to correct write port - always_comb begin : gen_write_multiplexer - case(w_dp_req_i.dst_protocol) - idma_pkg::INIT: begin - w_dp_req_ready = init_w_dp_ready; - buffer_out_ready = init_buffer_out_ready; - end - idma_pkg::OBI: begin - w_dp_req_ready = obi_w_dp_ready; - buffer_out_ready = obi_buffer_out_ready; - end - default: begin - w_dp_req_ready = 1'b0; - buffer_out_ready = '0; + r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; + w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; end - endcase end + + // load next idma request: if both machines are done! + assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; - // Demux write meta channel to correct write port - always_comb begin : gen_write_meta_channel_multiplexer - case(aw_req_i.dst_protocol) - idma_pkg::INIT: aw_ready_o = init_aw_ready; - idma_pkg::OBI: aw_ready_o = obi_aw_ready; - default: aw_ready_o = 1'b0; - endcase - end //-------------------------------------- - // Write Ports + // State //-------------------------------------- + `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) + `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) + `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) - idma_init_write #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_req_t ( init_req_t ), - .write_rsp_t ( init_rsp_t ) - ) i_idma_init_write ( - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::INIT) & w_dp_req_valid ), - .w_dp_ready_o ( init_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( init_w_dp_rsp ), - .w_dp_valid_o ( init_w_dp_rsp_valid ), - .w_dp_ready_i ( init_w_dp_rsp_ready ), - .write_meta_req_i ( aw_req_i.aw_req ), - .write_meta_valid_i ( (aw_req_i.dst_protocol == idma_pkg::INIT) & aw_valid_i ), - .write_meta_ready_o ( init_aw_ready ), - .write_req_o ( init_write_req_o ), - .write_rsp_i ( init_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( init_buffer_out_ready ) - ); - - idma_obi_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_req_t ( obi_req_t ), - .write_rsp_t ( obi_rsp_t ) - ) i_idma_obi_write ( - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::OBI) & w_dp_req_valid ), - .w_dp_ready_o ( obi_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( obi_w_dp_rsp ), - .w_dp_valid_o ( obi_w_dp_rsp_valid ), - .w_dp_ready_i ( obi_w_dp_rsp_ready ), - .aw_req_i ( aw_req_i.aw_req ), - .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::OBI) & aw_valid_i ), - .aw_ready_o ( obi_aw_ready ), - .write_req_o ( obi_write_req_o ), - .write_rsp_i ( obi_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( obi_buffer_out_ready ) - ); - - //-------------------------------------- - // Write Response FIFO - //-------------------------------------- - // Needed to be able to route the write reponses properly - // Insert when data write happens - // Remove when write response comes - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( idma_pkg::protocol_e ), - .PrintInfo ( PrintFifoInfo ) - ) i_write_response_fifo ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_dp_req_i.dst_protocol ), - .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), - .ready_o ( w_resp_fifo_in_ready ), - .data_o ( w_resp_fifo_out_protocol ), - .valid_o ( w_resp_fifo_out_valid ), - .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) - ); - - //-------------------------------------- - // Write Request Demultiplexer - //-------------------------------------- - - // Mux write port responses - always_comb begin : gen_write_reponse_multiplexer - w_dp_rsp_mux = '0; - w_dp_rsp_mux_valid = 1'b0; - init_w_dp_rsp_ready = 1'b0; - obi_w_dp_rsp_ready = 1'b0; - if ( w_resp_fifo_out_valid ) begin - case(w_resp_fifo_out_protocol) - idma_pkg::INIT: begin - w_dp_rsp_mux_valid = init_w_dp_rsp_valid; - w_dp_rsp_mux = init_w_dp_rsp; - init_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end - idma_pkg::OBI: begin - w_dp_rsp_mux_valid = obi_w_dp_rsp_valid; - w_dp_rsp_mux = obi_w_dp_rsp; - obi_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end - default: begin - w_dp_rsp_mux_valid = 1'b0; - w_dp_rsp_mux = '0; - end - endcase - end - end - - // Fall through register for the write response to be ready - fall_through_register #( - .T ( w_dp_rsp_t ) - ) i_write_rsp_channel_reg ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .clr_i ( 1'b0 ), - .testmode_i ( testmode_i ), - - .valid_i ( w_dp_rsp_mux_valid ), - .ready_o ( w_dp_rsp_mux_ready ), - .data_i ( w_dp_rsp_mux ), - - .valid_o ( w_dp_rsp_valid ), - .ready_i ( w_dp_rsp_ready ), - .data_o ( w_dp_rsp_o ) - ); - - // Join write response fifo and write port responses - stream_join #( - .N_INP ( 2 ) - ) i_write_stream_join ( - .inp_valid_i ( { w_resp_fifo_out_valid, w_dp_rsp_valid } ), - .inp_ready_o ( { w_resp_fifo_out_ready, w_dp_rsp_ready } ), - - .oup_valid_o ( w_dp_valid_o ), - .oup_ready_i ( w_dp_ready_i ) - ); //-------------------------------------- - // Module Control + // Assertions //-------------------------------------- - assign r_dp_busy_o = r_dp_valid_i; - assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; - assign buffer_busy_o = |buffer_out_valid; + // only support the decomposition of incremental bursts + `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & + req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & + req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) endmodule @@ -2939,7 +2830,7 @@ endmodule /// Legalizes a generic 1D transfer according to the rules given by the /// used protocol. -module idma_legalizer_rw_axi #( +module idma_legalizer_r_obi_w_axi #( /// Should both data shifts be done before the dataflow element? /// If this is enabled, then the data inserted into the dataflow element /// will no longer be word aligned, but only a single shifter is needed @@ -2998,12 +2889,16 @@ module idma_legalizer_rw_axi #( /// Write machine of the legalizer is busy output logic w_busy_o ); + function int unsigned max_size(input int unsigned a, b); + return a > b ? a : b; + endfunction + /// Stobe width localparam int unsigned StrbWidth = DataWidth / 8; /// Offset width localparam int unsigned OffsetWidth = $clog2(StrbWidth); /// The size of a page in byte - localparam int unsigned PageSize = 256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth; + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); /// The width of page offset byte addresses localparam int unsigned PageAddrWidth = $clog2(PageSize); @@ -3056,7 +2951,7 @@ module idma_legalizer_rw_axi #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_read_page_splitter ( - .not_bursting_i ( 1'b0 ), + .not_bursting_i ( 1'b1 ), .reduce_len_i ( opt_tf_q.src_reduce_len ), .max_llen_i ( opt_tf_q.src_max_llen ), @@ -3077,7 +2972,7 @@ module idma_legalizer_rw_axi #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_write_page_splitter ( - .not_bursting_i ( 1'b0 ), + .not_bursting_i ( opt_tf_q.dst_protocol inside { idma_pkg::OBI} ), .reduce_len_i ( opt_tf_q.dst_reduce_len ), .max_llen_i ( opt_tf_q.dst_max_llen ), @@ -3105,7 +3000,8 @@ module idma_legalizer_rw_axi #( r_num_bytes_possible = c_num_bytes_to_pb; w_num_bytes_possible = c_num_bytes_to_pb; - if (opt_tf_q.decouple_rw) begin + if (opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::OBI })) begin r_num_bytes_possible = r_num_bytes_to_pb; w_num_bytes_possible = w_num_bytes_to_pb; end @@ -3231,18 +3127,13 @@ module idma_legalizer_rw_axi #( // Read meta channel always_comb begin - r_req_o.ar_req.axi.ar_chan = '{ - id: opt_tf_q.axi_id, + r_req_o.ar_req.obi.a_chan = '{ addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 + be: '1, + we: 1'b0, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 }; end @@ -3307,7 +3198,8 @@ module idma_legalizer_rw_axi #( // * rw_decoupled: either machine advances always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw) begin + if ( opt_tf_q.decouple_rw + || (opt_tf_q.src_protocol inside { idma_pkg::OBI })) begin r_tf_ena = (r_ready_i & !flush_i) | kill_i; w_tf_ena = (w_ready_i & !flush_i) | kill_i; @@ -3359,7 +3251,7 @@ endmodule /// Legalizes a generic 1D transfer according to the rules given by the /// used protocol. -module idma_legalizer_r_obi_w_axi #( +module idma_legalizer_r_axi_w_obi #( /// Should both data shifts be done before the dataflow element? /// If this is enabled, then the data inserted into the dataflow element /// will no longer be word aligned, but only a single shifter is needed @@ -3480,7 +3372,7 @@ module idma_legalizer_r_obi_w_axi #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_read_page_splitter ( - .not_bursting_i ( 1'b1 ), + .not_bursting_i ( opt_tf_q.src_protocol inside { idma_pkg::OBI} ), .reduce_len_i ( opt_tf_q.src_reduce_len ), .max_llen_i ( opt_tf_q.src_max_llen ), @@ -3501,7 +3393,7 @@ module idma_legalizer_r_obi_w_axi #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_write_page_splitter ( - .not_bursting_i ( opt_tf_q.dst_protocol inside { idma_pkg::OBI} ), + .not_bursting_i ( 1'b1 ), .reduce_len_i ( opt_tf_q.dst_reduce_len ), .max_llen_i ( opt_tf_q.dst_max_llen ), @@ -3530,7 +3422,7 @@ module idma_legalizer_r_obi_w_axi #( w_num_bytes_possible = c_num_bytes_to_pb; if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::OBI })) begin + || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin r_num_bytes_possible = r_num_bytes_to_pb; w_num_bytes_possible = w_num_bytes_to_pb; end @@ -3656,13 +3548,18 @@ module idma_legalizer_r_obi_w_axi #( // Read meta channel always_comb begin - r_req_o.ar_req.obi.a_chan = '{ + r_req_o.ar_req.axi.ar_chan = '{ + id: opt_tf_q.axi_id, addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '1, - we: 1'b0, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 }; end @@ -3679,30 +3576,23 @@ module idma_legalizer_r_obi_w_axi #( // Write meta channel and data path always_comb begin - w_req_o.aw_req.axi.aw_chan = '{ - id: opt_tf_q.axi_id, + w_req_o.aw_req.obi.a_chan = '{ addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.dst_axi_opt.burst, - lock: opt_tf_q.dst_axi_opt.lock, - cache: opt_tf_q.dst_axi_opt.cache, - prot: opt_tf_q.dst_axi_opt.prot, - qos: opt_tf_q.dst_axi_opt.qos, - region: opt_tf_q.dst_axi_opt.region, - user: '0, - atop: '0 + be: '0, + we: 1, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 }; w_req_o.w_dp_req = '{ dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: w_req_o.aw_req.axi.aw_chan.len, - is_single: w_req_o.aw_req.axi.aw_chan.len == '0 + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: 'd0, + is_single: 1'b1 }; - end // last burst in generic 1D transfer? @@ -3728,7 +3618,7 @@ module idma_legalizer_r_obi_w_axi #( always_comb begin : proc_legalizer_flow_control if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::OBI })) begin + || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin r_tf_ena = (r_ready_i & !flush_i) | kill_i; w_tf_ena = (w_ready_i & !flush_i) | kill_i; @@ -3780,7 +3670,7 @@ endmodule /// Legalizes a generic 1D transfer according to the rules given by the /// used protocol. -module idma_legalizer_r_axi_w_obi #( +module idma_legalizer_rw_axi_rw_axis #( /// Should both data shifts be done before the dataflow element? /// If this is enabled, then the data inserted into the dataflow element /// will no longer be word aligned, but only a single shifter is needed @@ -3901,7 +3791,7 @@ module idma_legalizer_r_axi_w_obi #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_read_page_splitter ( - .not_bursting_i ( opt_tf_q.src_protocol inside { idma_pkg::OBI} ), + .not_bursting_i ( 1'b1 ), .reduce_len_i ( opt_tf_q.src_reduce_len ), .max_llen_i ( opt_tf_q.src_max_llen ), @@ -3910,7 +3800,13 @@ module idma_legalizer_r_axi_w_obi #( .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) ); - assign r_num_bytes_to_pb = r_page_num_bytes_to_pb; + always_comb begin : gen_read_num_bytes_to_pb_logic + case (opt_tf_q.src_protocol) + idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::AXI_STREAM: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + default: r_num_bytes_to_pb = '0; + endcase + end //-------------------------------------- // write boundary check @@ -3931,7 +3827,13 @@ module idma_legalizer_r_axi_w_obi #( .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) ); - assign w_num_bytes_to_pb = w_page_num_bytes_to_pb; + always_comb begin : gen_write_num_bytes_to_pb_logic + case (opt_tf_q.dst_protocol) + idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + idma_pkg::AXI_STREAM: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + default: w_num_bytes_to_pb = '0; + endcase + end //-------------------------------------- // page boundary check @@ -3951,7 +3853,8 @@ module idma_legalizer_r_axi_w_obi #( w_num_bytes_possible = c_num_bytes_to_pb; if (opt_tf_q.decouple_rw - || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin + || (opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM }) + || (opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM })) begin r_num_bytes_possible = r_num_bytes_to_pb; w_num_bytes_possible = w_num_bytes_to_pb; end @@ -4076,21 +3979,32 @@ module idma_legalizer_r_axi_w_obi #( //-------------------------------------- // Read meta channel - always_comb begin - r_req_o.ar_req.axi.ar_chan = '{ - id: opt_tf_q.axi_id, - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 - }; - + always_comb begin : gen_read_meta_channel + r_req_o.ar_req = '0; + case(opt_tf_q.src_protocol) + idma_pkg::AXI: begin + r_req_o.ar_req.axi.ar_chan = '{ + id: opt_tf_q.axi_id, + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.src_axi_opt.burst, + lock: opt_tf_q.src_axi_opt.lock, + cache: opt_tf_q.src_axi_opt.cache, + prot: opt_tf_q.src_axi_opt.prot, + qos: opt_tf_q.src_axi_opt.qos, + region: opt_tf_q.src_axi_opt.region, + user: '0 + }; + + end + idma_pkg::AXI_STREAM: begin + r_req_o.ar_req = '0; + + end + default: + r_req_o.ar_req = '0; + endcase end // assign the signals needed to set-up the read data path @@ -4104,26 +4018,69 @@ module idma_legalizer_r_axi_w_obi #( }; // Write meta channel and data path - always_comb begin - w_req_o.aw_req.obi.a_chan = '{ - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '0, - we: 1, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: 'd0, - is_single: 1'b1 - }; + always_comb begin : gen_write_meta_channel + w_req_o.aw_req = '0; + case(opt_tf_q.dst_protocol) + idma_pkg::AXI: begin + w_req_o.aw_req.axi.aw_chan = '{ + id: opt_tf_q.axi_id, + addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), + size: axi_pkg::size_t'(OffsetWidth), + burst: opt_tf_q.dst_axi_opt.burst, + lock: opt_tf_q.dst_axi_opt.lock, + cache: opt_tf_q.dst_axi_opt.cache, + prot: opt_tf_q.dst_axi_opt.prot, + qos: opt_tf_q.dst_axi_opt.qos, + region: opt_tf_q.dst_axi_opt.region, + user: '0, + atop: '0 + }; + + end + idma_pkg::AXI_STREAM: begin + w_req_o.aw_req.axis.t_chan = '{ + data: '0, + strb: '1, + keep: '0, + last: w_tf_q.length == w_num_bytes, + id: opt_tf_q.axi_id, + dest: w_tf_q.base_addr[$bits(w_req_o.aw_req.axis.t_chan.dest)-1:0], + user: w_tf_q.base_addr[$bits(w_req_o.aw_req.axis.t_chan.user)-1+:$bits(w_req_o.aw_req.axis.t_chan.dest)] + }; + + end + default: + w_req_o.aw_req = '0; + endcase + end + + // assign the signals needed to set-up the write data path + always_comb begin : gen_write_data_path + case (opt_tf_q.dst_protocol) + idma_pkg::AXI: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: w_req_o.aw_req.axi.aw_chan.len, + is_single: w_req_o.aw_req.axi.aw_chan.len == '0 + }; + + default: + w_req_o.w_dp_req = '{ + dst_protocol: opt_tf_q.dst_protocol, + offset: w_addr_offset, + tailer: OffsetWidth'(w_num_bytes + w_addr_offset), + shift: opt_tf_q.write_shift, + num_beats: 'd0, + is_single: 1'b1 + }; + endcase end + // last burst in generic 1D transfer? assign w_req_o.last = w_done; @@ -4147,7 +4104,8 @@ module idma_legalizer_r_axi_w_obi #( always_comb begin : proc_legalizer_flow_control if ( opt_tf_q.decouple_rw - || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin + || (opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM }) + || (opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM })) begin r_tf_ena = (r_ready_i & !flush_i) | kill_i; w_tf_ena = (w_ready_i & !flush_i) | kill_i; @@ -4199,7 +4157,7 @@ endmodule /// Legalizes a generic 1D transfer according to the rules given by the /// used protocol. -module idma_legalizer_rw_axi_rw_axis #( +module idma_legalizer_r_obi_rw_init_w_axi #( /// Should both data shifts be done before the dataflow element? /// If this is enabled, then the data inserted into the dataflow element /// will no longer be word aligned, but only a single shifter is needed @@ -4267,7 +4225,7 @@ module idma_legalizer_rw_axi_rw_axis #( /// Offset width localparam int unsigned OffsetWidth = $clog2(StrbWidth); /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, max_size(StrbWidth, StrbWidth)); /// The width of page offset byte addresses localparam int unsigned PageAddrWidth = $clog2(PageSize); @@ -4331,8 +4289,8 @@ module idma_legalizer_rw_axi_rw_axis #( always_comb begin : gen_read_num_bytes_to_pb_logic case (opt_tf_q.src_protocol) - idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - idma_pkg::AXI_STREAM: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::INIT: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; default: r_num_bytes_to_pb = '0; endcase end @@ -4359,7 +4317,7 @@ module idma_legalizer_rw_axi_rw_axis #( always_comb begin : gen_write_num_bytes_to_pb_logic case (opt_tf_q.dst_protocol) idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - idma_pkg::AXI_STREAM: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + idma_pkg::INIT: w_num_bytes_to_pb = w_page_num_bytes_to_pb; default: w_num_bytes_to_pb = '0; endcase end @@ -4382,8 +4340,8 @@ module idma_legalizer_rw_axi_rw_axis #( w_num_bytes_possible = c_num_bytes_to_pb; if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM }) - || (opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM })) begin + || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::INIT })) begin r_num_bytes_possible = r_num_bytes_to_pb; w_num_bytes_possible = w_num_bytes_to_pb; end @@ -4511,24 +4469,24 @@ module idma_legalizer_rw_axi_rw_axis #( always_comb begin : gen_read_meta_channel r_req_o.ar_req = '0; case(opt_tf_q.src_protocol) - idma_pkg::AXI: begin - r_req_o.ar_req.axi.ar_chan = '{ - id: opt_tf_q.axi_id, - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 + idma_pkg::INIT: begin + r_req_o.ar_req.init.req_chan = '{ + cfg: r_tf_q.base_addr, + term: '0, + strb: '0, + id: opt_tf_d.axi_id }; end - idma_pkg::AXI_STREAM: begin - r_req_o.ar_req = '0; + idma_pkg::OBI: begin + r_req_o.ar_req.obi.a_chan = '{ + addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, + be: '1, + we: 1'b0, + wdata: '0, + aid: opt_tf_q.axi_id, + a_optional: '0 + }; end default: @@ -4567,15 +4525,12 @@ module idma_legalizer_rw_axi_rw_axis #( }; end - idma_pkg::AXI_STREAM: begin - w_req_o.aw_req.axis.t_chan = '{ - data: '0, - strb: '1, - keep: '0, - last: w_tf_q.length == w_num_bytes, - id: opt_tf_q.axi_id, - dest: w_tf_q.base_addr[$bits(w_req_o.aw_req.axis.t_chan.dest)-1:0], - user: w_tf_q.base_addr[$bits(w_req_o.aw_req.axis.t_chan.user)-1+:$bits(w_req_o.aw_req.axis.t_chan.dest)] + idma_pkg::INIT: begin + w_req_o.aw_req.init.req_chan = '{ + cfg: w_tf_q.base_addr, + term: '0, + strb: '0, + id: opt_tf_d.axi_id }; end @@ -4633,8 +4588,8 @@ module idma_legalizer_rw_axi_rw_axis #( always_comb begin : proc_legalizer_flow_control if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM }) - || (opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM })) begin + || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::INIT })) begin r_tf_ena = (r_ready_i & !flush_i) | kill_i; w_tf_ena = (w_ready_i & !flush_i) | kill_i; @@ -4686,7 +4641,7 @@ endmodule /// Legalizes a generic 1D transfer according to the rules given by the /// used protocol. -module idma_legalizer_rw_axi_rw_obi #( +module idma_legalizer_r_axi_rw_init_rw_obi #( /// Should both data shifts be done before the dataflow element? /// If this is enabled, then the data inserted into the dataflow element /// will no longer be word aligned, but only a single shifter is needed @@ -4754,7 +4709,7 @@ module idma_legalizer_rw_axi_rw_obi #( /// Offset width localparam int unsigned OffsetWidth = $clog2(StrbWidth); /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); + localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, max_size(StrbWidth, StrbWidth)); /// The width of page offset byte addresses localparam int unsigned PageAddrWidth = $clog2(PageSize); @@ -4819,6 +4774,7 @@ module idma_legalizer_rw_axi_rw_obi #( always_comb begin : gen_read_num_bytes_to_pb_logic case (opt_tf_q.src_protocol) idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; + idma_pkg::INIT: r_num_bytes_to_pb = r_page_num_bytes_to_pb; idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; default: r_num_bytes_to_pb = '0; endcase @@ -4845,7 +4801,7 @@ module idma_legalizer_rw_axi_rw_obi #( always_comb begin : gen_write_num_bytes_to_pb_logic case (opt_tf_q.dst_protocol) - idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; + idma_pkg::INIT: w_num_bytes_to_pb = w_page_num_bytes_to_pb; idma_pkg::OBI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; default: w_num_bytes_to_pb = '0; endcase @@ -4869,8 +4825,8 @@ module idma_legalizer_rw_axi_rw_obi #( w_num_bytes_possible = c_num_bytes_to_pb; if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin + || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI })) begin r_num_bytes_possible = r_num_bytes_to_pb; w_num_bytes_possible = w_num_bytes_to_pb; end @@ -5013,6 +4969,15 @@ module idma_legalizer_rw_axi_rw_obi #( user: '0 }; + end + idma_pkg::INIT: begin + r_req_o.ar_req.init.req_chan = '{ + cfg: r_tf_q.base_addr, + term: '0, + strb: '0, + id: opt_tf_d.axi_id + }; + end idma_pkg::OBI: begin r_req_o.ar_req.obi.a_chan = '{ @@ -5044,20 +5009,12 @@ module idma_legalizer_rw_axi_rw_obi #( always_comb begin : gen_write_meta_channel w_req_o.aw_req = '0; case(opt_tf_q.dst_protocol) - idma_pkg::AXI: begin - w_req_o.aw_req.axi.aw_chan = '{ - id: opt_tf_q.axi_id, - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.dst_axi_opt.burst, - lock: opt_tf_q.dst_axi_opt.lock, - cache: opt_tf_q.dst_axi_opt.cache, - prot: opt_tf_q.dst_axi_opt.prot, - qos: opt_tf_q.dst_axi_opt.qos, - region: opt_tf_q.dst_axi_opt.region, - user: '0, - atop: '0 + idma_pkg::INIT: begin + w_req_o.aw_req.init.req_chan = '{ + cfg: w_tf_q.base_addr, + term: '0, + strb: '0, + id: opt_tf_d.axi_id }; end @@ -5080,16 +5037,6 @@ module idma_legalizer_rw_axi_rw_obi #( // assign the signals needed to set-up the write data path always_comb begin : gen_write_data_path case (opt_tf_q.dst_protocol) - idma_pkg::AXI: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: w_req_o.aw_req.axi.aw_chan.len, - is_single: w_req_o.aw_req.axi.aw_chan.len == '0 - }; - default: w_req_o.w_dp_req = '{ dst_protocol: opt_tf_q.dst_protocol, @@ -5126,8 +5073,8 @@ module idma_legalizer_rw_axi_rw_obi #( always_comb begin : proc_legalizer_flow_control if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin + || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) + || (opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI })) begin r_tf_ena = (r_ready_i & !flush_i) | kill_i; w_tf_ena = (w_ready_i & !flush_i) | kill_i; @@ -5173,479 +5120,698 @@ endmodule // - Thomas Benz // - Tobias Senti -`include "common_cells/registers.svh" -`include "common_cells/assertions.svh" +`include "axi/typedef.svh" `include "idma/guard.svh" -/// Legalizes a generic 1D transfer according to the rules given by the -/// used protocol. -module idma_legalizer_r_obi_rw_init_w_axi #( +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_rw_axi #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, /// Should both data shifts be done before the dataflow element? /// If this is enabled, then the data inserted into the dataflow element /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - parameter type idma_req_t = logic, - /// Read request type - parameter type idma_r_req_t = logic, - /// Write request type - parameter type idma_w_req_t = logic, - /// Mutable transfer type - parameter type idma_mut_tf_t = logic, - /// Mutable options type - parameter type idma_mut_tf_opt_t = logic + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b1, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) )( /// Clock input logic clk_i, /// Asynchronous reset, active low input logic rst_ni, + /// Testmode in + input logic testmode_i, - /// 1D request - input idma_req_t req_i, - /// 1D request valid - input logic valid_i, - /// 1D request ready - output logic ready_o, + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, - /// Read request; contains datapath and meta information - output idma_r_req_t r_req_o, - /// Read request valid - output logic r_valid_o, - /// Read request ready - input logic r_ready_i, + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, - /// Write request; contains datapath and meta information - output idma_w_req_t w_req_o, - /// Write request valid - output logic w_valid_o, - /// Write request ready - input logic w_ready_i, + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, - /// Invalidate the current burst transfer, stops emission of requests - input logic flush_i, - /// Kill the active 1D transfer; reload a new transfer - input logic kill_i, + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, - /// Read machine of the legalizer is busy - output logic r_busy_o, - /// Write machine of the legalizer is busy - output logic w_busy_o + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o ); - function int unsigned max_size(input int unsigned a, b); - return a > b ? a : b; - endfunction - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, max_size(StrbWidth, StrbWidth)); - /// The width of page offset byte addresses - localparam int unsigned PageAddrWidth = $clog2(PageSize); + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - /// Offset type - typedef logic [ OffsetWidth-1:0] offset_t; /// Address type - typedef logic [ AddrWidth-1:0] addr_t; - /// Page address type - typedef logic [PageAddrWidth-1:0] page_addr_t; - /// Page length type - typedef logic [ PageAddrWidth:0] page_len_t; - + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; - // state: internally hold one transfer, this is mutated - idma_mut_tf_t r_tf_d, r_tf_q; - idma_mut_tf_t w_tf_d, w_tf_q; - idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; - // enable signals for next mutable transfer storage - logic r_tf_ena; - logic w_tf_ena; + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; - // page boundaries - page_len_t r_page_num_bytes_to_pb; - page_len_t r_num_bytes_to_pb; - page_len_t w_page_num_bytes_to_pb; - page_len_t w_num_bytes_to_pb; - page_len_t c_num_bytes_to_pb; + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; - // read process - page_len_t r_num_bytes_possible; - page_len_t r_num_bytes; - offset_t r_addr_offset; - logic r_done; + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; - // write process - page_len_t w_num_bytes_possible; - page_len_t w_num_bytes; - offset_t w_addr_offset; - logic w_done; + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; - //-------------------------------------- - // read boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_read_page_splitter ( - .not_bursting_i ( 1'b1 ), + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; - .reduce_len_i ( opt_tf_q.src_reduce_len ), - .max_llen_i ( opt_tf_q.src_max_llen ), - - .addr_i ( r_tf_q.addr ), - .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) - ); - - always_comb begin : gen_read_num_bytes_to_pb_logic - case (opt_tf_q.src_protocol) - idma_pkg::INIT: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - default: r_num_bytes_to_pb = '0; - endcase - end - - //-------------------------------------- - // write boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_write_page_splitter ( - .not_bursting_i ( 1'b1 ), + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; - .reduce_len_i ( opt_tf_q.dst_reduce_len ), - .max_llen_i ( opt_tf_q.dst_max_llen ), - - .addr_i ( w_tf_q.addr ), - .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) - ); - always_comb begin : gen_write_num_bytes_to_pb_logic - case (opt_tf_q.dst_protocol) - idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - idma_pkg::INIT: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - default: w_num_bytes_to_pb = '0; - endcase - end + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; - //-------------------------------------- - // page boundary check - //-------------------------------------- - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - always_comb begin : proc_num_bytes_possible - // Default: Coupled - r_num_bytes_possible = c_num_bytes_to_pb; - w_num_bytes_possible = c_num_bytes_to_pb; + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; - if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::INIT })) begin - r_num_bytes_possible = r_num_bytes_to_pb; - w_num_bytes_possible = w_num_bytes_to_pb; - end - end + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; - assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; - assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; - // legalization process -> read and write is coupled together - always_comb begin : proc_read_write_transaction + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; - // default: keep state - r_tf_d = r_tf_q; - w_tf_d = w_tf_q; - opt_tf_d = opt_tf_q; + // Ax request from R-AW coupler to datapath + write_meta_channel_t aw_req_dp; - // default: not done - r_done = 1'b0; - w_done = 1'b0; + // Ax request from the decoupling stage to the datapath + read_meta_channel_t ar_req_dp; - //-------------------------------------- - // Legalize read transaction - //-------------------------------------- - // more bytes remaining than we can read - if (r_tf_q.length > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - r_tf_d.length = r_tf_q.length - r_num_bytes_possible; - // next address - r_tf_d.addr = r_tf_q.addr + r_num_bytes; + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; - // remaining bytes fit in one burst - end else begin - r_num_bytes = r_tf_q.length[PageAddrWidth:0]; - // finished - r_tf_d.valid = 1'b0; - r_done = 1'b1; - end + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; - //-------------------------------------- - // Legalize write transaction - //-------------------------------------- - // more bytes remaining than we can write - if (w_tf_q.length > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - w_tf_d.length = w_tf_q.length - w_num_bytes_possible; - // next address - w_tf_d.addr = w_tf_q.addr + w_num_bytes; + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; - // remaining bytes fit in one burst - end else begin - w_num_bytes = w_tf_q.length[PageAddrWidth:0]; - // finished - w_tf_d.valid = 1'b0; - w_done = 1'b1; - end + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; - //-------------------------------------- - // Kill - //-------------------------------------- - if (kill_i) begin - // kill the current state - r_tf_d = '0; - w_tf_d = '0; - r_done = 1'b1; - w_done = 1'b1; - end + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o & valid_i) begin + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; - // load all three mutable objects (source, destination, option) - // source or read - r_tf_d = '{ - length: req_i.length, - addr: req_i.src_addr, - valid: 1'b1, - base_addr: req_i.src_addr - }; - // destination or write - w_tf_d = '{ - length: req_i.length, - addr: req_i.dst_addr, - valid: 1'b1, - base_addr: req_i.dst_addr - }; - // options - opt_tf_d = '{ - src_protocol: req_i.opt.src_protocol, - dst_protocol: req_i.opt.dst_protocol, - read_shift: '0, - write_shift: '0, - decouple_rw: req_i.opt.beo.decouple_rw, - decouple_aw: req_i.opt.beo.decouple_aw, - src_max_llen: req_i.opt.beo.src_max_llen, - dst_max_llen: req_i.opt.beo.dst_max_llen, - src_reduce_len: req_i.opt.beo.src_reduce_len, - dst_reduce_len: req_i.opt.beo.dst_reduce_len, - axi_id: req_i.opt.axi_id, - src_axi_opt: req_i.opt.src, - dst_axi_opt: req_i.opt.dst, - super_last: req_i.opt.last - }; - // determine shift amount - if (CombinedShifter) begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = '0; - end else begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; end end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; end //-------------------------------------- - // Connect outputs + // Legalization //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_rw_axi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); - // Read meta channel - always_comb begin : gen_read_meta_channel - r_req_o.ar_req = '0; - case(opt_tf_q.src_protocol) - idma_pkg::INIT: begin - r_req_o.ar_req.init.req_chan = '{ - cfg: r_tf_q.base_addr, - term: '0, - strb: '0, - id: opt_tf_d.axi_id - }; - - end - idma_pkg::OBI: begin - r_req_o.ar_req.obi.a_chan = '{ - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '1, - we: 1'b0, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - end - default: - r_req_o.ar_req = '0; - endcase - end - - // assign the signals needed to set-up the read data path - assign r_req_o.r_dp_req = '{ - src_protocol: opt_tf_q.src_protocol, - offset: r_addr_offset, - tailer: OffsetWidth'(r_num_bytes + r_addr_offset), - shift: opt_tf_q.read_shift, - decouple_aw: opt_tf_q.decouple_aw, - is_single: r_num_bytes <= StrbWidth - }; + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); - // Write meta channel and data path - always_comb begin : gen_write_meta_channel - w_req_o.aw_req = '0; - case(opt_tf_q.dst_protocol) - idma_pkg::AXI: begin - w_req_o.aw_req.axi.aw_chan = '{ - id: opt_tf_q.axi_id, - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.dst_axi_opt.burst, - lock: opt_tf_q.dst_axi_opt.lock, - cache: opt_tf_q.dst_axi_opt.cache, - prot: opt_tf_q.dst_axi_opt.prot, - qos: opt_tf_q.dst_axi_opt.qos, - region: opt_tf_q.dst_axi_opt.region, - user: '0, - atop: '0 - }; - - end - idma_pkg::INIT: begin - w_req_o.aw_req.init.req_chan = '{ - cfg: w_tf_q.base_addr, - term: '0, - strb: '0, - id: opt_tf_d.axi_id - }; - - end - default: - w_req_o.aw_req = '0; - endcase - end + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); - // assign the signals needed to set-up the write data path - always_comb begin : gen_write_data_path - case (opt_tf_q.dst_protocol) - idma_pkg::AXI: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: w_req_o.aw_req.axi.aw_chan.len, - is_single: w_req_o.aw_req.axi.aw_chan.len == '0 - }; - - default: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: 'd0, - is_single: 1'b1 - }; - endcase - end + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; - // last burst in generic 1D transfer? - assign w_req_o.last = w_done; + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; - // last burst indicated by midend - assign w_req_o.super_last = opt_tf_q.super_last; + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; - // assign aw decouple flag - assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - // busy output - assign r_busy_o = r_tf_q.valid; - assign w_busy_o = w_tf_q.valid; + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; //-------------------------------------- - // Flow Control + // Error handler //-------------------------------------- - // only advance to next state if: - // * rw_coupled: both machines advance - // * rw_decoupled: either machine advances - - always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::INIT })) begin - r_tf_ena = (r_ready_i & !flush_i) | kill_i; - w_tf_ena = (w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; - end else begin - r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + idma_error_handler #( + .MetaFifoDepth ( MetaFifoDepth ), + .PrintFifoInfo ( PrintFifoInfo ), + .idma_rsp_t ( idma_rsp_t ), + .idma_eh_req_t ( idma_eh_req_t ), + .addr_t ( addr_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ) + ) i_idma_error_handler ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .rsp_o ( idma_rsp ), + .rsp_valid_o ( rsp_valid ), + .rsp_ready_i ( rsp_ready ), + .req_valid_i ( req_valid ), + .req_ready_i ( req_ready_o ), + .eh_i ( idma_eh_req_i ), + .eh_valid_i ( eh_req_valid_i ), + .eh_ready_o ( eh_req_ready_o ), + .r_addr_i ( r_req.ar_req.axi.ar_chan.addr ), + .w_addr_i ( w_req.aw_req.axi.aw_chan.addr ), + .r_consume_i ( r_valid & r_ready ), + .w_consume_i ( w_valid & w_ready ), + .legalizer_flush_o ( legalizer_flush ), + .legalizer_kill_o ( legalizer_kill ), + .dp_busy_i ( dp_busy ), + .dp_poison_o ( dp_poison ), + .r_dp_rsp_i ( r_dp_rsp ), + .r_dp_valid_i ( r_dp_rsp_valid ), + .r_dp_ready_o ( r_dp_rsp_ready ), + .w_dp_rsp_i ( w_dp_rsp ), + .w_dp_valid_i ( w_dp_rsp_valid ), + .w_dp_ready_o ( w_dp_rsp_ready ), + .w_last_burst_i ( w_last_burst ), + .w_super_last_i ( w_super_last ), + .fsm_busy_o ( busy_o.eh_fsm_busy ), + .cnt_busy_o ( busy_o.eh_cnt_busy ) + ); + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; - r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); end + ) end - - // load next idma request: if both machines are done! - assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; //-------------------------------------- - // State + // Datapath busy signal //-------------------------------------- - `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) - `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) - `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; + + + //-------------------------------------- + // Datapath decoupling + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + + fall_through_register #( + .T ( read_meta_channel_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_req.ar_req ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_rw_axi #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .axi_read_req_o ( axi_read_req_o ), + .axi_read_rsp_i ( axi_read_rsp_i ), + .axi_write_req_o ( axi_write_req_o ), + .axi_write_rsp_i ( axi_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + // instantiate the channel coupler + idma_channel_coupler #( + .NumAxInFlight ( NumAxInFlight ), + .AddrWidth ( AddrWidth ), + .UserWidth ( UserWidth ), + .AxiIdWidth ( AxiIdWidth ), + .PrintFifoInfo ( PrintFifoInfo ), + .axi_aw_chan_t ( write_meta_channel_t ) + ) i_idma_channel_coupler ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .r_rsp_valid_i ( r_chan_valid ), + .r_rsp_ready_i ( r_chan_ready ), + .r_rsp_first_i ( r_dp_rsp.first ), + .r_decouple_aw_i ( r_dp_req_out.decouple_aw ), + .aw_decouple_aw_i ( w_req.decouple_aw ), + .aw_req_i ( w_req.aw_req ), + .aw_valid_i ( w_valid ), + .aw_ready_o ( aw_ready ), + .aw_req_o ( aw_req_dp ), + .aw_valid_o ( aw_valid_dp ), + .aw_ready_i ( aw_ready_dp ), + .busy_o ( busy_o.raw_coupler_busy ) + ); + end else begin : gen_r_aw_bypass + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + fall_through_register #( + .T ( write_meta_channel_t ) + ) i_aw_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( w_valid ), + .ready_o ( aw_ready ), + .data_i ( w_req.aw_req ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp ), + .data_o ( aw_req_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end //-------------------------------------- // Assertions //-------------------------------------- - // only support the decomposition of incremental bursts - `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & - req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & - req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) endmodule @@ -5657,496 +5823,665 @@ endmodule // - Thomas Benz // - Tobias Senti -`include "common_cells/registers.svh" -`include "common_cells/assertions.svh" +`include "axi/typedef.svh" `include "idma/guard.svh" -/// Legalizes a generic 1D transfer according to the rules given by the -/// used protocol. -module idma_legalizer_r_axi_rw_init_rw_obi #( +/// The iDMA backend implements an arbitrary 1D copy engine +module idma_backend_r_obi_w_axi #( + /// Data width + parameter int unsigned DataWidth = 32'd16, + /// Address width + parameter int unsigned AddrWidth = 32'd24, + /// AXI user width + parameter int unsigned UserWidth = 32'd1, + /// AXI ID width + parameter int unsigned AxiIdWidth = 32'd1, + /// Number of transaction that can be in-flight concurrently + parameter int unsigned NumAxInFlight = 32'd2, + /// The depth of the internal reorder buffer: + /// - '2': minimal possible configuration + /// - '3': efficiently handle misaligned transfers (recommended) + parameter int unsigned BufferDepth = 32'd2, + /// With of a transfer: max transfer size is `2**TFLenWidth` bytes + parameter int unsigned TFLenWidth = 32'd24, + /// The depth of the memory system the backend is attached to + parameter int unsigned MemSysDepth = 32'd0, /// Should both data shifts be done before the dataflow element? /// If this is enabled, then the data inserted into the dataflow element /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - parameter type idma_req_t = logic, - /// Read request type - parameter type idma_r_req_t = logic, - /// Write request type - parameter type idma_w_req_t = logic, - /// Mutable transfer type - parameter type idma_mut_tf_t = logic, - /// Mutable options type - parameter type idma_mut_tf_opt_t = logic + parameter bit CombinedShifter = 1'b0, + /// Should the `R`-`AW` coupling hardware be present? (recommended) + parameter bit RAWCouplingAvail = 1'b0, + /// Mask invalid data on the manager interface + parameter bit MaskInvalidData = 1'b1, + /// Should hardware legalization be present? (recommended) + /// If not, software legalization is required to ensure the transfers are + /// AXI4-conformal + parameter bit HardwareLegalizer = 1'b1, + /// Reject zero-length transfers + parameter bit RejectZeroTransfers = 1'b1, + /// Should the error handler be present? + parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, + /// Print the info of the FIFO configuration + parameter bit PrintFifoInfo = 1'b0, + /// 1D iDMA request type + parameter type idma_req_t = logic, + /// iDMA response type + parameter type idma_rsp_t = logic, + /// Error Handler request type + parameter type idma_eh_req_t = logic, + /// iDMA busy signal + parameter type idma_busy_t = logic, + /// AXI4+ATOP Request and Response channel type + parameter type axi_req_t = logic, + parameter type axi_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, + /// Address Read Channel type + parameter type read_meta_channel_t = logic, + /// Address Write Channel type + parameter type write_meta_channel_t = logic, + /// Strobe Width (do not override!) + parameter int unsigned StrbWidth = DataWidth / 8, + /// Offset Width (do not override!) + parameter int unsigned OffsetWidth = $clog2(StrbWidth) )( /// Clock input logic clk_i, /// Asynchronous reset, active low input logic rst_ni, + /// Testmode in + input logic testmode_i, - /// 1D request - input idma_req_t req_i, - /// 1D request valid - input logic valid_i, - /// 1D request ready - output logic ready_o, + /// 1D iDMA request + input idma_req_t idma_req_i, + /// 1D iDMA request valid + input logic req_valid_i, + /// 1D iDMA request ready + output logic req_ready_o, - /// Read request; contains datapath and meta information - output idma_r_req_t r_req_o, - /// Read request valid - output logic r_valid_o, - /// Read request ready - input logic r_ready_i, + /// iDMA response + output idma_rsp_t idma_rsp_o, + /// iDMA response valid + output logic rsp_valid_o, + /// iDMA response ready + input logic rsp_ready_i, - /// Write request; contains datapath and meta information - output idma_w_req_t w_req_o, - /// Write request valid - output logic w_valid_o, - /// Write request ready - input logic w_ready_i, + /// Error handler request + input idma_eh_req_t idma_eh_req_i, + /// Error handler request valid + input logic eh_req_valid_i, + /// Error handler request ready + output logic eh_req_ready_o, - /// Invalidate the current burst transfer, stops emission of requests - input logic flush_i, - /// Kill the active 1D transfer; reload a new transfer - input logic kill_i, + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, - /// Read machine of the legalizer is busy - output logic r_busy_o, - /// Write machine of the legalizer is busy - output logic w_busy_o + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// iDMA busy flags + output idma_busy_t busy_o ); - function int unsigned max_size(input int unsigned a, b); - return a > b ? a : b; - endfunction - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, max_size(StrbWidth, StrbWidth)); - /// The width of page offset byte addresses - localparam int unsigned PageAddrWidth = $clog2(PageSize); + /// The localparam MetaFifoDepth holds the maximum number of transfers that can be + /// in-flight under any circumstances. + localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - /// Offset type - typedef logic [ OffsetWidth-1:0] offset_t; /// Address type - typedef logic [ AddrWidth-1:0] addr_t; - /// Page address type - typedef logic [PageAddrWidth-1:0] page_addr_t; - /// Page length type - typedef logic [ PageAddrWidth:0] page_len_t; + typedef logic [AddrWidth-1:0] addr_t; + /// DAta type + typedef logic [DataWidth-1:0] data_t; + /// Strobe type + typedef logic [StrbWidth-1:0] strb_t; + /// User type + typedef logic [UserWidth-1:0] user_t; + /// ID type + typedef logic [AxiIdWidth-1:0] id_t; + /// Offset type + typedef logic [OffsetWidth-1:0] offset_t; + /// Transfer length type + typedef logic [TFLenWidth-1:0] tf_len_t; + /// The datapath read request type holds all the information required to configure the read + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the read + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `decouple_aw`: If the transfer has the AW decoupled from the R + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e src_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + logic decouple_aw; + logic is_single; + } r_dp_req_t; - // state: internally hold one transfer, this is mutated - idma_mut_tf_t r_tf_d, r_tf_q; - idma_mut_tf_t w_tf_d, w_tf_q; - idma_mut_tf_opt_t opt_tf_d, opt_tf_q; + /// The datapath read response type provides feedback from the read part of the datapath: + /// - `resp`: The response from the R channel of the AXI4 manager interface + /// - `last`: The last flag from the R channel of the AXI4 manager interface + /// - `first`: Is the current item first beat in the burst + typedef struct packed { + axi_pkg::resp_t resp; + logic last; + logic first; + } r_dp_rsp_t; - // enable signals for next mutable transfer storage - logic r_tf_ena; - logic w_tf_ena; + /// The datapath write request type holds all the information required to configure the write + /// part of the datapath. The type consists of: + /// - `offset`: The bus offset of the write + /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the + /// bus width. + /// - `shift`: The amount the data needs to be shifted + /// - `num_beats`: The number of beats this burst consist of + /// - `is_single`: Is this transfer just one beat long? `(len == 0)` + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + offset_t offset; + offset_t tailer; + offset_t shift; + axi_pkg::len_t num_beats; + logic is_single; + } w_dp_req_t; - // page boundaries - page_len_t r_page_num_bytes_to_pb; - page_len_t r_num_bytes_to_pb; - page_len_t w_page_num_bytes_to_pb; - page_len_t w_num_bytes_to_pb; - page_len_t c_num_bytes_to_pb; + /// The datapath write response type provides feedback from the write part of the datapath: + /// - `resp`: The response from the B channel of the AXI4 manager interface + /// - `user`: The user field from the B channel of the AXI4 manager interface + typedef struct packed { + axi_pkg::resp_t resp; + user_t user; + } w_dp_rsp_t; - // read process - page_len_t r_num_bytes_possible; - page_len_t r_num_bytes; - offset_t r_addr_offset; - logic r_done; + /// The iDMA read request bundles an `AR` type and a datapath read response type together. + typedef struct packed { + r_dp_req_t r_dp_req; + read_meta_channel_t ar_req; + } idma_r_req_t; - // write process - page_len_t w_num_bytes_possible; - page_len_t w_num_bytes; - offset_t w_addr_offset; - logic w_done; + /// The iDMA write request bundles an `AW` type and a datapath write response type together. It + /// has an additional flags: + /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently + /// being processed + /// - `midend_last`: The current transfer is marked by the controlling as last + /// - `decouple_aw`: indicates this is an R-AW decoupled transfer + typedef struct packed { + w_dp_req_t w_dp_req; + write_meta_channel_t aw_req; + logic last; + logic super_last; + logic decouple_aw; + } idma_w_req_t; + /// The mutable transfer options type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + idma_pkg::protocol_e src_protocol; + idma_pkg::protocol_e dst_protocol; + offset_t read_shift; + offset_t write_shift; + logic decouple_rw; + logic decouple_aw; + logic [2:0] src_max_llen; + logic [2:0] dst_max_llen; + logic src_reduce_len; + logic dst_reduce_len; + id_t axi_id; + idma_pkg::axi_options_t src_axi_opt; + idma_pkg::axi_options_t dst_axi_opt; + logic super_last; + } idma_mut_tf_opt_t; - //-------------------------------------- - // read boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_read_page_splitter ( - .not_bursting_i ( 1'b1 ), + /// The mutable transfer type holds important information that is mutated by the + /// `legalizer` block. + typedef struct packed { + tf_len_t length; + addr_t addr; + logic valid; + addr_t base_addr; + } idma_mut_tf_t; - .reduce_len_i ( opt_tf_q.src_reduce_len ), - .max_llen_i ( opt_tf_q.src_max_llen ), - - .addr_i ( r_tf_q.addr ), - .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) - ); - - always_comb begin : gen_read_num_bytes_to_pb_logic - case (opt_tf_q.src_protocol) - idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - idma_pkg::INIT: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - default: r_num_bytes_to_pb = '0; - endcase - end - - //-------------------------------------- - // write boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_write_page_splitter ( - .not_bursting_i ( 1'b1 ), - - .reduce_len_i ( opt_tf_q.dst_reduce_len ), - .max_llen_i ( opt_tf_q.dst_max_llen ), - - .addr_i ( w_tf_q.addr ), - .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) - ); - always_comb begin : gen_write_num_bytes_to_pb_logic - case (opt_tf_q.dst_protocol) - idma_pkg::INIT: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - idma_pkg::OBI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - default: w_num_bytes_to_pb = '0; - endcase - end + // datapath busy indicates the datapath is actively working on a transfer. It is composed of + // the activity of the buffer as well as both the read and write machines + logic dp_busy; + // blanks invalid data + logic dp_poison; - //-------------------------------------- - // page boundary check - //-------------------------------------- - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; + // read and write requests and their handshaking signals + idma_r_req_t r_req; + idma_w_req_t w_req; + logic r_valid, w_valid; + logic r_ready, w_ready; + // It the current transfer the last burst in the 1D transfer? + logic w_last_burst; + logic w_last_ready; - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - always_comb begin : proc_num_bytes_possible - // Default: Coupled - r_num_bytes_possible = c_num_bytes_to_pb; - w_num_bytes_possible = c_num_bytes_to_pb; + // Super last flag: The current transfer is indicated as the last one by the controlling + // unit; e.g. by a midend + logic w_super_last; - if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI })) begin - r_num_bytes_possible = r_num_bytes_to_pb; - w_num_bytes_possible = w_num_bytes_to_pb; - end - end + // Datapath FIFO signals -> used to decouple legalizer and datapath + logic r_dp_req_in_ready, w_dp_req_in_ready; + logic r_dp_req_out_valid, w_dp_req_out_valid; + logic r_dp_req_out_ready, w_dp_req_out_ready; + r_dp_req_t r_dp_req_out; + w_dp_req_t w_dp_req_out; - assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; - assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; + // datapah responses + r_dp_rsp_t r_dp_rsp; + w_dp_rsp_t w_dp_rsp; + logic r_dp_rsp_valid, w_dp_rsp_valid; + logic r_dp_rsp_ready, w_dp_rsp_ready; - // legalization process -> read and write is coupled together - always_comb begin : proc_read_write_transaction + // Ax handshaking + logic ar_ready, ar_ready_dp; + logic aw_ready, aw_ready_dp; + logic aw_valid_dp, ar_valid_dp; - // default: keep state - r_tf_d = r_tf_q; - w_tf_d = w_tf_q; - opt_tf_d = opt_tf_q; + // Ax request from R-AW coupler to datapath + write_meta_channel_t aw_req_dp; - // default: not done - r_done = 1'b0; - w_done = 1'b0; + // Ax request from the decoupling stage to the datapath + read_meta_channel_t ar_req_dp; - //-------------------------------------- - // Legalize read transaction - //-------------------------------------- - // more bytes remaining than we can read - if (r_tf_q.length > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - r_tf_d.length = r_tf_q.length - r_num_bytes_possible; - // next address - r_tf_d.addr = r_tf_q.addr + r_num_bytes; + // flush and preemptively empty the legalizer + logic legalizer_flush, legalizer_kill; - // remaining bytes fit in one burst - end else begin - r_num_bytes = r_tf_q.length[PageAddrWidth:0]; - // finished - r_tf_d.valid = 1'b0; - r_done = 1'b1; - end + /// intermediate signals to reject zero length transfers + logic is_length_zero; + logic req_valid; + idma_rsp_t idma_rsp; + logic rsp_valid; + logic rsp_ready; - //-------------------------------------- - // Legalize write transaction - //-------------------------------------- - // more bytes remaining than we can write - if (w_tf_q.length > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - w_tf_d.length = w_tf_q.length - w_num_bytes_possible; - // next address - w_tf_d.addr = w_tf_q.addr + w_num_bytes; + // Respone Channel valid and ready -> needed for bursting + logic r_chan_valid; + logic r_chan_ready; - // remaining bytes fit in one burst - end else begin - w_num_bytes = w_tf_q.length[PageAddrWidth:0]; - // finished - w_tf_d.valid = 1'b0; - w_done = 1'b1; - end + //-------------------------------------- + // Reject Zero Length Transfers + //-------------------------------------- + if (RejectZeroTransfers) begin : gen_reject_zero_transfers + // is the current transfer length 0? + assign is_length_zero = idma_req_i.length == '0; - //-------------------------------------- - // Kill - //-------------------------------------- - if (kill_i) begin - // kill the current state - r_tf_d = '0; - w_tf_d = '0; - r_done = 1'b1; - w_done = 1'b1; - end + // bypass valid as long as length is not zero, otherwise suppress it + assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o & valid_i) begin + // modify response + always_comb begin : proc_modify_response_zero_length + // default: bypass + idma_rsp_o = idma_rsp; + rsp_ready = rsp_ready_i; + rsp_valid_o = rsp_valid; - // load all three mutable objects (source, destination, option) - // source or read - r_tf_d = '{ - length: req_i.length, - addr: req_i.src_addr, - valid: 1'b1, - base_addr: req_i.src_addr - }; - // destination or write - w_tf_d = '{ - length: req_i.length, - addr: req_i.dst_addr, - valid: 1'b1, - base_addr: req_i.dst_addr - }; - // options - opt_tf_d = '{ - src_protocol: req_i.opt.src_protocol, - dst_protocol: req_i.opt.dst_protocol, - read_shift: '0, - write_shift: '0, - decouple_rw: req_i.opt.beo.decouple_rw, - decouple_aw: req_i.opt.beo.decouple_aw, - src_max_llen: req_i.opt.beo.src_max_llen, - dst_max_llen: req_i.opt.beo.dst_max_llen, - src_reduce_len: req_i.opt.beo.src_reduce_len, - dst_reduce_len: req_i.opt.beo.dst_reduce_len, - axi_id: req_i.opt.axi_id, - src_axi_opt: req_i.opt.src, - dst_axi_opt: req_i.opt.dst, - super_last: req_i.opt.last - }; - // determine shift amount - if (CombinedShifter) begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = '0; - end else begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; + // a zero transfer happens + if (is_length_zero & req_valid_i & req_ready_o) begin + // block backend + rsp_ready = 1'b0; + // generate new response + rsp_valid_o = 1'b1; + idma_rsp_o = '0; + idma_rsp_o.error = 1'b1; + idma_rsp_o.pld.err_type = idma_pkg::BACKEND; end end + + // just bypass signals + end else begin : gen_bypass_zero_transfers + // bypass + assign req_valid = req_valid_i; + assign idma_rsp_o = idma_rsp; + assign rsp_ready = rsp_ready_i; + assign rsp_valid_o = rsp_valid; end //-------------------------------------- - // Connect outputs + // Legalization //-------------------------------------- + if (HardwareLegalizer) begin : gen_hw_legalizer + // hardware legalizer is present + idma_legalizer_r_obi_w_axi #( + .CombinedShifter ( CombinedShifter ), + .DataWidth ( DataWidth ), + .AddrWidth ( AddrWidth ), + .idma_req_t ( idma_req_t ), + .idma_r_req_t ( idma_r_req_t ), + .idma_w_req_t ( idma_w_req_t ), + .idma_mut_tf_t ( idma_mut_tf_t ), + .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) + ) i_idma_legalizer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .req_i ( idma_req_i ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .r_req_o ( r_req ), + .w_req_o ( w_req ), + .r_valid_o ( r_valid ), + .w_valid_o ( w_valid ), + .r_ready_i ( r_ready ), + .w_ready_i ( w_ready ), + .flush_i ( legalizer_flush ), + .kill_i ( legalizer_kill ), + .r_busy_o ( busy_o.r_leg_busy ), + .w_busy_o ( busy_o.w_leg_busy ) + ); - // Read meta channel - always_comb begin : gen_read_meta_channel - r_req_o.ar_req = '0; - case(opt_tf_q.src_protocol) - idma_pkg::AXI: begin - r_req_o.ar_req.axi.ar_chan = '{ - id: opt_tf_q.axi_id, - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 - }; - - end - idma_pkg::INIT: begin - r_req_o.ar_req.init.req_chan = '{ - cfg: r_tf_q.base_addr, - term: '0, - strb: '0, - id: opt_tf_d.axi_id - }; - - end - idma_pkg::OBI: begin - r_req_o.ar_req.obi.a_chan = '{ - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '1, - we: 1'b0, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - end - default: - r_req_o.ar_req = '0; - endcase - end - - // assign the signals needed to set-up the read data path - assign r_req_o.r_dp_req = '{ - src_protocol: opt_tf_q.src_protocol, - offset: r_addr_offset, - tailer: OffsetWidth'(r_num_bytes + r_addr_offset), - shift: opt_tf_q.read_shift, - decouple_aw: opt_tf_q.decouple_aw, - is_single: r_num_bytes <= StrbWidth - }; + end else begin : gen_no_hw_legalizer + // stream fork is used to synchronize the two decoupled channels without the need for a + // FIFO here. + stream_fork #( + .N_OUP ( 32'd2 ) + ) i_stream_fork ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .valid_i ( req_valid ), + .ready_o ( req_ready_o ), + .valid_o ( { r_valid, w_valid } ), + .ready_i ( { r_ready, w_ready } ) + ); - // Write meta channel and data path - always_comb begin : gen_write_meta_channel - w_req_o.aw_req = '0; - case(opt_tf_q.dst_protocol) - idma_pkg::INIT: begin - w_req_o.aw_req.init.req_chan = '{ - cfg: w_tf_q.base_addr, - term: '0, - strb: '0, - id: opt_tf_d.axi_id - }; - - end - idma_pkg::OBI: begin - w_req_o.aw_req.obi.a_chan = '{ - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '0, - we: 1, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - end - default: - w_req_o.aw_req = '0; - endcase - end + // local signal holding the length -> explicitly only doing the computation once + axi_pkg::len_t len; + assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - + 'd1) >> OffsetWidth); - // assign the signals needed to set-up the write data path - always_comb begin : gen_write_data_path - case (opt_tf_q.dst_protocol) - default: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: 'd0, - is_single: 1'b1 - }; - endcase - end + // assemble read datapath request + assign r_req.r_dp_req = '{ + src_protocol: idma_req_i.opt.src_protocol, + offset: idma_req_i.src_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), + decouple_aw: idma_req_i.opt.beo.decouple_aw, + is_single: len == '0 + }; + // assemble write datapath request + assign w_req.w_dp_req = '{ + dst_protocol: idma_req_i.opt.dst_protocol, + offset: idma_req_i.dst_addr[OffsetWidth-1:0], + tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), + shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), + num_beats: len, + is_single: len == '0 + }; - // last burst in generic 1D transfer? - assign w_req_o.last = w_done; + // if the legalizer is bypassed; every burst is the last of the 1D transfer + assign w_req.last = 1'b1; - // last burst indicated by midend - assign w_req_o.super_last = opt_tf_q.super_last; + // assign the last flag of the controlling unit + assign w_req.super_last = idma_req_i.opt.last; - // assign aw decouple flag - assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; + // bypass decouple signal + assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - // busy output - assign r_busy_o = r_tf_q.valid; - assign w_busy_o = w_tf_q.valid; + // there is no unit to be busy + assign busy_o.r_leg_busy = 1'b0; + assign busy_o.w_leg_busy = 1'b0; + end + + // data path, meta channels, and last queues have to be ready for the legalizer to be ready + assign r_ready = r_dp_req_in_ready & ar_ready; + assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; //-------------------------------------- - // Flow Control + // Error handler //-------------------------------------- - // only advance to next state if: - // * rw_coupled: both machines advance - // * rw_decoupled: either machine advances - - always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI })) begin - r_tf_ena = (r_ready_i & !flush_i) | kill_i; - w_tf_ena = (w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; - end else begin - r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; + if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); + end + ) + end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler + // bypass the signals, assign their neutral values + assign idma_rsp.error = 1'b0; + assign idma_rsp.pld = 1'b0; + assign idma_rsp.last = w_super_last; + assign rsp_valid = w_dp_rsp_valid & w_last_burst; + assign eh_req_ready_o = 1'b0; + assign legalizer_flush = 1'b0; + assign legalizer_kill = 1'b0; + assign dp_poison = 1'b0; + assign r_dp_rsp_ready = rsp_ready; + assign w_dp_rsp_ready = rsp_ready; + assign busy_o.eh_fsm_busy = 1'b0; + assign busy_o.eh_cnt_busy = 1'b0; - r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; + end else begin : gen_param_error + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Unexpected Error Capability"); end + ) end - - // load next idma request: if both machines are done! - assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; //-------------------------------------- - // State + // Datapath busy signal //-------------------------------------- - `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) - `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) - `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) + assign dp_busy = busy_o.buffer_busy | + busy_o.r_dp_busy | + busy_o.w_dp_busy; //-------------------------------------- - // Assertions + // Datapath decoupling //-------------------------------------- - // only support the decomposition of incremental bursts - `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & - req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & - req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( r_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_r_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( r_req.r_dp_req ), + .valid_i ( r_valid ), + .ready_o ( r_dp_req_in_ready ), + .data_o ( r_dp_req_out ), + .valid_o ( r_dp_req_out_valid ), + .ready_i ( r_dp_req_out_ready ) + ); + + stream_fifo_optimal_wrap #( + .Depth ( NumAxInFlight ), + .type_t ( w_dp_req_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_dp_req ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.w_dp_req ), + .valid_i ( w_valid ), + .ready_o ( w_dp_req_in_ready ), + .data_o ( w_dp_req_out ), + .valid_o ( w_dp_req_out_valid ), + .ready_i ( w_dp_req_out_ready ) + ); + + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + + fall_through_register #( + .T ( read_meta_channel_t ) + ) i_ar_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( r_valid ), + .ready_o ( ar_ready ), + .data_i ( r_req.ar_req ), + .valid_o ( ar_valid_dp ), + .ready_i ( ar_ready_dp ), + .data_o ( ar_req_dp ) + ); + + + //-------------------------------------- + // Last flag store + //-------------------------------------- + stream_fifo_optimal_wrap #( + .Depth ( MetaFifoDepth ), + .type_t ( logic [1:0] ), + .PrintInfo ( PrintFifoInfo ) + ) i_w_last ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( {w_req.super_last, w_req.last} ), + .valid_i ( w_valid & w_ready ), + .ready_o ( w_last_ready ), + .data_o ( {w_super_last, w_last_burst} ), + .valid_o ( /* NOT CONNECTED */ ), + .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) + ); + + //-------------------------------------- + // Transport Layer / Datapath + //-------------------------------------- + idma_transport_layer_r_obi_w_axi #( + .NumAxInFlight ( NumAxInFlight ), + .DataWidth ( DataWidth ), + .BufferDepth ( BufferDepth ), + .MaskInvalidData ( MaskInvalidData ), + .PrintFifoInfo ( PrintFifoInfo ), + .r_dp_req_t ( r_dp_req_t ), + .w_dp_req_t ( w_dp_req_t ), + .r_dp_rsp_t ( r_dp_rsp_t ), + .w_dp_rsp_t ( w_dp_rsp_t ), + .write_meta_channel_t ( write_meta_channel_t ), + .read_meta_channel_t ( read_meta_channel_t ), + .axi_req_t ( axi_req_t ), + .axi_rsp_t ( axi_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ) + ) i_idma_transport_layer ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .obi_read_req_o ( obi_read_req_o ), + .obi_read_rsp_i ( obi_read_rsp_i ), + .axi_write_req_o ( axi_write_req_o ), + .axi_write_rsp_i ( axi_write_rsp_i ), + .r_dp_req_i ( r_dp_req_out ), + .r_dp_valid_i ( r_dp_req_out_valid ), + .r_dp_ready_o ( r_dp_req_out_ready ), + .r_dp_rsp_o ( r_dp_rsp ), + .r_dp_valid_o ( r_dp_rsp_valid ), + .r_dp_ready_i ( r_dp_rsp_ready ), + .w_dp_req_i ( w_dp_req_out ), + .w_dp_valid_i ( w_dp_req_out_valid ), + .w_dp_ready_o ( w_dp_req_out_ready ), + .w_dp_rsp_o ( w_dp_rsp ), + .w_dp_valid_o ( w_dp_rsp_valid ), + .w_dp_ready_i ( w_dp_rsp_ready ), + .ar_req_i ( ar_req_dp ), + .ar_valid_i ( ar_valid_dp ), + .ar_ready_o ( ar_ready_dp ), + .aw_req_i ( aw_req_dp ), + .aw_valid_i ( aw_valid_dp ), + .aw_ready_o ( aw_ready_dp ), + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) + ); + + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + + if (RAWCouplingAvail) begin : gen_r_aw_coupler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) + end else begin : gen_r_aw_bypass + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + fall_through_register #( + .T ( write_meta_channel_t ) + ) i_aw_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( w_valid ), + .ready_o ( aw_ready ), + .data_i ( w_req.aw_req ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp ), + .data_o ( aw_req_dp ) + ); + + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end + + + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) + +endmodule + +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Authors: +// - Thomas Benz +// - Tobias Senti `include "axi/typedef.svh" `include "idma/guard.svh" /// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_rw_axi #( +module idma_backend_r_axi_w_obi #( /// Data width parameter int unsigned DataWidth = 32'd16, /// Address width @@ -6170,7 +6505,7 @@ module idma_backend_rw_axi #( /// will no longer be word aligned, but only a single shifter is needed parameter bit CombinedShifter = 1'b0, /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b1, + parameter bit RAWCouplingAvail = 1'b0, /// Mask invalid data on the manager interface parameter bit MaskInvalidData = 1'b1, /// Should hardware legalization be present? (recommended) @@ -6194,6 +6529,9 @@ module idma_backend_rw_axi #( /// AXI4+ATOP Request and Response channel type parameter type axi_req_t = logic, parameter type axi_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, /// Address Read Channel type parameter type read_meta_channel_t = logic, /// Address Write Channel type @@ -6236,10 +6574,10 @@ module idma_backend_rw_axi #( /// AXI4+ATOP read response input axi_rsp_t axi_read_rsp_i, - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, /// iDMA busy flags output idma_busy_t busy_o @@ -6467,7 +6805,7 @@ module idma_backend_rw_axi #( //-------------------------------------- if (HardwareLegalizer) begin : gen_hw_legalizer // hardware legalizer is present - idma_legalizer_rw_axi #( + idma_legalizer_r_axi_w_obi #( .CombinedShifter ( CombinedShifter ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), @@ -6556,45 +6894,11 @@ module idma_backend_rw_axi #( // Error handler //-------------------------------------- if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - idma_error_handler #( - .MetaFifoDepth ( MetaFifoDepth ), - .PrintFifoInfo ( PrintFifoInfo ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_eh_req_t ), - .addr_t ( addr_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ) - ) i_idma_error_handler ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid ), - .rsp_ready_i ( rsp_ready ), - .req_valid_i ( req_valid ), - .req_ready_i ( req_ready_o ), - .eh_i ( idma_eh_req_i ), - .eh_valid_i ( eh_req_valid_i ), - .eh_ready_o ( eh_req_ready_o ), - .r_addr_i ( r_req.ar_req.axi.ar_chan.addr ), - .w_addr_i ( w_req.aw_req.axi.aw_chan.addr ), - .r_consume_i ( r_valid & r_ready ), - .w_consume_i ( w_valid & w_ready ), - .legalizer_flush_o ( legalizer_flush ), - .legalizer_kill_o ( legalizer_kill ), - .dp_busy_i ( dp_busy ), - .dp_poison_o ( dp_poison ), - .r_dp_rsp_i ( r_dp_rsp ), - .r_dp_valid_i ( r_dp_rsp_valid ), - .r_dp_ready_o ( r_dp_rsp_ready ), - .w_dp_rsp_i ( w_dp_rsp ), - .w_dp_valid_i ( w_dp_rsp_valid ), - .w_dp_ready_o ( w_dp_rsp_ready ), - .w_last_burst_i ( w_last_burst ), - .w_super_last_i ( w_super_last ), - .fsm_busy_o ( busy_o.eh_fsm_busy ), - .cnt_busy_o ( busy_o.eh_cnt_busy ) - ); + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); + end + ) end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler // bypass the signals, assign their neutral values assign idma_rsp.error = 1'b0; @@ -6709,7 +7013,7 @@ module idma_backend_rw_axi #( //-------------------------------------- // Transport Layer / Datapath //-------------------------------------- - idma_transport_layer_rw_axi #( + idma_transport_layer_r_axi_w_obi #( .NumAxInFlight ( NumAxInFlight ), .DataWidth ( DataWidth ), .BufferDepth ( BufferDepth ), @@ -6722,15 +7026,17 @@ module idma_backend_rw_axi #( .write_meta_channel_t ( write_meta_channel_t ), .read_meta_channel_t ( read_meta_channel_t ), .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ) + .axi_rsp_t ( axi_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ) ) i_idma_transport_layer ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .testmode_i ( testmode_i ), .axi_read_req_o ( axi_read_req_o ), .axi_read_rsp_i ( axi_read_rsp_i ), - .axi_write_req_o ( axi_write_req_o ), - .axi_write_rsp_i ( axi_write_rsp_i ), + .obi_write_req_o ( obi_write_req_o ), + .obi_write_rsp_i ( obi_write_rsp_i ), .r_dp_req_i ( r_dp_req_out ), .r_dp_valid_i ( r_dp_req_out_valid ), .r_dp_ready_o ( r_dp_req_out_ready ), @@ -6762,47 +7068,30 @@ module idma_backend_rw_axi #( //-------------------------------------- if (RAWCouplingAvail) begin : gen_r_aw_coupler - // instantiate the channel coupler - idma_channel_coupler #( - .NumAxInFlight ( NumAxInFlight ), - .AddrWidth ( AddrWidth ), - .UserWidth ( UserWidth ), - .AxiIdWidth ( AxiIdWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .axi_aw_chan_t ( write_meta_channel_t ) - ) i_idma_channel_coupler ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .r_rsp_valid_i ( r_chan_valid ), - .r_rsp_ready_i ( r_chan_ready ), - .r_rsp_first_i ( r_dp_rsp.first ), - .r_decouple_aw_i ( r_dp_req_out.decouple_aw ), - .aw_decouple_aw_i ( w_req.decouple_aw ), - .aw_req_i ( w_req.aw_req ), - .aw_valid_i ( w_valid ), - .aw_ready_o ( aw_ready ), - .aw_req_o ( aw_req_dp ), - .aw_valid_o ( aw_valid_dp ), - .aw_ready_i ( aw_ready_dp ), - .busy_o ( busy_o.raw_coupler_busy ) - ); + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) end else begin : gen_r_aw_bypass - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - fall_through_register #( - .T ( write_meta_channel_t ) - ) i_aw_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( w_valid ), - .ready_o ( aw_ready ), - .data_i ( w_req.aw_req ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp ), - .data_o ( aw_req_dp ) + // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests + // As a write could depend on up to two reads + stream_fifo_optimal_wrap #( + .Depth ( 2 ), + .type_t ( write_meta_channel_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_req.aw_req ), + .valid_i ( w_valid && aw_ready ), + .ready_o ( aw_ready ), + .data_o ( aw_req_dp ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp && aw_valid_dp ) ); // no unit: not busy @@ -6849,7 +7138,7 @@ endmodule `include "idma/guard.svh" /// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_r_obi_w_axi #( +module idma_backend_rw_axi_rw_axis #( /// Data width parameter int unsigned DataWidth = 32'd16, /// Address width @@ -6897,9 +7186,9 @@ module idma_backend_r_obi_w_axi #( /// AXI4+ATOP Request and Response channel type parameter type axi_req_t = logic, parameter type axi_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic, + /// AXI Stream Request and Response channel type + parameter type axis_req_t = logic, + parameter type axis_rsp_t = logic, /// Address Read Channel type parameter type read_meta_channel_t = logic, /// Address Write Channel type @@ -6937,16 +7226,26 @@ module idma_backend_r_obi_w_axi #( /// Error handler request ready output logic eh_req_ready_o, - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, + /// AXI4+ATOP read request + output axi_req_t axi_read_req_o, + /// AXI4+ATOP read response + input axi_rsp_t axi_read_rsp_i, + + /// AXI Stream read request + input axis_req_t axis_read_req_i, + /// AXI Stream read response + output axis_rsp_t axis_read_rsp_o, /// AXI4+ATOP write request output axi_req_t axi_write_req_o, /// AXI4+ATOP write response input axi_rsp_t axi_write_rsp_i, + /// AXI Stream write request + output axis_req_t axis_write_req_o, + /// AXI Stream write response + input axis_rsp_t axis_write_rsp_i, + /// iDMA busy flags output idma_busy_t busy_o ); @@ -7027,6 +7326,10 @@ module idma_backend_r_obi_w_axi #( r_dp_req_t r_dp_req; read_meta_channel_t ar_req; } idma_r_req_t; + typedef struct packed { + idma_pkg::protocol_e src_protocol; + read_meta_channel_t ar_req; + } read_meta_channel_tagged_t; /// The iDMA write request bundles an `AW` type and a datapath write response type together. It /// has an additional flags: @@ -7041,6 +7344,10 @@ module idma_backend_r_obi_w_axi #( logic super_last; logic decouple_aw; } idma_w_req_t; + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + write_meta_channel_t aw_req; + } write_meta_channel_tagged_t; /// The mutable transfer options type holds important information that is mutated by the /// `legalizer` block. @@ -7082,6 +7389,8 @@ module idma_backend_r_obi_w_axi #( idma_w_req_t w_req; logic r_valid, w_valid; logic r_ready, w_ready; + read_meta_channel_tagged_t r_meta_req_tagged; + write_meta_channel_tagged_t w_meta_req_tagged; // It the current transfer the last burst in the 1D transfer? logic w_last_burst; @@ -7110,10 +7419,10 @@ module idma_backend_r_obi_w_axi #( logic aw_valid_dp, ar_valid_dp; // Ax request from R-AW coupler to datapath - write_meta_channel_t aw_req_dp; + write_meta_channel_tagged_t aw_req_dp; // Ax request from the decoupling stage to the datapath - read_meta_channel_t ar_req_dp; + read_meta_channel_tagged_t ar_req_dp; // flush and preemptively empty the legalizer logic legalizer_flush, legalizer_kill; @@ -7173,7 +7482,7 @@ module idma_backend_r_obi_w_axi #( //-------------------------------------- if (HardwareLegalizer) begin : gen_hw_legalizer // hardware legalizer is present - idma_legalizer_r_obi_w_axi #( + idma_legalizer_rw_axi_rw_axis #( .CombinedShifter ( CombinedShifter ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), @@ -7340,9 +7649,13 @@ module idma_backend_r_obi_w_axi #( // Add fall-through register to allow the input to be ready if the output is not. This // does not add a cycle of delay + assign r_meta_req_tagged = '{ + src_protocol: r_req.r_dp_req.src_protocol, + ar_req: r_req.ar_req + }; fall_through_register #( - .T ( read_meta_channel_t ) + .T ( read_meta_channel_tagged_t ) ) i_ar_fall_through_register ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -7350,7 +7663,7 @@ module idma_backend_r_obi_w_axi #( .clr_i ( 1'b0 ), .valid_i ( r_valid ), .ready_o ( ar_ready ), - .data_i ( r_req.ar_req ), + .data_i ( r_meta_req_tagged ), .valid_o ( ar_valid_dp ), .ready_i ( ar_ready_dp ), .data_o ( ar_req_dp ) @@ -7381,7 +7694,7 @@ module idma_backend_r_obi_w_axi #( //-------------------------------------- // Transport Layer / Datapath //-------------------------------------- - idma_transport_layer_r_obi_w_axi #( + idma_transport_layer_rw_axi_rw_axis #( .NumAxInFlight ( NumAxInFlight ), .DataWidth ( DataWidth ), .BufferDepth ( BufferDepth ), @@ -7392,19 +7705,25 @@ module idma_backend_r_obi_w_axi #( .r_dp_rsp_t ( r_dp_rsp_t ), .w_dp_rsp_t ( w_dp_rsp_t ), .write_meta_channel_t ( write_meta_channel_t ), + .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), .read_meta_channel_t ( read_meta_channel_t ), + .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), .axi_req_t ( axi_req_t ), .axi_rsp_t ( axi_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ) + .axis_req_t ( axis_req_t ), + .axis_rsp_t ( axis_rsp_t ) ) i_idma_transport_layer ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .testmode_i ( testmode_i ), - .obi_read_req_o ( obi_read_req_o ), - .obi_read_rsp_i ( obi_read_rsp_i ), + .axi_read_req_o ( axi_read_req_o ), + .axi_read_rsp_i ( axi_read_rsp_i ), + .axis_read_req_i ( axis_read_req_i ), + .axis_read_rsp_o ( axis_read_rsp_o ), .axi_write_req_o ( axi_write_req_o ), .axi_write_rsp_i ( axi_write_rsp_i ), + .axis_write_req_o ( axis_write_req_o ), + .axis_write_rsp_i ( axis_write_rsp_i ), .r_dp_req_i ( r_dp_req_out ), .r_dp_valid_i ( r_dp_req_out_valid ), .r_dp_ready_o ( r_dp_req_out_ready ), @@ -7434,6 +7753,10 @@ module idma_backend_r_obi_w_axi #( //-------------------------------------- // R-AW channel coupler //-------------------------------------- + assign w_meta_req_tagged = '{ + dst_protocol: w_req.w_dp_req.dst_protocol, + aw_req: w_req.aw_req + }; if (RAWCouplingAvail) begin : gen_r_aw_coupler `IDMA_NONSYNTH_BLOCK( @@ -7442,21 +7765,24 @@ module idma_backend_r_obi_w_axi #( end ) end else begin : gen_r_aw_bypass - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - fall_through_register #( - .T ( write_meta_channel_t ) - ) i_aw_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( w_valid ), - .ready_o ( aw_ready ), - .data_i ( w_req.aw_req ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp ), - .data_o ( aw_req_dp ) + // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests + // As a write could depend on up to two reads + stream_fifo_optimal_wrap #( + .Depth ( 2 ), + .type_t ( write_meta_channel_tagged_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_meta_req_tagged ), + .valid_i ( w_valid && aw_ready ), + .ready_o ( aw_ready ), + .data_o ( aw_req_dp ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp && aw_valid_dp ) ); // no unit: not busy @@ -7503,7 +7829,7 @@ endmodule `include "idma/guard.svh" /// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_r_axi_w_obi #( +module idma_backend_r_obi_rw_init_w_axi #( /// Data width parameter int unsigned DataWidth = 32'd16, /// Address width @@ -7551,6 +7877,9 @@ module idma_backend_r_axi_w_obi #( /// AXI4+ATOP Request and Response channel type parameter type axi_req_t = logic, parameter type axi_rsp_t = logic, + /// Memory Init Request and Response channel type + parameter type init_req_t = logic, + parameter type init_rsp_t = logic, /// OBI Request and Response channel type parameter type obi_req_t = logic, parameter type obi_rsp_t = logic, @@ -7591,15 +7920,25 @@ module idma_backend_r_axi_w_obi #( /// Error handler request ready output logic eh_req_ready_o, - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, + /// Memory Init read request + output init_req_t init_read_req_o, + /// Memory Init read response + input init_rsp_t init_read_rsp_i, - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, + + /// AXI4+ATOP write request + output axi_req_t axi_write_req_o, + /// AXI4+ATOP write response + input axi_rsp_t axi_write_rsp_i, + + /// Memory Init write request + output init_req_t init_write_req_o, + /// Memory Init write response + input init_rsp_t init_write_rsp_i, /// iDMA busy flags output idma_busy_t busy_o @@ -7681,6 +8020,10 @@ module idma_backend_r_axi_w_obi #( r_dp_req_t r_dp_req; read_meta_channel_t ar_req; } idma_r_req_t; + typedef struct packed { + idma_pkg::protocol_e src_protocol; + read_meta_channel_t ar_req; + } read_meta_channel_tagged_t; /// The iDMA write request bundles an `AW` type and a datapath write response type together. It /// has an additional flags: @@ -7695,6 +8038,10 @@ module idma_backend_r_axi_w_obi #( logic super_last; logic decouple_aw; } idma_w_req_t; + typedef struct packed { + idma_pkg::protocol_e dst_protocol; + write_meta_channel_t aw_req; + } write_meta_channel_tagged_t; /// The mutable transfer options type holds important information that is mutated by the /// `legalizer` block. @@ -7736,6 +8083,8 @@ module idma_backend_r_axi_w_obi #( idma_w_req_t w_req; logic r_valid, w_valid; logic r_ready, w_ready; + read_meta_channel_tagged_t r_meta_req_tagged; + write_meta_channel_tagged_t w_meta_req_tagged; // It the current transfer the last burst in the 1D transfer? logic w_last_burst; @@ -7764,10 +8113,10 @@ module idma_backend_r_axi_w_obi #( logic aw_valid_dp, ar_valid_dp; // Ax request from R-AW coupler to datapath - write_meta_channel_t aw_req_dp; + write_meta_channel_tagged_t aw_req_dp; // Ax request from the decoupling stage to the datapath - read_meta_channel_t ar_req_dp; + read_meta_channel_tagged_t ar_req_dp; // flush and preemptively empty the legalizer logic legalizer_flush, legalizer_kill; @@ -7827,7 +8176,7 @@ module idma_backend_r_axi_w_obi #( //-------------------------------------- if (HardwareLegalizer) begin : gen_hw_legalizer // hardware legalizer is present - idma_legalizer_r_axi_w_obi #( + idma_legalizer_r_obi_rw_init_w_axi #( .CombinedShifter ( CombinedShifter ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), @@ -7994,9 +8343,13 @@ module idma_backend_r_axi_w_obi #( // Add fall-through register to allow the input to be ready if the output is not. This // does not add a cycle of delay + assign r_meta_req_tagged = '{ + src_protocol: r_req.r_dp_req.src_protocol, + ar_req: r_req.ar_req + }; fall_through_register #( - .T ( read_meta_channel_t ) + .T ( read_meta_channel_tagged_t ) ) i_ar_fall_through_register ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -8004,7 +8357,7 @@ module idma_backend_r_axi_w_obi #( .clr_i ( 1'b0 ), .valid_i ( r_valid ), .ready_o ( ar_ready ), - .data_i ( r_req.ar_req ), + .data_i ( r_meta_req_tagged ), .valid_o ( ar_valid_dp ), .ready_i ( ar_ready_dp ), .data_o ( ar_req_dp ) @@ -8035,7 +8388,7 @@ module idma_backend_r_axi_w_obi #( //-------------------------------------- // Transport Layer / Datapath //-------------------------------------- - idma_transport_layer_r_axi_w_obi #( + idma_transport_layer_r_obi_rw_init_w_axi #( .NumAxInFlight ( NumAxInFlight ), .DataWidth ( DataWidth ), .BufferDepth ( BufferDepth ), @@ -8046,19 +8399,27 @@ module idma_backend_r_axi_w_obi #( .r_dp_rsp_t ( r_dp_rsp_t ), .w_dp_rsp_t ( w_dp_rsp_t ), .write_meta_channel_t ( write_meta_channel_t ), + .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), .read_meta_channel_t ( read_meta_channel_t ), + .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), .axi_req_t ( axi_req_t ), .axi_rsp_t ( axi_rsp_t ), + .init_req_t ( init_req_t ), + .init_rsp_t ( init_rsp_t ), .obi_req_t ( obi_req_t ), .obi_rsp_t ( obi_rsp_t ) ) i_idma_transport_layer ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .testmode_i ( testmode_i ), - .axi_read_req_o ( axi_read_req_o ), - .axi_read_rsp_i ( axi_read_rsp_i ), - .obi_write_req_o ( obi_write_req_o ), - .obi_write_rsp_i ( obi_write_rsp_i ), + .init_read_req_o ( init_read_req_o ), + .init_read_rsp_i ( init_read_rsp_i ), + .obi_read_req_o ( obi_read_req_o ), + .obi_read_rsp_i ( obi_read_rsp_i ), + .axi_write_req_o ( axi_write_req_o ), + .axi_write_rsp_i ( axi_write_rsp_i ), + .init_write_req_o ( init_write_req_o ), + .init_write_rsp_i ( init_write_rsp_i ), .r_dp_req_i ( r_dp_req_out ), .r_dp_valid_i ( r_dp_req_out_valid ), .r_dp_ready_o ( r_dp_req_out_ready ), @@ -8088,6 +8449,10 @@ module idma_backend_r_axi_w_obi #( //-------------------------------------- // R-AW channel coupler //-------------------------------------- + assign w_meta_req_tagged = '{ + dst_protocol: w_req.w_dp_req.dst_protocol, + aw_req: w_req.aw_req + }; if (RAWCouplingAvail) begin : gen_r_aw_coupler `IDMA_NONSYNTH_BLOCK( @@ -8096,25 +8461,22 @@ module idma_backend_r_axi_w_obi #( end ) end else begin : gen_r_aw_bypass - // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests - // As a write could depend on up to two reads - stream_fifo_optimal_wrap #( - .Depth ( 2 ), - .type_t ( write_meta_channel_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_aw_fifo ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.aw_req ), - .valid_i ( w_valid && aw_ready ), - .ready_o ( aw_ready ), - .data_o ( aw_req_dp ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp && aw_valid_dp ) - ); + // Add fall-through register to allow the input to be ready if the output is not. This + // does not add a cycle of delay + fall_through_register #( + .T ( write_meta_channel_tagged_t ) + ) i_aw_fall_through_register ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .testmode_i ( testmode_i ), + .clr_i ( 1'b0 ), + .valid_i ( w_valid ), + .ready_o ( aw_ready ), + .data_i ( w_meta_req_tagged ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp ), + .data_o ( aw_req_dp ) + ); // no unit: not busy assign busy_o.raw_coupler_busy = 1'b0; @@ -8160,7 +8522,7 @@ endmodule `include "idma/guard.svh" /// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_rw_axi_rw_axis #( +module idma_backend_r_axi_rw_init_rw_obi #( /// Data width parameter int unsigned DataWidth = 32'd16, /// Address width @@ -8208,9 +8570,12 @@ module idma_backend_rw_axi_rw_axis #( /// AXI4+ATOP Request and Response channel type parameter type axi_req_t = logic, parameter type axi_rsp_t = logic, - /// AXI Stream Request and Response channel type - parameter type axis_req_t = logic, - parameter type axis_rsp_t = logic, + /// Memory Init Request and Response channel type + parameter type init_req_t = logic, + parameter type init_rsp_t = logic, + /// OBI Request and Response channel type + parameter type obi_req_t = logic, + parameter type obi_rsp_t = logic, /// Address Read Channel type parameter type read_meta_channel_t = logic, /// Address Write Channel type @@ -8253,20 +8618,25 @@ module idma_backend_rw_axi_rw_axis #( /// AXI4+ATOP read response input axi_rsp_t axi_read_rsp_i, - /// AXI Stream read request - input axis_req_t axis_read_req_i, - /// AXI Stream read response - output axis_rsp_t axis_read_rsp_o, + /// Memory Init read request + output init_req_t init_read_req_o, + /// Memory Init read response + input init_rsp_t init_read_rsp_i, - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, + /// OBI read request + output obi_req_t obi_read_req_o, + /// OBI read response + input obi_rsp_t obi_read_rsp_i, - /// AXI Stream write request - output axis_req_t axis_write_req_o, - /// AXI Stream write response - input axis_rsp_t axis_write_rsp_i, + /// Memory Init write request + output init_req_t init_write_req_o, + /// Memory Init write response + input init_rsp_t init_write_rsp_i, + + /// OBI write request + output obi_req_t obi_write_req_o, + /// OBI write response + input obi_rsp_t obi_write_rsp_i, /// iDMA busy flags output idma_busy_t busy_o @@ -8504,7 +8874,7 @@ module idma_backend_rw_axi_rw_axis #( //-------------------------------------- if (HardwareLegalizer) begin : gen_hw_legalizer // hardware legalizer is present - idma_legalizer_rw_axi_rw_axis #( + idma_legalizer_r_axi_rw_init_rw_obi #( .CombinedShifter ( CombinedShifter ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), @@ -8716,7 +9086,7 @@ module idma_backend_rw_axi_rw_axis #( //-------------------------------------- // Transport Layer / Datapath //-------------------------------------- - idma_transport_layer_rw_axi_rw_axis #( + idma_transport_layer_r_axi_rw_init_rw_obi #( .NumAxInFlight ( NumAxInFlight ), .DataWidth ( DataWidth ), .BufferDepth ( BufferDepth ), @@ -8732,20 +9102,24 @@ module idma_backend_rw_axi_rw_axis #( .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), .axi_req_t ( axi_req_t ), .axi_rsp_t ( axi_rsp_t ), - .axis_req_t ( axis_req_t ), - .axis_rsp_t ( axis_rsp_t ) + .init_req_t ( init_req_t ), + .init_rsp_t ( init_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ) ) i_idma_transport_layer ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), .testmode_i ( testmode_i ), .axi_read_req_o ( axi_read_req_o ), .axi_read_rsp_i ( axi_read_rsp_i ), - .axis_read_req_i ( axis_read_req_i ), - .axis_read_rsp_o ( axis_read_rsp_o ), - .axi_write_req_o ( axi_write_req_o ), - .axi_write_rsp_i ( axi_write_rsp_i ), - .axis_write_req_o ( axis_write_req_o ), - .axis_write_rsp_i ( axis_write_rsp_i ), + .init_read_req_o ( init_read_req_o ), + .init_read_rsp_i ( init_read_rsp_i ), + .obi_read_req_o ( obi_read_req_o ), + .obi_read_rsp_i ( obi_read_rsp_i ), + .init_write_req_o ( init_write_req_o ), + .init_write_rsp_i ( init_write_rsp_i ), + .obi_write_req_o ( obi_write_req_o ), + .obi_write_rsp_i ( obi_write_rsp_i ), .r_dp_req_i ( r_dp_req_out ), .r_dp_valid_i ( r_dp_req_out_valid ), .r_dp_ready_o ( r_dp_req_out_ready ), @@ -8764,2537 +9138,78 @@ module idma_backend_rw_axi_rw_axis #( .aw_req_i ( aw_req_dp ), .aw_valid_i ( aw_valid_dp ), .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - assign w_meta_req_tagged = '{ - dst_protocol: w_req.w_dp_req.dst_protocol, - aw_req: w_req.aw_req - }; - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests - // As a write could depend on up to two reads - stream_fifo_optimal_wrap #( - .Depth ( 2 ), - .type_t ( write_meta_channel_tagged_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_aw_fifo ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_meta_req_tagged ), - .valid_i ( w_valid && aw_ready ), - .ready_o ( aw_ready ), - .data_o ( aw_req_dp ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp && aw_valid_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_rw_axi_rw_obi #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - typedef struct packed { - idma_pkg::protocol_e src_protocol; - read_meta_channel_t ar_req; - } read_meta_channel_tagged_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - write_meta_channel_t aw_req; - } write_meta_channel_tagged_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - read_meta_channel_tagged_t r_meta_req_tagged; - write_meta_channel_tagged_t w_meta_req_tagged; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_tagged_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_tagged_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_rw_axi_rw_obi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); - end - ) - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - assign r_meta_req_tagged = '{ - src_protocol: r_req.r_dp_req.src_protocol, - ar_req: r_req.ar_req - }; - - fall_through_register #( - .T ( read_meta_channel_tagged_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_meta_req_tagged ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_rw_axi_rw_obi #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .axi_read_req_o ( axi_read_req_o ), - .axi_read_rsp_i ( axi_read_rsp_i ), - .obi_read_req_o ( obi_read_req_o ), - .obi_read_rsp_i ( obi_read_rsp_i ), - .axi_write_req_o ( axi_write_req_o ), - .axi_write_rsp_i ( axi_write_rsp_i ), - .obi_write_req_o ( obi_write_req_o ), - .obi_write_rsp_i ( obi_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - assign w_meta_req_tagged = '{ - dst_protocol: w_req.w_dp_req.dst_protocol, - aw_req: w_req.aw_req - }; - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests - // As a write could depend on up to two reads - stream_fifo_optimal_wrap #( - .Depth ( 2 ), - .type_t ( write_meta_channel_tagged_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_aw_fifo ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_meta_req_tagged ), - .valid_i ( w_valid && aw_ready ), - .ready_o ( aw_ready ), - .data_o ( aw_req_dp ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp && aw_valid_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_r_obi_rw_init_w_axi #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// Memory Init Request and Response channel type - parameter type init_req_t = logic, - parameter type init_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// Memory Init read request - output init_req_t init_read_req_o, - /// Memory Init read response - input init_rsp_t init_read_rsp_i, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// Memory Init write request - output init_req_t init_write_req_o, - /// Memory Init write response - input init_rsp_t init_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - typedef struct packed { - idma_pkg::protocol_e src_protocol; - read_meta_channel_t ar_req; - } read_meta_channel_tagged_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - write_meta_channel_t aw_req; - } write_meta_channel_tagged_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - read_meta_channel_tagged_t r_meta_req_tagged; - write_meta_channel_tagged_t w_meta_req_tagged; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_tagged_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_tagged_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_r_obi_rw_init_w_axi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); - end - ) - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - assign r_meta_req_tagged = '{ - src_protocol: r_req.r_dp_req.src_protocol, - ar_req: r_req.ar_req - }; - - fall_through_register #( - .T ( read_meta_channel_tagged_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_meta_req_tagged ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_r_obi_rw_init_w_axi #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .init_req_t ( init_req_t ), - .init_rsp_t ( init_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .init_read_req_o ( init_read_req_o ), - .init_read_rsp_i ( init_read_rsp_i ), - .obi_read_req_o ( obi_read_req_o ), - .obi_read_rsp_i ( obi_read_rsp_i ), - .axi_write_req_o ( axi_write_req_o ), - .axi_write_rsp_i ( axi_write_rsp_i ), - .init_write_req_o ( init_write_req_o ), - .init_write_rsp_i ( init_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - assign w_meta_req_tagged = '{ - dst_protocol: w_req.w_dp_req.dst_protocol, - aw_req: w_req.aw_req - }; - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - fall_through_register #( - .T ( write_meta_channel_tagged_t ) - ) i_aw_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( w_valid ), - .ready_o ( aw_ready ), - .data_i ( w_meta_req_tagged ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp ), - .data_o ( aw_req_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_r_axi_rw_init_rw_obi #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// Memory Init Request and Response channel type - parameter type init_req_t = logic, - parameter type init_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// Memory Init read request - output init_req_t init_read_req_o, - /// Memory Init read response - input init_rsp_t init_read_rsp_i, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// Memory Init write request - output init_req_t init_write_req_o, - /// Memory Init write response - input init_rsp_t init_write_rsp_i, - - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - typedef struct packed { - idma_pkg::protocol_e src_protocol; - read_meta_channel_t ar_req; - } read_meta_channel_tagged_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - write_meta_channel_t aw_req; - } write_meta_channel_tagged_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - read_meta_channel_tagged_t r_meta_req_tagged; - write_meta_channel_tagged_t w_meta_req_tagged; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_tagged_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_tagged_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_r_axi_rw_init_rw_obi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); - end - ) - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - assign r_meta_req_tagged = '{ - src_protocol: r_req.r_dp_req.src_protocol, - ar_req: r_req.ar_req - }; - - fall_through_register #( - .T ( read_meta_channel_tagged_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_meta_req_tagged ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_r_axi_rw_init_rw_obi #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .init_req_t ( init_req_t ), - .init_rsp_t ( init_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .axi_read_req_o ( axi_read_req_o ), - .axi_read_rsp_i ( axi_read_rsp_i ), - .init_read_req_o ( init_read_req_o ), - .init_read_rsp_i ( init_read_rsp_i ), - .obi_read_req_o ( obi_read_req_o ), - .obi_read_rsp_i ( obi_read_rsp_i ), - .init_write_req_o ( init_write_req_o ), - .init_write_rsp_i ( init_write_rsp_i ), - .obi_write_req_o ( obi_write_req_o ), - .obi_write_rsp_i ( obi_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - assign w_meta_req_tagged = '{ - dst_protocol: w_req.w_dp_req.dst_protocol, - aw_req: w_req.aw_req - }; - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests - // As a write could depend on up to two reads - stream_fifo_optimal_wrap #( - .Depth ( 2 ), - .type_t ( write_meta_channel_tagged_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_aw_fifo ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_meta_req_tagged ), - .valid_i ( w_valid && aw_ready ), - .ready_o ( aw_ready ), - .data_o ( aw_req_dp ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp && aw_valid_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "axi_stream/typedef.svh" -`include "idma/typedef.svh" -`include "obi/typedef.svh" -`include "tilelink/typedef.svh" - -/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_rw_axi #( - /// Data width - parameter int unsigned DataWidth = 32'd32, - /// Address width - parameter int unsigned AddrWidth = 32'd32, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd3, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd32, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter bit ErrorHandling = 1'b1, - // Dependent parameters; do not override! - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth), - /// Address type (do not override!) - parameter type addr_t = logic[AddrWidth-1:0], - /// Data type (do not override!) - parameter type data_t = logic[DataWidth-1:0], - /// Strobe type (do not override!) - parameter type strb_t = logic[StrbWidth-1:0], - /// User type (do not override!) - parameter type user_t = logic[UserWidth-1:0], - /// ID type (do not override!) - parameter type id_t = logic[AxiIdWidth-1:0], - /// Transfer length type (do not override!) - parameter type tf_len_t = logic[TFLenWidth-1:0], - /// Offset type (do not override!) - parameter type offset_t = logic[OffsetWidth-1:0] -)( - input logic clk_i, - input logic rst_ni, - input logic test_i, - - input logic req_valid_i, - output logic req_ready_o, - - input tf_len_t req_length_i, - input addr_t req_src_addr_i, - input addr_t req_dst_addr_i, - input idma_pkg::protocol_e req_src_protocol_i, - input idma_pkg::protocol_e req_dst_protocol_i, - input id_t req_axi_id_i, - input axi_pkg::burst_t req_src_burst_i, - input axi_pkg::cache_t req_src_cache_i, - input logic req_src_lock_i, - input axi_pkg::prot_t req_src_prot_i, - input axi_pkg::qos_t req_src_qos_i, - input axi_pkg::region_t req_src_region_i, - input axi_pkg::burst_t req_dst_burst_i, - input axi_pkg::cache_t req_dst_cache_i, - input logic req_dst_lock_i, - input axi_pkg::prot_t req_dst_prot_i, - input axi_pkg::qos_t req_dst_qos_i, - input axi_pkg::region_t req_dst_region_i, - input logic req_decouple_aw_i, - input logic req_decouple_rw_i, - input logic [2:0] req_src_max_llen_i, - input logic [2:0] req_dst_max_llen_i, - input logic req_src_reduce_len_i, - input logic req_dst_reduce_len_i, - input logic req_last_i, - - output logic rsp_valid_o, - input logic rsp_ready_i, - - output axi_pkg::resp_t rsp_cause_o, - output idma_pkg::err_type_t rsp_err_type_o, - output addr_t rsp_burst_addr_o, - output logic rsp_error_o, - output logic rsp_last_o, - - input logic eh_req_valid_i, - output logic eh_req_ready_o, - input idma_pkg::idma_eh_req_t eh_req_i, - - output id_t axi_ar_id_o, - output addr_t axi_ar_addr_o, - output axi_pkg::len_t axi_ar_len_o, - output axi_pkg::size_t axi_ar_size_o, - output axi_pkg::burst_t axi_ar_burst_o, - output logic axi_ar_lock_o, - output axi_pkg::cache_t axi_ar_cache_o, - output axi_pkg::prot_t axi_ar_prot_o, - output axi_pkg::qos_t axi_ar_qos_o, - output axi_pkg::region_t axi_ar_region_o, - output user_t axi_ar_user_o, - output logic axi_ar_valid_o, - input logic axi_ar_ready_i, - input id_t axi_r_id_i, - input data_t axi_r_data_i, - input axi_pkg::resp_t axi_r_resp_i, - input logic axi_r_last_i, - input user_t axi_r_user_i, - input logic axi_r_valid_i, - output logic axi_r_ready_o, - - - output id_t axi_aw_id_o, - output addr_t axi_aw_addr_o, - output axi_pkg::len_t axi_aw_len_o, - output axi_pkg::size_t axi_aw_size_o, - output axi_pkg::burst_t axi_aw_burst_o, - output logic axi_aw_lock_o, - output axi_pkg::cache_t axi_aw_cache_o, - output axi_pkg::prot_t axi_aw_prot_o, - output axi_pkg::qos_t axi_aw_qos_o, - output axi_pkg::region_t axi_aw_region_o, - output axi_pkg::atop_t axi_aw_atop_o, - output user_t axi_aw_user_o, - output logic axi_aw_valid_o, - input logic axi_aw_ready_i, - output data_t axi_w_data_o, - output strb_t axi_w_strb_o, - output logic axi_w_last_o, - output user_t axi_w_user_o, - output logic axi_w_valid_o, - input logic axi_w_ready_i, - input id_t axi_b_id_i, - input axi_pkg::resp_t axi_b_resp_i, - input user_t axi_b_user_i, - input logic axi_b_valid_i, - output logic axi_b_ready_o, - - - output idma_pkg::idma_busy_t idma_busy_o -); - - /// Define the error handling capability - localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : - idma_pkg::NO_ERROR_HANDLING; - - // AXI4+ATOP typedefs -`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) -`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) - -`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) - -`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) -`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - - - // Meta Channel Widths - localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); - - /// Option struct: AXI4 id as well as AXI and backend options - /// - `last`: a flag can be set if this transfer is the last of a set of transfers - `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) - - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) - - /// 1D iDMA response payload: - /// - `cause`: the AXI response - /// - `err_type`: type of the error: read, write, internal, ... - /// - `burst_addr`: the burst address where the issue error occurred - `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) - - /// 1D iDMA response type: - /// - `last`: the response of the request that was marked with the `opt.last` flag - /// - `error`: 1 if an error occurred - /// - `pld`: the error payload - `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) - - - typedef struct packed { - axi_ar_chan_t ar_chan; - } axi_read_meta_channel_t; - - typedef struct packed { - axi_read_meta_channel_t axi; - } read_meta_channel_t; - - typedef struct packed { - axi_aw_chan_t aw_chan; - } axi_write_meta_channel_t; - - typedef struct packed { - axi_write_meta_channel_t axi; - } write_meta_channel_t; - - // local types - // AXI4+ATOP request and response - axi_req_t axi_read_req; - axi_rsp_t axi_read_rsp; - - axi_req_t axi_write_req; - axi_rsp_t axi_write_rsp; - - idma_req_t idma_req; - idma_rsp_t idma_rsp; - - idma_backend_rw_axi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .AxiIdWidth ( AxiIdWidth ), - .UserWidth ( UserWidth ), - .TFLenWidth ( TFLenWidth ), - .MaskInvalidData ( MaskInvalidData ), - .BufferDepth ( BufferDepth ), - .NumAxInFlight ( NumAxInFlight ), - .MemSysDepth ( MemSysDepth ), - .RAWCouplingAvail ( RAWCouplingAvail ), - .HardwareLegalizer ( HardwareLegalizer ), - .RejectZeroTransfers ( RejectZeroTransfers ), - .ErrorCap ( ErrorCap ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ) - ) i_idma_backend ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( test_i ), - .idma_req_i ( idma_req ), - .req_valid_i ( req_valid_i ), - .req_ready_o ( req_ready_o ), - .idma_rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid_o ), - .rsp_ready_i ( rsp_ready_i ), - .idma_eh_req_i ( eh_req_i ), - .eh_req_valid_i ( eh_req_valid_i ), - .eh_req_ready_o ( eh_req_ready_o ), - .axi_read_req_o ( axi_read_req ), - .axi_read_rsp_i ( axi_read_rsp ), - .axi_write_req_o ( axi_write_req ), - .axi_write_rsp_i ( axi_write_rsp ), - .busy_o ( idma_busy_o ) + .dp_poison_i ( dp_poison ), + .r_dp_busy_o ( busy_o.r_dp_busy ), + .w_dp_busy_o ( busy_o.w_dp_busy ), + .buffer_busy_o ( busy_o.buffer_busy ), + .r_chan_ready_o ( r_chan_ready ), + .r_chan_valid_o ( r_chan_valid ) ); - // flatten structs - assign idma_req.dst_addr = req_dst_addr_i; - assign idma_req.src_addr = req_src_addr_i; - assign idma_req.length = req_length_i; - assign idma_req.opt.src_protocol = req_src_protocol_i; - assign idma_req.opt.dst_protocol = req_dst_protocol_i; - assign idma_req.opt.axi_id = req_axi_id_i; - assign idma_req.opt.dst.cache = req_dst_cache_i; - assign idma_req.opt.dst.burst = req_dst_burst_i; - assign idma_req.opt.dst.qos = req_dst_qos_i; - assign idma_req.opt.dst.lock = req_dst_lock_i; - assign idma_req.opt.dst.prot = req_dst_prot_i; - assign idma_req.opt.dst.region = req_dst_region_i; - assign idma_req.opt.src.cache = req_src_cache_i; - assign idma_req.opt.src.burst = req_src_burst_i; - assign idma_req.opt.src.qos = req_src_qos_i; - assign idma_req.opt.src.lock = req_src_lock_i; - assign idma_req.opt.src.prot = req_src_prot_i; - assign idma_req.opt.src.region = req_src_region_i; - assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; - assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; - assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; - assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; - assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; - assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; - assign idma_req.opt.last = req_last_i; - - assign rsp_cause_o = idma_rsp.pld.cause; - assign rsp_err_type_o = idma_rsp.pld.err_type; - assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; - assign rsp_error_o = idma_rsp.error; - assign rsp_last_o = idma_rsp.last; - + //-------------------------------------- + // R-AW channel coupler + //-------------------------------------- + assign w_meta_req_tagged = '{ + dst_protocol: w_req.w_dp_req.dst_protocol, + aw_req: w_req.aw_req + }; - // AXI4+ATOP Read - assign axi_ar_id_o = axi_read_req.ar.id; - assign axi_ar_addr_o = axi_read_req.ar.addr; - assign axi_ar_len_o = axi_read_req.ar.len; - assign axi_ar_size_o = axi_read_req.ar.size; - assign axi_ar_burst_o = axi_read_req.ar.burst; - assign axi_ar_lock_o = axi_read_req.ar.lock; - assign axi_ar_cache_o = axi_read_req.ar.cache; - assign axi_ar_prot_o = axi_read_req.ar.prot; - assign axi_ar_qos_o = axi_read_req.ar.qos; - assign axi_ar_region_o = axi_read_req.ar.region; - assign axi_ar_user_o = axi_read_req.ar.user; - assign axi_ar_valid_o = axi_read_req.ar_valid; - assign axi_r_ready_o = axi_read_req.r_ready; - - assign axi_read_rsp.ar_ready = axi_ar_ready_i; - assign axi_read_rsp.r.id = axi_r_id_i; - assign axi_read_rsp.r.data = axi_r_data_i; - assign axi_read_rsp.r.resp = axi_r_resp_i; - assign axi_read_rsp.r.last = axi_r_last_i; - assign axi_read_rsp.r.user = axi_r_user_i; - assign axi_read_rsp.r_valid = axi_r_valid_i; - + if (RAWCouplingAvail) begin : gen_r_aw_coupler + `IDMA_NONSYNTH_BLOCK( + initial begin + $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); + end + ) + end else begin : gen_r_aw_bypass + // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests + // As a write could depend on up to two reads + stream_fifo_optimal_wrap #( + .Depth ( 2 ), + .type_t ( write_meta_channel_tagged_t ), + .PrintInfo ( PrintFifoInfo ) + ) i_aw_fifo ( + .clk_i, + .rst_ni, + .testmode_i, + .flush_i ( 1'b0 ), + .usage_o ( /* NOT CONNECTED */ ), + .data_i ( w_meta_req_tagged ), + .valid_i ( w_valid && aw_ready ), + .ready_o ( aw_ready ), + .data_o ( aw_req_dp ), + .valid_o ( aw_valid_dp ), + .ready_i ( aw_ready_dp && aw_valid_dp ) + ); + // no unit: not busy + assign busy_o.raw_coupler_busy = 1'b0; + end - // AXI4+ATOP Write - assign axi_aw_id_o = axi_write_req.aw.id; - assign axi_aw_addr_o = axi_write_req.aw.addr; - assign axi_aw_len_o = axi_write_req.aw.len; - assign axi_aw_size_o = axi_write_req.aw.size; - assign axi_aw_burst_o = axi_write_req.aw.burst; - assign axi_aw_lock_o = axi_write_req.aw.lock; - assign axi_aw_cache_o = axi_write_req.aw.cache; - assign axi_aw_prot_o = axi_write_req.aw.prot; - assign axi_aw_qos_o = axi_write_req.aw.qos; - assign axi_aw_region_o = axi_write_req.aw.region; - assign axi_aw_atop_o = axi_write_req.aw.atop; - assign axi_aw_user_o = axi_write_req.aw.user; - assign axi_aw_valid_o = axi_write_req.aw_valid; - assign axi_w_data_o = axi_write_req.w.data; - assign axi_w_strb_o = axi_write_req.w.strb; - assign axi_w_last_o = axi_write_req.w.last; - assign axi_w_user_o = axi_write_req.w.user; - assign axi_w_valid_o = axi_write_req.w_valid; - assign axi_b_ready_o = axi_write_req.b_ready; - - assign axi_write_rsp.aw_ready = axi_aw_ready_i; - assign axi_write_rsp.w_ready = axi_w_ready_i; - assign axi_write_rsp.b.id = axi_b_id_i; - assign axi_write_rsp.b.resp = axi_b_resp_i; - assign axi_write_rsp.b.user = axi_b_user_i; - assign axi_write_rsp.b_valid = axi_b_valid_i; - + //-------------------------------------- + // Assertions + //-------------------------------------- + `IDMA_NONSYNTH_BLOCK( + initial begin : proc_assert_params + axi_addr_width : assert(AddrWidth >= 32'd12) else + $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); + axi_id_width : assert(AxiIdWidth > 32'd0) else + $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); + axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, + 32'd512, 32'd1028}) else + $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); + axi_user_width : assert(UserWidth > 32'd0) else + $fatal(1, "Parameter `UserWidth` has to be > 0!"); + num_ax_in_flight : assert(NumAxInFlight > 32'd1) else + $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); + buffer_depth : assert(BufferDepth > 32'd1) else + $fatal(1, "Parameter `BufferDepth` has to be > 1!"); + tf_len_width : assert(TFLenWidth >= 32'd12) else + $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); + tf_len_width_max : assert(TFLenWidth <= AddrWidth) else + $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); + end + ) endmodule @@ -11313,7 +9228,7 @@ endmodule `include "tilelink/typedef.svh" /// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_r_obi_w_axi #( +module idma_backend_synth_rw_axi #( /// Data width parameter int unsigned DataWidth = 32'd32, /// Address width @@ -11339,7 +9254,7 @@ module idma_backend_synth_r_obi_w_axi #( /// Mask invalid data on the manager interface parameter bit MaskInvalidData = 1'b1, /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 0, + parameter bit RAWCouplingAvail = 1, /// Should hardware legalization be present? (recommended) /// If not, software legalization is required to ensure the transfers are /// AXI4-conformal @@ -11347,7 +9262,7 @@ module idma_backend_synth_r_obi_w_axi #( /// Reject zero-length transfers parameter bit RejectZeroTransfers = 1'b1, /// Should the error handler be present? - parameter bit ErrorHandling = 1'b0, + parameter bit ErrorHandling = 1'b1, // Dependent parameters; do not override! /// Strobe Width (do not override!) parameter int unsigned StrbWidth = DataWidth / 8, @@ -11414,18 +9329,26 @@ module idma_backend_synth_r_obi_w_axi #( output logic eh_req_ready_o, input idma_pkg::idma_eh_req_t eh_req_i, - output logic obi_read_req_a_req_o, - output addr_t obi_read_req_a_addr_o, - output logic obi_read_req_a_we_o, - output strb_t obi_read_req_a_be_o, - output data_t obi_read_req_a_wdata_o, - output logic obi_read_req_r_ready_o, - - input logic obi_read_rsp_a_gnt_i, - input logic obi_read_rsp_r_valid_i, - input data_t obi_read_rsp_r_rdata_i, - input id_t obi_read_rsp_r_rid_i, - input logic obi_read_rsp_r_err_i, + output id_t axi_ar_id_o, + output addr_t axi_ar_addr_o, + output axi_pkg::len_t axi_ar_len_o, + output axi_pkg::size_t axi_ar_size_o, + output axi_pkg::burst_t axi_ar_burst_o, + output logic axi_ar_lock_o, + output axi_pkg::cache_t axi_ar_cache_o, + output axi_pkg::prot_t axi_ar_prot_o, + output axi_pkg::qos_t axi_ar_qos_o, + output axi_pkg::region_t axi_ar_region_o, + output user_t axi_ar_user_o, + output logic axi_ar_valid_o, + input logic axi_ar_ready_i, + input id_t axi_r_id_i, + input data_t axi_r_data_i, + input axi_pkg::resp_t axi_r_resp_i, + input logic axi_r_last_i, + input user_t axi_r_user_i, + input logic axi_r_valid_i, + output logic axi_r_ready_o, output id_t axi_aw_id_o, @@ -11474,20 +9397,9 @@ module idma_backend_synth_r_obi_w_axi #( `AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - // OBI typedefs -`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) -`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) - -`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) -`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) - -`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) -`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) - - // Meta Channel Widths localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); /// Option struct: AXI4 id as well as AXI and backend options /// - `last`: a flag can be set if this transfer is the last of a set of transfers @@ -11513,11 +9425,11 @@ module idma_backend_synth_r_obi_w_axi #( typedef struct packed { - obi_a_chan_t a_chan; - } obi_read_meta_channel_t; + axi_ar_chan_t ar_chan; + } axi_read_meta_channel_t; typedef struct packed { - obi_read_meta_channel_t obi; + axi_read_meta_channel_t axi; } read_meta_channel_t; typedef struct packed { @@ -11530,19 +9442,16 @@ module idma_backend_synth_r_obi_w_axi #( // local types // AXI4+ATOP request and response + axi_req_t axi_read_req; + axi_rsp_t axi_read_rsp; axi_req_t axi_write_req; axi_rsp_t axi_write_rsp; - // OBI request and response - obi_req_t obi_read_req; - obi_rsp_t obi_read_rsp; - - idma_req_t idma_req; idma_rsp_t idma_rsp; - idma_backend_r_obi_w_axi #( + idma_backend_rw_axi #( .CombinedShifter ( CombinedShifter ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), @@ -11563,8 +9472,6 @@ module idma_backend_synth_r_obi_w_axi #( .idma_busy_t ( idma_pkg::idma_busy_t ), .axi_req_t ( axi_req_t ), .axi_rsp_t ( axi_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ), .write_meta_channel_t ( write_meta_channel_t ), .read_meta_channel_t ( read_meta_channel_t ) ) i_idma_backend ( @@ -11580,8 +9487,8 @@ module idma_backend_synth_r_obi_w_axi #( .idma_eh_req_i ( eh_req_i ), .eh_req_valid_i ( eh_req_valid_i ), .eh_req_ready_o ( eh_req_ready_o ), - .obi_read_req_o ( obi_read_req ), - .obi_read_rsp_i ( obi_read_rsp ), + .axi_read_req_o ( axi_read_req ), + .axi_read_rsp_i ( axi_read_rsp ), .axi_write_req_o ( axi_write_req ), .axi_write_rsp_i ( axi_write_rsp ), .busy_o ( idma_busy_o ) @@ -11621,19 +9528,28 @@ module idma_backend_synth_r_obi_w_axi #( assign rsp_last_o = idma_rsp.last; - // OBI Read - assign obi_read_req_a_req_o = obi_read_req.req; - assign obi_read_req_a_addr_o = obi_read_req.a.addr; - assign obi_read_req_a_we_o = obi_read_req.a.we; - assign obi_read_req_a_be_o = obi_read_req.a.be; - assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; - assign obi_read_req_r_ready_o = obi_read_req.rready; + // AXI4+ATOP Read + assign axi_ar_id_o = axi_read_req.ar.id; + assign axi_ar_addr_o = axi_read_req.ar.addr; + assign axi_ar_len_o = axi_read_req.ar.len; + assign axi_ar_size_o = axi_read_req.ar.size; + assign axi_ar_burst_o = axi_read_req.ar.burst; + assign axi_ar_lock_o = axi_read_req.ar.lock; + assign axi_ar_cache_o = axi_read_req.ar.cache; + assign axi_ar_prot_o = axi_read_req.ar.prot; + assign axi_ar_qos_o = axi_read_req.ar.qos; + assign axi_ar_region_o = axi_read_req.ar.region; + assign axi_ar_user_o = axi_read_req.ar.user; + assign axi_ar_valid_o = axi_read_req.ar_valid; + assign axi_r_ready_o = axi_read_req.r_ready; - assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; - assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; - assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; - assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; - assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; + assign axi_read_rsp.ar_ready = axi_ar_ready_i; + assign axi_read_rsp.r.id = axi_r_id_i; + assign axi_read_rsp.r.data = axi_r_data_i; + assign axi_read_rsp.r.resp = axi_r_resp_i; + assign axi_read_rsp.r.last = axi_r_last_i; + assign axi_read_rsp.r.user = axi_r_user_i; + assign axi_read_rsp.r_valid = axi_r_valid_i; @@ -11684,7 +9600,7 @@ endmodule `include "tilelink/typedef.svh" /// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_r_axi_w_obi #( +module idma_backend_synth_r_obi_w_axi #( /// Data width parameter int unsigned DataWidth = 32'd32, /// Address width @@ -11785,39 +9701,45 @@ module idma_backend_synth_r_axi_w_obi #( output logic eh_req_ready_o, input idma_pkg::idma_eh_req_t eh_req_i, - output id_t axi_ar_id_o, - output addr_t axi_ar_addr_o, - output axi_pkg::len_t axi_ar_len_o, - output axi_pkg::size_t axi_ar_size_o, - output axi_pkg::burst_t axi_ar_burst_o, - output logic axi_ar_lock_o, - output axi_pkg::cache_t axi_ar_cache_o, - output axi_pkg::prot_t axi_ar_prot_o, - output axi_pkg::qos_t axi_ar_qos_o, - output axi_pkg::region_t axi_ar_region_o, - output user_t axi_ar_user_o, - output logic axi_ar_valid_o, - input logic axi_ar_ready_i, - input id_t axi_r_id_i, - input data_t axi_r_data_i, - input axi_pkg::resp_t axi_r_resp_i, - input logic axi_r_last_i, - input user_t axi_r_user_i, - input logic axi_r_valid_i, - output logic axi_r_ready_o, + output logic obi_read_req_a_req_o, + output addr_t obi_read_req_a_addr_o, + output logic obi_read_req_a_we_o, + output strb_t obi_read_req_a_be_o, + output data_t obi_read_req_a_wdata_o, + output logic obi_read_req_r_ready_o, - - output logic obi_write_req_a_req_o, - output addr_t obi_write_req_a_addr_o, - output logic obi_write_req_a_we_o, - output strb_t obi_write_req_a_be_o, - output data_t obi_write_req_a_wdata_o, - output id_t obi_write_req_a_aid_o, - output logic obi_write_req_r_ready_o, + input logic obi_read_rsp_a_gnt_i, + input logic obi_read_rsp_r_valid_i, + input data_t obi_read_rsp_r_rdata_i, + input id_t obi_read_rsp_r_rid_i, + input logic obi_read_rsp_r_err_i, - input logic obi_write_rsp_a_gnt_i, - input logic obi_write_rsp_r_valid_i, - input data_t obi_write_rsp_r_rdata_i, + + output id_t axi_aw_id_o, + output addr_t axi_aw_addr_o, + output axi_pkg::len_t axi_aw_len_o, + output axi_pkg::size_t axi_aw_size_o, + output axi_pkg::burst_t axi_aw_burst_o, + output logic axi_aw_lock_o, + output axi_pkg::cache_t axi_aw_cache_o, + output axi_pkg::prot_t axi_aw_prot_o, + output axi_pkg::qos_t axi_aw_qos_o, + output axi_pkg::region_t axi_aw_region_o, + output axi_pkg::atop_t axi_aw_atop_o, + output user_t axi_aw_user_o, + output logic axi_aw_valid_o, + input logic axi_aw_ready_i, + output data_t axi_w_data_o, + output strb_t axi_w_strb_o, + output logic axi_w_last_o, + output user_t axi_w_user_o, + output logic axi_w_valid_o, + input logic axi_w_ready_i, + input id_t axi_b_id_i, + input axi_pkg::resp_t axi_b_resp_i, + input user_t axi_b_user_i, + input logic axi_b_valid_i, + output logic axi_b_ready_o, output idma_pkg::idma_busy_t idma_busy_o @@ -11851,7 +9773,7 @@ module idma_backend_synth_r_axi_w_obi #( // Meta Channel Widths - localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); + localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); /// Option struct: AXI4 id as well as AXI and backend options @@ -11878,36 +9800,36 @@ module idma_backend_synth_r_axi_w_obi #( typedef struct packed { - axi_ar_chan_t ar_chan; - } axi_read_meta_channel_t; + obi_a_chan_t a_chan; + } obi_read_meta_channel_t; typedef struct packed { - axi_read_meta_channel_t axi; + obi_read_meta_channel_t obi; } read_meta_channel_t; typedef struct packed { - obi_a_chan_t a_chan; - } obi_write_meta_channel_t; + axi_aw_chan_t aw_chan; + } axi_write_meta_channel_t; typedef struct packed { - obi_write_meta_channel_t obi; + axi_write_meta_channel_t axi; } write_meta_channel_t; // local types // AXI4+ATOP request and response - axi_req_t axi_read_req; - axi_rsp_t axi_read_rsp; + axi_req_t axi_write_req; + axi_rsp_t axi_write_rsp; // OBI request and response + obi_req_t obi_read_req; + obi_rsp_t obi_read_rsp; - obi_req_t obi_write_req; - obi_rsp_t obi_write_rsp; idma_req_t idma_req; idma_rsp_t idma_rsp; - idma_backend_r_axi_w_obi #( + idma_backend_r_obi_w_axi #( .CombinedShifter ( CombinedShifter ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), @@ -11945,10 +9867,10 @@ module idma_backend_synth_r_axi_w_obi #( .idma_eh_req_i ( eh_req_i ), .eh_req_valid_i ( eh_req_valid_i ), .eh_req_ready_o ( eh_req_ready_o ), - .axi_read_req_o ( axi_read_req ), - .axi_read_rsp_i ( axi_read_rsp ), - .obi_write_req_o ( obi_write_req ), - .obi_write_rsp_i ( obi_write_rsp ), + .obi_read_req_o ( obi_read_req ), + .obi_read_rsp_i ( obi_read_rsp ), + .axi_write_req_o ( axi_write_req ), + .axi_write_rsp_i ( axi_write_rsp ), .busy_o ( idma_busy_o ) ); @@ -11986,43 +9908,49 @@ module idma_backend_synth_r_axi_w_obi #( assign rsp_last_o = idma_rsp.last; - // AXI4+ATOP Read - assign axi_ar_id_o = axi_read_req.ar.id; - assign axi_ar_addr_o = axi_read_req.ar.addr; - assign axi_ar_len_o = axi_read_req.ar.len; - assign axi_ar_size_o = axi_read_req.ar.size; - assign axi_ar_burst_o = axi_read_req.ar.burst; - assign axi_ar_lock_o = axi_read_req.ar.lock; - assign axi_ar_cache_o = axi_read_req.ar.cache; - assign axi_ar_prot_o = axi_read_req.ar.prot; - assign axi_ar_qos_o = axi_read_req.ar.qos; - assign axi_ar_region_o = axi_read_req.ar.region; - assign axi_ar_user_o = axi_read_req.ar.user; - assign axi_ar_valid_o = axi_read_req.ar_valid; - assign axi_r_ready_o = axi_read_req.r_ready; + // OBI Read + assign obi_read_req_a_req_o = obi_read_req.req; + assign obi_read_req_a_addr_o = obi_read_req.a.addr; + assign obi_read_req_a_we_o = obi_read_req.a.we; + assign obi_read_req_a_be_o = obi_read_req.a.be; + assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; + assign obi_read_req_r_ready_o = obi_read_req.rready; - assign axi_read_rsp.ar_ready = axi_ar_ready_i; - assign axi_read_rsp.r.id = axi_r_id_i; - assign axi_read_rsp.r.data = axi_r_data_i; - assign axi_read_rsp.r.resp = axi_r_resp_i; - assign axi_read_rsp.r.last = axi_r_last_i; - assign axi_read_rsp.r.user = axi_r_user_i; - assign axi_read_rsp.r_valid = axi_r_valid_i; + assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; + assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; + assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; + assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; + assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; - // OBI Write - assign obi_write_req_a_req_o = obi_write_req.req; - assign obi_write_req_a_addr_o = obi_write_req.a.addr; - assign obi_write_req_a_we_o = obi_write_req.a.we; - assign obi_write_req_a_be_o = obi_write_req.a.be; - assign obi_write_req_a_wdata_o = obi_write_req.a.wdata; - assign obi_write_req_a_aid_o = obi_write_req.a.aid; - assign obi_write_req_r_ready_o = obi_write_req.rready; + // AXI4+ATOP Write + assign axi_aw_id_o = axi_write_req.aw.id; + assign axi_aw_addr_o = axi_write_req.aw.addr; + assign axi_aw_len_o = axi_write_req.aw.len; + assign axi_aw_size_o = axi_write_req.aw.size; + assign axi_aw_burst_o = axi_write_req.aw.burst; + assign axi_aw_lock_o = axi_write_req.aw.lock; + assign axi_aw_cache_o = axi_write_req.aw.cache; + assign axi_aw_prot_o = axi_write_req.aw.prot; + assign axi_aw_qos_o = axi_write_req.aw.qos; + assign axi_aw_region_o = axi_write_req.aw.region; + assign axi_aw_atop_o = axi_write_req.aw.atop; + assign axi_aw_user_o = axi_write_req.aw.user; + assign axi_aw_valid_o = axi_write_req.aw_valid; + assign axi_w_data_o = axi_write_req.w.data; + assign axi_w_strb_o = axi_write_req.w.strb; + assign axi_w_last_o = axi_write_req.w.last; + assign axi_w_user_o = axi_write_req.w.user; + assign axi_w_valid_o = axi_write_req.w_valid; + assign axi_b_ready_o = axi_write_req.b_ready; - assign obi_write_rsp.gnt = obi_write_rsp_a_gnt_i; - assign obi_write_rsp.rvalid = obi_write_rsp_r_valid_i; - assign obi_write_rsp.r.rdata = obi_write_rsp_r_rdata_i; + assign axi_write_rsp.aw_ready = axi_aw_ready_i; + assign axi_write_rsp.w_ready = axi_w_ready_i; + assign axi_write_rsp.b.id = axi_b_id_i; + assign axi_write_rsp.b.resp = axi_b_resp_i; + assign axi_write_rsp.b.user = axi_b_user_i; + assign axi_write_rsp.b_valid = axi_b_valid_i; @@ -12043,7 +9971,7 @@ endmodule `include "tilelink/typedef.svh" /// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_rw_axi_rw_axis #( +module idma_backend_synth_r_axi_w_obi #( /// Data width parameter int unsigned DataWidth = 32'd32, /// Address width @@ -12166,55 +10094,17 @@ module idma_backend_synth_rw_axi_rw_axis #( output logic axi_r_ready_o, - input data_t axis_read_data_i, - input strb_t axis_read_strb_i, - input strb_t axis_read_keep_i, - input logic axis_read_last_i, - input id_t axis_read_id_i, - input id_t axis_read_dest_i, - input user_t axis_read_user_i, - input logic axis_read_tvalid_i, - - output logic axis_read_tready_o, - - - output id_t axi_aw_id_o, - output addr_t axi_aw_addr_o, - output axi_pkg::len_t axi_aw_len_o, - output axi_pkg::size_t axi_aw_size_o, - output axi_pkg::burst_t axi_aw_burst_o, - output logic axi_aw_lock_o, - output axi_pkg::cache_t axi_aw_cache_o, - output axi_pkg::prot_t axi_aw_prot_o, - output axi_pkg::qos_t axi_aw_qos_o, - output axi_pkg::region_t axi_aw_region_o, - output axi_pkg::atop_t axi_aw_atop_o, - output user_t axi_aw_user_o, - output logic axi_aw_valid_o, - input logic axi_aw_ready_i, - output data_t axi_w_data_o, - output strb_t axi_w_strb_o, - output logic axi_w_last_o, - output user_t axi_w_user_o, - output logic axi_w_valid_o, - input logic axi_w_ready_i, - input id_t axi_b_id_i, - input axi_pkg::resp_t axi_b_resp_i, - input user_t axi_b_user_i, - input logic axi_b_valid_i, - output logic axi_b_ready_o, - - - output data_t axis_write_data_o, - output strb_t axis_write_strb_o, - output strb_t axis_write_keep_o, - output logic axis_write_last_o, - output id_t axis_write_id_o, - output id_t axis_write_dest_o, - output user_t axis_write_user_o, - output logic axis_write_tvalid_o, + output logic obi_write_req_a_req_o, + output addr_t obi_write_req_a_addr_o, + output logic obi_write_req_a_we_o, + output strb_t obi_write_req_a_be_o, + output data_t obi_write_req_a_wdata_o, + output id_t obi_write_req_a_aid_o, + output logic obi_write_req_r_ready_o, - input logic axis_write_tready_i, + input logic obi_write_rsp_a_gnt_i, + input logic obi_write_rsp_r_valid_i, + input data_t obi_write_rsp_r_rdata_i, output idma_pkg::idma_busy_t idma_busy_o @@ -12236,17 +10126,20 @@ module idma_backend_synth_rw_axi_rw_axis #( `AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - // AXI Stream typedefs -`AXI_STREAM_TYPEDEF_S_CHAN_T(axis_t_chan_t, data_t, strb_t, strb_t, id_t, id_t, user_t) + // OBI typedefs +`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) +`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) -`AXI_STREAM_TYPEDEF_REQ_T(axis_req_t, axis_t_chan_t) -`AXI_STREAM_TYPEDEF_RSP_T(axis_rsp_t) +`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) +`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + +`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) +`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) // Meta Channel Widths - localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned axis_t_chan_width = $bits(axis_t_chan_t); + localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); /// Option struct: AXI4 id as well as AXI and backend options /// - `last`: a flag can be set if this transfer is the last of a set of transfers @@ -12270,38 +10163,21 @@ module idma_backend_synth_rw_axi_rw_axis #( /// - `pld`: the error payload `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) - function int unsigned max_width(input int unsigned a, b); - return (a > b) ? a : b; - endfunction typedef struct packed { axi_ar_chan_t ar_chan; - logic[max_width(axi_ar_chan_width, axis_t_chan_width)-axi_ar_chan_width:0] padding; - } axi_read_ar_chan_padded_t; - - typedef struct packed { - axis_t_chan_t t_chan; - logic[max_width(axi_ar_chan_width, axis_t_chan_width)-axis_t_chan_width:0] padding; - } axis_read_t_chan_padded_t; + } axi_read_meta_channel_t; - typedef union packed { - axi_read_ar_chan_padded_t axi; - axis_read_t_chan_padded_t axis; + typedef struct packed { + axi_read_meta_channel_t axi; } read_meta_channel_t; typedef struct packed { - axi_aw_chan_t aw_chan; - logic[max_width(axi_aw_chan_width, axis_t_chan_width)-axi_aw_chan_width:0] padding; - } axi_write_aw_chan_padded_t; + obi_a_chan_t a_chan; + } obi_write_meta_channel_t; typedef struct packed { - axis_t_chan_t t_chan; - logic[max_width(axi_aw_chan_width, axis_t_chan_width)-axis_t_chan_width:0] padding; - } axis_write_t_chan_padded_t; - - typedef union packed { - axi_write_aw_chan_padded_t axi; - axis_write_t_chan_padded_t axis; + obi_write_meta_channel_t obi; } write_meta_channel_t; // local types @@ -12309,20 +10185,16 @@ module idma_backend_synth_rw_axi_rw_axis #( axi_req_t axi_read_req; axi_rsp_t axi_read_rsp; - axi_req_t axi_write_req; - axi_rsp_t axi_write_rsp; - // AXI Stream request and response - axis_req_t axis_read_req; - axis_rsp_t axis_read_rsp; + // OBI request and response - axis_req_t axis_write_req; - axis_rsp_t axis_write_rsp; + obi_req_t obi_write_req; + obi_rsp_t obi_write_rsp; idma_req_t idma_req; idma_rsp_t idma_rsp; - idma_backend_rw_axi_rw_axis #( + idma_backend_r_axi_w_obi #( .CombinedShifter ( CombinedShifter ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), @@ -12343,8 +10215,8 @@ module idma_backend_synth_rw_axi_rw_axis #( .idma_busy_t ( idma_pkg::idma_busy_t ), .axi_req_t ( axi_req_t ), .axi_rsp_t ( axi_rsp_t ), - .axis_req_t ( axis_req_t ), - .axis_rsp_t ( axis_rsp_t ), + .obi_req_t ( obi_req_t ), + .obi_rsp_t ( obi_rsp_t ), .write_meta_channel_t ( write_meta_channel_t ), .read_meta_channel_t ( read_meta_channel_t ) ) i_idma_backend ( @@ -12362,12 +10234,8 @@ module idma_backend_synth_rw_axi_rw_axis #( .eh_req_ready_o ( eh_req_ready_o ), .axi_read_req_o ( axi_read_req ), .axi_read_rsp_i ( axi_read_rsp ), - .axis_read_req_i ( axis_read_req ), - .axis_read_rsp_o ( axis_read_rsp ), - .axi_write_req_o ( axi_write_req ), - .axi_write_rsp_i ( axi_write_rsp ), - .axis_write_req_o ( axis_write_req ), - .axis_write_rsp_i ( axis_write_rsp ), + .obi_write_req_o ( obi_write_req ), + .obi_write_rsp_i ( obi_write_rsp ), .busy_o ( idma_busy_o ) ); @@ -12430,61 +10298,18 @@ module idma_backend_synth_rw_axi_rw_axis #( - // AXI Stream Read - assign axis_read_req.t.data = axis_read_data_i; - assign axis_read_req.t.strb = axis_read_strb_i; - assign axis_read_req.t.keep = axis_read_keep_i; - assign axis_read_req.t.last = axis_read_last_i; - assign axis_read_req.t.id = axis_read_id_i; - assign axis_read_req.t.dest = axis_read_dest_i; - assign axis_read_req.t.user = axis_read_user_i; - assign axis_read_req.tvalid = axis_read_tvalid_i; - - assign axis_read_tready_o = axis_read_rsp.tready; - - - - // AXI4+ATOP Write - assign axi_aw_id_o = axi_write_req.aw.id; - assign axi_aw_addr_o = axi_write_req.aw.addr; - assign axi_aw_len_o = axi_write_req.aw.len; - assign axi_aw_size_o = axi_write_req.aw.size; - assign axi_aw_burst_o = axi_write_req.aw.burst; - assign axi_aw_lock_o = axi_write_req.aw.lock; - assign axi_aw_cache_o = axi_write_req.aw.cache; - assign axi_aw_prot_o = axi_write_req.aw.prot; - assign axi_aw_qos_o = axi_write_req.aw.qos; - assign axi_aw_region_o = axi_write_req.aw.region; - assign axi_aw_atop_o = axi_write_req.aw.atop; - assign axi_aw_user_o = axi_write_req.aw.user; - assign axi_aw_valid_o = axi_write_req.aw_valid; - assign axi_w_data_o = axi_write_req.w.data; - assign axi_w_strb_o = axi_write_req.w.strb; - assign axi_w_last_o = axi_write_req.w.last; - assign axi_w_user_o = axi_write_req.w.user; - assign axi_w_valid_o = axi_write_req.w_valid; - assign axi_b_ready_o = axi_write_req.b_ready; - - assign axi_write_rsp.aw_ready = axi_aw_ready_i; - assign axi_write_rsp.w_ready = axi_w_ready_i; - assign axi_write_rsp.b.id = axi_b_id_i; - assign axi_write_rsp.b.resp = axi_b_resp_i; - assign axi_write_rsp.b.user = axi_b_user_i; - assign axi_write_rsp.b_valid = axi_b_valid_i; - - - - // AXI Stream Write - assign axis_write_data_o = axis_write_req.t.data; - assign axis_write_strb_o = axis_write_req.t.strb; - assign axis_write_keep_o = axis_write_req.t.keep; - assign axis_write_last_o = axis_write_req.t.last; - assign axis_write_id_o = axis_write_req.t.id; - assign axis_write_dest_o = axis_write_req.t.dest; - assign axis_write_user_o = axis_write_req.t.user; - assign axis_write_tvalid_o = axis_write_req.tvalid; + // OBI Write + assign obi_write_req_a_req_o = obi_write_req.req; + assign obi_write_req_a_addr_o = obi_write_req.a.addr; + assign obi_write_req_a_we_o = obi_write_req.a.we; + assign obi_write_req_a_be_o = obi_write_req.a.be; + assign obi_write_req_a_wdata_o = obi_write_req.a.wdata; + assign obi_write_req_a_aid_o = obi_write_req.a.aid; + assign obi_write_req_r_ready_o = obi_write_req.rready; - assign axis_write_rsp.tready = axis_write_tready_i; + assign obi_write_rsp.gnt = obi_write_rsp_a_gnt_i; + assign obi_write_rsp.rvalid = obi_write_rsp_r_valid_i; + assign obi_write_rsp.r.rdata = obi_write_rsp_r_rdata_i; @@ -12505,7 +10330,7 @@ endmodule `include "tilelink/typedef.svh" /// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_rw_axi_rw_obi #( +module idma_backend_synth_rw_axi_rw_axis #( /// Data width parameter int unsigned DataWidth = 32'd32, /// Address width @@ -12628,18 +10453,16 @@ module idma_backend_synth_rw_axi_rw_obi #( output logic axi_r_ready_o, - output logic obi_read_req_a_req_o, - output addr_t obi_read_req_a_addr_o, - output logic obi_read_req_a_we_o, - output strb_t obi_read_req_a_be_o, - output data_t obi_read_req_a_wdata_o, - output logic obi_read_req_r_ready_o, + input data_t axis_read_data_i, + input strb_t axis_read_strb_i, + input strb_t axis_read_keep_i, + input logic axis_read_last_i, + input id_t axis_read_id_i, + input id_t axis_read_dest_i, + input user_t axis_read_user_i, + input logic axis_read_tvalid_i, - input logic obi_read_rsp_a_gnt_i, - input logic obi_read_rsp_r_valid_i, - input data_t obi_read_rsp_r_rdata_i, - input id_t obi_read_rsp_r_rid_i, - input logic obi_read_rsp_r_err_i, + output logic axis_read_tready_o, output id_t axi_aw_id_o, @@ -12669,17 +10492,16 @@ module idma_backend_synth_rw_axi_rw_obi #( output logic axi_b_ready_o, - output logic obi_write_req_a_req_o, - output addr_t obi_write_req_a_addr_o, - output logic obi_write_req_a_we_o, - output strb_t obi_write_req_a_be_o, - output data_t obi_write_req_a_wdata_o, - output id_t obi_write_req_a_aid_o, - output logic obi_write_req_r_ready_o, + output data_t axis_write_data_o, + output strb_t axis_write_strb_o, + output strb_t axis_write_keep_o, + output logic axis_write_last_o, + output id_t axis_write_id_o, + output id_t axis_write_dest_o, + output user_t axis_write_user_o, + output logic axis_write_tvalid_o, - input logic obi_write_rsp_a_gnt_i, - input logic obi_write_rsp_r_valid_i, - input data_t obi_write_rsp_r_rdata_i, + input logic axis_write_tready_i, output idma_pkg::idma_busy_t idma_busy_o @@ -12701,21 +10523,17 @@ module idma_backend_synth_rw_axi_rw_obi #( `AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - // OBI typedefs -`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) -`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) - -`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) -`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) + // AXI Stream typedefs +`AXI_STREAM_TYPEDEF_S_CHAN_T(axis_t_chan_t, data_t, strb_t, strb_t, id_t, id_t, user_t) -`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) -`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) +`AXI_STREAM_TYPEDEF_REQ_T(axis_req_t, axis_t_chan_t) +`AXI_STREAM_TYPEDEF_RSP_T(axis_rsp_t) // Meta Channel Widths localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); + localparam int unsigned axis_t_chan_width = $bits(axis_t_chan_t); /// Option struct: AXI4 id as well as AXI and backend options /// - `last`: a flag can be set if this transfer is the last of a set of transfers @@ -12745,32 +10563,32 @@ module idma_backend_synth_rw_axi_rw_obi #( typedef struct packed { axi_ar_chan_t ar_chan; - logic[max_width(axi_ar_chan_width, obi_a_chan_width)-axi_ar_chan_width:0] padding; + logic[max_width(axi_ar_chan_width, axis_t_chan_width)-axi_ar_chan_width:0] padding; } axi_read_ar_chan_padded_t; typedef struct packed { - obi_a_chan_t a_chan; - logic[max_width(axi_ar_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; - } obi_read_a_chan_padded_t; + axis_t_chan_t t_chan; + logic[max_width(axi_ar_chan_width, axis_t_chan_width)-axis_t_chan_width:0] padding; + } axis_read_t_chan_padded_t; typedef union packed { axi_read_ar_chan_padded_t axi; - obi_read_a_chan_padded_t obi; + axis_read_t_chan_padded_t axis; } read_meta_channel_t; typedef struct packed { axi_aw_chan_t aw_chan; - logic[max_width(axi_aw_chan_width, obi_a_chan_width)-axi_aw_chan_width:0] padding; + logic[max_width(axi_aw_chan_width, axis_t_chan_width)-axi_aw_chan_width:0] padding; } axi_write_aw_chan_padded_t; typedef struct packed { - obi_a_chan_t a_chan; - logic[max_width(axi_aw_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; - } obi_write_a_chan_padded_t; + axis_t_chan_t t_chan; + logic[max_width(axi_aw_chan_width, axis_t_chan_width)-axis_t_chan_width:0] padding; + } axis_write_t_chan_padded_t; typedef union packed { axi_write_aw_chan_padded_t axi; - obi_write_a_chan_padded_t obi; + axis_write_t_chan_padded_t axis; } write_meta_channel_t; // local types @@ -12781,17 +10599,17 @@ module idma_backend_synth_rw_axi_rw_obi #( axi_req_t axi_write_req; axi_rsp_t axi_write_rsp; - // OBI request and response - obi_req_t obi_read_req; - obi_rsp_t obi_read_rsp; + // AXI Stream request and response + axis_req_t axis_read_req; + axis_rsp_t axis_read_rsp; - obi_req_t obi_write_req; - obi_rsp_t obi_write_rsp; + axis_req_t axis_write_req; + axis_rsp_t axis_write_rsp; idma_req_t idma_req; idma_rsp_t idma_rsp; - idma_backend_rw_axi_rw_obi #( + idma_backend_rw_axi_rw_axis #( .CombinedShifter ( CombinedShifter ), .DataWidth ( DataWidth ), .AddrWidth ( AddrWidth ), @@ -12812,8 +10630,8 @@ module idma_backend_synth_rw_axi_rw_obi #( .idma_busy_t ( idma_pkg::idma_busy_t ), .axi_req_t ( axi_req_t ), .axi_rsp_t ( axi_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ), + .axis_req_t ( axis_req_t ), + .axis_rsp_t ( axis_rsp_t ), .write_meta_channel_t ( write_meta_channel_t ), .read_meta_channel_t ( read_meta_channel_t ) ) i_idma_backend ( @@ -12831,12 +10649,12 @@ module idma_backend_synth_rw_axi_rw_obi #( .eh_req_ready_o ( eh_req_ready_o ), .axi_read_req_o ( axi_read_req ), .axi_read_rsp_i ( axi_read_rsp ), - .obi_read_req_o ( obi_read_req ), - .obi_read_rsp_i ( obi_read_rsp ), + .axis_read_req_i ( axis_read_req ), + .axis_read_rsp_o ( axis_read_rsp ), .axi_write_req_o ( axi_write_req ), .axi_write_rsp_i ( axi_write_rsp ), - .obi_write_req_o ( obi_write_req ), - .obi_write_rsp_i ( obi_write_rsp ), + .axis_write_req_o ( axis_write_req ), + .axis_write_rsp_i ( axis_write_rsp ), .busy_o ( idma_busy_o ) ); @@ -12899,19 +10717,17 @@ module idma_backend_synth_rw_axi_rw_obi #( - // OBI Read - assign obi_read_req_a_req_o = obi_read_req.req; - assign obi_read_req_a_addr_o = obi_read_req.a.addr; - assign obi_read_req_a_we_o = obi_read_req.a.we; - assign obi_read_req_a_be_o = obi_read_req.a.be; - assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; - assign obi_read_req_r_ready_o = obi_read_req.rready; + // AXI Stream Read + assign axis_read_req.t.data = axis_read_data_i; + assign axis_read_req.t.strb = axis_read_strb_i; + assign axis_read_req.t.keep = axis_read_keep_i; + assign axis_read_req.t.last = axis_read_last_i; + assign axis_read_req.t.id = axis_read_id_i; + assign axis_read_req.t.dest = axis_read_dest_i; + assign axis_read_req.t.user = axis_read_user_i; + assign axis_read_req.tvalid = axis_read_tvalid_i; - assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; - assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; - assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; - assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; - assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; + assign axis_read_tready_o = axis_read_rsp.tready; @@ -12945,18 +10761,17 @@ module idma_backend_synth_rw_axi_rw_obi #( - // OBI Write - assign obi_write_req_a_req_o = obi_write_req.req; - assign obi_write_req_a_addr_o = obi_write_req.a.addr; - assign obi_write_req_a_we_o = obi_write_req.a.we; - assign obi_write_req_a_be_o = obi_write_req.a.be; - assign obi_write_req_a_wdata_o = obi_write_req.a.wdata; - assign obi_write_req_a_aid_o = obi_write_req.a.aid; - assign obi_write_req_r_ready_o = obi_write_req.rready; + // AXI Stream Write + assign axis_write_data_o = axis_write_req.t.data; + assign axis_write_strb_o = axis_write_req.t.strb; + assign axis_write_keep_o = axis_write_req.t.keep; + assign axis_write_last_o = axis_write_req.t.last; + assign axis_write_id_o = axis_write_req.t.id; + assign axis_write_dest_o = axis_write_req.t.dest; + assign axis_write_user_o = axis_write_req.t.user; + assign axis_write_tvalid_o = axis_write_req.tvalid; - assign obi_write_rsp.gnt = obi_write_rsp_a_gnt_i; - assign obi_write_rsp.rvalid = obi_write_rsp_r_valid_i; - assign obi_write_rsp.r.rdata = obi_write_rsp_r_rdata_i; + assign axis_write_rsp.tready = axis_write_tready_i; @@ -21602,6 +19417,17 @@ module idma_reg32_3d #( // register signals reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; + always_comb begin + stream_idx_o = '0; + for (int r = 0; r < NumRegs; r++) begin + for (int c = 0; c < NumStreams; c++) begin + if (dma_reg2hw[r].next_id[c].re) begin + stream_idx_o = c; + end + end + end + end + // generate the registers for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs @@ -21629,12 +19455,8 @@ module idma_reg32_3d #( logic read_happens; always_comb begin : proc_launch read_happens = 1'b0; - stream_idx_o = '0; for (int c = 0; c < NumStreams; c++) begin read_happens |= dma_reg2hw[i].next_id[c].re; - if (dma_reg2hw[i].next_id[c].re) begin - stream_idx_o = c; - end end arb_valid[i] = read_happens; end @@ -21650,8 +19472,8 @@ module idma_reg32_3d #( arb_dma_req[i].burst_req.dst_addr = dma_reg2hw[i].dst_addr_low.q; // Protocols - arb_dma_req[i].burst_req.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); - arb_dma_req[i].burst_req.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); + arb_dma_req[i].burst_req.opt.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); + arb_dma_req[i].burst_req.opt.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); // Current backend only supports incremental burst arb_dma_req[i].burst_req.opt.src.burst = axi_pkg::BURST_INCR; @@ -21787,6 +19609,17 @@ module idma_reg64_2d #( // register signals reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; + always_comb begin + stream_idx_o = '0; + for (int r = 0; r < NumRegs; r++) begin + for (int c = 0; c < NumStreams; c++) begin + if (dma_reg2hw[r].next_id[c].re) begin + stream_idx_o = c; + end + end + end + end + // generate the registers for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs @@ -21814,12 +19647,8 @@ module idma_reg64_2d #( logic read_happens; always_comb begin : proc_launch read_happens = 1'b0; - stream_idx_o = '0; for (int c = 0; c < NumStreams; c++) begin read_happens |= dma_reg2hw[i].next_id[c].re; - if (dma_reg2hw[i].next_id[c].re) begin - stream_idx_o = c; - end end arb_valid[i] = read_happens; end @@ -21835,8 +19664,8 @@ module idma_reg64_2d #( arb_dma_req[i].burst_req.dst_addr = {dma_reg2hw[i].dst_addr_high.q, dma_reg2hw[i].dst_addr_low.q}; // Protocols - arb_dma_req[i].burst_req.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); - arb_dma_req[i].burst_req.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); + arb_dma_req[i].burst_req.opt.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); + arb_dma_req[i].burst_req.opt.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); // Current backend only supports incremental burst arb_dma_req[i].burst_req.opt.src.burst = axi_pkg::BURST_INCR; @@ -21968,6 +19797,17 @@ module idma_reg64_1d #( // register signals reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; + always_comb begin + stream_idx_o = '0; + for (int r = 0; r < NumRegs; r++) begin + for (int c = 0; c < NumStreams; c++) begin + if (dma_reg2hw[r].next_id[c].re) begin + stream_idx_o = c; + end + end + end + end + // generate the registers for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs @@ -21995,12 +19835,8 @@ module idma_reg64_1d #( logic read_happens; always_comb begin : proc_launch read_happens = 1'b0; - stream_idx_o = '0; for (int c = 0; c < NumStreams; c++) begin read_happens |= dma_reg2hw[i].next_id[c].re; - if (dma_reg2hw[i].next_id[c].re) begin - stream_idx_o = c; - end end arb_valid[i] = read_happens; end @@ -22016,8 +19852,8 @@ module idma_reg64_1d #( arb_dma_req[i].dst_addr = {dma_reg2hw[i].dst_addr_high.q, dma_reg2hw[i].dst_addr_low.q}; // Protocols - arb_dma_req[i].src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); - arb_dma_req[i].dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); + arb_dma_req[i].opt.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); + arb_dma_req[i].opt.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); // Current backend only supports incremental burst arb_dma_req[i].opt.src.burst = axi_pkg::BURST_INCR; From 87372fa185df34edcd0fcf9937439a4d454151fc Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Thu, 27 Jun 2024 15:11:34 +0200 Subject: [PATCH 08/13] change tagged meta req assignment to always_comb bc of vopt issues --- src/backend/tpl/idma_backend.sv.tpl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/backend/tpl/idma_backend.sv.tpl b/src/backend/tpl/idma_backend.sv.tpl index d50d5cd1..29e46a6c 100644 --- a/src/backend/tpl/idma_backend.sv.tpl +++ b/src/backend/tpl/idma_backend.sv.tpl @@ -628,10 +628,10 @@ _rsp_t ${protocol}_write_rsp_i, // Add fall-through register to allow the input to be ready if the output is not. This // does not add a cycle of delay % if not one_read_port: - assign r_meta_req_tagged = '{ - src_protocol: r_req.r_dp_req.src_protocol, - ar_req: r_req.ar_req - }; + always_comb begin : assign_r_meta_req + r_meta_req_tagged.src_protocol = r_req.r_dp_req.src_protocol; + r_meta_req_tagged.ar_req = r_req.ar_req; + end % endif fall_through_register #( @@ -776,10 +776,10 @@ _rsp_t ${protocol}_write_rsp_i, // R-AW channel coupler //-------------------------------------- % if not one_write_port: - assign w_meta_req_tagged = '{ - dst_protocol: w_req.w_dp_req.dst_protocol, - aw_req: w_req.aw_req - }; + always_comb begin : assign_tagged_w_req // need to have an always_comb block for Questa to not crap itself + w_meta_req_tagged.dst_protocol = w_req.w_dp_req.dst_protocol; + w_meta_req_tagged.aw_req = w_req.aw_req; + end % endif if (RAWCouplingAvail) begin : gen_r_aw_coupler From 5dd0061a5947f98e53b48bc7ae6fa95db1cd4e0a Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Thu, 27 Jun 2024 15:12:15 +0200 Subject: [PATCH 09/13] reg FE: fix ctrl response handshk and dim assignments --- src/frontend/reg/tpl/idma_reg.sv.tpl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/frontend/reg/tpl/idma_reg.sv.tpl b/src/frontend/reg/tpl/idma_reg.sv.tpl index 40ae8fb7..4fc08495 100644 --- a/src/frontend/reg/tpl/idma_reg.sv.tpl +++ b/src/frontend/reg/tpl/idma_reg.sv.tpl @@ -87,15 +87,16 @@ module idma_${identifier} #( .devmode_i ( 1'b1 ) ); + logic read_happens; // DMA backpressure always_comb begin : proc_dma_backpressure // ready signal dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; - dma_ctrl_rsp_o[i].ready = arb_ready[i]; + dma_ctrl_rsp_o[i].ready = read_happens ? arb_ready[i] : dma_ctrl_rsp[i]; end // valid signals - logic read_happens; + always_comb begin : proc_launch read_happens = 1'b0; for (int c = 0; c < NumStreams; c++) begin @@ -159,13 +160,13 @@ module idma_${identifier} #( // Disable higher dimensions if ( dma_reg2hw[i].conf.enable_nd.q == 0) begin % for nd in range(0, num_dim-1): - arb_dma_req[i].d_req[${nd}].reps = '0; + arb_dma_req[i].d_req[${nd}].reps = ${"'0" if nd != num_dim-2 else "'d1"}; % endfor end % for nd in range(1, num_dim-1): else if ( dma_reg2hw[i].conf.enable_nd.q == ${nd}) begin % for snd in range(nd, num_dim-1): - arb_dma_req[i].d_req[${snd}].reps = '0; + arb_dma_req[i].d_req[${snd}].reps = 'd1; % endfor end % endfor From 40d8e354945d0fd13a7a01838530cb8293a600ab Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Thu, 27 Jun 2024 15:13:24 +0200 Subject: [PATCH 10/13] fix number of protocol bits and location --- util/mario/frontend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/mario/frontend.py b/util/mario/frontend.py index 70c31901..4459927d 100644 --- a/util/mario/frontend.py +++ b/util/mario/frontend.py @@ -11,7 +11,7 @@ import math from mako.template import Template -NUM_PROT_BITS = 3 - 1 +NUM_PROT_BITS = 3 def render_register(content: dict): """Render a register""" @@ -131,8 +131,8 @@ def render_reg_hjson(fe_ids: dict, tpl_file: str) -> str: 'params': params, 'registers': regs, 'dim_range': f'{10+num_dim_bits}:10', - 'src_prot_range': f'{10+num_dim_bits+NUM_PROT_BITS}:{10+num_dim_bits}', - 'dst_prot_range': f'{10+num_dim_bits+2*NUM_PROT_BITS}:{10+num_dim_bits+NUM_PROT_BITS}' + 'src_prot_range': f'{10+num_dim_bits+NUM_PROT_BITS}:{10+num_dim_bits+1}', + 'dst_prot_range': f'{10+num_dim_bits+2*NUM_PROT_BITS}:{10+num_dim_bits+NUM_PROT_BITS+1}' } # render From ea7649a38919fcccd0a3b85204b739544737dc73 Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Thu, 27 Jun 2024 15:17:45 +0200 Subject: [PATCH 11/13] fix legalizer generation when burst and non-burst protocols combined --- target/rtl/idma_generated.sv | 119 ++++++++++++++++++----------------- util/mario/legalizer.py | 19 ++++-- 2 files changed, 74 insertions(+), 64 deletions(-) diff --git a/target/rtl/idma_generated.sv b/target/rtl/idma_generated.sv index 4603c5bd..ad6034ef 100644 --- a/target/rtl/idma_generated.sv +++ b/target/rtl/idma_generated.sv @@ -3791,7 +3791,7 @@ module idma_legalizer_rw_axi_rw_axis #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_read_page_splitter ( - .not_bursting_i ( 1'b1 ), + .not_bursting_i ( opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM} ), .reduce_len_i ( opt_tf_q.src_reduce_len ), .max_llen_i ( opt_tf_q.src_max_llen ), @@ -3818,7 +3818,7 @@ module idma_legalizer_rw_axi_rw_axis #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_write_page_splitter ( - .not_bursting_i ( 1'b1 ), + .not_bursting_i ( opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM} ), .reduce_len_i ( opt_tf_q.dst_reduce_len ), .max_llen_i ( opt_tf_q.dst_max_llen ), @@ -4305,7 +4305,7 @@ module idma_legalizer_r_obi_rw_init_w_axi #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_write_page_splitter ( - .not_bursting_i ( 1'b1 ), + .not_bursting_i ( opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI} ), .reduce_len_i ( opt_tf_q.dst_reduce_len ), .max_llen_i ( opt_tf_q.dst_max_llen ), @@ -4762,7 +4762,7 @@ module idma_legalizer_r_axi_rw_init_rw_obi #( .page_len_t ( page_len_t ), .page_addr_t ( page_addr_t ) ) i_read_page_splitter ( - .not_bursting_i ( 1'b1 ), + .not_bursting_i ( opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI} ), .reduce_len_i ( opt_tf_q.src_reduce_len ), .max_llen_i ( opt_tf_q.src_max_llen ), @@ -7649,10 +7649,10 @@ module idma_backend_rw_axi_rw_axis #( // Add fall-through register to allow the input to be ready if the output is not. This // does not add a cycle of delay - assign r_meta_req_tagged = '{ - src_protocol: r_req.r_dp_req.src_protocol, - ar_req: r_req.ar_req - }; + always_comb begin : assign_r_meta_req + r_meta_req_tagged.src_protocol = r_req.r_dp_req.src_protocol; + r_meta_req_tagged.ar_req = r_req.ar_req; + end fall_through_register #( .T ( read_meta_channel_tagged_t ) @@ -7753,10 +7753,10 @@ module idma_backend_rw_axi_rw_axis #( //-------------------------------------- // R-AW channel coupler //-------------------------------------- - assign w_meta_req_tagged = '{ - dst_protocol: w_req.w_dp_req.dst_protocol, - aw_req: w_req.aw_req - }; + always_comb begin : assign_tagged_w_req // need to have an always_comb block for Questa to not crap itself + w_meta_req_tagged.dst_protocol = w_req.w_dp_req.dst_protocol; + w_meta_req_tagged.aw_req = w_req.aw_req; + end if (RAWCouplingAvail) begin : gen_r_aw_coupler `IDMA_NONSYNTH_BLOCK( @@ -8343,10 +8343,10 @@ module idma_backend_r_obi_rw_init_w_axi #( // Add fall-through register to allow the input to be ready if the output is not. This // does not add a cycle of delay - assign r_meta_req_tagged = '{ - src_protocol: r_req.r_dp_req.src_protocol, - ar_req: r_req.ar_req - }; + always_comb begin : assign_r_meta_req + r_meta_req_tagged.src_protocol = r_req.r_dp_req.src_protocol; + r_meta_req_tagged.ar_req = r_req.ar_req; + end fall_through_register #( .T ( read_meta_channel_tagged_t ) @@ -8449,10 +8449,10 @@ module idma_backend_r_obi_rw_init_w_axi #( //-------------------------------------- // R-AW channel coupler //-------------------------------------- - assign w_meta_req_tagged = '{ - dst_protocol: w_req.w_dp_req.dst_protocol, - aw_req: w_req.aw_req - }; + always_comb begin : assign_tagged_w_req // need to have an always_comb block for Questa to not crap itself + w_meta_req_tagged.dst_protocol = w_req.w_dp_req.dst_protocol; + w_meta_req_tagged.aw_req = w_req.aw_req; + end if (RAWCouplingAvail) begin : gen_r_aw_coupler `IDMA_NONSYNTH_BLOCK( @@ -9041,10 +9041,10 @@ module idma_backend_r_axi_rw_init_rw_obi #( // Add fall-through register to allow the input to be ready if the output is not. This // does not add a cycle of delay - assign r_meta_req_tagged = '{ - src_protocol: r_req.r_dp_req.src_protocol, - ar_req: r_req.ar_req - }; + always_comb begin : assign_r_meta_req + r_meta_req_tagged.src_protocol = r_req.r_dp_req.src_protocol; + r_meta_req_tagged.ar_req = r_req.ar_req; + end fall_through_register #( .T ( read_meta_channel_tagged_t ) @@ -9149,10 +9149,10 @@ module idma_backend_r_axi_rw_init_rw_obi #( //-------------------------------------- // R-AW channel coupler //-------------------------------------- - assign w_meta_req_tagged = '{ - dst_protocol: w_req.w_dp_req.dst_protocol, - aw_req: w_req.aw_req - }; + always_comb begin : assign_tagged_w_req // need to have an always_comb block for Questa to not crap itself + w_meta_req_tagged.dst_protocol = w_req.w_dp_req.dst_protocol; + w_meta_req_tagged.aw_req = w_req.aw_req; + end if (RAWCouplingAvail) begin : gen_r_aw_coupler `IDMA_NONSYNTH_BLOCK( @@ -12105,7 +12105,7 @@ package idma_reg32_3d_reg_pkg; // Register width information to check illegal writes parameter logic [3:0] IDMA_REG32_3D_PERMIT [58] = '{ - 4'b 0011, // index[ 0] IDMA_REG32_3D_CONF + 4'b 0111, // index[ 0] IDMA_REG32_3D_CONF 4'b 0011, // index[ 1] IDMA_REG32_3D_STATUS_0 4'b 0011, // index[ 2] IDMA_REG32_3D_STATUS_1 4'b 0011, // index[ 3] IDMA_REG32_3D_STATUS_2 @@ -12485,7 +12485,7 @@ package idma_reg64_2d_reg_pkg; // Register width information to check illegal writes parameter logic [3:0] IDMA_REG64_2D_PERMIT [61] = '{ - 4'b 0011, // index[ 0] IDMA_REG64_2D_CONF + 4'b 0111, // index[ 0] IDMA_REG64_2D_CONF 4'b 0011, // index[ 1] IDMA_REG64_2D_STATUS_0 4'b 0011, // index[ 2] IDMA_REG64_2D_STATUS_1 4'b 0011, // index[ 3] IDMA_REG64_2D_STATUS_2 @@ -12826,7 +12826,7 @@ package idma_reg64_1d_reg_pkg; // Register width information to check illegal writes parameter logic [3:0] IDMA_REG64_1D_PERMIT [55] = '{ - 4'b 0011, // index[ 0] IDMA_REG64_1D_CONF + 4'b 0111, // index[ 0] IDMA_REG64_1D_CONF 4'b 0011, // index[ 1] IDMA_REG64_1D_STATUS_0 4'b 0011, // index[ 2] IDMA_REG64_1D_STATUS_1 4'b 0011, // index[ 3] IDMA_REG64_1D_STATUS_2 @@ -13550,7 +13550,7 @@ module idma_reg32_3d_reg_top #( ); - // F[src_protocol]: 13:11 + // F[src_protocol]: 14:12 prim_subreg #( .DW (3), .SWACCESS("RW"), @@ -13576,7 +13576,7 @@ module idma_reg32_3d_reg_top #( ); - // F[dst_protocol]: 15:13 + // F[dst_protocol]: 17:15 prim_subreg #( .DW (3), .SWACCESS("RW"), @@ -14771,10 +14771,10 @@ module idma_reg32_3d_reg_top #( assign conf_enable_nd_wd = reg_wdata[11:10]; assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_protocol_wd = reg_wdata[13:11]; + assign conf_src_protocol_wd = reg_wdata[14:12]; assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_protocol_wd = reg_wdata[15:13]; + assign conf_dst_protocol_wd = reg_wdata[17:15]; assign status_0_re = addr_hit[1] & reg_re & !reg_error; @@ -14911,8 +14911,8 @@ module idma_reg32_3d_reg_top #( reg_rdata_next[6:4] = conf_src_max_llen_qs; reg_rdata_next[9:7] = conf_dst_max_llen_qs; reg_rdata_next[11:10] = conf_enable_nd_qs; - reg_rdata_next[13:11] = conf_src_protocol_qs; - reg_rdata_next[15:13] = conf_dst_protocol_qs; + reg_rdata_next[14:12] = conf_src_protocol_qs; + reg_rdata_next[17:15] = conf_dst_protocol_qs; end addr_hit[1]: begin @@ -15629,7 +15629,7 @@ module idma_reg64_2d_reg_top #( ); - // F[src_protocol]: 12:10 + // F[src_protocol]: 13:11 prim_subreg #( .DW (3), .SWACCESS("RW"), @@ -15655,7 +15655,7 @@ module idma_reg64_2d_reg_top #( ); - // F[dst_protocol]: 14:12 + // F[dst_protocol]: 16:14 prim_subreg #( .DW (3), .SWACCESS("RW"), @@ -16937,10 +16937,10 @@ module idma_reg64_2d_reg_top #( assign conf_enable_nd_wd = reg_wdata[10]; assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_protocol_wd = reg_wdata[12:10]; + assign conf_src_protocol_wd = reg_wdata[13:11]; assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_protocol_wd = reg_wdata[14:12]; + assign conf_dst_protocol_wd = reg_wdata[16:14]; assign status_0_re = addr_hit[1] & reg_re & !reg_error; @@ -17086,8 +17086,8 @@ module idma_reg64_2d_reg_top #( reg_rdata_next[6:4] = conf_src_max_llen_qs; reg_rdata_next[9:7] = conf_dst_max_llen_qs; reg_rdata_next[10] = conf_enable_nd_qs; - reg_rdata_next[12:10] = conf_src_protocol_qs; - reg_rdata_next[14:12] = conf_dst_protocol_qs; + reg_rdata_next[13:11] = conf_src_protocol_qs; + reg_rdata_next[16:14] = conf_dst_protocol_qs; end addr_hit[1]: begin @@ -17798,7 +17798,7 @@ module idma_reg64_1d_reg_top #( ); - // F[src_protocol]: 12:10 + // F[src_protocol]: 13:11 prim_subreg #( .DW (3), .SWACCESS("RW"), @@ -17824,7 +17824,7 @@ module idma_reg64_1d_reg_top #( ); - // F[dst_protocol]: 14:12 + // F[dst_protocol]: 16:14 prim_subreg #( .DW (3), .SWACCESS("RW"), @@ -18932,10 +18932,10 @@ module idma_reg64_1d_reg_top #( assign conf_enable_nd_wd = reg_wdata[10]; assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_protocol_wd = reg_wdata[12:10]; + assign conf_src_protocol_wd = reg_wdata[13:11]; assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_protocol_wd = reg_wdata[14:12]; + assign conf_dst_protocol_wd = reg_wdata[16:14]; assign status_0_re = addr_hit[1] & reg_re & !reg_error; @@ -19063,8 +19063,8 @@ module idma_reg64_1d_reg_top #( reg_rdata_next[6:4] = conf_src_max_llen_qs; reg_rdata_next[9:7] = conf_dst_max_llen_qs; reg_rdata_next[10] = conf_enable_nd_qs; - reg_rdata_next[12:10] = conf_src_protocol_qs; - reg_rdata_next[14:12] = conf_dst_protocol_qs; + reg_rdata_next[13:11] = conf_src_protocol_qs; + reg_rdata_next[16:14] = conf_dst_protocol_qs; end addr_hit[1]: begin @@ -19444,15 +19444,16 @@ module idma_reg32_3d #( .devmode_i ( 1'b1 ) ); + logic read_happens; // DMA backpressure always_comb begin : proc_dma_backpressure // ready signal dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; - dma_ctrl_rsp_o[i].ready = arb_ready[i]; + dma_ctrl_rsp_o[i].ready = read_happens ? arb_ready[i] : dma_ctrl_rsp[i]; end // valid signals - logic read_happens; + always_comb begin : proc_launch read_happens = 1'b0; for (int c = 0; c < NumStreams; c++) begin @@ -19501,10 +19502,10 @@ module idma_reg32_3d #( // Disable higher dimensions if ( dma_reg2hw[i].conf.enable_nd.q == 0) begin arb_dma_req[i].d_req[0].reps = '0; - arb_dma_req[i].d_req[1].reps = '0; + arb_dma_req[i].d_req[1].reps = 'd1; end else if ( dma_reg2hw[i].conf.enable_nd.q == 1) begin - arb_dma_req[i].d_req[1].reps = '0; + arb_dma_req[i].d_req[1].reps = 'd1; end end @@ -19636,15 +19637,16 @@ module idma_reg64_2d #( .devmode_i ( 1'b1 ) ); + logic read_happens; // DMA backpressure always_comb begin : proc_dma_backpressure // ready signal dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; - dma_ctrl_rsp_o[i].ready = arb_ready[i]; + dma_ctrl_rsp_o[i].ready = read_happens ? arb_ready[i] : dma_ctrl_rsp[i]; end // valid signals - logic read_happens; + always_comb begin : proc_launch read_happens = 1'b0; for (int c = 0; c < NumStreams; c++) begin @@ -19692,7 +19694,7 @@ module idma_reg64_2d #( // Disable higher dimensions if ( dma_reg2hw[i].conf.enable_nd.q == 0) begin - arb_dma_req[i].d_req[0].reps = '0; + arb_dma_req[i].d_req[0].reps = 'd1; end end @@ -19824,15 +19826,16 @@ module idma_reg64_1d #( .devmode_i ( 1'b1 ) ); + logic read_happens; // DMA backpressure always_comb begin : proc_dma_backpressure // ready signal dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; - dma_ctrl_rsp_o[i].ready = arb_ready[i]; + dma_ctrl_rsp_o[i].ready = read_happens ? arb_ready[i] : dma_ctrl_rsp[i]; end // valid signals - logic read_happens; + always_comb begin : proc_launch read_happens = 1'b0; for (int c = 0; c < NumStreams; c++) begin diff --git a/util/mario/legalizer.py b/util/mario/legalizer.py index 7982b693..c1a00364 100644 --- a/util/mario/legalizer.py +++ b/util/mario/legalizer.py @@ -56,6 +56,13 @@ def render_legalizer(prot_ids: dict, db: dict, tpl_file: str) -> str: data_path = indent_block(db[wp]['legalizer_write_data_path'], 3 - swp, 4) db[wp]['legalizer_write_data_path'] = data_path + + has_page_read_bursting = eval_key(used_read_prots, 'bursts', 'split_at_page_boundary', db) + has_pow2_read_bursting = eval_key(used_read_prots, 'bursts', 'only_pow2', db) + has_read_bursting = has_page_read_bursting or has_pow2_read_bursting + has_page_write_bursting = eval_key(used_write_prots, 'bursts', 'split_at_page_boundary', db) + has_pow2_write_bursting = eval_key(used_write_prots, 'bursts', 'only_pow2', db) + has_write_bursting = has_page_write_bursting or has_pow2_write_bursting # assemble context context = { 'name_uniqueifier': prot_id, @@ -66,17 +73,17 @@ def render_legalizer(prot_ids: dict, db: dict, tpl_file: str) -> str: 'one_read_port': srp, 'one_write_port': swp, 'no_read_bursting': - eval_key(used_read_prots, 'bursts', 'not_supported', db), + not has_read_bursting, 'has_page_read_bursting': - eval_key(used_read_prots, 'bursts', 'split_at_page_boundary', db), + has_page_read_bursting, 'has_pow2_read_bursting': - eval_key(used_read_prots, 'bursts', 'only_pow2', db), + has_pow2_read_bursting, 'no_write_bursting': - eval_key(used_write_prots, 'bursts', 'not_supported', db), + not has_write_bursting, 'has_page_write_bursting': - eval_key(used_write_prots, 'bursts', 'split_at_page_boundary', db), + has_page_write_bursting, 'has_pow2_write_bursting': - eval_key(used_write_prots, 'bursts', 'only_pow2', db), + has_pow2_write_bursting, 'used_non_bursting_write_protocols': prot_key(used_read_prots, 'bursts', 'not_supported', db), 'used_non_bursting_read_protocols': From d6d7d99b67648e9b02e081c1504f8dd108a8d99b Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Thu, 27 Jun 2024 17:36:11 +0200 Subject: [PATCH 12/13] PULP iDMA wrap passes simple tests and is not unnecessarily slow --- Bender.yml | 2 +- src/pulp_idma_wrap.sv | 166 +++++++++++++++++++++++++++++++----------- 2 files changed, 125 insertions(+), 43 deletions(-) diff --git a/Bender.yml b/Bender.yml index 404a0137..f1ba0bee 100644 --- a/Bender.yml +++ b/Bender.yml @@ -19,7 +19,7 @@ dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.33.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.3 } - obi: { git: "https://github.com/pulp-platform/obi.git", version: 0.1.2 } + obi: { git: "https://github.com/pulp-platform/obi.git", rev: "2ee698211db5c007bd0d207ebd646ce79f0472ec" } export_include_dirs: - src/include diff --git a/src/pulp_idma_wrap.sv b/src/pulp_idma_wrap.sv index 1e7ad6ee..bd3f7d32 100644 --- a/src/pulp_idma_wrap.sv +++ b/src/pulp_idma_wrap.sv @@ -150,9 +150,9 @@ module pulp_idma_wrap #( obi_req_t [NUM_BIDIR_STREAMS-1:0] - obi_read_req_from_dma, obi_reorg_req, obi_write_req, obi_read_req_muxed; + obi_read_req_from_dma, obi_read_req_from_rrc, obi_reorg_req_from_dma, obi_reorg_req_from_rrc, obi_write_req_from_dma, obi_write_req_from_rrc, obi_read_req_muxed; obi_rsp_t [NUM_BIDIR_STREAMS-1:0] - obi_read_rsp_to_dma, obi_reorg_rsp, obi_write_rsp, obi_read_rsp_to_mux; + obi_read_rsp_to_dma, obi_read_rsp_to_rrc, obi_reorg_rsp_to_dma, obi_reorg_rsp_to_rrc, obi_write_rsp_to_dma, obi_write_rsp_to_rrc, obi_read_rsp_to_mux; // BUS definitions @@ -411,7 +411,7 @@ module pulp_idma_wrap #( .TFLenWidth (TFLenWidth), .MemSysDepth (32'd0), .CombinedShifter (1'b1), - .RAWCouplingAvail (1'b1), + .RAWCouplingAvail (1'b0), .MaskInvalidData (1'b0), .HardwareLegalizer (1'b1), .RejectZeroTransfers (1'b1), @@ -528,7 +528,7 @@ axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) .TFLenWidth (TFLenWidth), .MemSysDepth (32'd0), .CombinedShifter (1'b1), - .RAWCouplingAvail (1'b1), + .RAWCouplingAvail (1'b0), .MaskInvalidData (1'b0), .HardwareLegalizer (1'b1), .RejectZeroTransfers (1'b1), @@ -561,12 +561,12 @@ axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) .axi_read_rsp_i (dma_rsp[s]), .init_read_req_o (init_read_req), .init_read_rsp_i (init_read_rsp), - .obi_read_req_o (obi_reorg_req[s/2]), - .obi_read_rsp_i (obi_reorg_rsp[s/2]), + .obi_read_req_o (obi_reorg_req_from_dma[s/2]), + .obi_read_rsp_i (obi_reorg_rsp_to_dma[s/2]), .init_write_req_o(init_write_req), .init_write_rsp_i(init_write_rsp), - .obi_write_req_o (obi_write_req[s/2]), - .obi_write_rsp_i (obi_write_rsp[s/2]), + .obi_write_req_o (obi_write_req_from_dma[s/2]), + .obi_write_rsp_i (obi_write_rsp_to_dma[s/2]), .busy_o (idma_busy[s]) ); @@ -588,9 +588,18 @@ axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) // ------------------------------------------------------ for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin if (MUX_READ) begin - localparam obi_pkg::obi_cfg_t sbr_obi_cfg = obi_pkg::obi_default_cfg( - AXI_ADDR_WIDTH, AXI_DATA_WIDTH, 0, obi_pkg::ObiMinimalOptionalConfig - ); + localparam obi_pkg::obi_cfg_t sbr_obi_cfg = '{ + UseRReady: 1'b1, + CombGnt: 1'b0, + AddrWidth: AXI_ADDR_WIDTH, + DataWidth: AXI_DATA_WIDTH, + IdWidth: 0, + Integrity: 1'b0, + BeFull: 1'b1, + OptionalCfg: obi_pkg::ObiMinimalOptionalConfig + }; + + // iDMA OBI obi_mux #( .SbrPortObiCfg (sbr_obi_cfg), @@ -602,22 +611,95 @@ axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) .mgr_port_obi_req_t(obi_req_t), .mgr_port_obi_rsp_t(obi_rsp_t), .NumSbrPorts (2), - .NumMaxTrans (1), + .NumMaxTrans (2), .UseIdForRouting (1'b0) ) obi_read_mux_i ( .clk_i, .rst_ni, .testmode_i (test_mode_i), - .sbr_ports_req_i({obi_reorg_req, obi_read_req_from_dma}), - .sbr_ports_rsp_o({obi_reorg_rsp, obi_read_rsp_to_dma}), - .mgr_port_req_o (obi_read_req_muxed), - .mgr_port_rsp_i (obi_read_rsp_to_mux) + .sbr_ports_req_i({obi_reorg_req_from_dma[s], obi_read_req_from_dma[s]}), + .sbr_ports_rsp_o({obi_reorg_rsp_to_dma[s], obi_read_rsp_to_dma[s]}), + .mgr_port_req_o (obi_read_req_muxed[s]), + .mgr_port_rsp_i (obi_read_rsp_to_mux[s]) ); + assign obi_reorg_req_from_rrc = '0; + assign obi_reorg_rsp_to_rrc = '0; end else begin // if (MUX_READ) // pass through the read req/rsp from/to dma assign obi_read_req_muxed = obi_read_req_from_dma; assign obi_read_rsp_to_dma = obi_read_rsp_to_mux; - end + + obi_rready_converter #( + .obi_a_chan_t(obi_a_chan_t), + .obi_r_chan_t(obi_r_chan_t), + .DEPTH(1) + ) + obi_rready_converter_reorg_i ( + .clk_i, + .rst_ni, + .test_mode_i, + .sbr_a_chan_i(obi_reorg_req_from_dma[s].a), + .req_i(obi_reorg_req_from_dma[s].req), + .gnt_o(obi_reorg_rsp_to_dma[s].gnt), + .rready_i(obi_reorg_req_from_dma[s].rready), + .sbr_r_chan_o(obi_reorg_rsp_to_dma[s].r), + .rvalid_o(obi_reorg_rsp_to_dma[s].rvalid), + .mgr_a_chan_o(obi_reorg_req_from_rrc[s].a), + .req_o(obi_reorg_req_from_rrc[s].req), + .rready_o(obi_reorg_req_from_rrc[s].rready), + .mgr_r_chan_i(obi_reorg_rsp_to_rrc[s].r), + .gnt_i(obi_reorg_rsp_to_rrc[s].gnt), + .rvalid_i(obi_reorg_rsp_to_rrc[s].rvalid) + ); + end // else: !if(MUX_READ) + + obi_rready_converter #( + .obi_a_chan_t(obi_a_chan_t), + .obi_r_chan_t(obi_r_chan_t), + .DEPTH(1) + ) + obi_rready_converter_read_i ( + .clk_i, + .rst_ni, + .test_mode_i, + .sbr_a_chan_i(obi_read_req_muxed[s].a), + .req_i(obi_read_req_muxed[s].req), + .gnt_o(obi_read_rsp_to_mux[s].gnt), + .rready_i(obi_read_req_muxed[s].rready), + .sbr_r_chan_o(obi_read_rsp_to_mux[s].r), + .rvalid_o(obi_read_rsp_to_mux[s].rvalid), + .mgr_a_chan_o(obi_read_req_from_rrc[s].a), + .req_o(obi_read_req_from_rrc[s].req), + .rready_o(obi_read_req_from_rrc[s].rready), + .mgr_r_chan_i(obi_read_rsp_to_rrc[s].r), + .gnt_i(obi_read_rsp_to_rrc[s].gnt), + .rvalid_i(obi_read_rsp_to_rrc[s].rvalid) + ); + + + + obi_rready_converter #( + .obi_a_chan_t(obi_a_chan_t), + .obi_r_chan_t(obi_r_chan_t), + .DEPTH(1) + ) + obi_rready_converter_wr_i ( + .clk_i, + .rst_ni, + .test_mode_i, + .sbr_a_chan_i(obi_write_req_from_dma[s].a), + .req_i(obi_write_req_from_dma[s].req), + .gnt_o(obi_write_rsp_to_dma[s].gnt), + .rready_i(obi_write_req_from_dma[s].rready), + .sbr_r_chan_o(obi_write_rsp_to_dma[s].r), + .rvalid_o(obi_write_rsp_to_dma[s].rvalid), + .mgr_a_chan_o(obi_write_req_from_rrc[s].a), + .req_o(obi_write_req_from_rrc[s].req), + .rready_o(obi_write_req_from_rrc[s].rready), + .mgr_r_chan_i(obi_write_rsp_to_rrc[s].r), + .gnt_i(obi_write_rsp_to_rrc[s].gnt), + .rvalid_i(obi_write_rsp_to_rrc[s].rvalid) + ); end @@ -643,15 +725,15 @@ axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) ) i_mem_to_banks_read ( .clk_i, .rst_ni, - .req_i(obi_read_req_muxed[s].req), - .gnt_o(obi_read_rsp_to_mux[s].gnt), - .addr_i(obi_read_req_muxed[s].a.addr), - .wdata_i(obi_read_req_muxed[s].a.wdata), - .strb_i(obi_read_req_muxed[s].a.be), + .req_i(obi_read_req_from_rrc[s].req), + .gnt_o(obi_read_rsp_to_rrc[s].gnt), + .addr_i(obi_read_req_from_rrc[s].a.addr), + .wdata_i(obi_read_req_from_rrc[s].a.wdata), + .strb_i(obi_read_req_from_rrc[s].a.be), .atop_i('0), - .we_i(obi_read_req_muxed[s].a.we), - .rvalid_o(obi_read_rsp_to_mux[s].rvalid), - .rdata_o(obi_read_rsp_to_mux[s].r.rdata), + .we_i(obi_read_req_from_rrc[s].a.we), + .rvalid_o(obi_read_rsp_to_rrc[s].rvalid), + .rdata_o(obi_read_rsp_to_rrc[s].r.rdata), .bank_req_o({ tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].req }), @@ -701,15 +783,15 @@ axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) ) i_mem_to_banks_reorg ( .clk_i, .rst_ni, - .req_i(obi_reorg_req[s].req), - .gnt_o(obi_reorg_rsp[s].gnt), - .addr_i(obi_reorg_req[s].a.addr), - .wdata_i(obi_reorg_req[s].a.wdata), - .strb_i(obi_reorg_req[s].a.be), + .req_i(obi_reorg_req_from_rrc[s].req), + .gnt_o(obi_reorg_rsp_to_rrc[s].gnt), + .addr_i(obi_reorg_req_from_rrc[s].a.addr), + .wdata_i(obi_reorg_req_from_rrc[s].a.wdata), + .strb_i(obi_reorg_req_from_rrc[s].a.be), .atop_i('0), - .we_i(obi_reorg_req[s].a.we), - .rvalid_o(obi_reorg_rsp[s].rvalid), - .rdata_o(obi_reorg_rsp[s].r.rdata), + .we_i(obi_reorg_req_from_rrc[s].a.we), + .rvalid_o(obi_reorg_rsp_to_rrc[s].rvalid), + .rdata_o(obi_reorg_rsp_to_rrc[s].r.rdata), .bank_req_o({ tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].req }), @@ -757,15 +839,15 @@ axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) ) i_mem_to_banks_write ( .clk_i, .rst_ni, - .req_i(obi_write_req[s].req), - .gnt_o(obi_write_rsp[s].gnt), - .addr_i(obi_write_req[s].a.addr), - .wdata_i(obi_write_req[s].a.wdata), - .strb_i(obi_write_req[s].a.be), + .req_i(obi_write_req_from_rrc[s].req), + .gnt_o(obi_write_rsp_to_rrc[s].gnt), + .addr_i(obi_write_req_from_rrc[s].a.addr), + .wdata_i(obi_write_req_from_rrc[s].a.wdata), + .strb_i(obi_write_req_from_rrc[s].a.be), .atop_i('0), - .we_i(obi_write_req[s].a.we), - .rvalid_o(obi_write_rsp[s].rvalid), - .rdata_o(obi_write_rsp[s].r.rdata), + .we_i(obi_write_req_from_rrc[s].a.we), + .rvalid_o(obi_write_rsp_to_rrc[s].rvalid), + .rdata_o(obi_write_rsp_to_rrc[s].r.rdata), .bank_req_o({ tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].req }), @@ -782,7 +864,7 @@ axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].be, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].be }), .bank_atop_o( /* NOT CONNECTED */), - .bank_we_o({tcdm_master_we_0, tcdm_master_we_0}), + .bank_we_o({tcdm_master_we_1, tcdm_master_we_0}), .bank_rvalid_i({ tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].r_valid, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].r_valid From 0486d099d3d11b94b6141b52718e7659dfa99a37 Mon Sep 17 00:00:00 2001 From: Georg Rutishauser Date: Fri, 28 Jun 2024 15:57:59 +0200 Subject: [PATCH 13/13] prepare for PR (whitespace and generated files) --- Bender.yml | 6 +- src/frontend/reg/tpl/idma_reg.sv.tpl | 4 +- src/pulp_idma_wrap.sv | 888 -- target/rtl/idma_generated.sv | 19916 ------------------------- util/mario/legalizer.py | 2 +- 5 files changed, 5 insertions(+), 20811 deletions(-) delete mode 100644 src/pulp_idma_wrap.sv delete mode 100644 target/rtl/idma_generated.sv diff --git a/Bender.yml b/Bender.yml index f1ba0bee..adc686f1 100644 --- a/Bender.yml +++ b/Bender.yml @@ -19,7 +19,7 @@ dependencies: common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.33.0 } common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.3 } register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.3 } - obi: { git: "https://github.com/pulp-platform/obi.git", rev: "2ee698211db5c007bd0d207ebd646ce79f0472ec" } + obi: { git: "https://github.com/pulp-platform/obi.git", version: 0.1.2 } export_include_dirs: - src/include @@ -52,8 +52,6 @@ sources: - src/backend/idma_obi_write.sv - src/backend/idma_tilelink_read.sv - src/backend/idma_tilelink_write.sv - # Level 2 - - src/pulp_idma_wrap.sv # Generated content - target: rtl @@ -70,7 +68,7 @@ sources: - src/midend/idma_rt_midend.sv # RISC-V opcode package for ooc use of inst64 - - target: rtl + - target: all(rtl,snitch_cluster) files: # Level 0 - src/frontend/inst64/idma_inst64_snitch_pkg.sv diff --git a/src/frontend/reg/tpl/idma_reg.sv.tpl b/src/frontend/reg/tpl/idma_reg.sv.tpl index 4fc08495..f40b984e 100644 --- a/src/frontend/reg/tpl/idma_reg.sv.tpl +++ b/src/frontend/reg/tpl/idma_reg.sv.tpl @@ -70,7 +70,7 @@ module idma_${identifier} #( end end end - + // generate the registers for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs @@ -96,7 +96,7 @@ module idma_${identifier} #( end // valid signals - + always_comb begin : proc_launch read_happens = 1'b0; for (int c = 0; c < NumStreams; c++) begin diff --git a/src/pulp_idma_wrap.sv b/src/pulp_idma_wrap.sv deleted file mode 100644 index bd3f7d32..00000000 --- a/src/pulp_idma_wrap.sv +++ /dev/null @@ -1,888 +0,0 @@ -// Copyright 2022 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -/* - * dmac_wrap.sv - * Thomas Benz - * Michael Rogenmoser - * Georg Rutishauser - */ - -// DMA Core wrapper - -`include "axi/assign.svh" -`include "axi/typedef.svh" -`include "obi/typedef.svh" -`include "idma/typedef.svh" -`include "register_interface/typedef.svh" - -`define MY_MAX(a,b) (a > b ? a : b) - -module pulp_idma_wrap #( - parameter int unsigned NB_CORES = 4, - parameter int unsigned AXI_ADDR_WIDTH = 32, - parameter int unsigned AXI_DATA_WIDTH = 64, - parameter int unsigned AXI_USER_WIDTH = 6, - parameter int unsigned AXI_ID_WIDTH = 4, - parameter int unsigned PE_ID_WIDTH = 1, - parameter int unsigned NB_PE_PORTS = 1, - parameter int unsigned DATA_WIDTH = 32, - parameter int unsigned ADDR_WIDTH = 32, - parameter int unsigned BE_WIDTH = DATA_WIDTH / 8, - parameter type axi_req_t = logic, - parameter type axi_resp_t = logic, - // bidirectional streams: range 1 to 8 - parameter int unsigned NUM_BIDIR_STREAMS = 1, - parameter int unsigned NB_OUTSND_BURSTS = 8, - // queue depth per stream - parameter int unsigned GLOBAL_QUEUE_DEPTH = 2, - // mux read ports between tcdm-tcdm and tcdm-axi? - parameter bit MUX_READ = 1'b0, - // 4 ports per stream if read ports muxed, otherwise 6 - localparam int unsigned NB_TCDM_PORTS_PER_STRM = 4 + (!MUX_READ) * 2 -) ( // verilog_format: off // verible does not manage to align this :( - input logic clk_i, - input logic rst_ni, - input logic test_mode_i, - XBAR_PERIPH_BUS.Slave pe_ctrl_slave[NB_PE_PORTS-1:0], - XBAR_TCDM_BUS.Slave ctrl_slave[NB_CORES-1:0], - hci_core_intf.master tcdm_master[NB_TCDM_PORTS_PER_STRM*NUM_BIDIR_STREAMS-1:0], - output axi_req_t [NUM_BIDIR_STREAMS-1:0] ext_master_req_o, - input axi_resp_t [NUM_BIDIR_STREAMS-1:0] ext_master_resp_i, - output logic [NB_CORES-1:0] term_event_o, - output logic [NB_CORES-1:0] term_irq_o, - output logic [NB_PE_PORTS-1:0] term_event_pe_o, - output logic [NB_PE_PORTS-1:0] term_irq_pe_o, - output logic busy_o -); // verilog_format: on - - localparam int unsigned NumRegs = NB_CORES + NB_PE_PORTS; - localparam int unsigned NumStreams = 32'd2 * NUM_BIDIR_STREAMS; - localparam int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams); - - // CORE --> MCHAN CTRL INTERFACE BUS SIGNALS - logic [NumRegs-1:0][ DATA_WIDTH-1:0] config_wdata; - logic [NumRegs-1:0][ ADDR_WIDTH-1:0] config_add; - logic [NumRegs-1:0] config_req; - logic [NumRegs-1:0] config_wen; - logic [NumRegs-1:0][ BE_WIDTH-1:0] config_be; - logic [NumRegs-1:0][PE_ID_WIDTH-1:0] config_id; - logic [NumRegs-1:0] config_gnt; - logic [NumRegs-1:0][ DATA_WIDTH-1:0] config_r_rdata; - logic [NumRegs-1:0] config_r_valid; - logic [NumRegs-1:0] config_r_opc; - logic [NumRegs-1:0][PE_ID_WIDTH-1:0] config_r_id; - - // tie-off pe control ports - for (genvar i = 0; i < NB_CORES; i++) begin : gen_ctrl_registers - assign config_add[i] = ctrl_slave[i].add; - assign config_req[i] = ctrl_slave[i].req; - assign config_wdata[i] = ctrl_slave[i].wdata; - assign config_wen[i] = ctrl_slave[i].wen; - assign config_be[i] = ctrl_slave[i].be; - assign config_id[i] = '0; - assign ctrl_slave[i].gnt = config_gnt[i]; - assign ctrl_slave[i].r_opc = config_r_opc[i]; - assign ctrl_slave[i].r_valid = config_r_valid[i]; - assign ctrl_slave[i].r_rdata = config_r_rdata[i]; - end - - for (genvar i = 0; i < NB_PE_PORTS; i++) begin : gen_pe_ctrl_registers - assign config_add[NB_CORES+i] = pe_ctrl_slave[i].add; - assign config_req[NB_CORES+i] = pe_ctrl_slave[i].req; - assign config_wdata[NB_CORES+i] = pe_ctrl_slave[i].wdata; - assign config_wen[NB_CORES+i] = pe_ctrl_slave[i].wen; - assign config_be[NB_CORES+i] = pe_ctrl_slave[i].be; - assign config_id[NB_CORES+i] = pe_ctrl_slave[i].id; - assign pe_ctrl_slave[i].gnt = config_gnt[NB_CORES+i]; - assign pe_ctrl_slave[i].r_opc = config_r_opc[NB_CORES+i]; - assign pe_ctrl_slave[i].r_valid = config_r_valid[NB_CORES+i]; - assign pe_ctrl_slave[i].r_rdata = config_r_rdata[NB_CORES+i]; - assign pe_ctrl_slave[i].r_id = config_r_id[NB_CORES+i]; - end - - // Types types - typedef logic [AXI_ADDR_WIDTH-1:0] addr_t; - typedef logic [ADDR_WIDTH-1:0] mem_addr_t; - typedef logic [AXI_DATA_WIDTH-1:0] data_t; - typedef logic [AXI_ID_WIDTH-1:0] id_t; - typedef logic [AXI_DATA_WIDTH/8-1:0] strb_t; - typedef logic [AXI_USER_WIDTH-1:0] user_t; - - // // AXI4+ATOP channels typedefs - //`AXI_TYPEDEF_ALL(axi_int, addr_t, id_t, data_t, strb_t, user_t) - `AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) - `AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) - `AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) - `AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) - `AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) - // Memory Init typedefs - /// init read request - typedef struct packed { - logic [AXI_ADDR_WIDTH-1:0] cfg; - logic [AXI_DATA_WIDTH-1:0] term; - logic [AXI_DATA_WIDTH/8-1:0] strb; - logic [AXI_ID_WIDTH-1:0] id; - } init_req_chan_t; - - typedef struct packed { - init_req_chan_t req_chan; - logic req_valid; - logic rsp_ready; - } init_req_t; - - typedef struct packed {logic [AXI_DATA_WIDTH-1:0] init;} init_rsp_chan_t; - - typedef struct packed { - init_rsp_chan_t rsp_chan; - logic rsp_valid; - logic req_ready; - } init_rsp_t; - - // OBI typedefs - `OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) - `OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) - `OBI_TYPEDEF_A_CHAN_T(obi_a_chan_t, AXI_ADDR_WIDTH, AXI_DATA_WIDTH, 0, a_optional_t) - `OBI_TYPEDEF_R_CHAN_T(obi_r_chan_t, AXI_DATA_WIDTH, 0, r_optional_t) - `OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) - `OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) - - - obi_req_t [NUM_BIDIR_STREAMS-1:0] - obi_read_req_from_dma, obi_read_req_from_rrc, obi_reorg_req_from_dma, obi_reorg_req_from_rrc, obi_write_req_from_dma, obi_write_req_from_rrc, obi_read_req_muxed; - obi_rsp_t [NUM_BIDIR_STREAMS-1:0] - obi_read_rsp_to_dma, obi_read_rsp_to_rrc, obi_reorg_rsp_to_dma, obi_reorg_rsp_to_rrc, obi_write_rsp_to_dma, obi_write_rsp_to_rrc, obi_read_rsp_to_mux; - - - // BUS definitions - axi_req_t [NUM_BIDIR_STREAMS-1:0] soc_req; - axi_resp_t [NUM_BIDIR_STREAMS-1:0] soc_rsp; - axi_req_t [ NumStreams-1:0] dma_req; - axi_resp_t [ NumStreams-1:0] dma_rsp; - - // interface to structs - for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin : gen_connect_interface - assign ext_master_req_o[s] = soc_req[s]; - assign soc_rsp[s] = ext_master_resp_i[s]; - end - - // connect RW axi buses - for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin : gen_rw_axi_connection - axi_rw_join #( - .axi_req_t (axi_req_t), - .axi_resp_t(axi_resp_t) - ) i_init_axi_rw_join ( - .clk_i, - .rst_ni, - .slv_read_req_i (dma_req[2*s+1]), - .slv_read_resp_o (dma_rsp[2*s+1]), - .slv_write_req_i (dma_req[2*s]), - .slv_write_resp_o(dma_rsp[2*s]), - .mst_req_o (soc_req[s]), - .mst_resp_i (soc_rsp[s]) - ); - end - - // Register BUS definitions - localparam int unsigned RegAddrWidth = 32'd10; - `REG_BUS_TYPEDEF_ALL(dma_regs, logic[RegAddrWidth-1:0], logic[DATA_WIDTH-1:0], - logic[BE_WIDTH-1:0]) - dma_regs_req_t [NumRegs-1:0] dma_regs_req; - dma_regs_rsp_t [NumRegs-1:0] dma_regs_rsp; - - // iDMA struct definitions - localparam int unsigned TFLenWidth = AXI_ADDR_WIDTH; - localparam int unsigned NumDim = 32'd3; // Support 2D midend for 2D transfers - localparam int unsigned RepWidth = 32'd32; - localparam int unsigned StrideWidth = 32'd32; - typedef logic [TFLenWidth-1:0] tf_len_t; - typedef logic [RepWidth-1:0] reps_t; - typedef logic [StrideWidth-1:0] strides_t; - - // iDMA request / response types - `IDMA_TYPEDEF_FULL_REQ_T(idma_req_t, id_t, addr_t, tf_len_t) - `IDMA_TYPEDEF_FULL_RSP_T(idma_rsp_t, addr_t) - - // iDMA ND request - `IDMA_TYPEDEF_FULL_ND_REQ_T(idma_nd_req_t, idma_req_t, reps_t, strides_t) - - logic [StreamWidth-1:0] stream_idx; - - idma_nd_req_t [NumStreams-1:0] twod_req, twod_req_queue; - idma_req_t [NumStreams-1:0] idma_req; - idma_rsp_t [NumStreams-1:0] idma_rsp; - - logic one_fe_valid; - logic [NumStreams-1:0] fe_valid, twod_queue_valid, be_valid, be_rsp_valid; - logic [NumStreams-1:0] fe_ready, twod_queue_ready, be_ready, be_rsp_ready; - logic [NumStreams-1:0] trans_complete, midend_busy; - idma_pkg::idma_busy_t [NumStreams-1:0] idma_busy; - - logic [31:0][NumStreams-1:0] done_id, next_id; - - // ------------------------------------------------------ - // FRONTEND - // ------------------------------------------------------ - - for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs - periph_to_reg #( - .AW (RegAddrWidth), - .DW (DATA_WIDTH), - .BW (BE_WIDTH), - .IW (PE_ID_WIDTH), - .req_t(dma_regs_req_t), - .rsp_t(dma_regs_rsp_t) - ) i_pe_translate ( - .clk_i, - .rst_ni, - .req_i (config_req[i]), - .add_i (config_add[i][RegAddrWidth-1:0]), - .wen_i (config_wen[i]), - .wdata_i (config_wdata[i]), - .be_i (config_be[i]), - .id_i (config_id[i]), - .gnt_o (config_gnt[i]), - .r_rdata_o(config_r_rdata[i]), - .r_opc_o (config_r_opc[i]), - .r_id_o (config_r_id[i]), - .r_valid_o(config_r_valid[i]), - .reg_req_o(dma_regs_req[i]), - .reg_rsp_i(dma_regs_rsp[i]) - ); - end - - idma_reg32_3d #( - .NumRegs (NumRegs), - .NumStreams (NumStreams), - .IdCounterWidth(32'd32), - .reg_req_t (dma_regs_req_t), - .reg_rsp_t (dma_regs_rsp_t), - .dma_req_t (idma_nd_req_t) - ) i_idma_reg32_3d ( - .clk_i, - .rst_ni, - .dma_ctrl_req_i(dma_regs_req), - .dma_ctrl_rsp_o(dma_regs_rsp), - .dma_req_o (twod_req), - .req_valid_o (one_fe_valid), - .req_ready_i (fe_ready[stream_idx]), - .next_id_i (next_id[stream_idx]), - .stream_idx_o (stream_idx), - .done_id_i (done_id), - .busy_i (idma_busy), - .midend_busy_i (midend_busy) - ); - - always_comb begin : proc_connect_valids - fe_valid = '0; - fe_valid[stream_idx] = one_fe_valid; - end - - // interrupts and events (currently broadcast tx_cplt event only) - assign term_event_pe_o = |trans_complete ? '1 : '0; - assign term_irq_pe_o = '0; - assign term_event_o = |trans_complete ? '1 : '0; - assign term_irq_o = '0; - - assign busy_o = |midend_busy | |idma_busy; - - for (genvar s = 0; s < NumStreams; s++) begin : gen_streams - - // ------------------------------------------------------ - // ID counters - // ------------------------------------------------------ - idma_transfer_id_gen #( - .IdWidth(32'd32) - ) i_idma_transfer_id_gen ( - .clk_i, - .rst_ni, - .issue_i (fe_valid[s] & fe_ready[s]), - .retire_i (trans_complete[s]), - .next_o (next_id[s]), - .completed_o(done_id[s]) - ); - - - // ------------------------------------------------------ - // MIDEND - // ------------------------------------------------------ - // global (2D) request FIFO - stream_fifo #( - .DEPTH(GLOBAL_QUEUE_DEPTH), - .T (idma_nd_req_t) - ) i_3D_request_fifo ( - .clk_i, - .rst_ni, - .flush_i (1'b0), - .testmode_i(test_mode_i), - .usage_o ( /*NOT CONNECTED*/), - .data_i (twod_req), - .valid_i (fe_valid[s]), - .ready_o (fe_ready[s]), - .data_o (twod_req_queue[s]), - .valid_o (twod_queue_valid[s]), - .ready_i (twod_queue_ready[s]) - ); - - localparam logic [1:0][31:0] RepWidths = '{default: 32'd32}; - - idma_nd_midend #( - .NumDim (NumDim), - .addr_t (addr_t), - .idma_req_t (idma_req_t), - .idma_rsp_t (idma_rsp_t), - .idma_nd_req_t(idma_nd_req_t), - .RepWidths (RepWidths) - ) i_idma_3D_midend ( - .clk_i, - .rst_ni, - .nd_req_i (twod_req_queue[s]), - .nd_req_valid_i (twod_queue_valid[s]), - .nd_req_ready_o (twod_queue_ready[s]), - .nd_rsp_o ( /*NOT CONNECTED*/), - .nd_rsp_valid_o (trans_complete[s]), - .nd_rsp_ready_i (1'b1), // Always ready to accept completed transfers - .burst_req_o (idma_req[s]), - .burst_req_valid_o(be_valid[s]), - .burst_req_ready_i(be_ready[s]), - .burst_rsp_i (idma_rsp[s]), - .burst_rsp_valid_i(be_rsp_valid[s]), - .burst_rsp_ready_o(be_rsp_ready[s]), - .busy_o (midend_busy[s]) - ); - - // ------------------------------------------------------ - // BACKEND - // ------------------------------------------------------ - - // even channels: copy out data - if (s[0] == 1'b0) begin : gen_cpy_out - - // Meta Channel Widths - localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width( - AXI_ADDR_WIDTH, AXI_ID_WIDTH, AXI_USER_WIDTH - ); - localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); - localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); - - - typedef struct packed { - init_req_chan_t req_chan; - logic [`MY_MAX(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; - } init_read_req_chan_padded_t; - - typedef struct packed { - obi_a_chan_t a_chan; - logic [`MY_MAX(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; - } obi_read_a_chan_padded_t; - - typedef union packed { - init_read_req_chan_padded_t init; - obi_read_a_chan_padded_t obi; - } read_meta_channel_t; - - typedef struct packed { - axi_aw_chan_t aw_chan; - logic [`MY_MAX(axi_aw_chan_width, init_req_chan_width)-axi_aw_chan_width:0] padding; - } axi_write_aw_chan_padded_t; - - typedef struct packed { - init_req_chan_t req_chan; - logic [`MY_MAX(axi_aw_chan_width, init_req_chan_width)-init_req_chan_width:0] padding; - } init_write_req_chan_padded_t; - - typedef union packed { - axi_write_aw_chan_padded_t axi; - init_write_req_chan_padded_t init; - } write_meta_channel_t; - - // local buses - init_req_t init_read_req, init_write_req; - init_rsp_t init_read_rsp, init_write_rsp; - - idma_backend_r_obi_rw_init_w_axi #( - .DataWidth (AXI_DATA_WIDTH), - .AddrWidth (AXI_ADDR_WIDTH), - .UserWidth (AXI_USER_WIDTH), - .AxiIdWidth (AXI_ID_WIDTH), - .NumAxInFlight (NB_OUTSND_BURSTS), - .BufferDepth (32'd3), - .TFLenWidth (TFLenWidth), - .MemSysDepth (32'd0), - .CombinedShifter (1'b1), - .RAWCouplingAvail (1'b0), - .MaskInvalidData (1'b0), - .HardwareLegalizer (1'b1), - .RejectZeroTransfers (1'b1), - .idma_req_t (idma_req_t), - .idma_rsp_t (idma_rsp_t), - .idma_eh_req_t (idma_pkg::idma_eh_req_t), - .idma_busy_t (idma_pkg::idma_busy_t), - .axi_req_t (axi_req_t), - .axi_rsp_t (axi_resp_t), - .init_req_t (init_req_t), - .init_rsp_t (init_rsp_t), - .obi_req_t (obi_req_t), - .obi_rsp_t (obi_rsp_t), - .read_meta_channel_t (read_meta_channel_t), - .write_meta_channel_t(write_meta_channel_t) - ) i_idma_backend_r_obi_rw_init_w_axi ( - .clk_i, - .rst_ni, - .testmode_i (test_mode_i), - .idma_req_i (idma_req[s]), - .req_valid_i (be_valid[s]), - .req_ready_o (be_ready[s]), - .idma_rsp_o (idma_rsp[s]), - .rsp_valid_o (be_rsp_valid[s]), - .rsp_ready_i (be_rsp_ready[s]), - .idma_eh_req_i ('b0), - .eh_req_valid_i (1'b0), - .eh_req_ready_o ( /* NOT CONNECTED */), - .init_read_req_o (init_read_req), - .init_read_rsp_i (init_read_rsp), - .obi_read_req_o (obi_read_req_from_dma[s/2]), - .obi_read_rsp_i (obi_read_rsp_to_dma[s/2]), - .axi_write_req_o (dma_req[s]), - .axi_write_rsp_i (dma_rsp[s]), - .init_write_req_o(init_write_req), - .init_write_rsp_i(init_write_rsp), - .busy_o (idma_busy[s]) - ); - - // implement zero memory using init protocol - assign init_read_rsp.rsp_chan.init = '0; - assign init_read_rsp.rsp_valid = init_read_req.req_valid; // might need spill register - assign init_read_rsp.req_ready = 1'b1; - - // implement /dev/null - assign init_write_rsp.rsp_chan.init = '0; - assign init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register - assign init_write_rsp.req_ready = 1'b1; - - - // odd channels: copy in data - end else begin : gen_cpy_in - - // Meta Channel Widths - localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width( - AXI_ADDR_WIDTH, AXI_ID_WIDTH, AXI_USER_WIDTH - ); - localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); - localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); - - function int unsigned max_width(input int unsigned a, b); - return (a > b) ? a : b; - endfunction - - typedef struct packed { - axi_ar_chan_t ar_chan; - logic [`MY_MAX( -axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width) -)-axi_ar_chan_width:0] padding; - } axi_read_ar_chan_padded_t; - - typedef struct packed { - init_req_chan_t req_chan; - logic [`MY_MAX(axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width))-init_req_chan_width:0] padding; - } init_read_req_chan_padded_t; - - typedef struct packed { - obi_a_chan_t a_chan; - logic [`MY_MAX(axi_ar_chan_width, `MY_MAX(init_req_chan_width, obi_a_chan_width))-obi_a_chan_width:0] padding; - } obi_read_a_chan_padded_t; - - typedef union packed { - axi_read_ar_chan_padded_t axi; - init_read_req_chan_padded_t init; - obi_read_a_chan_padded_t obi; - } read_meta_channel_t; - - typedef struct packed { - init_req_chan_t req_chan; - logic [`MY_MAX(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; - } init_write_req_chan_padded_t; - - typedef struct packed { - obi_a_chan_t a_chan; - logic [`MY_MAX(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; - } obi_write_a_chan_padded_t; - - typedef union packed { - init_write_req_chan_padded_t init; - obi_write_a_chan_padded_t obi; - } write_meta_channel_t; - - // local buses - init_req_t init_read_req, init_write_req; - init_rsp_t init_read_rsp, init_write_rsp; - - idma_backend_r_axi_rw_init_rw_obi #( - .DataWidth (AXI_DATA_WIDTH), - .AddrWidth (AXI_ADDR_WIDTH), - .UserWidth (AXI_USER_WIDTH), - .AxiIdWidth (AXI_ID_WIDTH), - .NumAxInFlight (NB_OUTSND_BURSTS), - .BufferDepth (32'd3), - .TFLenWidth (TFLenWidth), - .MemSysDepth (32'd0), - .CombinedShifter (1'b1), - .RAWCouplingAvail (1'b0), - .MaskInvalidData (1'b0), - .HardwareLegalizer (1'b1), - .RejectZeroTransfers (1'b1), - .idma_req_t (idma_req_t), - .idma_rsp_t (idma_rsp_t), - .idma_eh_req_t (idma_pkg::idma_eh_req_t), - .idma_busy_t (idma_pkg::idma_busy_t), - .axi_req_t (axi_req_t), - .axi_rsp_t (axi_resp_t), - .init_req_t (init_req_t), - .init_rsp_t (init_rsp_t), - .obi_req_t (obi_req_t), - .obi_rsp_t (obi_rsp_t), - .read_meta_channel_t (read_meta_channel_t), - .write_meta_channel_t(write_meta_channel_t) - ) i_idma_backend_r_axi_rw_init_rw_obi ( - .clk_i, - .rst_ni, - .testmode_i (test_mode_i), - .idma_req_i (idma_req[s]), - .req_valid_i (be_valid[s]), - .req_ready_o (be_ready[s]), - .idma_rsp_o (idma_rsp[s]), - .rsp_valid_o (be_rsp_valid[s]), - .rsp_ready_i (be_rsp_ready[s]), - .idma_eh_req_i ('b0), - .eh_req_valid_i (1'b0), - .eh_req_ready_o ( /* NOT CONNECTED */), - .axi_read_req_o (dma_req[s]), - .axi_read_rsp_i (dma_rsp[s]), - .init_read_req_o (init_read_req), - .init_read_rsp_i (init_read_rsp), - .obi_read_req_o (obi_reorg_req_from_dma[s/2]), - .obi_read_rsp_i (obi_reorg_rsp_to_dma[s/2]), - .init_write_req_o(init_write_req), - .init_write_rsp_i(init_write_rsp), - .obi_write_req_o (obi_write_req_from_dma[s/2]), - .obi_write_rsp_i (obi_write_rsp_to_dma[s/2]), - .busy_o (idma_busy[s]) - ); - - // implement zero memory using init protocol - assign init_read_rsp.rsp_chan.init = '0; - assign init_read_rsp.rsp_valid = init_read_req.req_valid; // might need spill register - assign init_read_rsp.req_ready = 1'b1; - - // implement /dev/null - assign init_write_rsp.rsp_chan.init = '0; - assign init_write_rsp.rsp_valid = init_read_req.req_valid; // might need spill register - assign init_write_rsp.req_ready = 1'b1; - end : gen_cpy_in - end : gen_streams - - - // ------------------------------------------------------ - // MUX read OBI connections if specified - // ------------------------------------------------------ - for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin - if (MUX_READ) begin - localparam obi_pkg::obi_cfg_t sbr_obi_cfg = '{ - UseRReady: 1'b1, - CombGnt: 1'b0, - AddrWidth: AXI_ADDR_WIDTH, - DataWidth: AXI_DATA_WIDTH, - IdWidth: 0, - Integrity: 1'b0, - BeFull: 1'b1, - OptionalCfg: obi_pkg::ObiMinimalOptionalConfig - }; - - // iDMA OBI - - obi_mux #( - .SbrPortObiCfg (sbr_obi_cfg), - .MgrPortObiCfg (sbr_obi_cfg), - .sbr_port_obi_req_t(obi_req_t), - .sbr_port_a_chan_t (obi_a_chan_t), - .sbr_port_obi_rsp_t(obi_rsp_t), - .sbr_port_r_chan_t (obi_r_chan_t), - .mgr_port_obi_req_t(obi_req_t), - .mgr_port_obi_rsp_t(obi_rsp_t), - .NumSbrPorts (2), - .NumMaxTrans (2), - .UseIdForRouting (1'b0) - ) obi_read_mux_i ( - .clk_i, - .rst_ni, - .testmode_i (test_mode_i), - .sbr_ports_req_i({obi_reorg_req_from_dma[s], obi_read_req_from_dma[s]}), - .sbr_ports_rsp_o({obi_reorg_rsp_to_dma[s], obi_read_rsp_to_dma[s]}), - .mgr_port_req_o (obi_read_req_muxed[s]), - .mgr_port_rsp_i (obi_read_rsp_to_mux[s]) - ); - assign obi_reorg_req_from_rrc = '0; - assign obi_reorg_rsp_to_rrc = '0; - end else begin // if (MUX_READ) - // pass through the read req/rsp from/to dma - assign obi_read_req_muxed = obi_read_req_from_dma; - assign obi_read_rsp_to_dma = obi_read_rsp_to_mux; - - obi_rready_converter #( - .obi_a_chan_t(obi_a_chan_t), - .obi_r_chan_t(obi_r_chan_t), - .DEPTH(1) - ) - obi_rready_converter_reorg_i ( - .clk_i, - .rst_ni, - .test_mode_i, - .sbr_a_chan_i(obi_reorg_req_from_dma[s].a), - .req_i(obi_reorg_req_from_dma[s].req), - .gnt_o(obi_reorg_rsp_to_dma[s].gnt), - .rready_i(obi_reorg_req_from_dma[s].rready), - .sbr_r_chan_o(obi_reorg_rsp_to_dma[s].r), - .rvalid_o(obi_reorg_rsp_to_dma[s].rvalid), - .mgr_a_chan_o(obi_reorg_req_from_rrc[s].a), - .req_o(obi_reorg_req_from_rrc[s].req), - .rready_o(obi_reorg_req_from_rrc[s].rready), - .mgr_r_chan_i(obi_reorg_rsp_to_rrc[s].r), - .gnt_i(obi_reorg_rsp_to_rrc[s].gnt), - .rvalid_i(obi_reorg_rsp_to_rrc[s].rvalid) - ); - end // else: !if(MUX_READ) - - obi_rready_converter #( - .obi_a_chan_t(obi_a_chan_t), - .obi_r_chan_t(obi_r_chan_t), - .DEPTH(1) - ) - obi_rready_converter_read_i ( - .clk_i, - .rst_ni, - .test_mode_i, - .sbr_a_chan_i(obi_read_req_muxed[s].a), - .req_i(obi_read_req_muxed[s].req), - .gnt_o(obi_read_rsp_to_mux[s].gnt), - .rready_i(obi_read_req_muxed[s].rready), - .sbr_r_chan_o(obi_read_rsp_to_mux[s].r), - .rvalid_o(obi_read_rsp_to_mux[s].rvalid), - .mgr_a_chan_o(obi_read_req_from_rrc[s].a), - .req_o(obi_read_req_from_rrc[s].req), - .rready_o(obi_read_req_from_rrc[s].rready), - .mgr_r_chan_i(obi_read_rsp_to_rrc[s].r), - .gnt_i(obi_read_rsp_to_rrc[s].gnt), - .rvalid_i(obi_read_rsp_to_rrc[s].rvalid) - ); - - - - obi_rready_converter #( - .obi_a_chan_t(obi_a_chan_t), - .obi_r_chan_t(obi_r_chan_t), - .DEPTH(1) - ) - obi_rready_converter_wr_i ( - .clk_i, - .rst_ni, - .test_mode_i, - .sbr_a_chan_i(obi_write_req_from_dma[s].a), - .req_i(obi_write_req_from_dma[s].req), - .gnt_o(obi_write_rsp_to_dma[s].gnt), - .rready_i(obi_write_req_from_dma[s].rready), - .sbr_r_chan_o(obi_write_rsp_to_dma[s].r), - .rvalid_o(obi_write_rsp_to_dma[s].rvalid), - .mgr_a_chan_o(obi_write_req_from_rrc[s].a), - .req_o(obi_write_req_from_rrc[s].req), - .rready_o(obi_write_req_from_rrc[s].rready), - .mgr_r_chan_i(obi_write_rsp_to_rrc[s].r), - .gnt_i(obi_write_rsp_to_rrc[s].gnt), - .rvalid_i(obi_write_rsp_to_rrc[s].rvalid) - ); - end - - - // ------------------------------------------------------ - // TCDM connections - // ------------------------------------------------------ - for (genvar s = 0; s < NUM_BIDIR_STREAMS; s++) begin - - logic tcdm_master_we_0; - logic tcdm_master_we_1; - logic tcdm_master_we_2; - logic tcdm_master_we_3; - logic tcdm_master_we_4; - logic tcdm_master_we_5; - - mem_to_banks #( - .AddrWidth(AXI_ADDR_WIDTH), - .DataWidth(AXI_DATA_WIDTH), - .NumBanks (32'd2), - .HideStrb (1'b1), - .MaxTrans (32'd1), - .FifoDepth(32'd1) - ) i_mem_to_banks_read ( - .clk_i, - .rst_ni, - .req_i(obi_read_req_from_rrc[s].req), - .gnt_o(obi_read_rsp_to_rrc[s].gnt), - .addr_i(obi_read_req_from_rrc[s].a.addr), - .wdata_i(obi_read_req_from_rrc[s].a.wdata), - .strb_i(obi_read_req_from_rrc[s].a.be), - .atop_i('0), - .we_i(obi_read_req_from_rrc[s].a.we), - .rvalid_o(obi_read_rsp_to_rrc[s].rvalid), - .rdata_o(obi_read_rsp_to_rrc[s].r.rdata), - .bank_req_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].req - }), - .bank_gnt_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].gnt, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].gnt - }), - .bank_addr_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].add, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].add - }), - .bank_wdata_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].data, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].data - }), - .bank_strb_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].be, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].be - }), - .bank_atop_o( /* NOT CONNECTED */), - .bank_we_o({tcdm_master_we_3, tcdm_master_we_2}), - .bank_rvalid_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].r_valid, - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].r_valid - }), - .bank_rdata_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].r_data, - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].r_data - }) - ); - - - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].boffs = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].lrdy = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].user = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].boffs = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].lrdy = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].user = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+2].wen = !tcdm_master_we_2; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+3].wen = !tcdm_master_we_3; - - if (!MUX_READ) begin // if we don't mux the read, we have 6*NUM_BIDIR_STREAMS interfaces and the reorg - // interface goes straight to TCDM masters 5 and 4. - mem_to_banks #( - .AddrWidth(AXI_ADDR_WIDTH), - .DataWidth(AXI_DATA_WIDTH), - .NumBanks (32'd2), - .HideStrb (1'b1), - .MaxTrans (32'd1), - .FifoDepth(32'd1) - ) i_mem_to_banks_reorg ( - .clk_i, - .rst_ni, - .req_i(obi_reorg_req_from_rrc[s].req), - .gnt_o(obi_reorg_rsp_to_rrc[s].gnt), - .addr_i(obi_reorg_req_from_rrc[s].a.addr), - .wdata_i(obi_reorg_req_from_rrc[s].a.wdata), - .strb_i(obi_reorg_req_from_rrc[s].a.be), - .atop_i('0), - .we_i(obi_reorg_req_from_rrc[s].a.we), - .rvalid_o(obi_reorg_rsp_to_rrc[s].rvalid), - .rdata_o(obi_reorg_rsp_to_rrc[s].r.rdata), - .bank_req_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].req - }), - .bank_gnt_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].gnt, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].gnt - }), - .bank_addr_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].add, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].add - }), - .bank_wdata_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].data, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].data - }), - .bank_strb_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].be, tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].be - }), - .bank_atop_o( /* NOT CONNECTED */), - .bank_we_o({tcdm_master_we_5, tcdm_master_we_4}), - .bank_rvalid_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].r_valid, - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].r_valid - }), - .bank_rdata_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].r_data, - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].r_data - }) - ); - - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].boffs = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].lrdy = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].user = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].boffs = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].lrdy = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].user = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+4].wen = !tcdm_master_we_4; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+5].wen = !tcdm_master_we_5; - - end - mem_to_banks #( - .AddrWidth(AXI_ADDR_WIDTH), - .DataWidth(AXI_DATA_WIDTH), - .NumBanks (32'd2), - .HideStrb (1'b1), - .MaxTrans (32'd1), - .FifoDepth(32'd1) - ) i_mem_to_banks_write ( - .clk_i, - .rst_ni, - .req_i(obi_write_req_from_rrc[s].req), - .gnt_o(obi_write_rsp_to_rrc[s].gnt), - .addr_i(obi_write_req_from_rrc[s].a.addr), - .wdata_i(obi_write_req_from_rrc[s].a.wdata), - .strb_i(obi_write_req_from_rrc[s].a.be), - .atop_i('0), - .we_i(obi_write_req_from_rrc[s].a.we), - .rvalid_o(obi_write_rsp_to_rrc[s].rvalid), - .rdata_o(obi_write_rsp_to_rrc[s].r.rdata), - .bank_req_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].req, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].req - }), - .bank_gnt_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].gnt, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].gnt - }), - .bank_addr_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].add, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].add - }), - .bank_wdata_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].data, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].data - }), - .bank_strb_o({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].be, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].be - }), - .bank_atop_o( /* NOT CONNECTED */), - .bank_we_o({tcdm_master_we_1, tcdm_master_we_0}), - .bank_rvalid_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].r_valid, - tcdm_master[NB_TCDM_PORTS_PER_STRM*s].r_valid - }), - .bank_rdata_i({ - tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].r_data, tcdm_master[NB_TCDM_PORTS_PER_STRM*s].r_data - }) - ); - - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+0].boffs = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+0].lrdy = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+0].user = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].boffs = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].lrdy = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].user = '0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+0].wen = !tcdm_master_we_0; - assign tcdm_master[NB_TCDM_PORTS_PER_STRM*s+1].wen = !tcdm_master_we_1; - - end -endmodule -`undef MY_MAX diff --git a/target/rtl/idma_generated.sv b/target/rtl/idma_generated.sv deleted file mode 100644 index ad6034ef..00000000 --- a/target/rtl/idma_generated.sv +++ /dev/null @@ -1,19916 +0,0 @@ -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "idma/guard.svh" -`include "common_cells/registers.svh" - -/// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_rw_axi #( - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// `r_dp_req_t` type: - parameter type r_dp_req_t = logic, - /// `w_dp_req_t` type: - parameter type w_dp_req_t = logic, - /// `r_dp_rsp_t` type: - parameter type r_dp_rsp_t = logic, - /// `w_dp_rsp_t` type: - parameter type w_dp_rsp_t = logic, - /// Write Meta channel type - parameter type write_meta_channel_t = logic, - /// Read Meta channel type - parameter type read_meta_channel_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// Read datapath request - input r_dp_req_t r_dp_req_i, - /// Read datapath request valid - input logic r_dp_valid_i, - /// Read datapath request ready - output logic r_dp_ready_o, - - /// Read datapath response - output r_dp_rsp_t r_dp_rsp_o, - /// Read datapath response valid - output logic r_dp_valid_o, - /// Read datapath response valid - input logic r_dp_ready_i, - - /// Write datapath request - input w_dp_req_t w_dp_req_i, - /// Write datapath request valid - input logic w_dp_valid_i, - /// Write datapath request ready - output logic w_dp_ready_o, - - /// Write datapath response - output w_dp_rsp_t w_dp_rsp_o, - /// Write datapath response valid - output logic w_dp_valid_o, - /// Write datapath response valid - input logic w_dp_ready_i, - - /// Read meta request - input read_meta_channel_t ar_req_i, - /// Read meta request valid - input logic ar_valid_i, - /// Read meta request ready - output logic ar_ready_o, - - /// Write meta request - input write_meta_channel_t aw_req_i, - /// Write meta request valid - input logic aw_valid_i, - /// Write meta request ready - output logic aw_ready_o, - - /// Datapath poison signal - input logic dp_poison_i, - - /// Response channel valid and ready - output logic r_chan_ready_o, - output logic r_chan_valid_o, - - /// Read part of the datapath is busy - output logic r_dp_busy_o, - /// Write part of the datapath is busy - output logic w_dp_busy_o, - /// Buffer is busy - output logic buffer_busy_o -); - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - - /// Data type - typedef logic [DataWidth-1:0] data_t; - /// Offset type - typedef logic [StrbWidth-1:0] strb_t; - /// Byte type - typedef logic [7:0] byte_t; - - // inbound control signals to the read buffer: controlled by the read process - strb_t buffer_in_valid; - - strb_t buffer_in_ready; - // outbound control signals of the buffer: controlled by the write process - strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t - buffer_out_ready, buffer_out_ready_shifted; - - // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] - buffer_in, buffer_in_shifted; - // aligned and coalesced data leaving the buffer - byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; - - //-------------------------------------- - // Read Ports - //-------------------------------------- - - idma_axi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .ar_chan_t ( read_meta_channel_t ), - .read_req_t ( axi_req_t ), - .read_rsp_t ( axi_rsp_t ) - ) i_idma_axi_read ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( r_dp_valid_i ), - .r_dp_ready_o ( r_dp_ready_o ), - .r_dp_rsp_o ( r_dp_rsp_o ), - .r_dp_valid_o ( r_dp_valid_o ), - .r_dp_ready_i ( r_dp_ready_i ), - .ar_req_i ( ar_req_i ), - .ar_valid_i ( ar_valid_i ), - .ar_ready_o ( ar_ready_o ), - .read_req_o ( axi_read_req_o ), - .read_rsp_i ( axi_read_rsp_i ), - .r_chan_valid_o ( r_chan_valid_o ), - .r_chan_ready_o ( r_chan_ready_o ), - .buffer_in_o ( buffer_in ), - .buffer_in_valid_o ( buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - //-------------------------------------- - // Read Barrel shifter - //-------------------------------------- - - assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); - - //-------------------------------------- - // Buffer - //-------------------------------------- - - idma_dataflow_element #( - .BufferDepth ( BufferDepth ), - .StrbWidth ( StrbWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .strb_t ( strb_t ), - .byte_t ( byte_t ) - ) i_dataflow_element ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .data_i ( buffer_in_shifted ), - .valid_i ( buffer_in_valid ), - .ready_o ( buffer_in_ready ), - .data_o ( buffer_out ), - .valid_o ( buffer_out_valid ), - .ready_i ( buffer_out_ready_shifted ) - ); - - //-------------------------------------- - // Write Barrel shifter - //-------------------------------------- - - assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); - assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; - assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; - - //-------------------------------------- - // Write Ports - //-------------------------------------- - - idma_axi_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .aw_chan_t ( write_meta_channel_t ), - .write_req_t ( axi_req_t ), - .write_rsp_t ( axi_rsp_t ) - ) i_idma_axi_write ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( w_dp_valid_i ), - .w_dp_ready_o ( w_dp_ready_o ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( w_dp_rsp_o ), - .w_dp_valid_o ( w_dp_valid_o ), - .w_dp_ready_i ( w_dp_ready_i ), - .aw_req_i ( aw_req_i ), - .aw_valid_i ( aw_valid_i ), - .aw_ready_o ( aw_ready_o ), - .write_req_o ( axi_write_req_o ), - .write_rsp_i ( axi_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( buffer_out_ready ) - ); - - //-------------------------------------- - // Module Control - //-------------------------------------- - assign r_dp_busy_o = r_dp_valid_i; - assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; - assign buffer_busy_o = |buffer_out_valid; - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "idma/guard.svh" -`include "common_cells/registers.svh" - -/// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_r_obi_w_axi #( - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// `r_dp_req_t` type: - parameter type r_dp_req_t = logic, - /// `w_dp_req_t` type: - parameter type w_dp_req_t = logic, - /// `r_dp_rsp_t` type: - parameter type r_dp_rsp_t = logic, - /// `w_dp_rsp_t` type: - parameter type w_dp_rsp_t = logic, - /// Write Meta channel type - parameter type write_meta_channel_t = logic, - /// Read Meta channel type - parameter type read_meta_channel_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// Read datapath request - input r_dp_req_t r_dp_req_i, - /// Read datapath request valid - input logic r_dp_valid_i, - /// Read datapath request ready - output logic r_dp_ready_o, - - /// Read datapath response - output r_dp_rsp_t r_dp_rsp_o, - /// Read datapath response valid - output logic r_dp_valid_o, - /// Read datapath response valid - input logic r_dp_ready_i, - - /// Write datapath request - input w_dp_req_t w_dp_req_i, - /// Write datapath request valid - input logic w_dp_valid_i, - /// Write datapath request ready - output logic w_dp_ready_o, - - /// Write datapath response - output w_dp_rsp_t w_dp_rsp_o, - /// Write datapath response valid - output logic w_dp_valid_o, - /// Write datapath response valid - input logic w_dp_ready_i, - - /// Read meta request - input read_meta_channel_t ar_req_i, - /// Read meta request valid - input logic ar_valid_i, - /// Read meta request ready - output logic ar_ready_o, - - /// Write meta request - input write_meta_channel_t aw_req_i, - /// Write meta request valid - input logic aw_valid_i, - /// Write meta request ready - output logic aw_ready_o, - - /// Datapath poison signal - input logic dp_poison_i, - - /// Response channel valid and ready - output logic r_chan_ready_o, - output logic r_chan_valid_o, - - /// Read part of the datapath is busy - output logic r_dp_busy_o, - /// Write part of the datapath is busy - output logic w_dp_busy_o, - /// Buffer is busy - output logic buffer_busy_o -); - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - - /// Data type - typedef logic [DataWidth-1:0] data_t; - /// Offset type - typedef logic [StrbWidth-1:0] strb_t; - /// Byte type - typedef logic [7:0] byte_t; - - // inbound control signals to the read buffer: controlled by the read process - strb_t buffer_in_valid; - - strb_t buffer_in_ready; - // outbound control signals of the buffer: controlled by the write process - strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t - buffer_out_ready, buffer_out_ready_shifted; - - // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] - buffer_in, buffer_in_shifted; - // aligned and coalesced data leaving the buffer - byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; - - //-------------------------------------- - // Read Ports - //-------------------------------------- - - idma_obi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .read_meta_chan_t ( read_meta_channel_t ), - .read_req_t ( obi_req_t ), - .read_rsp_t ( obi_rsp_t ) - ) i_idma_obi_read ( - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( r_dp_valid_i ), - .r_dp_ready_o ( r_dp_ready_o ), - .r_dp_rsp_o ( r_dp_rsp_o ), - .r_dp_valid_o ( r_dp_valid_o ), - .r_dp_ready_i ( r_dp_ready_i ), - .read_meta_req_i ( ar_req_i ), - .read_meta_valid_i ( ar_valid_i ), - .read_meta_ready_o ( ar_ready_o ), - .read_req_o ( obi_read_req_o ), - .read_rsp_i ( obi_read_rsp_i ), - .r_chan_valid_o ( r_chan_valid_o ), - .r_chan_ready_o ( r_chan_ready_o ), - .buffer_in_o ( buffer_in ), - .buffer_in_valid_o ( buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - //-------------------------------------- - // Read Barrel shifter - //-------------------------------------- - - assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); - - //-------------------------------------- - // Buffer - //-------------------------------------- - - idma_dataflow_element #( - .BufferDepth ( BufferDepth ), - .StrbWidth ( StrbWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .strb_t ( strb_t ), - .byte_t ( byte_t ) - ) i_dataflow_element ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .data_i ( buffer_in_shifted ), - .valid_i ( buffer_in_valid ), - .ready_o ( buffer_in_ready ), - .data_o ( buffer_out ), - .valid_o ( buffer_out_valid ), - .ready_i ( buffer_out_ready_shifted ) - ); - - //-------------------------------------- - // Write Barrel shifter - //-------------------------------------- - - assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); - assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; - assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; - - //-------------------------------------- - // Write Ports - //-------------------------------------- - - idma_axi_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .aw_chan_t ( write_meta_channel_t ), - .write_req_t ( axi_req_t ), - .write_rsp_t ( axi_rsp_t ) - ) i_idma_axi_write ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( w_dp_valid_i ), - .w_dp_ready_o ( w_dp_ready_o ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( w_dp_rsp_o ), - .w_dp_valid_o ( w_dp_valid_o ), - .w_dp_ready_i ( w_dp_ready_i ), - .aw_req_i ( aw_req_i ), - .aw_valid_i ( aw_valid_i ), - .aw_ready_o ( aw_ready_o ), - .write_req_o ( axi_write_req_o ), - .write_rsp_i ( axi_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( buffer_out_ready ) - ); - - //-------------------------------------- - // Module Control - //-------------------------------------- - assign r_dp_busy_o = r_dp_valid_i; - assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; - assign buffer_busy_o = |buffer_out_valid; - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "idma/guard.svh" -`include "common_cells/registers.svh" - -/// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_r_axi_w_obi #( - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// `r_dp_req_t` type: - parameter type r_dp_req_t = logic, - /// `w_dp_req_t` type: - parameter type w_dp_req_t = logic, - /// `r_dp_rsp_t` type: - parameter type r_dp_rsp_t = logic, - /// `w_dp_rsp_t` type: - parameter type w_dp_rsp_t = logic, - /// Write Meta channel type - parameter type write_meta_channel_t = logic, - /// Read Meta channel type - parameter type read_meta_channel_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, - - /// Read datapath request - input r_dp_req_t r_dp_req_i, - /// Read datapath request valid - input logic r_dp_valid_i, - /// Read datapath request ready - output logic r_dp_ready_o, - - /// Read datapath response - output r_dp_rsp_t r_dp_rsp_o, - /// Read datapath response valid - output logic r_dp_valid_o, - /// Read datapath response valid - input logic r_dp_ready_i, - - /// Write datapath request - input w_dp_req_t w_dp_req_i, - /// Write datapath request valid - input logic w_dp_valid_i, - /// Write datapath request ready - output logic w_dp_ready_o, - - /// Write datapath response - output w_dp_rsp_t w_dp_rsp_o, - /// Write datapath response valid - output logic w_dp_valid_o, - /// Write datapath response valid - input logic w_dp_ready_i, - - /// Read meta request - input read_meta_channel_t ar_req_i, - /// Read meta request valid - input logic ar_valid_i, - /// Read meta request ready - output logic ar_ready_o, - - /// Write meta request - input write_meta_channel_t aw_req_i, - /// Write meta request valid - input logic aw_valid_i, - /// Write meta request ready - output logic aw_ready_o, - - /// Datapath poison signal - input logic dp_poison_i, - - /// Response channel valid and ready - output logic r_chan_ready_o, - output logic r_chan_valid_o, - - /// Read part of the datapath is busy - output logic r_dp_busy_o, - /// Write part of the datapath is busy - output logic w_dp_busy_o, - /// Buffer is busy - output logic buffer_busy_o -); - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - - /// Data type - typedef logic [DataWidth-1:0] data_t; - /// Offset type - typedef logic [StrbWidth-1:0] strb_t; - /// Byte type - typedef logic [7:0] byte_t; - - // inbound control signals to the read buffer: controlled by the read process - strb_t buffer_in_valid; - - strb_t buffer_in_ready; - // outbound control signals of the buffer: controlled by the write process - strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t - buffer_out_ready, buffer_out_ready_shifted; - - // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] - buffer_in, buffer_in_shifted; - // aligned and coalesced data leaving the buffer - byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; - - //-------------------------------------- - // Read Ports - //-------------------------------------- - - idma_axi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .ar_chan_t ( read_meta_channel_t ), - .read_req_t ( axi_req_t ), - .read_rsp_t ( axi_rsp_t ) - ) i_idma_axi_read ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( r_dp_valid_i ), - .r_dp_ready_o ( r_dp_ready_o ), - .r_dp_rsp_o ( r_dp_rsp_o ), - .r_dp_valid_o ( r_dp_valid_o ), - .r_dp_ready_i ( r_dp_ready_i ), - .ar_req_i ( ar_req_i ), - .ar_valid_i ( ar_valid_i ), - .ar_ready_o ( ar_ready_o ), - .read_req_o ( axi_read_req_o ), - .read_rsp_i ( axi_read_rsp_i ), - .r_chan_valid_o ( r_chan_valid_o ), - .r_chan_ready_o ( r_chan_ready_o ), - .buffer_in_o ( buffer_in ), - .buffer_in_valid_o ( buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - //-------------------------------------- - // Read Barrel shifter - //-------------------------------------- - - assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); - - //-------------------------------------- - // Buffer - //-------------------------------------- - - idma_dataflow_element #( - .BufferDepth ( BufferDepth ), - .StrbWidth ( StrbWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .strb_t ( strb_t ), - .byte_t ( byte_t ) - ) i_dataflow_element ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .data_i ( buffer_in_shifted ), - .valid_i ( buffer_in_valid ), - .ready_o ( buffer_in_ready ), - .data_o ( buffer_out ), - .valid_o ( buffer_out_valid ), - .ready_i ( buffer_out_ready_shifted ) - ); - - //-------------------------------------- - // Write Barrel shifter - //-------------------------------------- - - assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); - assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; - assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; - - //-------------------------------------- - // Write Ports - //-------------------------------------- - - idma_obi_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_req_t ( obi_req_t ), - .write_rsp_t ( obi_rsp_t ) - ) i_idma_obi_write ( - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( w_dp_valid_i ), - .w_dp_ready_o ( w_dp_ready_o ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( w_dp_rsp_o ), - .w_dp_valid_o ( w_dp_valid_o ), - .w_dp_ready_i ( w_dp_ready_i ), - .aw_req_i ( aw_req_i ), - .aw_valid_i ( aw_valid_i ), - .aw_ready_o ( aw_ready_o ), - .write_req_o ( obi_write_req_o ), - .write_rsp_i ( obi_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( buffer_out_ready ) - ); - - //-------------------------------------- - // Module Control - //-------------------------------------- - assign r_dp_busy_o = r_dp_valid_i; - assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; - assign buffer_busy_o = |buffer_out_valid; - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "idma/guard.svh" -`include "common_cells/registers.svh" - -/// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_rw_axi_rw_axis #( - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// `r_dp_req_t` type: - parameter type r_dp_req_t = logic, - /// `w_dp_req_t` type: - parameter type w_dp_req_t = logic, - /// `r_dp_rsp_t` type: - parameter type r_dp_rsp_t = logic, - /// `w_dp_rsp_t` type: - parameter type w_dp_rsp_t = logic, - /// Write Meta channel type - parameter type write_meta_channel_t = logic, - parameter type write_meta_channel_tagged_t = logic, - /// Read Meta channel type - parameter type read_meta_channel_t = logic, - parameter type read_meta_channel_tagged_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// AXI Stream Request and Response channel type - parameter type axis_req_t = logic, - parameter type axis_rsp_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// AXI Stream read request - input axis_req_t axis_read_req_i, - /// AXI Stream read response - output axis_rsp_t axis_read_rsp_o, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// AXI Stream write request - output axis_req_t axis_write_req_o, - /// AXI Stream write response - input axis_rsp_t axis_write_rsp_i, - - /// Read datapath request - input r_dp_req_t r_dp_req_i, - /// Read datapath request valid - input logic r_dp_valid_i, - /// Read datapath request ready - output logic r_dp_ready_o, - - /// Read datapath response - output r_dp_rsp_t r_dp_rsp_o, - /// Read datapath response valid - output logic r_dp_valid_o, - /// Read datapath response valid - input logic r_dp_ready_i, - - /// Write datapath request - input w_dp_req_t w_dp_req_i, - /// Write datapath request valid - input logic w_dp_valid_i, - /// Write datapath request ready - output logic w_dp_ready_o, - - /// Write datapath response - output w_dp_rsp_t w_dp_rsp_o, - /// Write datapath response valid - output logic w_dp_valid_o, - /// Write datapath response valid - input logic w_dp_ready_i, - - /// Read meta request - input read_meta_channel_tagged_t ar_req_i, - /// Read meta request valid - input logic ar_valid_i, - /// Read meta request ready - output logic ar_ready_o, - - /// Write meta request - input write_meta_channel_tagged_t aw_req_i, - /// Write meta request valid - input logic aw_valid_i, - /// Write meta request ready - output logic aw_ready_o, - - /// Datapath poison signal - input logic dp_poison_i, - - /// Response channel valid and ready - output logic r_chan_ready_o, - output logic r_chan_valid_o, - - /// Read part of the datapath is busy - output logic r_dp_busy_o, - /// Write part of the datapath is busy - output logic w_dp_busy_o, - /// Buffer is busy - output logic buffer_busy_o -); - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - - /// Data type - typedef logic [DataWidth-1:0] data_t; - /// Offset type - typedef logic [StrbWidth-1:0] strb_t; - /// Byte type - typedef logic [7:0] byte_t; - - // inbound control signals to the read buffer: controlled by the read process - strb_t axi_buffer_in_valid, axis_buffer_in_valid, buffer_in_valid; - - strb_t buffer_in_ready; - // outbound control signals of the buffer: controlled by the write process - strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t axi_buffer_out_ready, axis_buffer_out_ready, - buffer_out_ready, buffer_out_ready_shifted; - - // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] axi_buffer_in, axis_buffer_in, - buffer_in, buffer_in_shifted; - // aligned and coalesced data leaving the buffer - byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; - - // Read multiplexed signals - logic axi_r_chan_valid, axis_r_chan_valid; - logic axi_r_chan_ready, axis_r_chan_ready; - logic axi_r_dp_valid, axis_r_dp_valid; - logic axi_r_dp_ready, axis_r_dp_ready; - r_dp_rsp_t axi_r_dp_rsp, axis_r_dp_rsp; - - logic axi_ar_ready, axis_ar_ready; - - // Write multiplexed signals - logic axi_w_dp_rsp_valid, axis_w_dp_rsp_valid; - logic axi_w_dp_rsp_ready, axis_w_dp_rsp_ready; - logic axi_w_dp_ready, axis_w_dp_ready; - w_dp_rsp_t axi_w_dp_rsp, axis_w_dp_rsp; - - logic axi_aw_ready, axis_aw_ready; - logic w_dp_req_valid, w_dp_req_ready; - logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; - logic w_dp_rsp_valid, w_dp_rsp_ready; - w_dp_rsp_t w_dp_rsp_mux; - - // Write Response FIFO signals - logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; - idma_pkg::protocol_e w_resp_fifo_out_protocol; - logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; - - //-------------------------------------- - // Read Ports - //-------------------------------------- - - idma_axi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .ar_chan_t ( read_meta_channel_t ), - .read_req_t ( axi_req_t ), - .read_rsp_t ( axi_rsp_t ) - ) i_idma_axi_read ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_valid_i ), - .r_dp_ready_o ( axi_r_dp_ready ), - .r_dp_rsp_o ( axi_r_dp_rsp ), - .r_dp_valid_o ( axi_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_ready_i ), - .ar_req_i ( ar_req_i.ar_req ), - .ar_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI) & ar_valid_i ), - .ar_ready_o ( axi_ar_ready ), - .read_req_o ( axi_read_req_o ), - .read_rsp_i ( axi_read_rsp_i ), - .r_chan_valid_o ( axi_r_chan_valid ), - .r_chan_ready_o ( axi_r_chan_ready ), - .buffer_in_o ( axi_buffer_in ), - .buffer_in_valid_o ( axi_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - idma_axis_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .read_meta_chan_t ( read_meta_channel_t ), - .read_req_t ( axis_req_t ), - .read_rsp_t ( axis_rsp_t ) - ) i_idma_axis_read ( - .r_dp_req_i ( r_dp_req_i ), - .r_dp_req_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI_STREAM) & r_dp_valid_i ), - .r_dp_req_ready_o ( axis_r_dp_ready ), - .r_dp_rsp_o ( axis_r_dp_rsp ), - .r_dp_rsp_valid_o ( axis_r_dp_valid ), - .r_dp_rsp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI_STREAM) & r_dp_ready_i ), - .read_meta_req_i ( ar_req_i.ar_req ), - .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI_STREAM) & ar_valid_i ), - .read_meta_ready_o ( axis_ar_ready ), - .read_req_i ( axis_read_req_i ), - .read_rsp_o ( axis_read_rsp_o ), - .r_chan_valid_o ( axis_r_chan_valid ), - .r_chan_ready_o ( axis_r_chan_ready ), - .buffer_in_o ( axis_buffer_in ), - .buffer_in_valid_o ( axis_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - //-------------------------------------- - // Read Multiplexers - //-------------------------------------- - - always_comb begin : gen_read_meta_channel_multiplexer - case(ar_req_i.src_protocol) - idma_pkg::AXI: ar_ready_o = axi_ar_ready; - idma_pkg::AXI_STREAM: ar_ready_o = axis_ar_ready; - default: ar_ready_o = 1'b0; - endcase - end - - always_comb begin : gen_read_multiplexer - case(r_dp_req_i.src_protocol) - idma_pkg::AXI: begin - r_chan_valid_o = axi_r_chan_valid; - r_chan_ready_o = axi_r_chan_ready; - - r_dp_ready_o = axi_r_dp_ready; - r_dp_rsp_o = axi_r_dp_rsp; - r_dp_valid_o = axi_r_dp_valid; - - buffer_in = axi_buffer_in; - buffer_in_valid = axi_buffer_in_valid; - end - idma_pkg::AXI_STREAM: begin - r_chan_valid_o = axis_r_chan_valid; - r_chan_ready_o = axis_r_chan_ready; - - r_dp_ready_o = axis_r_dp_ready; - r_dp_rsp_o = axis_r_dp_rsp; - r_dp_valid_o = axis_r_dp_valid; - - buffer_in = axis_buffer_in; - buffer_in_valid = axis_buffer_in_valid; - end - default: begin - r_chan_valid_o = 1'b0; - r_chan_ready_o = 1'b0; - - r_dp_ready_o = 1'b0; - r_dp_rsp_o = '0; - r_dp_valid_o = 1'b0; - - buffer_in = '0; - buffer_in_valid = '0; - end - endcase - end - - //-------------------------------------- - // Read Barrel shifter - //-------------------------------------- - - assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); - - //-------------------------------------- - // Buffer - //-------------------------------------- - - idma_dataflow_element #( - .BufferDepth ( BufferDepth ), - .StrbWidth ( StrbWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .strb_t ( strb_t ), - .byte_t ( byte_t ) - ) i_dataflow_element ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .data_i ( buffer_in_shifted ), - .valid_i ( buffer_in_valid ), - .ready_o ( buffer_in_ready ), - .data_o ( buffer_out ), - .valid_o ( buffer_out_valid ), - .ready_i ( buffer_out_ready_shifted ) - ); - - //-------------------------------------- - // Write Barrel shifter - //-------------------------------------- - - assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); - assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; - assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; - - //-------------------------------------- - // Write Request Demultiplexer - //-------------------------------------- - - // Split write request to write response fifo and write ports - stream_fork #( - .N_OUP ( 2 ) - ) i_write_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( w_dp_valid_i ), - .ready_o ( w_dp_ready_o ), - .valid_o ( { w_resp_fifo_in_valid, w_dp_req_valid } ), - .ready_i ( { w_resp_fifo_in_ready, w_dp_req_ready } ) - ); - - // Demux write request to correct write port - always_comb begin : gen_write_multiplexer - case(w_dp_req_i.dst_protocol) - idma_pkg::AXI: begin - w_dp_req_ready = axi_w_dp_ready; - buffer_out_ready = axi_buffer_out_ready; - end - idma_pkg::AXI_STREAM: begin - w_dp_req_ready = axis_w_dp_ready; - buffer_out_ready = axis_buffer_out_ready; - end - default: begin - w_dp_req_ready = 1'b0; - buffer_out_ready = '0; - end - endcase - end - - // Demux write meta channel to correct write port - always_comb begin : gen_write_meta_channel_multiplexer - case(aw_req_i.dst_protocol) - idma_pkg::AXI: aw_ready_o = axi_aw_ready; - idma_pkg::AXI_STREAM: aw_ready_o = axis_aw_ready; - default: aw_ready_o = 1'b0; - endcase - end - - //-------------------------------------- - // Write Ports - //-------------------------------------- - - idma_axi_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .aw_chan_t ( write_meta_channel_t ), - .write_req_t ( axi_req_t ), - .write_rsp_t ( axi_rsp_t ) - ) i_idma_axi_write ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::AXI) & w_dp_req_valid ), - .w_dp_ready_o ( axi_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( axi_w_dp_rsp ), - .w_dp_valid_o ( axi_w_dp_rsp_valid ), - .w_dp_ready_i ( axi_w_dp_rsp_ready ), - .aw_req_i ( aw_req_i.aw_req ), - .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::AXI) & aw_valid_i ), - .aw_ready_o ( axi_aw_ready ), - .write_req_o ( axi_write_req_o ), - .write_rsp_i ( axi_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( axi_buffer_out_ready ) - ); - - idma_axis_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_req_t ( axis_req_t ), - .write_rsp_t ( axis_rsp_t ) - ) i_idma_axis_write ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .w_dp_req_i ( w_dp_req_i ), - .w_dp_req_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::AXI_STREAM) & w_dp_req_valid ), - .w_dp_req_ready_o ( axis_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( axis_w_dp_rsp ), - .w_dp_rsp_valid_o ( axis_w_dp_rsp_valid ), - .w_dp_rsp_ready_i ( axis_w_dp_rsp_ready ), - .aw_req_i ( aw_req_i.aw_req ), - .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::AXI_STREAM) & aw_valid_i ), - .aw_ready_o ( axis_aw_ready ), - .write_req_o ( axis_write_req_o ), - .write_rsp_i ( axis_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( axis_buffer_out_ready ) - ); - - //-------------------------------------- - // Write Response FIFO - //-------------------------------------- - // Needed to be able to route the write reponses properly - // Insert when data write happens - // Remove when write response comes - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( idma_pkg::protocol_e ), - .PrintInfo ( PrintFifoInfo ) - ) i_write_response_fifo ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_dp_req_i.dst_protocol ), - .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), - .ready_o ( w_resp_fifo_in_ready ), - .data_o ( w_resp_fifo_out_protocol ), - .valid_o ( w_resp_fifo_out_valid ), - .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) - ); - - //-------------------------------------- - // Write Request Demultiplexer - //-------------------------------------- - - // Mux write port responses - always_comb begin : gen_write_reponse_multiplexer - w_dp_rsp_mux = '0; - w_dp_rsp_mux_valid = 1'b0; - axi_w_dp_rsp_ready = 1'b0; - axis_w_dp_rsp_ready = 1'b0; - if ( w_resp_fifo_out_valid ) begin - case(w_resp_fifo_out_protocol) - idma_pkg::AXI: begin - w_dp_rsp_mux_valid = axi_w_dp_rsp_valid; - w_dp_rsp_mux = axi_w_dp_rsp; - axi_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end - idma_pkg::AXI_STREAM: begin - w_dp_rsp_mux_valid = axis_w_dp_rsp_valid; - w_dp_rsp_mux = axis_w_dp_rsp; - axis_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end - default: begin - w_dp_rsp_mux_valid = 1'b0; - w_dp_rsp_mux = '0; - end - endcase - end - end - - // Fall through register for the write response to be ready - fall_through_register #( - .T ( w_dp_rsp_t ) - ) i_write_rsp_channel_reg ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .clr_i ( 1'b0 ), - .testmode_i ( testmode_i ), - - .valid_i ( w_dp_rsp_mux_valid ), - .ready_o ( w_dp_rsp_mux_ready ), - .data_i ( w_dp_rsp_mux ), - - .valid_o ( w_dp_rsp_valid ), - .ready_i ( w_dp_rsp_ready ), - .data_o ( w_dp_rsp_o ) - ); - - // Join write response fifo and write port responses - stream_join #( - .N_INP ( 2 ) - ) i_write_stream_join ( - .inp_valid_i ( { w_resp_fifo_out_valid, w_dp_rsp_valid } ), - .inp_ready_o ( { w_resp_fifo_out_ready, w_dp_rsp_ready } ), - - .oup_valid_o ( w_dp_valid_o ), - .oup_ready_i ( w_dp_ready_i ) - ); - - //-------------------------------------- - // Module Control - //-------------------------------------- - assign r_dp_busy_o = r_dp_valid_i; - assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; - assign buffer_busy_o = |buffer_out_valid; - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "idma/guard.svh" -`include "common_cells/registers.svh" - -/// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_r_obi_rw_init_w_axi #( - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// `r_dp_req_t` type: - parameter type r_dp_req_t = logic, - /// `w_dp_req_t` type: - parameter type w_dp_req_t = logic, - /// `r_dp_rsp_t` type: - parameter type r_dp_rsp_t = logic, - /// `w_dp_rsp_t` type: - parameter type w_dp_rsp_t = logic, - /// Write Meta channel type - parameter type write_meta_channel_t = logic, - parameter type write_meta_channel_tagged_t = logic, - /// Read Meta channel type - parameter type read_meta_channel_t = logic, - parameter type read_meta_channel_tagged_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// Memory Init Request and Response channel type - parameter type init_req_t = logic, - parameter type init_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// Memory Init read request - output init_req_t init_read_req_o, - /// Memory Init read response - input init_rsp_t init_read_rsp_i, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// Memory Init write request - output init_req_t init_write_req_o, - /// Memory Init write response - input init_rsp_t init_write_rsp_i, - - /// Read datapath request - input r_dp_req_t r_dp_req_i, - /// Read datapath request valid - input logic r_dp_valid_i, - /// Read datapath request ready - output logic r_dp_ready_o, - - /// Read datapath response - output r_dp_rsp_t r_dp_rsp_o, - /// Read datapath response valid - output logic r_dp_valid_o, - /// Read datapath response valid - input logic r_dp_ready_i, - - /// Write datapath request - input w_dp_req_t w_dp_req_i, - /// Write datapath request valid - input logic w_dp_valid_i, - /// Write datapath request ready - output logic w_dp_ready_o, - - /// Write datapath response - output w_dp_rsp_t w_dp_rsp_o, - /// Write datapath response valid - output logic w_dp_valid_o, - /// Write datapath response valid - input logic w_dp_ready_i, - - /// Read meta request - input read_meta_channel_tagged_t ar_req_i, - /// Read meta request valid - input logic ar_valid_i, - /// Read meta request ready - output logic ar_ready_o, - - /// Write meta request - input write_meta_channel_tagged_t aw_req_i, - /// Write meta request valid - input logic aw_valid_i, - /// Write meta request ready - output logic aw_ready_o, - - /// Datapath poison signal - input logic dp_poison_i, - - /// Response channel valid and ready - output logic r_chan_ready_o, - output logic r_chan_valid_o, - - /// Read part of the datapath is busy - output logic r_dp_busy_o, - /// Write part of the datapath is busy - output logic w_dp_busy_o, - /// Buffer is busy - output logic buffer_busy_o -); - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - - /// Data type - typedef logic [DataWidth-1:0] data_t; - /// Offset type - typedef logic [StrbWidth-1:0] strb_t; - /// Byte type - typedef logic [7:0] byte_t; - - // inbound control signals to the read buffer: controlled by the read process - strb_t init_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; - - strb_t buffer_in_ready; - // outbound control signals of the buffer: controlled by the write process - strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t axi_buffer_out_ready, init_buffer_out_ready, - buffer_out_ready, buffer_out_ready_shifted; - - // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] init_buffer_in, obi_buffer_in, - buffer_in, buffer_in_shifted; - // aligned and coalesced data leaving the buffer - byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; - - // Read multiplexed signals - logic init_r_chan_valid, obi_r_chan_valid; - logic init_r_chan_ready, obi_r_chan_ready; - logic init_r_dp_valid, obi_r_dp_valid; - logic init_r_dp_ready, obi_r_dp_ready; - r_dp_rsp_t init_r_dp_rsp, obi_r_dp_rsp; - - logic init_ar_ready, obi_ar_ready; - - // Write multiplexed signals - logic axi_w_dp_rsp_valid, init_w_dp_rsp_valid; - logic axi_w_dp_rsp_ready, init_w_dp_rsp_ready; - logic axi_w_dp_ready, init_w_dp_ready; - w_dp_rsp_t axi_w_dp_rsp, init_w_dp_rsp; - - logic axi_aw_ready, init_aw_ready; - logic w_dp_req_valid, w_dp_req_ready; - logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; - logic w_dp_rsp_valid, w_dp_rsp_ready; - w_dp_rsp_t w_dp_rsp_mux; - - // Write Response FIFO signals - logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; - idma_pkg::protocol_e w_resp_fifo_out_protocol; - logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; - - //-------------------------------------- - // Read Ports - //-------------------------------------- - - idma_init_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .read_meta_chan_t ( read_meta_channel_t ), - .read_req_t ( init_req_t ), - .read_rsp_t ( init_rsp_t ) - ) i_idma_init_read ( - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_valid_i ), - .r_dp_ready_o ( init_r_dp_ready ), - .r_dp_rsp_o ( init_r_dp_rsp ), - .r_dp_valid_o ( init_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_ready_i ), - .read_meta_req_i ( ar_req_i.ar_req ), - .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::INIT) & ar_valid_i ), - .read_meta_ready_o ( init_ar_ready ), - .read_req_o ( init_read_req_o ), - .read_rsp_i ( init_read_rsp_i ), - .r_chan_valid_o ( init_r_chan_valid ), - .r_chan_ready_o ( init_r_chan_ready ), - .buffer_in_o ( init_buffer_in ), - .buffer_in_valid_o ( init_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - idma_obi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .read_meta_chan_t ( read_meta_channel_t ), - .read_req_t ( obi_req_t ), - .read_rsp_t ( obi_rsp_t ) - ) i_idma_obi_read ( - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_valid_i ), - .r_dp_ready_o ( obi_r_dp_ready ), - .r_dp_rsp_o ( obi_r_dp_rsp ), - .r_dp_valid_o ( obi_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_ready_i ), - .read_meta_req_i ( ar_req_i.ar_req ), - .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::OBI) & ar_valid_i ), - .read_meta_ready_o ( obi_ar_ready ), - .read_req_o ( obi_read_req_o ), - .read_rsp_i ( obi_read_rsp_i ), - .r_chan_valid_o ( obi_r_chan_valid ), - .r_chan_ready_o ( obi_r_chan_ready ), - .buffer_in_o ( obi_buffer_in ), - .buffer_in_valid_o ( obi_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - //-------------------------------------- - // Read Multiplexers - //-------------------------------------- - - always_comb begin : gen_read_meta_channel_multiplexer - case(ar_req_i.src_protocol) - idma_pkg::INIT: ar_ready_o = init_ar_ready; - idma_pkg::OBI: ar_ready_o = obi_ar_ready; - default: ar_ready_o = 1'b0; - endcase - end - - always_comb begin : gen_read_multiplexer - case(r_dp_req_i.src_protocol) - idma_pkg::INIT: begin - r_chan_valid_o = init_r_chan_valid; - r_chan_ready_o = init_r_chan_ready; - - r_dp_ready_o = init_r_dp_ready; - r_dp_rsp_o = init_r_dp_rsp; - r_dp_valid_o = init_r_dp_valid; - - buffer_in = init_buffer_in; - buffer_in_valid = init_buffer_in_valid; - end - idma_pkg::OBI: begin - r_chan_valid_o = obi_r_chan_valid; - r_chan_ready_o = obi_r_chan_ready; - - r_dp_ready_o = obi_r_dp_ready; - r_dp_rsp_o = obi_r_dp_rsp; - r_dp_valid_o = obi_r_dp_valid; - - buffer_in = obi_buffer_in; - buffer_in_valid = obi_buffer_in_valid; - end - default: begin - r_chan_valid_o = 1'b0; - r_chan_ready_o = 1'b0; - - r_dp_ready_o = 1'b0; - r_dp_rsp_o = '0; - r_dp_valid_o = 1'b0; - - buffer_in = '0; - buffer_in_valid = '0; - end - endcase - end - - //-------------------------------------- - // Read Barrel shifter - //-------------------------------------- - - assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); - - //-------------------------------------- - // Buffer - //-------------------------------------- - - idma_dataflow_element #( - .BufferDepth ( BufferDepth ), - .StrbWidth ( StrbWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .strb_t ( strb_t ), - .byte_t ( byte_t ) - ) i_dataflow_element ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .data_i ( buffer_in_shifted ), - .valid_i ( buffer_in_valid ), - .ready_o ( buffer_in_ready ), - .data_o ( buffer_out ), - .valid_o ( buffer_out_valid ), - .ready_i ( buffer_out_ready_shifted ) - ); - - //-------------------------------------- - // Write Barrel shifter - //-------------------------------------- - - assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); - assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; - assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; - - //-------------------------------------- - // Write Request Demultiplexer - //-------------------------------------- - - // Split write request to write response fifo and write ports - stream_fork #( - .N_OUP ( 2 ) - ) i_write_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( w_dp_valid_i ), - .ready_o ( w_dp_ready_o ), - .valid_o ( { w_resp_fifo_in_valid, w_dp_req_valid } ), - .ready_i ( { w_resp_fifo_in_ready, w_dp_req_ready } ) - ); - - // Demux write request to correct write port - always_comb begin : gen_write_multiplexer - case(w_dp_req_i.dst_protocol) - idma_pkg::AXI: begin - w_dp_req_ready = axi_w_dp_ready; - buffer_out_ready = axi_buffer_out_ready; - end - idma_pkg::INIT: begin - w_dp_req_ready = init_w_dp_ready; - buffer_out_ready = init_buffer_out_ready; - end - default: begin - w_dp_req_ready = 1'b0; - buffer_out_ready = '0; - end - endcase - end - - // Demux write meta channel to correct write port - always_comb begin : gen_write_meta_channel_multiplexer - case(aw_req_i.dst_protocol) - idma_pkg::AXI: aw_ready_o = axi_aw_ready; - idma_pkg::INIT: aw_ready_o = init_aw_ready; - default: aw_ready_o = 1'b0; - endcase - end - - //-------------------------------------- - // Write Ports - //-------------------------------------- - - idma_axi_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .aw_chan_t ( write_meta_channel_t ), - .write_req_t ( axi_req_t ), - .write_rsp_t ( axi_rsp_t ) - ) i_idma_axi_write ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::AXI) & w_dp_req_valid ), - .w_dp_ready_o ( axi_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( axi_w_dp_rsp ), - .w_dp_valid_o ( axi_w_dp_rsp_valid ), - .w_dp_ready_i ( axi_w_dp_rsp_ready ), - .aw_req_i ( aw_req_i.aw_req ), - .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::AXI) & aw_valid_i ), - .aw_ready_o ( axi_aw_ready ), - .write_req_o ( axi_write_req_o ), - .write_rsp_i ( axi_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( axi_buffer_out_ready ) - ); - - idma_init_write #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_req_t ( init_req_t ), - .write_rsp_t ( init_rsp_t ) - ) i_idma_init_write ( - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::INIT) & w_dp_req_valid ), - .w_dp_ready_o ( init_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( init_w_dp_rsp ), - .w_dp_valid_o ( init_w_dp_rsp_valid ), - .w_dp_ready_i ( init_w_dp_rsp_ready ), - .write_meta_req_i ( aw_req_i.aw_req ), - .write_meta_valid_i ( (aw_req_i.dst_protocol == idma_pkg::INIT) & aw_valid_i ), - .write_meta_ready_o ( init_aw_ready ), - .write_req_o ( init_write_req_o ), - .write_rsp_i ( init_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( init_buffer_out_ready ) - ); - - //-------------------------------------- - // Write Response FIFO - //-------------------------------------- - // Needed to be able to route the write reponses properly - // Insert when data write happens - // Remove when write response comes - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( idma_pkg::protocol_e ), - .PrintInfo ( PrintFifoInfo ) - ) i_write_response_fifo ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_dp_req_i.dst_protocol ), - .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), - .ready_o ( w_resp_fifo_in_ready ), - .data_o ( w_resp_fifo_out_protocol ), - .valid_o ( w_resp_fifo_out_valid ), - .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) - ); - - //-------------------------------------- - // Write Request Demultiplexer - //-------------------------------------- - - // Mux write port responses - always_comb begin : gen_write_reponse_multiplexer - w_dp_rsp_mux = '0; - w_dp_rsp_mux_valid = 1'b0; - axi_w_dp_rsp_ready = 1'b0; - init_w_dp_rsp_ready = 1'b0; - if ( w_resp_fifo_out_valid ) begin - case(w_resp_fifo_out_protocol) - idma_pkg::AXI: begin - w_dp_rsp_mux_valid = axi_w_dp_rsp_valid; - w_dp_rsp_mux = axi_w_dp_rsp; - axi_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end - idma_pkg::INIT: begin - w_dp_rsp_mux_valid = init_w_dp_rsp_valid; - w_dp_rsp_mux = init_w_dp_rsp; - init_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end - default: begin - w_dp_rsp_mux_valid = 1'b0; - w_dp_rsp_mux = '0; - end - endcase - end - end - - // Fall through register for the write response to be ready - fall_through_register #( - .T ( w_dp_rsp_t ) - ) i_write_rsp_channel_reg ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .clr_i ( 1'b0 ), - .testmode_i ( testmode_i ), - - .valid_i ( w_dp_rsp_mux_valid ), - .ready_o ( w_dp_rsp_mux_ready ), - .data_i ( w_dp_rsp_mux ), - - .valid_o ( w_dp_rsp_valid ), - .ready_i ( w_dp_rsp_ready ), - .data_o ( w_dp_rsp_o ) - ); - - // Join write response fifo and write port responses - stream_join #( - .N_INP ( 2 ) - ) i_write_stream_join ( - .inp_valid_i ( { w_resp_fifo_out_valid, w_dp_rsp_valid } ), - .inp_ready_o ( { w_resp_fifo_out_ready, w_dp_rsp_ready } ), - - .oup_valid_o ( w_dp_valid_o ), - .oup_ready_i ( w_dp_ready_i ) - ); - - //-------------------------------------- - // Module Control - //-------------------------------------- - assign r_dp_busy_o = r_dp_valid_i; - assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; - assign buffer_busy_o = |buffer_out_valid; - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "idma/guard.svh" -`include "common_cells/registers.svh" - -/// Implementing the transport layer in the iDMA backend. -module idma_transport_layer_r_axi_rw_init_rw_obi #( - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// `r_dp_req_t` type: - parameter type r_dp_req_t = logic, - /// `w_dp_req_t` type: - parameter type w_dp_req_t = logic, - /// `r_dp_rsp_t` type: - parameter type r_dp_rsp_t = logic, - /// `w_dp_rsp_t` type: - parameter type w_dp_rsp_t = logic, - /// Write Meta channel type - parameter type write_meta_channel_t = logic, - parameter type write_meta_channel_tagged_t = logic, - /// Read Meta channel type - parameter type read_meta_channel_t = logic, - parameter type read_meta_channel_tagged_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// Memory Init Request and Response channel type - parameter type init_req_t = logic, - parameter type init_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// Memory Init read request - output init_req_t init_read_req_o, - /// Memory Init read response - input init_rsp_t init_read_rsp_i, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// Memory Init write request - output init_req_t init_write_req_o, - /// Memory Init write response - input init_rsp_t init_write_rsp_i, - - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, - - /// Read datapath request - input r_dp_req_t r_dp_req_i, - /// Read datapath request valid - input logic r_dp_valid_i, - /// Read datapath request ready - output logic r_dp_ready_o, - - /// Read datapath response - output r_dp_rsp_t r_dp_rsp_o, - /// Read datapath response valid - output logic r_dp_valid_o, - /// Read datapath response valid - input logic r_dp_ready_i, - - /// Write datapath request - input w_dp_req_t w_dp_req_i, - /// Write datapath request valid - input logic w_dp_valid_i, - /// Write datapath request ready - output logic w_dp_ready_o, - - /// Write datapath response - output w_dp_rsp_t w_dp_rsp_o, - /// Write datapath response valid - output logic w_dp_valid_o, - /// Write datapath response valid - input logic w_dp_ready_i, - - /// Read meta request - input read_meta_channel_tagged_t ar_req_i, - /// Read meta request valid - input logic ar_valid_i, - /// Read meta request ready - output logic ar_ready_o, - - /// Write meta request - input write_meta_channel_tagged_t aw_req_i, - /// Write meta request valid - input logic aw_valid_i, - /// Write meta request ready - output logic aw_ready_o, - - /// Datapath poison signal - input logic dp_poison_i, - - /// Response channel valid and ready - output logic r_chan_ready_o, - output logic r_chan_valid_o, - - /// Read part of the datapath is busy - output logic r_dp_busy_o, - /// Write part of the datapath is busy - output logic w_dp_busy_o, - /// Buffer is busy - output logic buffer_busy_o -); - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - - /// Data type - typedef logic [DataWidth-1:0] data_t; - /// Offset type - typedef logic [StrbWidth-1:0] strb_t; - /// Byte type - typedef logic [7:0] byte_t; - - // inbound control signals to the read buffer: controlled by the read process - strb_t axi_buffer_in_valid, init_buffer_in_valid, obi_buffer_in_valid, buffer_in_valid; - - strb_t buffer_in_ready; - // outbound control signals of the buffer: controlled by the write process - strb_t buffer_out_valid, buffer_out_valid_shifted; - strb_t init_buffer_out_ready, obi_buffer_out_ready, - buffer_out_ready, buffer_out_ready_shifted; - - // shifted data flowing into the buffer - byte_t [StrbWidth-1:0] axi_buffer_in, init_buffer_in, obi_buffer_in, - buffer_in, buffer_in_shifted; - // aligned and coalesced data leaving the buffer - byte_t [StrbWidth-1:0] buffer_out, buffer_out_shifted; - - // Read multiplexed signals - logic axi_r_chan_valid, init_r_chan_valid, obi_r_chan_valid; - logic axi_r_chan_ready, init_r_chan_ready, obi_r_chan_ready; - logic axi_r_dp_valid, init_r_dp_valid, obi_r_dp_valid; - logic axi_r_dp_ready, init_r_dp_ready, obi_r_dp_ready; - r_dp_rsp_t axi_r_dp_rsp, init_r_dp_rsp, obi_r_dp_rsp; - - logic axi_ar_ready, init_ar_ready, obi_ar_ready; - - // Write multiplexed signals - logic init_w_dp_rsp_valid, obi_w_dp_rsp_valid; - logic init_w_dp_rsp_ready, obi_w_dp_rsp_ready; - logic init_w_dp_ready, obi_w_dp_ready; - w_dp_rsp_t init_w_dp_rsp, obi_w_dp_rsp; - - logic init_aw_ready, obi_aw_ready; - logic w_dp_req_valid, w_dp_req_ready; - logic w_dp_rsp_mux_valid, w_dp_rsp_mux_ready; - logic w_dp_rsp_valid, w_dp_rsp_ready; - w_dp_rsp_t w_dp_rsp_mux; - - // Write Response FIFO signals - logic w_resp_fifo_in_valid, w_resp_fifo_in_ready; - idma_pkg::protocol_e w_resp_fifo_out_protocol; - logic w_resp_fifo_out_valid, w_resp_fifo_out_ready; - - //-------------------------------------- - // Read Ports - //-------------------------------------- - - idma_axi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .ar_chan_t ( read_meta_channel_t ), - .read_req_t ( axi_req_t ), - .read_rsp_t ( axi_rsp_t ) - ) i_idma_axi_read ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_valid_i ), - .r_dp_ready_o ( axi_r_dp_ready ), - .r_dp_rsp_o ( axi_r_dp_rsp ), - .r_dp_valid_o ( axi_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::AXI) & r_dp_ready_i ), - .ar_req_i ( ar_req_i.ar_req ), - .ar_valid_i ( (ar_req_i.src_protocol == idma_pkg::AXI) & ar_valid_i ), - .ar_ready_o ( axi_ar_ready ), - .read_req_o ( axi_read_req_o ), - .read_rsp_i ( axi_read_rsp_i ), - .r_chan_valid_o ( axi_r_chan_valid ), - .r_chan_ready_o ( axi_r_chan_ready ), - .buffer_in_o ( axi_buffer_in ), - .buffer_in_valid_o ( axi_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - idma_init_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .read_meta_chan_t ( read_meta_channel_t ), - .read_req_t ( init_req_t ), - .read_rsp_t ( init_rsp_t ) - ) i_idma_init_read ( - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_valid_i ), - .r_dp_ready_o ( init_r_dp_ready ), - .r_dp_rsp_o ( init_r_dp_rsp ), - .r_dp_valid_o ( init_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::INIT) & r_dp_ready_i ), - .read_meta_req_i ( ar_req_i.ar_req ), - .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::INIT) & ar_valid_i ), - .read_meta_ready_o ( init_ar_ready ), - .read_req_o ( init_read_req_o ), - .read_rsp_i ( init_read_rsp_i ), - .r_chan_valid_o ( init_r_chan_valid ), - .r_chan_ready_o ( init_r_chan_ready ), - .buffer_in_o ( init_buffer_in ), - .buffer_in_valid_o ( init_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - idma_obi_read #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .strb_t ( strb_t ), - .r_dp_req_t ( r_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .read_meta_chan_t ( read_meta_channel_t ), - .read_req_t ( obi_req_t ), - .read_rsp_t ( obi_rsp_t ) - ) i_idma_obi_read ( - .r_dp_req_i ( r_dp_req_i ), - .r_dp_valid_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_valid_i ), - .r_dp_ready_o ( obi_r_dp_ready ), - .r_dp_rsp_o ( obi_r_dp_rsp ), - .r_dp_valid_o ( obi_r_dp_valid ), - .r_dp_ready_i ( (r_dp_req_i.src_protocol == idma_pkg::OBI) & r_dp_ready_i ), - .read_meta_req_i ( ar_req_i.ar_req ), - .read_meta_valid_i ( (ar_req_i.src_protocol == idma_pkg::OBI) & ar_valid_i ), - .read_meta_ready_o ( obi_ar_ready ), - .read_req_o ( obi_read_req_o ), - .read_rsp_i ( obi_read_rsp_i ), - .r_chan_valid_o ( obi_r_chan_valid ), - .r_chan_ready_o ( obi_r_chan_ready ), - .buffer_in_o ( obi_buffer_in ), - .buffer_in_valid_o ( obi_buffer_in_valid ), - .buffer_in_ready_i ( buffer_in_ready ) - ); - - //-------------------------------------- - // Read Multiplexers - //-------------------------------------- - - always_comb begin : gen_read_meta_channel_multiplexer - case(ar_req_i.src_protocol) - idma_pkg::AXI: ar_ready_o = axi_ar_ready; - idma_pkg::INIT: ar_ready_o = init_ar_ready; - idma_pkg::OBI: ar_ready_o = obi_ar_ready; - default: ar_ready_o = 1'b0; - endcase - end - - always_comb begin : gen_read_multiplexer - case(r_dp_req_i.src_protocol) - idma_pkg::AXI: begin - r_chan_valid_o = axi_r_chan_valid; - r_chan_ready_o = axi_r_chan_ready; - - r_dp_ready_o = axi_r_dp_ready; - r_dp_rsp_o = axi_r_dp_rsp; - r_dp_valid_o = axi_r_dp_valid; - - buffer_in = axi_buffer_in; - buffer_in_valid = axi_buffer_in_valid; - end - idma_pkg::INIT: begin - r_chan_valid_o = init_r_chan_valid; - r_chan_ready_o = init_r_chan_ready; - - r_dp_ready_o = init_r_dp_ready; - r_dp_rsp_o = init_r_dp_rsp; - r_dp_valid_o = init_r_dp_valid; - - buffer_in = init_buffer_in; - buffer_in_valid = init_buffer_in_valid; - end - idma_pkg::OBI: begin - r_chan_valid_o = obi_r_chan_valid; - r_chan_ready_o = obi_r_chan_ready; - - r_dp_ready_o = obi_r_dp_ready; - r_dp_rsp_o = obi_r_dp_rsp; - r_dp_valid_o = obi_r_dp_valid; - - buffer_in = obi_buffer_in; - buffer_in_valid = obi_buffer_in_valid; - end - default: begin - r_chan_valid_o = 1'b0; - r_chan_ready_o = 1'b0; - - r_dp_ready_o = 1'b0; - r_dp_rsp_o = '0; - r_dp_valid_o = 1'b0; - - buffer_in = '0; - buffer_in_valid = '0; - end - endcase - end - - //-------------------------------------- - // Read Barrel shifter - //-------------------------------------- - - assign buffer_in_shifted = {buffer_in, buffer_in} >> (r_dp_req_i.shift * 8); - - //-------------------------------------- - // Buffer - //-------------------------------------- - - idma_dataflow_element #( - .BufferDepth ( BufferDepth ), - .StrbWidth ( StrbWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .strb_t ( strb_t ), - .byte_t ( byte_t ) - ) i_dataflow_element ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .data_i ( buffer_in_shifted ), - .valid_i ( buffer_in_valid ), - .ready_o ( buffer_in_ready ), - .data_o ( buffer_out ), - .valid_o ( buffer_out_valid ), - .ready_i ( buffer_out_ready_shifted ) - ); - - //-------------------------------------- - // Write Barrel shifter - //-------------------------------------- - - assign buffer_out_shifted = {buffer_out, buffer_out} >> (w_dp_req_i.shift*8); - assign buffer_out_valid_shifted = {buffer_out_valid, buffer_out_valid} >> w_dp_req_i.shift; - assign buffer_out_ready_shifted = {buffer_out_ready, buffer_out_ready} >> - w_dp_req_i.shift; - - //-------------------------------------- - // Write Request Demultiplexer - //-------------------------------------- - - // Split write request to write response fifo and write ports - stream_fork #( - .N_OUP ( 2 ) - ) i_write_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( w_dp_valid_i ), - .ready_o ( w_dp_ready_o ), - .valid_o ( { w_resp_fifo_in_valid, w_dp_req_valid } ), - .ready_i ( { w_resp_fifo_in_ready, w_dp_req_ready } ) - ); - - // Demux write request to correct write port - always_comb begin : gen_write_multiplexer - case(w_dp_req_i.dst_protocol) - idma_pkg::INIT: begin - w_dp_req_ready = init_w_dp_ready; - buffer_out_ready = init_buffer_out_ready; - end - idma_pkg::OBI: begin - w_dp_req_ready = obi_w_dp_ready; - buffer_out_ready = obi_buffer_out_ready; - end - default: begin - w_dp_req_ready = 1'b0; - buffer_out_ready = '0; - end - endcase - end - - // Demux write meta channel to correct write port - always_comb begin : gen_write_meta_channel_multiplexer - case(aw_req_i.dst_protocol) - idma_pkg::INIT: aw_ready_o = init_aw_ready; - idma_pkg::OBI: aw_ready_o = obi_aw_ready; - default: aw_ready_o = 1'b0; - endcase - end - - //-------------------------------------- - // Write Ports - //-------------------------------------- - - idma_init_write #( - .StrbWidth ( StrbWidth ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_req_t ( init_req_t ), - .write_rsp_t ( init_rsp_t ) - ) i_idma_init_write ( - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::INIT) & w_dp_req_valid ), - .w_dp_ready_o ( init_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( init_w_dp_rsp ), - .w_dp_valid_o ( init_w_dp_rsp_valid ), - .w_dp_ready_i ( init_w_dp_rsp_ready ), - .write_meta_req_i ( aw_req_i.aw_req ), - .write_meta_valid_i ( (aw_req_i.dst_protocol == idma_pkg::INIT) & aw_valid_i ), - .write_meta_ready_o ( init_aw_ready ), - .write_req_o ( init_write_req_o ), - .write_rsp_i ( init_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( init_buffer_out_ready ) - ); - - idma_obi_write #( - .StrbWidth ( StrbWidth ), - .MaskInvalidData ( MaskInvalidData ), - .byte_t ( byte_t ), - .data_t ( data_t ), - .strb_t ( strb_t ), - .w_dp_req_t ( w_dp_req_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_req_t ( obi_req_t ), - .write_rsp_t ( obi_rsp_t ) - ) i_idma_obi_write ( - .w_dp_req_i ( w_dp_req_i ), - .w_dp_valid_i ( (w_dp_req_i.dst_protocol == idma_pkg::OBI) & w_dp_req_valid ), - .w_dp_ready_o ( obi_w_dp_ready ), - .dp_poison_i ( dp_poison_i ), - .w_dp_rsp_o ( obi_w_dp_rsp ), - .w_dp_valid_o ( obi_w_dp_rsp_valid ), - .w_dp_ready_i ( obi_w_dp_rsp_ready ), - .aw_req_i ( aw_req_i.aw_req ), - .aw_valid_i ( (aw_req_i.dst_protocol == idma_pkg::OBI) & aw_valid_i ), - .aw_ready_o ( obi_aw_ready ), - .write_req_o ( obi_write_req_o ), - .write_rsp_i ( obi_write_rsp_i ), - .buffer_out_i ( buffer_out_shifted ), - .buffer_out_valid_i ( buffer_out_valid_shifted ), - .buffer_out_ready_o ( obi_buffer_out_ready ) - ); - - //-------------------------------------- - // Write Response FIFO - //-------------------------------------- - // Needed to be able to route the write reponses properly - // Insert when data write happens - // Remove when write response comes - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( idma_pkg::protocol_e ), - .PrintInfo ( PrintFifoInfo ) - ) i_write_response_fifo ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_dp_req_i.dst_protocol ), - .valid_i ( w_resp_fifo_in_valid && w_resp_fifo_in_ready ), - .ready_o ( w_resp_fifo_in_ready ), - .data_o ( w_resp_fifo_out_protocol ), - .valid_o ( w_resp_fifo_out_valid ), - .ready_i ( w_resp_fifo_out_ready && w_resp_fifo_out_valid ) - ); - - //-------------------------------------- - // Write Request Demultiplexer - //-------------------------------------- - - // Mux write port responses - always_comb begin : gen_write_reponse_multiplexer - w_dp_rsp_mux = '0; - w_dp_rsp_mux_valid = 1'b0; - init_w_dp_rsp_ready = 1'b0; - obi_w_dp_rsp_ready = 1'b0; - if ( w_resp_fifo_out_valid ) begin - case(w_resp_fifo_out_protocol) - idma_pkg::INIT: begin - w_dp_rsp_mux_valid = init_w_dp_rsp_valid; - w_dp_rsp_mux = init_w_dp_rsp; - init_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end - idma_pkg::OBI: begin - w_dp_rsp_mux_valid = obi_w_dp_rsp_valid; - w_dp_rsp_mux = obi_w_dp_rsp; - obi_w_dp_rsp_ready = w_dp_rsp_mux_ready; - end - default: begin - w_dp_rsp_mux_valid = 1'b0; - w_dp_rsp_mux = '0; - end - endcase - end - end - - // Fall through register for the write response to be ready - fall_through_register #( - .T ( w_dp_rsp_t ) - ) i_write_rsp_channel_reg ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .clr_i ( 1'b0 ), - .testmode_i ( testmode_i ), - - .valid_i ( w_dp_rsp_mux_valid ), - .ready_o ( w_dp_rsp_mux_ready ), - .data_i ( w_dp_rsp_mux ), - - .valid_o ( w_dp_rsp_valid ), - .ready_i ( w_dp_rsp_ready ), - .data_o ( w_dp_rsp_o ) - ); - - // Join write response fifo and write port responses - stream_join #( - .N_INP ( 2 ) - ) i_write_stream_join ( - .inp_valid_i ( { w_resp_fifo_out_valid, w_dp_rsp_valid } ), - .inp_ready_o ( { w_resp_fifo_out_ready, w_dp_rsp_ready } ), - - .oup_valid_o ( w_dp_valid_o ), - .oup_ready_i ( w_dp_ready_i ) - ); - - //-------------------------------------- - // Module Control - //-------------------------------------- - assign r_dp_busy_o = r_dp_valid_i; - assign w_dp_busy_o = w_dp_valid_i | w_dp_ready_o; - assign buffer_busy_o = |buffer_out_valid; - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "common_cells/registers.svh" -`include "common_cells/assertions.svh" -`include "idma/guard.svh" - -/// Legalizes a generic 1D transfer according to the rules given by the -/// used protocol. -module idma_legalizer_rw_axi #( - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - parameter type idma_req_t = logic, - /// Read request type - parameter type idma_r_req_t = logic, - /// Write request type - parameter type idma_w_req_t = logic, - /// Mutable transfer type - parameter type idma_mut_tf_t = logic, - /// Mutable options type - parameter type idma_mut_tf_opt_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - - /// 1D request - input idma_req_t req_i, - /// 1D request valid - input logic valid_i, - /// 1D request ready - output logic ready_o, - - /// Read request; contains datapath and meta information - output idma_r_req_t r_req_o, - /// Read request valid - output logic r_valid_o, - /// Read request ready - input logic r_ready_i, - - /// Write request; contains datapath and meta information - output idma_w_req_t w_req_o, - /// Write request valid - output logic w_valid_o, - /// Write request ready - input logic w_ready_i, - - /// Invalidate the current burst transfer, stops emission of requests - input logic flush_i, - /// Kill the active 1D transfer; reload a new transfer - input logic kill_i, - - /// Read machine of the legalizer is busy - output logic r_busy_o, - /// Write machine of the legalizer is busy - output logic w_busy_o -); - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - /// The size of a page in byte - localparam int unsigned PageSize = 256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth; - /// The width of page offset byte addresses - localparam int unsigned PageAddrWidth = $clog2(PageSize); - - /// Offset type - typedef logic [ OffsetWidth-1:0] offset_t; - /// Address type - typedef logic [ AddrWidth-1:0] addr_t; - /// Page address type - typedef logic [PageAddrWidth-1:0] page_addr_t; - /// Page length type - typedef logic [ PageAddrWidth:0] page_len_t; - - - // state: internally hold one transfer, this is mutated - idma_mut_tf_t r_tf_d, r_tf_q; - idma_mut_tf_t w_tf_d, w_tf_q; - idma_mut_tf_opt_t opt_tf_d, opt_tf_q; - - // enable signals for next mutable transfer storage - logic r_tf_ena; - logic w_tf_ena; - - // page boundaries - page_len_t r_page_num_bytes_to_pb; - page_len_t r_num_bytes_to_pb; - page_len_t w_page_num_bytes_to_pb; - page_len_t w_num_bytes_to_pb; - page_len_t c_num_bytes_to_pb; - - // read process - page_len_t r_num_bytes_possible; - page_len_t r_num_bytes; - offset_t r_addr_offset; - logic r_done; - - // write process - page_len_t w_num_bytes_possible; - page_len_t w_num_bytes; - offset_t w_addr_offset; - logic w_done; - - - //-------------------------------------- - // read boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_read_page_splitter ( - .not_bursting_i ( 1'b0 ), - - .reduce_len_i ( opt_tf_q.src_reduce_len ), - .max_llen_i ( opt_tf_q.src_max_llen ), - - .addr_i ( r_tf_q.addr ), - .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) - ); - - assign r_num_bytes_to_pb = r_page_num_bytes_to_pb; - - //-------------------------------------- - // write boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_write_page_splitter ( - .not_bursting_i ( 1'b0 ), - - .reduce_len_i ( opt_tf_q.dst_reduce_len ), - .max_llen_i ( opt_tf_q.dst_max_llen ), - - .addr_i ( w_tf_q.addr ), - .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) - ); - - assign w_num_bytes_to_pb = w_page_num_bytes_to_pb; - - //-------------------------------------- - // page boundary check - //-------------------------------------- - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; - - - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - always_comb begin : proc_num_bytes_possible - // Default: Coupled - r_num_bytes_possible = c_num_bytes_to_pb; - w_num_bytes_possible = c_num_bytes_to_pb; - - if (opt_tf_q.decouple_rw) begin - r_num_bytes_possible = r_num_bytes_to_pb; - w_num_bytes_possible = w_num_bytes_to_pb; - end - end - - assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; - assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; - - // legalization process -> read and write is coupled together - always_comb begin : proc_read_write_transaction - - // default: keep state - r_tf_d = r_tf_q; - w_tf_d = w_tf_q; - opt_tf_d = opt_tf_q; - - // default: not done - r_done = 1'b0; - w_done = 1'b0; - - //-------------------------------------- - // Legalize read transaction - //-------------------------------------- - // more bytes remaining than we can read - if (r_tf_q.length > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - r_tf_d.length = r_tf_q.length - r_num_bytes_possible; - // next address - r_tf_d.addr = r_tf_q.addr + r_num_bytes; - - // remaining bytes fit in one burst - end else begin - r_num_bytes = r_tf_q.length[PageAddrWidth:0]; - // finished - r_tf_d.valid = 1'b0; - r_done = 1'b1; - end - - //-------------------------------------- - // Legalize write transaction - //-------------------------------------- - // more bytes remaining than we can write - if (w_tf_q.length > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - w_tf_d.length = w_tf_q.length - w_num_bytes_possible; - // next address - w_tf_d.addr = w_tf_q.addr + w_num_bytes; - - // remaining bytes fit in one burst - end else begin - w_num_bytes = w_tf_q.length[PageAddrWidth:0]; - // finished - w_tf_d.valid = 1'b0; - w_done = 1'b1; - end - - //-------------------------------------- - // Kill - //-------------------------------------- - if (kill_i) begin - // kill the current state - r_tf_d = '0; - w_tf_d = '0; - r_done = 1'b1; - w_done = 1'b1; - end - - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o & valid_i) begin - - // load all three mutable objects (source, destination, option) - // source or read - r_tf_d = '{ - length: req_i.length, - addr: req_i.src_addr, - valid: 1'b1, - base_addr: req_i.src_addr - }; - // destination or write - w_tf_d = '{ - length: req_i.length, - addr: req_i.dst_addr, - valid: 1'b1, - base_addr: req_i.dst_addr - }; - // options - opt_tf_d = '{ - src_protocol: req_i.opt.src_protocol, - dst_protocol: req_i.opt.dst_protocol, - read_shift: '0, - write_shift: '0, - decouple_rw: req_i.opt.beo.decouple_rw, - decouple_aw: req_i.opt.beo.decouple_aw, - src_max_llen: req_i.opt.beo.src_max_llen, - dst_max_llen: req_i.opt.beo.dst_max_llen, - src_reduce_len: req_i.opt.beo.src_reduce_len, - dst_reduce_len: req_i.opt.beo.dst_reduce_len, - axi_id: req_i.opt.axi_id, - src_axi_opt: req_i.opt.src, - dst_axi_opt: req_i.opt.dst, - super_last: req_i.opt.last - }; - // determine shift amount - if (CombinedShifter) begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = '0; - end else begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; - end - end - end - - - //-------------------------------------- - // Connect outputs - //-------------------------------------- - - // Read meta channel - always_comb begin - r_req_o.ar_req.axi.ar_chan = '{ - id: opt_tf_q.axi_id, - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 - }; - - end - - // assign the signals needed to set-up the read data path - assign r_req_o.r_dp_req = '{ - src_protocol: opt_tf_q.src_protocol, - offset: r_addr_offset, - tailer: OffsetWidth'(r_num_bytes + r_addr_offset), - shift: opt_tf_q.read_shift, - decouple_aw: opt_tf_q.decouple_aw, - is_single: r_num_bytes <= StrbWidth - }; - - // Write meta channel and data path - always_comb begin - w_req_o.aw_req.axi.aw_chan = '{ - id: opt_tf_q.axi_id, - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.dst_axi_opt.burst, - lock: opt_tf_q.dst_axi_opt.lock, - cache: opt_tf_q.dst_axi_opt.cache, - prot: opt_tf_q.dst_axi_opt.prot, - qos: opt_tf_q.dst_axi_opt.qos, - region: opt_tf_q.dst_axi_opt.region, - user: '0, - atop: '0 - }; - - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: w_req_o.aw_req.axi.aw_chan.len, - is_single: w_req_o.aw_req.axi.aw_chan.len == '0 - }; - - end - - // last burst in generic 1D transfer? - assign w_req_o.last = w_done; - - // last burst indicated by midend - assign w_req_o.super_last = opt_tf_q.super_last; - - // assign aw decouple flag - assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; - - // busy output - assign r_busy_o = r_tf_q.valid; - assign w_busy_o = w_tf_q.valid; - - - //-------------------------------------- - // Flow Control - //-------------------------------------- - // only advance to next state if: - // * rw_coupled: both machines advance - // * rw_decoupled: either machine advances - - always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw) begin - r_tf_ena = (r_ready_i & !flush_i) | kill_i; - w_tf_ena = (w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; - end else begin - r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; - end - end - - // load next idma request: if both machines are done! - assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; - - - //-------------------------------------- - // State - //-------------------------------------- - `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) - `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) - `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) - - - //-------------------------------------- - // Assertions - //-------------------------------------- - // only support the decomposition of incremental bursts - `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & - req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & - req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "common_cells/registers.svh" -`include "common_cells/assertions.svh" -`include "idma/guard.svh" - -/// Legalizes a generic 1D transfer according to the rules given by the -/// used protocol. -module idma_legalizer_r_obi_w_axi #( - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - parameter type idma_req_t = logic, - /// Read request type - parameter type idma_r_req_t = logic, - /// Write request type - parameter type idma_w_req_t = logic, - /// Mutable transfer type - parameter type idma_mut_tf_t = logic, - /// Mutable options type - parameter type idma_mut_tf_opt_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - - /// 1D request - input idma_req_t req_i, - /// 1D request valid - input logic valid_i, - /// 1D request ready - output logic ready_o, - - /// Read request; contains datapath and meta information - output idma_r_req_t r_req_o, - /// Read request valid - output logic r_valid_o, - /// Read request ready - input logic r_ready_i, - - /// Write request; contains datapath and meta information - output idma_w_req_t w_req_o, - /// Write request valid - output logic w_valid_o, - /// Write request ready - input logic w_ready_i, - - /// Invalidate the current burst transfer, stops emission of requests - input logic flush_i, - /// Kill the active 1D transfer; reload a new transfer - input logic kill_i, - - /// Read machine of the legalizer is busy - output logic r_busy_o, - /// Write machine of the legalizer is busy - output logic w_busy_o -); - function int unsigned max_size(input int unsigned a, b); - return a > b ? a : b; - endfunction - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); - /// The width of page offset byte addresses - localparam int unsigned PageAddrWidth = $clog2(PageSize); - - /// Offset type - typedef logic [ OffsetWidth-1:0] offset_t; - /// Address type - typedef logic [ AddrWidth-1:0] addr_t; - /// Page address type - typedef logic [PageAddrWidth-1:0] page_addr_t; - /// Page length type - typedef logic [ PageAddrWidth:0] page_len_t; - - - // state: internally hold one transfer, this is mutated - idma_mut_tf_t r_tf_d, r_tf_q; - idma_mut_tf_t w_tf_d, w_tf_q; - idma_mut_tf_opt_t opt_tf_d, opt_tf_q; - - // enable signals for next mutable transfer storage - logic r_tf_ena; - logic w_tf_ena; - - // page boundaries - page_len_t r_page_num_bytes_to_pb; - page_len_t r_num_bytes_to_pb; - page_len_t w_page_num_bytes_to_pb; - page_len_t w_num_bytes_to_pb; - page_len_t c_num_bytes_to_pb; - - // read process - page_len_t r_num_bytes_possible; - page_len_t r_num_bytes; - offset_t r_addr_offset; - logic r_done; - - // write process - page_len_t w_num_bytes_possible; - page_len_t w_num_bytes; - offset_t w_addr_offset; - logic w_done; - - - //-------------------------------------- - // read boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_read_page_splitter ( - .not_bursting_i ( 1'b1 ), - - .reduce_len_i ( opt_tf_q.src_reduce_len ), - .max_llen_i ( opt_tf_q.src_max_llen ), - - .addr_i ( r_tf_q.addr ), - .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) - ); - - assign r_num_bytes_to_pb = r_page_num_bytes_to_pb; - - //-------------------------------------- - // write boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_write_page_splitter ( - .not_bursting_i ( opt_tf_q.dst_protocol inside { idma_pkg::OBI} ), - - .reduce_len_i ( opt_tf_q.dst_reduce_len ), - .max_llen_i ( opt_tf_q.dst_max_llen ), - - .addr_i ( w_tf_q.addr ), - .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) - ); - - assign w_num_bytes_to_pb = w_page_num_bytes_to_pb; - - //-------------------------------------- - // page boundary check - //-------------------------------------- - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; - - - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - always_comb begin : proc_num_bytes_possible - // Default: Coupled - r_num_bytes_possible = c_num_bytes_to_pb; - w_num_bytes_possible = c_num_bytes_to_pb; - - if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::OBI })) begin - r_num_bytes_possible = r_num_bytes_to_pb; - w_num_bytes_possible = w_num_bytes_to_pb; - end - end - - assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; - assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; - - // legalization process -> read and write is coupled together - always_comb begin : proc_read_write_transaction - - // default: keep state - r_tf_d = r_tf_q; - w_tf_d = w_tf_q; - opt_tf_d = opt_tf_q; - - // default: not done - r_done = 1'b0; - w_done = 1'b0; - - //-------------------------------------- - // Legalize read transaction - //-------------------------------------- - // more bytes remaining than we can read - if (r_tf_q.length > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - r_tf_d.length = r_tf_q.length - r_num_bytes_possible; - // next address - r_tf_d.addr = r_tf_q.addr + r_num_bytes; - - // remaining bytes fit in one burst - end else begin - r_num_bytes = r_tf_q.length[PageAddrWidth:0]; - // finished - r_tf_d.valid = 1'b0; - r_done = 1'b1; - end - - //-------------------------------------- - // Legalize write transaction - //-------------------------------------- - // more bytes remaining than we can write - if (w_tf_q.length > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - w_tf_d.length = w_tf_q.length - w_num_bytes_possible; - // next address - w_tf_d.addr = w_tf_q.addr + w_num_bytes; - - // remaining bytes fit in one burst - end else begin - w_num_bytes = w_tf_q.length[PageAddrWidth:0]; - // finished - w_tf_d.valid = 1'b0; - w_done = 1'b1; - end - - //-------------------------------------- - // Kill - //-------------------------------------- - if (kill_i) begin - // kill the current state - r_tf_d = '0; - w_tf_d = '0; - r_done = 1'b1; - w_done = 1'b1; - end - - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o & valid_i) begin - - // load all three mutable objects (source, destination, option) - // source or read - r_tf_d = '{ - length: req_i.length, - addr: req_i.src_addr, - valid: 1'b1, - base_addr: req_i.src_addr - }; - // destination or write - w_tf_d = '{ - length: req_i.length, - addr: req_i.dst_addr, - valid: 1'b1, - base_addr: req_i.dst_addr - }; - // options - opt_tf_d = '{ - src_protocol: req_i.opt.src_protocol, - dst_protocol: req_i.opt.dst_protocol, - read_shift: '0, - write_shift: '0, - decouple_rw: req_i.opt.beo.decouple_rw, - decouple_aw: req_i.opt.beo.decouple_aw, - src_max_llen: req_i.opt.beo.src_max_llen, - dst_max_llen: req_i.opt.beo.dst_max_llen, - src_reduce_len: req_i.opt.beo.src_reduce_len, - dst_reduce_len: req_i.opt.beo.dst_reduce_len, - axi_id: req_i.opt.axi_id, - src_axi_opt: req_i.opt.src, - dst_axi_opt: req_i.opt.dst, - super_last: req_i.opt.last - }; - // determine shift amount - if (CombinedShifter) begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = '0; - end else begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; - end - end - end - - - //-------------------------------------- - // Connect outputs - //-------------------------------------- - - // Read meta channel - always_comb begin - r_req_o.ar_req.obi.a_chan = '{ - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '1, - we: 1'b0, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - end - - // assign the signals needed to set-up the read data path - assign r_req_o.r_dp_req = '{ - src_protocol: opt_tf_q.src_protocol, - offset: r_addr_offset, - tailer: OffsetWidth'(r_num_bytes + r_addr_offset), - shift: opt_tf_q.read_shift, - decouple_aw: opt_tf_q.decouple_aw, - is_single: r_num_bytes <= StrbWidth - }; - - // Write meta channel and data path - always_comb begin - w_req_o.aw_req.axi.aw_chan = '{ - id: opt_tf_q.axi_id, - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.dst_axi_opt.burst, - lock: opt_tf_q.dst_axi_opt.lock, - cache: opt_tf_q.dst_axi_opt.cache, - prot: opt_tf_q.dst_axi_opt.prot, - qos: opt_tf_q.dst_axi_opt.qos, - region: opt_tf_q.dst_axi_opt.region, - user: '0, - atop: '0 - }; - - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: w_req_o.aw_req.axi.aw_chan.len, - is_single: w_req_o.aw_req.axi.aw_chan.len == '0 - }; - - end - - // last burst in generic 1D transfer? - assign w_req_o.last = w_done; - - // last burst indicated by midend - assign w_req_o.super_last = opt_tf_q.super_last; - - // assign aw decouple flag - assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; - - // busy output - assign r_busy_o = r_tf_q.valid; - assign w_busy_o = w_tf_q.valid; - - - //-------------------------------------- - // Flow Control - //-------------------------------------- - // only advance to next state if: - // * rw_coupled: both machines advance - // * rw_decoupled: either machine advances - - always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::OBI })) begin - r_tf_ena = (r_ready_i & !flush_i) | kill_i; - w_tf_ena = (w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; - end else begin - r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; - end - end - - // load next idma request: if both machines are done! - assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; - - - //-------------------------------------- - // State - //-------------------------------------- - `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) - `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) - `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) - - - //-------------------------------------- - // Assertions - //-------------------------------------- - // only support the decomposition of incremental bursts - `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & - req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & - req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "common_cells/registers.svh" -`include "common_cells/assertions.svh" -`include "idma/guard.svh" - -/// Legalizes a generic 1D transfer according to the rules given by the -/// used protocol. -module idma_legalizer_r_axi_w_obi #( - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - parameter type idma_req_t = logic, - /// Read request type - parameter type idma_r_req_t = logic, - /// Write request type - parameter type idma_w_req_t = logic, - /// Mutable transfer type - parameter type idma_mut_tf_t = logic, - /// Mutable options type - parameter type idma_mut_tf_opt_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - - /// 1D request - input idma_req_t req_i, - /// 1D request valid - input logic valid_i, - /// 1D request ready - output logic ready_o, - - /// Read request; contains datapath and meta information - output idma_r_req_t r_req_o, - /// Read request valid - output logic r_valid_o, - /// Read request ready - input logic r_ready_i, - - /// Write request; contains datapath and meta information - output idma_w_req_t w_req_o, - /// Write request valid - output logic w_valid_o, - /// Write request ready - input logic w_ready_i, - - /// Invalidate the current burst transfer, stops emission of requests - input logic flush_i, - /// Kill the active 1D transfer; reload a new transfer - input logic kill_i, - - /// Read machine of the legalizer is busy - output logic r_busy_o, - /// Write machine of the legalizer is busy - output logic w_busy_o -); - function int unsigned max_size(input int unsigned a, b); - return a > b ? a : b; - endfunction - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); - /// The width of page offset byte addresses - localparam int unsigned PageAddrWidth = $clog2(PageSize); - - /// Offset type - typedef logic [ OffsetWidth-1:0] offset_t; - /// Address type - typedef logic [ AddrWidth-1:0] addr_t; - /// Page address type - typedef logic [PageAddrWidth-1:0] page_addr_t; - /// Page length type - typedef logic [ PageAddrWidth:0] page_len_t; - - - // state: internally hold one transfer, this is mutated - idma_mut_tf_t r_tf_d, r_tf_q; - idma_mut_tf_t w_tf_d, w_tf_q; - idma_mut_tf_opt_t opt_tf_d, opt_tf_q; - - // enable signals for next mutable transfer storage - logic r_tf_ena; - logic w_tf_ena; - - // page boundaries - page_len_t r_page_num_bytes_to_pb; - page_len_t r_num_bytes_to_pb; - page_len_t w_page_num_bytes_to_pb; - page_len_t w_num_bytes_to_pb; - page_len_t c_num_bytes_to_pb; - - // read process - page_len_t r_num_bytes_possible; - page_len_t r_num_bytes; - offset_t r_addr_offset; - logic r_done; - - // write process - page_len_t w_num_bytes_possible; - page_len_t w_num_bytes; - offset_t w_addr_offset; - logic w_done; - - - //-------------------------------------- - // read boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_read_page_splitter ( - .not_bursting_i ( opt_tf_q.src_protocol inside { idma_pkg::OBI} ), - - .reduce_len_i ( opt_tf_q.src_reduce_len ), - .max_llen_i ( opt_tf_q.src_max_llen ), - - .addr_i ( r_tf_q.addr ), - .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) - ); - - assign r_num_bytes_to_pb = r_page_num_bytes_to_pb; - - //-------------------------------------- - // write boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_write_page_splitter ( - .not_bursting_i ( 1'b1 ), - - .reduce_len_i ( opt_tf_q.dst_reduce_len ), - .max_llen_i ( opt_tf_q.dst_max_llen ), - - .addr_i ( w_tf_q.addr ), - .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) - ); - - assign w_num_bytes_to_pb = w_page_num_bytes_to_pb; - - //-------------------------------------- - // page boundary check - //-------------------------------------- - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; - - - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - always_comb begin : proc_num_bytes_possible - // Default: Coupled - r_num_bytes_possible = c_num_bytes_to_pb; - w_num_bytes_possible = c_num_bytes_to_pb; - - if (opt_tf_q.decouple_rw - || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin - r_num_bytes_possible = r_num_bytes_to_pb; - w_num_bytes_possible = w_num_bytes_to_pb; - end - end - - assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; - assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; - - // legalization process -> read and write is coupled together - always_comb begin : proc_read_write_transaction - - // default: keep state - r_tf_d = r_tf_q; - w_tf_d = w_tf_q; - opt_tf_d = opt_tf_q; - - // default: not done - r_done = 1'b0; - w_done = 1'b0; - - //-------------------------------------- - // Legalize read transaction - //-------------------------------------- - // more bytes remaining than we can read - if (r_tf_q.length > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - r_tf_d.length = r_tf_q.length - r_num_bytes_possible; - // next address - r_tf_d.addr = r_tf_q.addr + r_num_bytes; - - // remaining bytes fit in one burst - end else begin - r_num_bytes = r_tf_q.length[PageAddrWidth:0]; - // finished - r_tf_d.valid = 1'b0; - r_done = 1'b1; - end - - //-------------------------------------- - // Legalize write transaction - //-------------------------------------- - // more bytes remaining than we can write - if (w_tf_q.length > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - w_tf_d.length = w_tf_q.length - w_num_bytes_possible; - // next address - w_tf_d.addr = w_tf_q.addr + w_num_bytes; - - // remaining bytes fit in one burst - end else begin - w_num_bytes = w_tf_q.length[PageAddrWidth:0]; - // finished - w_tf_d.valid = 1'b0; - w_done = 1'b1; - end - - //-------------------------------------- - // Kill - //-------------------------------------- - if (kill_i) begin - // kill the current state - r_tf_d = '0; - w_tf_d = '0; - r_done = 1'b1; - w_done = 1'b1; - end - - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o & valid_i) begin - - // load all three mutable objects (source, destination, option) - // source or read - r_tf_d = '{ - length: req_i.length, - addr: req_i.src_addr, - valid: 1'b1, - base_addr: req_i.src_addr - }; - // destination or write - w_tf_d = '{ - length: req_i.length, - addr: req_i.dst_addr, - valid: 1'b1, - base_addr: req_i.dst_addr - }; - // options - opt_tf_d = '{ - src_protocol: req_i.opt.src_protocol, - dst_protocol: req_i.opt.dst_protocol, - read_shift: '0, - write_shift: '0, - decouple_rw: req_i.opt.beo.decouple_rw, - decouple_aw: req_i.opt.beo.decouple_aw, - src_max_llen: req_i.opt.beo.src_max_llen, - dst_max_llen: req_i.opt.beo.dst_max_llen, - src_reduce_len: req_i.opt.beo.src_reduce_len, - dst_reduce_len: req_i.opt.beo.dst_reduce_len, - axi_id: req_i.opt.axi_id, - src_axi_opt: req_i.opt.src, - dst_axi_opt: req_i.opt.dst, - super_last: req_i.opt.last - }; - // determine shift amount - if (CombinedShifter) begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = '0; - end else begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; - end - end - end - - - //-------------------------------------- - // Connect outputs - //-------------------------------------- - - // Read meta channel - always_comb begin - r_req_o.ar_req.axi.ar_chan = '{ - id: opt_tf_q.axi_id, - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 - }; - - end - - // assign the signals needed to set-up the read data path - assign r_req_o.r_dp_req = '{ - src_protocol: opt_tf_q.src_protocol, - offset: r_addr_offset, - tailer: OffsetWidth'(r_num_bytes + r_addr_offset), - shift: opt_tf_q.read_shift, - decouple_aw: opt_tf_q.decouple_aw, - is_single: r_num_bytes <= StrbWidth - }; - - // Write meta channel and data path - always_comb begin - w_req_o.aw_req.obi.a_chan = '{ - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '0, - we: 1, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: 'd0, - is_single: 1'b1 - }; - end - - // last burst in generic 1D transfer? - assign w_req_o.last = w_done; - - // last burst indicated by midend - assign w_req_o.super_last = opt_tf_q.super_last; - - // assign aw decouple flag - assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; - - // busy output - assign r_busy_o = r_tf_q.valid; - assign w_busy_o = w_tf_q.valid; - - - //-------------------------------------- - // Flow Control - //-------------------------------------- - // only advance to next state if: - // * rw_coupled: both machines advance - // * rw_decoupled: either machine advances - - always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw - || (opt_tf_q.dst_protocol inside { idma_pkg::OBI })) begin - r_tf_ena = (r_ready_i & !flush_i) | kill_i; - w_tf_ena = (w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; - end else begin - r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; - end - end - - // load next idma request: if both machines are done! - assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; - - - //-------------------------------------- - // State - //-------------------------------------- - `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) - `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) - `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) - - - //-------------------------------------- - // Assertions - //-------------------------------------- - // only support the decomposition of incremental bursts - `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & - req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & - req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "common_cells/registers.svh" -`include "common_cells/assertions.svh" -`include "idma/guard.svh" - -/// Legalizes a generic 1D transfer according to the rules given by the -/// used protocol. -module idma_legalizer_rw_axi_rw_axis #( - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - parameter type idma_req_t = logic, - /// Read request type - parameter type idma_r_req_t = logic, - /// Write request type - parameter type idma_w_req_t = logic, - /// Mutable transfer type - parameter type idma_mut_tf_t = logic, - /// Mutable options type - parameter type idma_mut_tf_opt_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - - /// 1D request - input idma_req_t req_i, - /// 1D request valid - input logic valid_i, - /// 1D request ready - output logic ready_o, - - /// Read request; contains datapath and meta information - output idma_r_req_t r_req_o, - /// Read request valid - output logic r_valid_o, - /// Read request ready - input logic r_ready_i, - - /// Write request; contains datapath and meta information - output idma_w_req_t w_req_o, - /// Write request valid - output logic w_valid_o, - /// Write request ready - input logic w_ready_i, - - /// Invalidate the current burst transfer, stops emission of requests - input logic flush_i, - /// Kill the active 1D transfer; reload a new transfer - input logic kill_i, - - /// Read machine of the legalizer is busy - output logic r_busy_o, - /// Write machine of the legalizer is busy - output logic w_busy_o -); - function int unsigned max_size(input int unsigned a, b); - return a > b ? a : b; - endfunction - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, StrbWidth); - /// The width of page offset byte addresses - localparam int unsigned PageAddrWidth = $clog2(PageSize); - - /// Offset type - typedef logic [ OffsetWidth-1:0] offset_t; - /// Address type - typedef logic [ AddrWidth-1:0] addr_t; - /// Page address type - typedef logic [PageAddrWidth-1:0] page_addr_t; - /// Page length type - typedef logic [ PageAddrWidth:0] page_len_t; - - - // state: internally hold one transfer, this is mutated - idma_mut_tf_t r_tf_d, r_tf_q; - idma_mut_tf_t w_tf_d, w_tf_q; - idma_mut_tf_opt_t opt_tf_d, opt_tf_q; - - // enable signals for next mutable transfer storage - logic r_tf_ena; - logic w_tf_ena; - - // page boundaries - page_len_t r_page_num_bytes_to_pb; - page_len_t r_num_bytes_to_pb; - page_len_t w_page_num_bytes_to_pb; - page_len_t w_num_bytes_to_pb; - page_len_t c_num_bytes_to_pb; - - // read process - page_len_t r_num_bytes_possible; - page_len_t r_num_bytes; - offset_t r_addr_offset; - logic r_done; - - // write process - page_len_t w_num_bytes_possible; - page_len_t w_num_bytes; - offset_t w_addr_offset; - logic w_done; - - - //-------------------------------------- - // read boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_read_page_splitter ( - .not_bursting_i ( opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM} ), - - .reduce_len_i ( opt_tf_q.src_reduce_len ), - .max_llen_i ( opt_tf_q.src_max_llen ), - - .addr_i ( r_tf_q.addr ), - .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) - ); - - always_comb begin : gen_read_num_bytes_to_pb_logic - case (opt_tf_q.src_protocol) - idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - idma_pkg::AXI_STREAM: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - default: r_num_bytes_to_pb = '0; - endcase - end - - //-------------------------------------- - // write boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_write_page_splitter ( - .not_bursting_i ( opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM} ), - - .reduce_len_i ( opt_tf_q.dst_reduce_len ), - .max_llen_i ( opt_tf_q.dst_max_llen ), - - .addr_i ( w_tf_q.addr ), - .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) - ); - - always_comb begin : gen_write_num_bytes_to_pb_logic - case (opt_tf_q.dst_protocol) - idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - idma_pkg::AXI_STREAM: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - default: w_num_bytes_to_pb = '0; - endcase - end - - //-------------------------------------- - // page boundary check - //-------------------------------------- - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; - - - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - always_comb begin : proc_num_bytes_possible - // Default: Coupled - r_num_bytes_possible = c_num_bytes_to_pb; - w_num_bytes_possible = c_num_bytes_to_pb; - - if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM }) - || (opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM })) begin - r_num_bytes_possible = r_num_bytes_to_pb; - w_num_bytes_possible = w_num_bytes_to_pb; - end - end - - assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; - assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; - - // legalization process -> read and write is coupled together - always_comb begin : proc_read_write_transaction - - // default: keep state - r_tf_d = r_tf_q; - w_tf_d = w_tf_q; - opt_tf_d = opt_tf_q; - - // default: not done - r_done = 1'b0; - w_done = 1'b0; - - //-------------------------------------- - // Legalize read transaction - //-------------------------------------- - // more bytes remaining than we can read - if (r_tf_q.length > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - r_tf_d.length = r_tf_q.length - r_num_bytes_possible; - // next address - r_tf_d.addr = r_tf_q.addr + r_num_bytes; - - // remaining bytes fit in one burst - end else begin - r_num_bytes = r_tf_q.length[PageAddrWidth:0]; - // finished - r_tf_d.valid = 1'b0; - r_done = 1'b1; - end - - //-------------------------------------- - // Legalize write transaction - //-------------------------------------- - // more bytes remaining than we can write - if (w_tf_q.length > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - w_tf_d.length = w_tf_q.length - w_num_bytes_possible; - // next address - w_tf_d.addr = w_tf_q.addr + w_num_bytes; - - // remaining bytes fit in one burst - end else begin - w_num_bytes = w_tf_q.length[PageAddrWidth:0]; - // finished - w_tf_d.valid = 1'b0; - w_done = 1'b1; - end - - //-------------------------------------- - // Kill - //-------------------------------------- - if (kill_i) begin - // kill the current state - r_tf_d = '0; - w_tf_d = '0; - r_done = 1'b1; - w_done = 1'b1; - end - - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o & valid_i) begin - - // load all three mutable objects (source, destination, option) - // source or read - r_tf_d = '{ - length: req_i.length, - addr: req_i.src_addr, - valid: 1'b1, - base_addr: req_i.src_addr - }; - // destination or write - w_tf_d = '{ - length: req_i.length, - addr: req_i.dst_addr, - valid: 1'b1, - base_addr: req_i.dst_addr - }; - // options - opt_tf_d = '{ - src_protocol: req_i.opt.src_protocol, - dst_protocol: req_i.opt.dst_protocol, - read_shift: '0, - write_shift: '0, - decouple_rw: req_i.opt.beo.decouple_rw, - decouple_aw: req_i.opt.beo.decouple_aw, - src_max_llen: req_i.opt.beo.src_max_llen, - dst_max_llen: req_i.opt.beo.dst_max_llen, - src_reduce_len: req_i.opt.beo.src_reduce_len, - dst_reduce_len: req_i.opt.beo.dst_reduce_len, - axi_id: req_i.opt.axi_id, - src_axi_opt: req_i.opt.src, - dst_axi_opt: req_i.opt.dst, - super_last: req_i.opt.last - }; - // determine shift amount - if (CombinedShifter) begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = '0; - end else begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; - end - end - end - - - //-------------------------------------- - // Connect outputs - //-------------------------------------- - - // Read meta channel - always_comb begin : gen_read_meta_channel - r_req_o.ar_req = '0; - case(opt_tf_q.src_protocol) - idma_pkg::AXI: begin - r_req_o.ar_req.axi.ar_chan = '{ - id: opt_tf_q.axi_id, - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 - }; - - end - idma_pkg::AXI_STREAM: begin - r_req_o.ar_req = '0; - - end - default: - r_req_o.ar_req = '0; - endcase - end - - // assign the signals needed to set-up the read data path - assign r_req_o.r_dp_req = '{ - src_protocol: opt_tf_q.src_protocol, - offset: r_addr_offset, - tailer: OffsetWidth'(r_num_bytes + r_addr_offset), - shift: opt_tf_q.read_shift, - decouple_aw: opt_tf_q.decouple_aw, - is_single: r_num_bytes <= StrbWidth - }; - - // Write meta channel and data path - always_comb begin : gen_write_meta_channel - w_req_o.aw_req = '0; - case(opt_tf_q.dst_protocol) - idma_pkg::AXI: begin - w_req_o.aw_req.axi.aw_chan = '{ - id: opt_tf_q.axi_id, - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.dst_axi_opt.burst, - lock: opt_tf_q.dst_axi_opt.lock, - cache: opt_tf_q.dst_axi_opt.cache, - prot: opt_tf_q.dst_axi_opt.prot, - qos: opt_tf_q.dst_axi_opt.qos, - region: opt_tf_q.dst_axi_opt.region, - user: '0, - atop: '0 - }; - - end - idma_pkg::AXI_STREAM: begin - w_req_o.aw_req.axis.t_chan = '{ - data: '0, - strb: '1, - keep: '0, - last: w_tf_q.length == w_num_bytes, - id: opt_tf_q.axi_id, - dest: w_tf_q.base_addr[$bits(w_req_o.aw_req.axis.t_chan.dest)-1:0], - user: w_tf_q.base_addr[$bits(w_req_o.aw_req.axis.t_chan.user)-1+:$bits(w_req_o.aw_req.axis.t_chan.dest)] - }; - - end - default: - w_req_o.aw_req = '0; - endcase - end - - // assign the signals needed to set-up the write data path - always_comb begin : gen_write_data_path - case (opt_tf_q.dst_protocol) - idma_pkg::AXI: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: w_req_o.aw_req.axi.aw_chan.len, - is_single: w_req_o.aw_req.axi.aw_chan.len == '0 - }; - - default: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: 'd0, - is_single: 1'b1 - }; - endcase - end - - - // last burst in generic 1D transfer? - assign w_req_o.last = w_done; - - // last burst indicated by midend - assign w_req_o.super_last = opt_tf_q.super_last; - - // assign aw decouple flag - assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; - - // busy output - assign r_busy_o = r_tf_q.valid; - assign w_busy_o = w_tf_q.valid; - - - //-------------------------------------- - // Flow Control - //-------------------------------------- - // only advance to next state if: - // * rw_coupled: both machines advance - // * rw_decoupled: either machine advances - - always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::AXI_STREAM }) - || (opt_tf_q.dst_protocol inside { idma_pkg::AXI_STREAM })) begin - r_tf_ena = (r_ready_i & !flush_i) | kill_i; - w_tf_ena = (w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; - end else begin - r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; - end - end - - // load next idma request: if both machines are done! - assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; - - - //-------------------------------------- - // State - //-------------------------------------- - `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) - `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) - `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) - - - //-------------------------------------- - // Assertions - //-------------------------------------- - // only support the decomposition of incremental bursts - `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & - req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & - req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "common_cells/registers.svh" -`include "common_cells/assertions.svh" -`include "idma/guard.svh" - -/// Legalizes a generic 1D transfer according to the rules given by the -/// used protocol. -module idma_legalizer_r_obi_rw_init_w_axi #( - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - parameter type idma_req_t = logic, - /// Read request type - parameter type idma_r_req_t = logic, - /// Write request type - parameter type idma_w_req_t = logic, - /// Mutable transfer type - parameter type idma_mut_tf_t = logic, - /// Mutable options type - parameter type idma_mut_tf_opt_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - - /// 1D request - input idma_req_t req_i, - /// 1D request valid - input logic valid_i, - /// 1D request ready - output logic ready_o, - - /// Read request; contains datapath and meta information - output idma_r_req_t r_req_o, - /// Read request valid - output logic r_valid_o, - /// Read request ready - input logic r_ready_i, - - /// Write request; contains datapath and meta information - output idma_w_req_t w_req_o, - /// Write request valid - output logic w_valid_o, - /// Write request ready - input logic w_ready_i, - - /// Invalidate the current burst transfer, stops emission of requests - input logic flush_i, - /// Kill the active 1D transfer; reload a new transfer - input logic kill_i, - - /// Read machine of the legalizer is busy - output logic r_busy_o, - /// Write machine of the legalizer is busy - output logic w_busy_o -); - function int unsigned max_size(input int unsigned a, b); - return a > b ? a : b; - endfunction - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, max_size(StrbWidth, StrbWidth)); - /// The width of page offset byte addresses - localparam int unsigned PageAddrWidth = $clog2(PageSize); - - /// Offset type - typedef logic [ OffsetWidth-1:0] offset_t; - /// Address type - typedef logic [ AddrWidth-1:0] addr_t; - /// Page address type - typedef logic [PageAddrWidth-1:0] page_addr_t; - /// Page length type - typedef logic [ PageAddrWidth:0] page_len_t; - - - // state: internally hold one transfer, this is mutated - idma_mut_tf_t r_tf_d, r_tf_q; - idma_mut_tf_t w_tf_d, w_tf_q; - idma_mut_tf_opt_t opt_tf_d, opt_tf_q; - - // enable signals for next mutable transfer storage - logic r_tf_ena; - logic w_tf_ena; - - // page boundaries - page_len_t r_page_num_bytes_to_pb; - page_len_t r_num_bytes_to_pb; - page_len_t w_page_num_bytes_to_pb; - page_len_t w_num_bytes_to_pb; - page_len_t c_num_bytes_to_pb; - - // read process - page_len_t r_num_bytes_possible; - page_len_t r_num_bytes; - offset_t r_addr_offset; - logic r_done; - - // write process - page_len_t w_num_bytes_possible; - page_len_t w_num_bytes; - offset_t w_addr_offset; - logic w_done; - - - //-------------------------------------- - // read boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_read_page_splitter ( - .not_bursting_i ( 1'b1 ), - - .reduce_len_i ( opt_tf_q.src_reduce_len ), - .max_llen_i ( opt_tf_q.src_max_llen ), - - .addr_i ( r_tf_q.addr ), - .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) - ); - - always_comb begin : gen_read_num_bytes_to_pb_logic - case (opt_tf_q.src_protocol) - idma_pkg::INIT: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - default: r_num_bytes_to_pb = '0; - endcase - end - - //-------------------------------------- - // write boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_write_page_splitter ( - .not_bursting_i ( opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI} ), - - .reduce_len_i ( opt_tf_q.dst_reduce_len ), - .max_llen_i ( opt_tf_q.dst_max_llen ), - - .addr_i ( w_tf_q.addr ), - .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) - ); - - always_comb begin : gen_write_num_bytes_to_pb_logic - case (opt_tf_q.dst_protocol) - idma_pkg::AXI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - idma_pkg::INIT: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - default: w_num_bytes_to_pb = '0; - endcase - end - - //-------------------------------------- - // page boundary check - //-------------------------------------- - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; - - - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - always_comb begin : proc_num_bytes_possible - // Default: Coupled - r_num_bytes_possible = c_num_bytes_to_pb; - w_num_bytes_possible = c_num_bytes_to_pb; - - if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::INIT })) begin - r_num_bytes_possible = r_num_bytes_to_pb; - w_num_bytes_possible = w_num_bytes_to_pb; - end - end - - assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; - assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; - - // legalization process -> read and write is coupled together - always_comb begin : proc_read_write_transaction - - // default: keep state - r_tf_d = r_tf_q; - w_tf_d = w_tf_q; - opt_tf_d = opt_tf_q; - - // default: not done - r_done = 1'b0; - w_done = 1'b0; - - //-------------------------------------- - // Legalize read transaction - //-------------------------------------- - // more bytes remaining than we can read - if (r_tf_q.length > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - r_tf_d.length = r_tf_q.length - r_num_bytes_possible; - // next address - r_tf_d.addr = r_tf_q.addr + r_num_bytes; - - // remaining bytes fit in one burst - end else begin - r_num_bytes = r_tf_q.length[PageAddrWidth:0]; - // finished - r_tf_d.valid = 1'b0; - r_done = 1'b1; - end - - //-------------------------------------- - // Legalize write transaction - //-------------------------------------- - // more bytes remaining than we can write - if (w_tf_q.length > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - w_tf_d.length = w_tf_q.length - w_num_bytes_possible; - // next address - w_tf_d.addr = w_tf_q.addr + w_num_bytes; - - // remaining bytes fit in one burst - end else begin - w_num_bytes = w_tf_q.length[PageAddrWidth:0]; - // finished - w_tf_d.valid = 1'b0; - w_done = 1'b1; - end - - //-------------------------------------- - // Kill - //-------------------------------------- - if (kill_i) begin - // kill the current state - r_tf_d = '0; - w_tf_d = '0; - r_done = 1'b1; - w_done = 1'b1; - end - - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o & valid_i) begin - - // load all three mutable objects (source, destination, option) - // source or read - r_tf_d = '{ - length: req_i.length, - addr: req_i.src_addr, - valid: 1'b1, - base_addr: req_i.src_addr - }; - // destination or write - w_tf_d = '{ - length: req_i.length, - addr: req_i.dst_addr, - valid: 1'b1, - base_addr: req_i.dst_addr - }; - // options - opt_tf_d = '{ - src_protocol: req_i.opt.src_protocol, - dst_protocol: req_i.opt.dst_protocol, - read_shift: '0, - write_shift: '0, - decouple_rw: req_i.opt.beo.decouple_rw, - decouple_aw: req_i.opt.beo.decouple_aw, - src_max_llen: req_i.opt.beo.src_max_llen, - dst_max_llen: req_i.opt.beo.dst_max_llen, - src_reduce_len: req_i.opt.beo.src_reduce_len, - dst_reduce_len: req_i.opt.beo.dst_reduce_len, - axi_id: req_i.opt.axi_id, - src_axi_opt: req_i.opt.src, - dst_axi_opt: req_i.opt.dst, - super_last: req_i.opt.last - }; - // determine shift amount - if (CombinedShifter) begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = '0; - end else begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; - end - end - end - - - //-------------------------------------- - // Connect outputs - //-------------------------------------- - - // Read meta channel - always_comb begin : gen_read_meta_channel - r_req_o.ar_req = '0; - case(opt_tf_q.src_protocol) - idma_pkg::INIT: begin - r_req_o.ar_req.init.req_chan = '{ - cfg: r_tf_q.base_addr, - term: '0, - strb: '0, - id: opt_tf_d.axi_id - }; - - end - idma_pkg::OBI: begin - r_req_o.ar_req.obi.a_chan = '{ - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '1, - we: 1'b0, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - end - default: - r_req_o.ar_req = '0; - endcase - end - - // assign the signals needed to set-up the read data path - assign r_req_o.r_dp_req = '{ - src_protocol: opt_tf_q.src_protocol, - offset: r_addr_offset, - tailer: OffsetWidth'(r_num_bytes + r_addr_offset), - shift: opt_tf_q.read_shift, - decouple_aw: opt_tf_q.decouple_aw, - is_single: r_num_bytes <= StrbWidth - }; - - // Write meta channel and data path - always_comb begin : gen_write_meta_channel - w_req_o.aw_req = '0; - case(opt_tf_q.dst_protocol) - idma_pkg::AXI: begin - w_req_o.aw_req.axi.aw_chan = '{ - id: opt_tf_q.axi_id, - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((w_num_bytes + w_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.dst_axi_opt.burst, - lock: opt_tf_q.dst_axi_opt.lock, - cache: opt_tf_q.dst_axi_opt.cache, - prot: opt_tf_q.dst_axi_opt.prot, - qos: opt_tf_q.dst_axi_opt.qos, - region: opt_tf_q.dst_axi_opt.region, - user: '0, - atop: '0 - }; - - end - idma_pkg::INIT: begin - w_req_o.aw_req.init.req_chan = '{ - cfg: w_tf_q.base_addr, - term: '0, - strb: '0, - id: opt_tf_d.axi_id - }; - - end - default: - w_req_o.aw_req = '0; - endcase - end - - // assign the signals needed to set-up the write data path - always_comb begin : gen_write_data_path - case (opt_tf_q.dst_protocol) - idma_pkg::AXI: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: w_req_o.aw_req.axi.aw_chan.len, - is_single: w_req_o.aw_req.axi.aw_chan.len == '0 - }; - - default: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: 'd0, - is_single: 1'b1 - }; - endcase - end - - - // last burst in generic 1D transfer? - assign w_req_o.last = w_done; - - // last burst indicated by midend - assign w_req_o.super_last = opt_tf_q.super_last; - - // assign aw decouple flag - assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; - - // busy output - assign r_busy_o = r_tf_q.valid; - assign w_busy_o = w_tf_q.valid; - - - //-------------------------------------- - // Flow Control - //-------------------------------------- - // only advance to next state if: - // * rw_coupled: both machines advance - // * rw_decoupled: either machine advances - - always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::INIT })) begin - r_tf_ena = (r_ready_i & !flush_i) | kill_i; - w_tf_ena = (w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; - end else begin - r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; - end - end - - // load next idma request: if both machines are done! - assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; - - - //-------------------------------------- - // State - //-------------------------------------- - `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) - `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) - `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) - - - //-------------------------------------- - // Assertions - //-------------------------------------- - // only support the decomposition of incremental bursts - `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & - req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & - req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "common_cells/registers.svh" -`include "common_cells/assertions.svh" -`include "idma/guard.svh" - -/// Legalizes a generic 1D transfer according to the rules given by the -/// used protocol. -module idma_legalizer_r_axi_rw_init_rw_obi #( - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - parameter type idma_req_t = logic, - /// Read request type - parameter type idma_r_req_t = logic, - /// Write request type - parameter type idma_w_req_t = logic, - /// Mutable transfer type - parameter type idma_mut_tf_t = logic, - /// Mutable options type - parameter type idma_mut_tf_opt_t = logic -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - - /// 1D request - input idma_req_t req_i, - /// 1D request valid - input logic valid_i, - /// 1D request ready - output logic ready_o, - - /// Read request; contains datapath and meta information - output idma_r_req_t r_req_o, - /// Read request valid - output logic r_valid_o, - /// Read request ready - input logic r_ready_i, - - /// Write request; contains datapath and meta information - output idma_w_req_t w_req_o, - /// Write request valid - output logic w_valid_o, - /// Write request ready - input logic w_ready_i, - - /// Invalidate the current burst transfer, stops emission of requests - input logic flush_i, - /// Kill the active 1D transfer; reload a new transfer - input logic kill_i, - - /// Read machine of the legalizer is busy - output logic r_busy_o, - /// Write machine of the legalizer is busy - output logic w_busy_o -); - function int unsigned max_size(input int unsigned a, b); - return a > b ? a : b; - endfunction - - /// Stobe width - localparam int unsigned StrbWidth = DataWidth / 8; - /// Offset width - localparam int unsigned OffsetWidth = $clog2(StrbWidth); - /// The size of a page in byte - localparam int unsigned PageSize = max_size(256 * StrbWidth > 4096 ? 4096 : 256 * StrbWidth, max_size(StrbWidth, StrbWidth)); - /// The width of page offset byte addresses - localparam int unsigned PageAddrWidth = $clog2(PageSize); - - /// Offset type - typedef logic [ OffsetWidth-1:0] offset_t; - /// Address type - typedef logic [ AddrWidth-1:0] addr_t; - /// Page address type - typedef logic [PageAddrWidth-1:0] page_addr_t; - /// Page length type - typedef logic [ PageAddrWidth:0] page_len_t; - - - // state: internally hold one transfer, this is mutated - idma_mut_tf_t r_tf_d, r_tf_q; - idma_mut_tf_t w_tf_d, w_tf_q; - idma_mut_tf_opt_t opt_tf_d, opt_tf_q; - - // enable signals for next mutable transfer storage - logic r_tf_ena; - logic w_tf_ena; - - // page boundaries - page_len_t r_page_num_bytes_to_pb; - page_len_t r_num_bytes_to_pb; - page_len_t w_page_num_bytes_to_pb; - page_len_t w_num_bytes_to_pb; - page_len_t c_num_bytes_to_pb; - - // read process - page_len_t r_num_bytes_possible; - page_len_t r_num_bytes; - offset_t r_addr_offset; - logic r_done; - - // write process - page_len_t w_num_bytes_possible; - page_len_t w_num_bytes; - offset_t w_addr_offset; - logic w_done; - - - //-------------------------------------- - // read boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_read_page_splitter ( - .not_bursting_i ( opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI} ), - - .reduce_len_i ( opt_tf_q.src_reduce_len ), - .max_llen_i ( opt_tf_q.src_max_llen ), - - .addr_i ( r_tf_q.addr ), - .num_bytes_to_pb_o ( r_page_num_bytes_to_pb ) - ); - - always_comb begin : gen_read_num_bytes_to_pb_logic - case (opt_tf_q.src_protocol) - idma_pkg::AXI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - idma_pkg::INIT: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - idma_pkg::OBI: r_num_bytes_to_pb = r_page_num_bytes_to_pb; - default: r_num_bytes_to_pb = '0; - endcase - end - - //-------------------------------------- - // write boundary check - //-------------------------------------- - idma_legalizer_page_splitter #( - .OffsetWidth ( OffsetWidth ), - .PageAddrWidth ( PageSize ), - .addr_t ( addr_t ), - .page_len_t ( page_len_t ), - .page_addr_t ( page_addr_t ) - ) i_write_page_splitter ( - .not_bursting_i ( 1'b1 ), - - .reduce_len_i ( opt_tf_q.dst_reduce_len ), - .max_llen_i ( opt_tf_q.dst_max_llen ), - - .addr_i ( w_tf_q.addr ), - .num_bytes_to_pb_o ( w_page_num_bytes_to_pb ) - ); - - always_comb begin : gen_write_num_bytes_to_pb_logic - case (opt_tf_q.dst_protocol) - idma_pkg::INIT: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - idma_pkg::OBI: w_num_bytes_to_pb = w_page_num_bytes_to_pb; - default: w_num_bytes_to_pb = '0; - endcase - end - - //-------------------------------------- - // page boundary check - //-------------------------------------- - // how many transfers are remaining when concerning both r/w pages? - // take the boundary that is closer - assign c_num_bytes_to_pb = (r_num_bytes_to_pb > w_num_bytes_to_pb) ? - w_num_bytes_to_pb : r_num_bytes_to_pb; - - - //-------------------------------------- - // Synchronized R/W process - //-------------------------------------- - always_comb begin : proc_num_bytes_possible - // Default: Coupled - r_num_bytes_possible = c_num_bytes_to_pb; - w_num_bytes_possible = c_num_bytes_to_pb; - - if (opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI })) begin - r_num_bytes_possible = r_num_bytes_to_pb; - w_num_bytes_possible = w_num_bytes_to_pb; - end - end - - assign r_addr_offset = r_tf_q.addr[OffsetWidth-1:0]; - assign w_addr_offset = w_tf_q.addr[OffsetWidth-1:0]; - - // legalization process -> read and write is coupled together - always_comb begin : proc_read_write_transaction - - // default: keep state - r_tf_d = r_tf_q; - w_tf_d = w_tf_q; - opt_tf_d = opt_tf_q; - - // default: not done - r_done = 1'b0; - w_done = 1'b0; - - //-------------------------------------- - // Legalize read transaction - //-------------------------------------- - // more bytes remaining than we can read - if (r_tf_q.length > r_num_bytes_possible) begin - r_num_bytes = r_num_bytes_possible; - // calculate remainder - r_tf_d.length = r_tf_q.length - r_num_bytes_possible; - // next address - r_tf_d.addr = r_tf_q.addr + r_num_bytes; - - // remaining bytes fit in one burst - end else begin - r_num_bytes = r_tf_q.length[PageAddrWidth:0]; - // finished - r_tf_d.valid = 1'b0; - r_done = 1'b1; - end - - //-------------------------------------- - // Legalize write transaction - //-------------------------------------- - // more bytes remaining than we can write - if (w_tf_q.length > w_num_bytes_possible) begin - w_num_bytes = w_num_bytes_possible; - // calculate remainder - w_tf_d.length = w_tf_q.length - w_num_bytes_possible; - // next address - w_tf_d.addr = w_tf_q.addr + w_num_bytes; - - // remaining bytes fit in one burst - end else begin - w_num_bytes = w_tf_q.length[PageAddrWidth:0]; - // finished - w_tf_d.valid = 1'b0; - w_done = 1'b1; - end - - //-------------------------------------- - // Kill - //-------------------------------------- - if (kill_i) begin - // kill the current state - r_tf_d = '0; - w_tf_d = '0; - r_done = 1'b1; - w_done = 1'b1; - end - - //-------------------------------------- - // Refill - //-------------------------------------- - // new request is taken in if both r and w machines are ready. - if (ready_o & valid_i) begin - - // load all three mutable objects (source, destination, option) - // source or read - r_tf_d = '{ - length: req_i.length, - addr: req_i.src_addr, - valid: 1'b1, - base_addr: req_i.src_addr - }; - // destination or write - w_tf_d = '{ - length: req_i.length, - addr: req_i.dst_addr, - valid: 1'b1, - base_addr: req_i.dst_addr - }; - // options - opt_tf_d = '{ - src_protocol: req_i.opt.src_protocol, - dst_protocol: req_i.opt.dst_protocol, - read_shift: '0, - write_shift: '0, - decouple_rw: req_i.opt.beo.decouple_rw, - decouple_aw: req_i.opt.beo.decouple_aw, - src_max_llen: req_i.opt.beo.src_max_llen, - dst_max_llen: req_i.opt.beo.dst_max_llen, - src_reduce_len: req_i.opt.beo.src_reduce_len, - dst_reduce_len: req_i.opt.beo.dst_reduce_len, - axi_id: req_i.opt.axi_id, - src_axi_opt: req_i.opt.src, - dst_axi_opt: req_i.opt.dst, - super_last: req_i.opt.last - }; - // determine shift amount - if (CombinedShifter) begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0] - req_i.dst_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = '0; - end else begin - opt_tf_d.read_shift = req_i.src_addr[OffsetWidth-1:0]; - opt_tf_d.write_shift = - req_i.dst_addr[OffsetWidth-1:0]; - end - end - end - - - //-------------------------------------- - // Connect outputs - //-------------------------------------- - - // Read meta channel - always_comb begin : gen_read_meta_channel - r_req_o.ar_req = '0; - case(opt_tf_q.src_protocol) - idma_pkg::AXI: begin - r_req_o.ar_req.axi.ar_chan = '{ - id: opt_tf_q.axi_id, - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - len: ((r_num_bytes + r_addr_offset - 'd1) >> OffsetWidth), - size: axi_pkg::size_t'(OffsetWidth), - burst: opt_tf_q.src_axi_opt.burst, - lock: opt_tf_q.src_axi_opt.lock, - cache: opt_tf_q.src_axi_opt.cache, - prot: opt_tf_q.src_axi_opt.prot, - qos: opt_tf_q.src_axi_opt.qos, - region: opt_tf_q.src_axi_opt.region, - user: '0 - }; - - end - idma_pkg::INIT: begin - r_req_o.ar_req.init.req_chan = '{ - cfg: r_tf_q.base_addr, - term: '0, - strb: '0, - id: opt_tf_d.axi_id - }; - - end - idma_pkg::OBI: begin - r_req_o.ar_req.obi.a_chan = '{ - addr: { r_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '1, - we: 1'b0, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - end - default: - r_req_o.ar_req = '0; - endcase - end - - // assign the signals needed to set-up the read data path - assign r_req_o.r_dp_req = '{ - src_protocol: opt_tf_q.src_protocol, - offset: r_addr_offset, - tailer: OffsetWidth'(r_num_bytes + r_addr_offset), - shift: opt_tf_q.read_shift, - decouple_aw: opt_tf_q.decouple_aw, - is_single: r_num_bytes <= StrbWidth - }; - - // Write meta channel and data path - always_comb begin : gen_write_meta_channel - w_req_o.aw_req = '0; - case(opt_tf_q.dst_protocol) - idma_pkg::INIT: begin - w_req_o.aw_req.init.req_chan = '{ - cfg: w_tf_q.base_addr, - term: '0, - strb: '0, - id: opt_tf_d.axi_id - }; - - end - idma_pkg::OBI: begin - w_req_o.aw_req.obi.a_chan = '{ - addr: { w_tf_q.addr[AddrWidth-1:OffsetWidth], {{OffsetWidth}{1'b0}} }, - be: '0, - we: 1, - wdata: '0, - aid: opt_tf_q.axi_id, - a_optional: '0 - }; - - end - default: - w_req_o.aw_req = '0; - endcase - end - - // assign the signals needed to set-up the write data path - always_comb begin : gen_write_data_path - case (opt_tf_q.dst_protocol) - default: - w_req_o.w_dp_req = '{ - dst_protocol: opt_tf_q.dst_protocol, - offset: w_addr_offset, - tailer: OffsetWidth'(w_num_bytes + w_addr_offset), - shift: opt_tf_q.write_shift, - num_beats: 'd0, - is_single: 1'b1 - }; - endcase - end - - - // last burst in generic 1D transfer? - assign w_req_o.last = w_done; - - // last burst indicated by midend - assign w_req_o.super_last = opt_tf_q.super_last; - - // assign aw decouple flag - assign w_req_o.decouple_aw = opt_tf_q.decouple_aw; - - // busy output - assign r_busy_o = r_tf_q.valid; - assign w_busy_o = w_tf_q.valid; - - - //-------------------------------------- - // Flow Control - //-------------------------------------- - // only advance to next state if: - // * rw_coupled: both machines advance - // * rw_decoupled: either machine advances - - always_comb begin : proc_legalizer_flow_control - if ( opt_tf_q.decouple_rw - || (opt_tf_q.src_protocol inside { idma_pkg::INIT, idma_pkg::OBI }) - || (opt_tf_q.dst_protocol inside { idma_pkg::INIT, idma_pkg::OBI })) begin - r_tf_ena = (r_ready_i & !flush_i) | kill_i; - w_tf_ena = (w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & w_ready_i & !flush_i; - end else begin - r_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - w_tf_ena = (r_ready_i & w_ready_i & !flush_i) | kill_i; - - r_valid_o = r_tf_q.valid & w_ready_i & r_ready_i & !flush_i; - w_valid_o = w_tf_q.valid & r_ready_i & w_ready_i & !flush_i; - end - end - - // load next idma request: if both machines are done! - assign ready_o = r_done & w_done & r_ready_i & w_ready_i & !flush_i; - - - //-------------------------------------- - // State - //-------------------------------------- - `FF (opt_tf_q, opt_tf_d, '0, clk_i, rst_ni) - `FFL(r_tf_q, r_tf_d, r_tf_ena, '0, clk_i, rst_ni) - `FFL(w_tf_q, w_tf_d, w_tf_ena, '0, clk_i, rst_ni) - - - //-------------------------------------- - // Assertions - //-------------------------------------- - // only support the decomposition of incremental bursts - `ASSERT_NEVER(OnlyIncrementalBurstsSRC, (ready_o & valid_i & - req_i.opt.src.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - `ASSERT_NEVER(OnlyIncrementalBurstsDST, (ready_o & valid_i & - req_i.opt.dst.burst != axi_pkg::BURST_INCR), clk_i, !rst_ni) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_rw_axi #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b1, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_rw_axi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - idma_error_handler #( - .MetaFifoDepth ( MetaFifoDepth ), - .PrintFifoInfo ( PrintFifoInfo ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_eh_req_t ), - .addr_t ( addr_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ) - ) i_idma_error_handler ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid ), - .rsp_ready_i ( rsp_ready ), - .req_valid_i ( req_valid ), - .req_ready_i ( req_ready_o ), - .eh_i ( idma_eh_req_i ), - .eh_valid_i ( eh_req_valid_i ), - .eh_ready_o ( eh_req_ready_o ), - .r_addr_i ( r_req.ar_req.axi.ar_chan.addr ), - .w_addr_i ( w_req.aw_req.axi.aw_chan.addr ), - .r_consume_i ( r_valid & r_ready ), - .w_consume_i ( w_valid & w_ready ), - .legalizer_flush_o ( legalizer_flush ), - .legalizer_kill_o ( legalizer_kill ), - .dp_busy_i ( dp_busy ), - .dp_poison_o ( dp_poison ), - .r_dp_rsp_i ( r_dp_rsp ), - .r_dp_valid_i ( r_dp_rsp_valid ), - .r_dp_ready_o ( r_dp_rsp_ready ), - .w_dp_rsp_i ( w_dp_rsp ), - .w_dp_valid_i ( w_dp_rsp_valid ), - .w_dp_ready_o ( w_dp_rsp_ready ), - .w_last_burst_i ( w_last_burst ), - .w_super_last_i ( w_super_last ), - .fsm_busy_o ( busy_o.eh_fsm_busy ), - .cnt_busy_o ( busy_o.eh_cnt_busy ) - ); - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - - fall_through_register #( - .T ( read_meta_channel_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_req.ar_req ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_rw_axi #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .axi_read_req_o ( axi_read_req_o ), - .axi_read_rsp_i ( axi_read_rsp_i ), - .axi_write_req_o ( axi_write_req_o ), - .axi_write_rsp_i ( axi_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - // instantiate the channel coupler - idma_channel_coupler #( - .NumAxInFlight ( NumAxInFlight ), - .AddrWidth ( AddrWidth ), - .UserWidth ( UserWidth ), - .AxiIdWidth ( AxiIdWidth ), - .PrintFifoInfo ( PrintFifoInfo ), - .axi_aw_chan_t ( write_meta_channel_t ) - ) i_idma_channel_coupler ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .r_rsp_valid_i ( r_chan_valid ), - .r_rsp_ready_i ( r_chan_ready ), - .r_rsp_first_i ( r_dp_rsp.first ), - .r_decouple_aw_i ( r_dp_req_out.decouple_aw ), - .aw_decouple_aw_i ( w_req.decouple_aw ), - .aw_req_i ( w_req.aw_req ), - .aw_valid_i ( w_valid ), - .aw_ready_o ( aw_ready ), - .aw_req_o ( aw_req_dp ), - .aw_valid_o ( aw_valid_dp ), - .aw_ready_i ( aw_ready_dp ), - .busy_o ( busy_o.raw_coupler_busy ) - ); - end else begin : gen_r_aw_bypass - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - fall_through_register #( - .T ( write_meta_channel_t ) - ) i_aw_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( w_valid ), - .ready_o ( aw_ready ), - .data_i ( w_req.aw_req ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp ), - .data_o ( aw_req_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_r_obi_w_axi #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_r_obi_w_axi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); - end - ) - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - - fall_through_register #( - .T ( read_meta_channel_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_req.ar_req ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_r_obi_w_axi #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .obi_read_req_o ( obi_read_req_o ), - .obi_read_rsp_i ( obi_read_rsp_i ), - .axi_write_req_o ( axi_write_req_o ), - .axi_write_rsp_i ( axi_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - fall_through_register #( - .T ( write_meta_channel_t ) - ) i_aw_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( w_valid ), - .ready_o ( aw_ready ), - .data_i ( w_req.aw_req ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp ), - .data_o ( aw_req_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_r_axi_w_obi #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_r_axi_w_obi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); - end - ) - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - - fall_through_register #( - .T ( read_meta_channel_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_req.ar_req ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_r_axi_w_obi #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .axi_read_req_o ( axi_read_req_o ), - .axi_read_rsp_i ( axi_read_rsp_i ), - .obi_write_req_o ( obi_write_req_o ), - .obi_write_rsp_i ( obi_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests - // As a write could depend on up to two reads - stream_fifo_optimal_wrap #( - .Depth ( 2 ), - .type_t ( write_meta_channel_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_aw_fifo ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.aw_req ), - .valid_i ( w_valid && aw_ready ), - .ready_o ( aw_ready ), - .data_o ( aw_req_dp ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp && aw_valid_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_rw_axi_rw_axis #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// AXI Stream Request and Response channel type - parameter type axis_req_t = logic, - parameter type axis_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// AXI Stream read request - input axis_req_t axis_read_req_i, - /// AXI Stream read response - output axis_rsp_t axis_read_rsp_o, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// AXI Stream write request - output axis_req_t axis_write_req_o, - /// AXI Stream write response - input axis_rsp_t axis_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - typedef struct packed { - idma_pkg::protocol_e src_protocol; - read_meta_channel_t ar_req; - } read_meta_channel_tagged_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - write_meta_channel_t aw_req; - } write_meta_channel_tagged_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - read_meta_channel_tagged_t r_meta_req_tagged; - write_meta_channel_tagged_t w_meta_req_tagged; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_tagged_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_tagged_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_rw_axi_rw_axis #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); - end - ) - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - always_comb begin : assign_r_meta_req - r_meta_req_tagged.src_protocol = r_req.r_dp_req.src_protocol; - r_meta_req_tagged.ar_req = r_req.ar_req; - end - - fall_through_register #( - .T ( read_meta_channel_tagged_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_meta_req_tagged ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_rw_axi_rw_axis #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .axis_req_t ( axis_req_t ), - .axis_rsp_t ( axis_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .axi_read_req_o ( axi_read_req_o ), - .axi_read_rsp_i ( axi_read_rsp_i ), - .axis_read_req_i ( axis_read_req_i ), - .axis_read_rsp_o ( axis_read_rsp_o ), - .axi_write_req_o ( axi_write_req_o ), - .axi_write_rsp_i ( axi_write_rsp_i ), - .axis_write_req_o ( axis_write_req_o ), - .axis_write_rsp_i ( axis_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - always_comb begin : assign_tagged_w_req // need to have an always_comb block for Questa to not crap itself - w_meta_req_tagged.dst_protocol = w_req.w_dp_req.dst_protocol; - w_meta_req_tagged.aw_req = w_req.aw_req; - end - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests - // As a write could depend on up to two reads - stream_fifo_optimal_wrap #( - .Depth ( 2 ), - .type_t ( write_meta_channel_tagged_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_aw_fifo ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_meta_req_tagged ), - .valid_i ( w_valid && aw_ready ), - .ready_o ( aw_ready ), - .data_o ( aw_req_dp ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp && aw_valid_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_r_obi_rw_init_w_axi #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// Memory Init Request and Response channel type - parameter type init_req_t = logic, - parameter type init_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// Memory Init read request - output init_req_t init_read_req_o, - /// Memory Init read response - input init_rsp_t init_read_rsp_i, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// AXI4+ATOP write request - output axi_req_t axi_write_req_o, - /// AXI4+ATOP write response - input axi_rsp_t axi_write_rsp_i, - - /// Memory Init write request - output init_req_t init_write_req_o, - /// Memory Init write response - input init_rsp_t init_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - typedef struct packed { - idma_pkg::protocol_e src_protocol; - read_meta_channel_t ar_req; - } read_meta_channel_tagged_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - write_meta_channel_t aw_req; - } write_meta_channel_tagged_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - read_meta_channel_tagged_t r_meta_req_tagged; - write_meta_channel_tagged_t w_meta_req_tagged; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_tagged_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_tagged_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_r_obi_rw_init_w_axi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); - end - ) - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - always_comb begin : assign_r_meta_req - r_meta_req_tagged.src_protocol = r_req.r_dp_req.src_protocol; - r_meta_req_tagged.ar_req = r_req.ar_req; - end - - fall_through_register #( - .T ( read_meta_channel_tagged_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_meta_req_tagged ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_r_obi_rw_init_w_axi #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .init_req_t ( init_req_t ), - .init_rsp_t ( init_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .init_read_req_o ( init_read_req_o ), - .init_read_rsp_i ( init_read_rsp_i ), - .obi_read_req_o ( obi_read_req_o ), - .obi_read_rsp_i ( obi_read_rsp_i ), - .axi_write_req_o ( axi_write_req_o ), - .axi_write_rsp_i ( axi_write_rsp_i ), - .init_write_req_o ( init_write_req_o ), - .init_write_rsp_i ( init_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - always_comb begin : assign_tagged_w_req // need to have an always_comb block for Questa to not crap itself - w_meta_req_tagged.dst_protocol = w_req.w_dp_req.dst_protocol; - w_meta_req_tagged.aw_req = w_req.aw_req; - end - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - fall_through_register #( - .T ( write_meta_channel_tagged_t ) - ) i_aw_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( w_valid ), - .ready_o ( aw_ready ), - .data_i ( w_meta_req_tagged ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp ), - .data_o ( aw_req_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "idma/guard.svh" - -/// The iDMA backend implements an arbitrary 1D copy engine -module idma_backend_r_axi_rw_init_rw_obi #( - /// Data width - parameter int unsigned DataWidth = 32'd16, - /// Address width - parameter int unsigned AddrWidth = 32'd24, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd2, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd2, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd24, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter idma_pkg::error_cap_e ErrorCap = idma_pkg::NO_ERROR_HANDLING, - /// Print the info of the FIFO configuration - parameter bit PrintFifoInfo = 1'b0, - /// 1D iDMA request type - parameter type idma_req_t = logic, - /// iDMA response type - parameter type idma_rsp_t = logic, - /// Error Handler request type - parameter type idma_eh_req_t = logic, - /// iDMA busy signal - parameter type idma_busy_t = logic, - /// AXI4+ATOP Request and Response channel type - parameter type axi_req_t = logic, - parameter type axi_rsp_t = logic, - /// Memory Init Request and Response channel type - parameter type init_req_t = logic, - parameter type init_rsp_t = logic, - /// OBI Request and Response channel type - parameter type obi_req_t = logic, - parameter type obi_rsp_t = logic, - /// Address Read Channel type - parameter type read_meta_channel_t = logic, - /// Address Write Channel type - parameter type write_meta_channel_t = logic, - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth) -)( - /// Clock - input logic clk_i, - /// Asynchronous reset, active low - input logic rst_ni, - /// Testmode in - input logic testmode_i, - - /// 1D iDMA request - input idma_req_t idma_req_i, - /// 1D iDMA request valid - input logic req_valid_i, - /// 1D iDMA request ready - output logic req_ready_o, - - /// iDMA response - output idma_rsp_t idma_rsp_o, - /// iDMA response valid - output logic rsp_valid_o, - /// iDMA response ready - input logic rsp_ready_i, - - /// Error handler request - input idma_eh_req_t idma_eh_req_i, - /// Error handler request valid - input logic eh_req_valid_i, - /// Error handler request ready - output logic eh_req_ready_o, - - /// AXI4+ATOP read request - output axi_req_t axi_read_req_o, - /// AXI4+ATOP read response - input axi_rsp_t axi_read_rsp_i, - - /// Memory Init read request - output init_req_t init_read_req_o, - /// Memory Init read response - input init_rsp_t init_read_rsp_i, - - /// OBI read request - output obi_req_t obi_read_req_o, - /// OBI read response - input obi_rsp_t obi_read_rsp_i, - - /// Memory Init write request - output init_req_t init_write_req_o, - /// Memory Init write response - input init_rsp_t init_write_rsp_i, - - /// OBI write request - output obi_req_t obi_write_req_o, - /// OBI write response - input obi_rsp_t obi_write_rsp_i, - - /// iDMA busy flags - output idma_busy_t busy_o -); - - /// The localparam MetaFifoDepth holds the maximum number of transfers that can be - /// in-flight under any circumstances. - localparam int unsigned MetaFifoDepth = BufferDepth + NumAxInFlight + MemSysDepth; - - /// Address type - typedef logic [AddrWidth-1:0] addr_t; - /// DAta type - typedef logic [DataWidth-1:0] data_t; - /// Strobe type - typedef logic [StrbWidth-1:0] strb_t; - /// User type - typedef logic [UserWidth-1:0] user_t; - /// ID type - typedef logic [AxiIdWidth-1:0] id_t; - /// Offset type - typedef logic [OffsetWidth-1:0] offset_t; - /// Transfer length type - typedef logic [TFLenWidth-1:0] tf_len_t; - - /// The datapath read request type holds all the information required to configure the read - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the read - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `decouple_aw`: If the transfer has the AW decoupled from the R - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e src_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - logic decouple_aw; - logic is_single; - } r_dp_req_t; - - /// The datapath read response type provides feedback from the read part of the datapath: - /// - `resp`: The response from the R channel of the AXI4 manager interface - /// - `last`: The last flag from the R channel of the AXI4 manager interface - /// - `first`: Is the current item first beat in the burst - typedef struct packed { - axi_pkg::resp_t resp; - logic last; - logic first; - } r_dp_rsp_t; - - /// The datapath write request type holds all the information required to configure the write - /// part of the datapath. The type consists of: - /// - `offset`: The bus offset of the write - /// - `trailer`: How many empty bytes are required to pad the transfer to a multiple of the - /// bus width. - /// - `shift`: The amount the data needs to be shifted - /// - `num_beats`: The number of beats this burst consist of - /// - `is_single`: Is this transfer just one beat long? `(len == 0)` - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - offset_t offset; - offset_t tailer; - offset_t shift; - axi_pkg::len_t num_beats; - logic is_single; - } w_dp_req_t; - - /// The datapath write response type provides feedback from the write part of the datapath: - /// - `resp`: The response from the B channel of the AXI4 manager interface - /// - `user`: The user field from the B channel of the AXI4 manager interface - typedef struct packed { - axi_pkg::resp_t resp; - user_t user; - } w_dp_rsp_t; - - /// The iDMA read request bundles an `AR` type and a datapath read response type together. - typedef struct packed { - r_dp_req_t r_dp_req; - read_meta_channel_t ar_req; - } idma_r_req_t; - typedef struct packed { - idma_pkg::protocol_e src_protocol; - read_meta_channel_t ar_req; - } read_meta_channel_tagged_t; - - /// The iDMA write request bundles an `AW` type and a datapath write response type together. It - /// has an additional flags: - /// - `last`: indicating the current burst is the last one of the generic 1D transfer currently - /// being processed - /// - `midend_last`: The current transfer is marked by the controlling as last - /// - `decouple_aw`: indicates this is an R-AW decoupled transfer - typedef struct packed { - w_dp_req_t w_dp_req; - write_meta_channel_t aw_req; - logic last; - logic super_last; - logic decouple_aw; - } idma_w_req_t; - typedef struct packed { - idma_pkg::protocol_e dst_protocol; - write_meta_channel_t aw_req; - } write_meta_channel_tagged_t; - - /// The mutable transfer options type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - idma_pkg::protocol_e src_protocol; - idma_pkg::protocol_e dst_protocol; - offset_t read_shift; - offset_t write_shift; - logic decouple_rw; - logic decouple_aw; - logic [2:0] src_max_llen; - logic [2:0] dst_max_llen; - logic src_reduce_len; - logic dst_reduce_len; - id_t axi_id; - idma_pkg::axi_options_t src_axi_opt; - idma_pkg::axi_options_t dst_axi_opt; - logic super_last; - } idma_mut_tf_opt_t; - - /// The mutable transfer type holds important information that is mutated by the - /// `legalizer` block. - typedef struct packed { - tf_len_t length; - addr_t addr; - logic valid; - addr_t base_addr; - } idma_mut_tf_t; - - - // datapath busy indicates the datapath is actively working on a transfer. It is composed of - // the activity of the buffer as well as both the read and write machines - logic dp_busy; - // blanks invalid data - logic dp_poison; - - // read and write requests and their handshaking signals - idma_r_req_t r_req; - idma_w_req_t w_req; - logic r_valid, w_valid; - logic r_ready, w_ready; - read_meta_channel_tagged_t r_meta_req_tagged; - write_meta_channel_tagged_t w_meta_req_tagged; - - // It the current transfer the last burst in the 1D transfer? - logic w_last_burst; - logic w_last_ready; - - // Super last flag: The current transfer is indicated as the last one by the controlling - // unit; e.g. by a midend - logic w_super_last; - - // Datapath FIFO signals -> used to decouple legalizer and datapath - logic r_dp_req_in_ready, w_dp_req_in_ready; - logic r_dp_req_out_valid, w_dp_req_out_valid; - logic r_dp_req_out_ready, w_dp_req_out_ready; - r_dp_req_t r_dp_req_out; - w_dp_req_t w_dp_req_out; - - // datapah responses - r_dp_rsp_t r_dp_rsp; - w_dp_rsp_t w_dp_rsp; - logic r_dp_rsp_valid, w_dp_rsp_valid; - logic r_dp_rsp_ready, w_dp_rsp_ready; - - // Ax handshaking - logic ar_ready, ar_ready_dp; - logic aw_ready, aw_ready_dp; - logic aw_valid_dp, ar_valid_dp; - - // Ax request from R-AW coupler to datapath - write_meta_channel_tagged_t aw_req_dp; - - // Ax request from the decoupling stage to the datapath - read_meta_channel_tagged_t ar_req_dp; - - // flush and preemptively empty the legalizer - logic legalizer_flush, legalizer_kill; - - /// intermediate signals to reject zero length transfers - logic is_length_zero; - logic req_valid; - idma_rsp_t idma_rsp; - logic rsp_valid; - logic rsp_ready; - - // Respone Channel valid and ready -> needed for bursting - logic r_chan_valid; - logic r_chan_ready; - - //-------------------------------------- - // Reject Zero Length Transfers - //-------------------------------------- - if (RejectZeroTransfers) begin : gen_reject_zero_transfers - // is the current transfer length 0? - assign is_length_zero = idma_req_i.length == '0; - - // bypass valid as long as length is not zero, otherwise suppress it - assign req_valid = is_length_zero ? 1'b0 : req_valid_i; - - // modify response - always_comb begin : proc_modify_response_zero_length - // default: bypass - idma_rsp_o = idma_rsp; - rsp_ready = rsp_ready_i; - rsp_valid_o = rsp_valid; - - // a zero transfer happens - if (is_length_zero & req_valid_i & req_ready_o) begin - // block backend - rsp_ready = 1'b0; - // generate new response - rsp_valid_o = 1'b1; - idma_rsp_o = '0; - idma_rsp_o.error = 1'b1; - idma_rsp_o.pld.err_type = idma_pkg::BACKEND; - end - end - - // just bypass signals - end else begin : gen_bypass_zero_transfers - // bypass - assign req_valid = req_valid_i; - assign idma_rsp_o = idma_rsp; - assign rsp_ready = rsp_ready_i; - assign rsp_valid_o = rsp_valid; - end - - - //-------------------------------------- - // Legalization - //-------------------------------------- - if (HardwareLegalizer) begin : gen_hw_legalizer - // hardware legalizer is present - idma_legalizer_r_axi_rw_init_rw_obi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .idma_req_t ( idma_req_t ), - .idma_r_req_t ( idma_r_req_t ), - .idma_w_req_t ( idma_w_req_t ), - .idma_mut_tf_t ( idma_mut_tf_t ), - .idma_mut_tf_opt_t ( idma_mut_tf_opt_t ) - ) i_idma_legalizer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .req_i ( idma_req_i ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .r_req_o ( r_req ), - .w_req_o ( w_req ), - .r_valid_o ( r_valid ), - .w_valid_o ( w_valid ), - .r_ready_i ( r_ready ), - .w_ready_i ( w_ready ), - .flush_i ( legalizer_flush ), - .kill_i ( legalizer_kill ), - .r_busy_o ( busy_o.r_leg_busy ), - .w_busy_o ( busy_o.w_leg_busy ) - ); - - end else begin : gen_no_hw_legalizer - // stream fork is used to synchronize the two decoupled channels without the need for a - // FIFO here. - stream_fork #( - .N_OUP ( 32'd2 ) - ) i_stream_fork ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .valid_i ( req_valid ), - .ready_o ( req_ready_o ), - .valid_o ( { r_valid, w_valid } ), - .ready_i ( { r_ready, w_ready } ) - ); - - // local signal holding the length -> explicitly only doing the computation once - axi_pkg::len_t len; - assign len = ((idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0] - - 'd1) >> OffsetWidth); - - // assemble read datapath request - assign r_req.r_dp_req = '{ - src_protocol: idma_req_i.opt.src_protocol, - offset: idma_req_i.src_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.src_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(idma_req_i.src_addr[OffsetWidth-1:0]), - decouple_aw: idma_req_i.opt.beo.decouple_aw, - is_single: len == '0 - }; - - // assemble write datapath request - assign w_req.w_dp_req = '{ - dst_protocol: idma_req_i.opt.dst_protocol, - offset: idma_req_i.dst_addr[OffsetWidth-1:0], - tailer: OffsetWidth'(idma_req_i.length + idma_req_i.dst_addr[OffsetWidth-1:0]), - shift: OffsetWidth'(- idma_req_i.dst_addr[OffsetWidth-1:0]), - num_beats: len, - is_single: len == '0 - }; - - // if the legalizer is bypassed; every burst is the last of the 1D transfer - assign w_req.last = 1'b1; - - // assign the last flag of the controlling unit - assign w_req.super_last = idma_req_i.opt.last; - - // bypass decouple signal - assign w_req.decouple_aw = idma_req_i.opt.beo.decouple_aw; - - // there is no unit to be busy - assign busy_o.r_leg_busy = 1'b0; - assign busy_o.w_leg_busy = 1'b0; - end - - // data path, meta channels, and last queues have to be ready for the legalizer to be ready - assign r_ready = r_dp_req_in_ready & ar_ready; - assign w_ready = w_dp_req_in_ready & aw_ready & w_last_ready; - - - //-------------------------------------- - // Error handler - //-------------------------------------- - if (ErrorCap == idma_pkg::ERROR_HANDLING) begin : gen_error_handler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Error Handling only implemented for AXI to AXI DMA!"); - end - ) - end else if (ErrorCap == idma_pkg::NO_ERROR_HANDLING) begin : gen_no_error_handler - // bypass the signals, assign their neutral values - assign idma_rsp.error = 1'b0; - assign idma_rsp.pld = 1'b0; - assign idma_rsp.last = w_super_last; - assign rsp_valid = w_dp_rsp_valid & w_last_burst; - assign eh_req_ready_o = 1'b0; - assign legalizer_flush = 1'b0; - assign legalizer_kill = 1'b0; - assign dp_poison = 1'b0; - assign r_dp_rsp_ready = rsp_ready; - assign w_dp_rsp_ready = rsp_ready; - assign busy_o.eh_fsm_busy = 1'b0; - assign busy_o.eh_cnt_busy = 1'b0; - - end else begin : gen_param_error - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Unexpected Error Capability"); - end - ) - end - - - //-------------------------------------- - // Datapath busy signal - //-------------------------------------- - assign dp_busy = busy_o.buffer_busy | - busy_o.r_dp_busy | - busy_o.w_dp_busy; - - - //-------------------------------------- - // Datapath decoupling - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( r_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_r_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( r_req.r_dp_req ), - .valid_i ( r_valid ), - .ready_o ( r_dp_req_in_ready ), - .data_o ( r_dp_req_out ), - .valid_o ( r_dp_req_out_valid ), - .ready_i ( r_dp_req_out_ready ) - ); - - stream_fifo_optimal_wrap #( - .Depth ( NumAxInFlight ), - .type_t ( w_dp_req_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_dp_req ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_req.w_dp_req ), - .valid_i ( w_valid ), - .ready_o ( w_dp_req_in_ready ), - .data_o ( w_dp_req_out ), - .valid_o ( w_dp_req_out_valid ), - .ready_i ( w_dp_req_out_ready ) - ); - - // Add fall-through register to allow the input to be ready if the output is not. This - // does not add a cycle of delay - always_comb begin : assign_r_meta_req - r_meta_req_tagged.src_protocol = r_req.r_dp_req.src_protocol; - r_meta_req_tagged.ar_req = r_req.ar_req; - end - - fall_through_register #( - .T ( read_meta_channel_tagged_t ) - ) i_ar_fall_through_register ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .clr_i ( 1'b0 ), - .valid_i ( r_valid ), - .ready_o ( ar_ready ), - .data_i ( r_meta_req_tagged ), - .valid_o ( ar_valid_dp ), - .ready_i ( ar_ready_dp ), - .data_o ( ar_req_dp ) - ); - - - //-------------------------------------- - // Last flag store - //-------------------------------------- - stream_fifo_optimal_wrap #( - .Depth ( MetaFifoDepth ), - .type_t ( logic [1:0] ), - .PrintInfo ( PrintFifoInfo ) - ) i_w_last ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( {w_req.super_last, w_req.last} ), - .valid_i ( w_valid & w_ready ), - .ready_o ( w_last_ready ), - .data_o ( {w_super_last, w_last_burst} ), - .valid_o ( /* NOT CONNECTED */ ), - .ready_i ( w_dp_rsp_valid & w_dp_rsp_ready ) - ); - - //-------------------------------------- - // Transport Layer / Datapath - //-------------------------------------- - idma_transport_layer_r_axi_rw_init_rw_obi #( - .NumAxInFlight ( NumAxInFlight ), - .DataWidth ( DataWidth ), - .BufferDepth ( BufferDepth ), - .MaskInvalidData ( MaskInvalidData ), - .PrintFifoInfo ( PrintFifoInfo ), - .r_dp_req_t ( r_dp_req_t ), - .w_dp_req_t ( w_dp_req_t ), - .r_dp_rsp_t ( r_dp_rsp_t ), - .w_dp_rsp_t ( w_dp_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .write_meta_channel_tagged_t ( write_meta_channel_tagged_t ), - .read_meta_channel_t ( read_meta_channel_t ), - .read_meta_channel_tagged_t ( read_meta_channel_tagged_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .init_req_t ( init_req_t ), - .init_rsp_t ( init_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ) - ) i_idma_transport_layer ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( testmode_i ), - .axi_read_req_o ( axi_read_req_o ), - .axi_read_rsp_i ( axi_read_rsp_i ), - .init_read_req_o ( init_read_req_o ), - .init_read_rsp_i ( init_read_rsp_i ), - .obi_read_req_o ( obi_read_req_o ), - .obi_read_rsp_i ( obi_read_rsp_i ), - .init_write_req_o ( init_write_req_o ), - .init_write_rsp_i ( init_write_rsp_i ), - .obi_write_req_o ( obi_write_req_o ), - .obi_write_rsp_i ( obi_write_rsp_i ), - .r_dp_req_i ( r_dp_req_out ), - .r_dp_valid_i ( r_dp_req_out_valid ), - .r_dp_ready_o ( r_dp_req_out_ready ), - .r_dp_rsp_o ( r_dp_rsp ), - .r_dp_valid_o ( r_dp_rsp_valid ), - .r_dp_ready_i ( r_dp_rsp_ready ), - .w_dp_req_i ( w_dp_req_out ), - .w_dp_valid_i ( w_dp_req_out_valid ), - .w_dp_ready_o ( w_dp_req_out_ready ), - .w_dp_rsp_o ( w_dp_rsp ), - .w_dp_valid_o ( w_dp_rsp_valid ), - .w_dp_ready_i ( w_dp_rsp_ready ), - .ar_req_i ( ar_req_dp ), - .ar_valid_i ( ar_valid_dp ), - .ar_ready_o ( ar_ready_dp ), - .aw_req_i ( aw_req_dp ), - .aw_valid_i ( aw_valid_dp ), - .aw_ready_o ( aw_ready_dp ), - .dp_poison_i ( dp_poison ), - .r_dp_busy_o ( busy_o.r_dp_busy ), - .w_dp_busy_o ( busy_o.w_dp_busy ), - .buffer_busy_o ( busy_o.buffer_busy ), - .r_chan_ready_o ( r_chan_ready ), - .r_chan_valid_o ( r_chan_valid ) - ); - - //-------------------------------------- - // R-AW channel coupler - //-------------------------------------- - always_comb begin : assign_tagged_w_req // need to have an always_comb block for Questa to not crap itself - w_meta_req_tagged.dst_protocol = w_req.w_dp_req.dst_protocol; - w_meta_req_tagged.aw_req = w_req.aw_req; - end - - if (RAWCouplingAvail) begin : gen_r_aw_coupler - `IDMA_NONSYNTH_BLOCK( - initial begin - $fatal(1, "Channel Coupler only implemented for AXI DMAs!"); - end - ) - end else begin : gen_r_aw_bypass - // Atleast one write protocol uses combined aw and w -> Need to buffer read meta requests - // As a write could depend on up to two reads - stream_fifo_optimal_wrap #( - .Depth ( 2 ), - .type_t ( write_meta_channel_tagged_t ), - .PrintInfo ( PrintFifoInfo ) - ) i_aw_fifo ( - .clk_i, - .rst_ni, - .testmode_i, - .flush_i ( 1'b0 ), - .usage_o ( /* NOT CONNECTED */ ), - .data_i ( w_meta_req_tagged ), - .valid_i ( w_valid && aw_ready ), - .ready_o ( aw_ready ), - .data_o ( aw_req_dp ), - .valid_o ( aw_valid_dp ), - .ready_i ( aw_ready_dp && aw_valid_dp ) - ); - - // no unit: not busy - assign busy_o.raw_coupler_busy = 1'b0; - end - - - //-------------------------------------- - // Assertions - //-------------------------------------- - `IDMA_NONSYNTH_BLOCK( - initial begin : proc_assert_params - axi_addr_width : assert(AddrWidth >= 32'd12) else - $fatal(1, "Parameter `AddrWidth` has to be >= 12!"); - axi_id_width : assert(AxiIdWidth > 32'd0) else - $fatal(1, "Parameter `AxiIdWidth` has to be > 0!"); - axi_data_width : assert(DataWidth inside {32'd16, 32'd32, 32'd64, 32'd128, 32'd256, - 32'd512, 32'd1028}) else - $fatal(1, "Parameter `DataWidth` has to be at least 16 and inside the AXI4 spec!"); - axi_user_width : assert(UserWidth > 32'd0) else - $fatal(1, "Parameter `UserWidth` has to be > 0!"); - num_ax_in_flight : assert(NumAxInFlight > 32'd1) else - $fatal(1, "Parameter `NumAxInFlight` has to be > 1!"); - buffer_depth : assert(BufferDepth > 32'd1) else - $fatal(1, "Parameter `BufferDepth` has to be > 1!"); - tf_len_width : assert(TFLenWidth >= 32'd12) else - $fatal(1, "Parameter `BufferDepth` has to be >= 12!"); - tf_len_width_max : assert(TFLenWidth <= AddrWidth) else - $fatal(1, "Parameter `TFLenWidth` has to be <= `AddrWidth`!"); - end - ) - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "axi_stream/typedef.svh" -`include "idma/typedef.svh" -`include "obi/typedef.svh" -`include "tilelink/typedef.svh" - -/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_rw_axi #( - /// Data width - parameter int unsigned DataWidth = 32'd32, - /// Address width - parameter int unsigned AddrWidth = 32'd32, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd3, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd32, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 1, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter bit ErrorHandling = 1'b1, - // Dependent parameters; do not override! - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth), - /// Address type (do not override!) - parameter type addr_t = logic[AddrWidth-1:0], - /// Data type (do not override!) - parameter type data_t = logic[DataWidth-1:0], - /// Strobe type (do not override!) - parameter type strb_t = logic[StrbWidth-1:0], - /// User type (do not override!) - parameter type user_t = logic[UserWidth-1:0], - /// ID type (do not override!) - parameter type id_t = logic[AxiIdWidth-1:0], - /// Transfer length type (do not override!) - parameter type tf_len_t = logic[TFLenWidth-1:0], - /// Offset type (do not override!) - parameter type offset_t = logic[OffsetWidth-1:0] -)( - input logic clk_i, - input logic rst_ni, - input logic test_i, - - input logic req_valid_i, - output logic req_ready_o, - - input tf_len_t req_length_i, - input addr_t req_src_addr_i, - input addr_t req_dst_addr_i, - input idma_pkg::protocol_e req_src_protocol_i, - input idma_pkg::protocol_e req_dst_protocol_i, - input id_t req_axi_id_i, - input axi_pkg::burst_t req_src_burst_i, - input axi_pkg::cache_t req_src_cache_i, - input logic req_src_lock_i, - input axi_pkg::prot_t req_src_prot_i, - input axi_pkg::qos_t req_src_qos_i, - input axi_pkg::region_t req_src_region_i, - input axi_pkg::burst_t req_dst_burst_i, - input axi_pkg::cache_t req_dst_cache_i, - input logic req_dst_lock_i, - input axi_pkg::prot_t req_dst_prot_i, - input axi_pkg::qos_t req_dst_qos_i, - input axi_pkg::region_t req_dst_region_i, - input logic req_decouple_aw_i, - input logic req_decouple_rw_i, - input logic [2:0] req_src_max_llen_i, - input logic [2:0] req_dst_max_llen_i, - input logic req_src_reduce_len_i, - input logic req_dst_reduce_len_i, - input logic req_last_i, - - output logic rsp_valid_o, - input logic rsp_ready_i, - - output axi_pkg::resp_t rsp_cause_o, - output idma_pkg::err_type_t rsp_err_type_o, - output addr_t rsp_burst_addr_o, - output logic rsp_error_o, - output logic rsp_last_o, - - input logic eh_req_valid_i, - output logic eh_req_ready_o, - input idma_pkg::idma_eh_req_t eh_req_i, - - output id_t axi_ar_id_o, - output addr_t axi_ar_addr_o, - output axi_pkg::len_t axi_ar_len_o, - output axi_pkg::size_t axi_ar_size_o, - output axi_pkg::burst_t axi_ar_burst_o, - output logic axi_ar_lock_o, - output axi_pkg::cache_t axi_ar_cache_o, - output axi_pkg::prot_t axi_ar_prot_o, - output axi_pkg::qos_t axi_ar_qos_o, - output axi_pkg::region_t axi_ar_region_o, - output user_t axi_ar_user_o, - output logic axi_ar_valid_o, - input logic axi_ar_ready_i, - input id_t axi_r_id_i, - input data_t axi_r_data_i, - input axi_pkg::resp_t axi_r_resp_i, - input logic axi_r_last_i, - input user_t axi_r_user_i, - input logic axi_r_valid_i, - output logic axi_r_ready_o, - - - output id_t axi_aw_id_o, - output addr_t axi_aw_addr_o, - output axi_pkg::len_t axi_aw_len_o, - output axi_pkg::size_t axi_aw_size_o, - output axi_pkg::burst_t axi_aw_burst_o, - output logic axi_aw_lock_o, - output axi_pkg::cache_t axi_aw_cache_o, - output axi_pkg::prot_t axi_aw_prot_o, - output axi_pkg::qos_t axi_aw_qos_o, - output axi_pkg::region_t axi_aw_region_o, - output axi_pkg::atop_t axi_aw_atop_o, - output user_t axi_aw_user_o, - output logic axi_aw_valid_o, - input logic axi_aw_ready_i, - output data_t axi_w_data_o, - output strb_t axi_w_strb_o, - output logic axi_w_last_o, - output user_t axi_w_user_o, - output logic axi_w_valid_o, - input logic axi_w_ready_i, - input id_t axi_b_id_i, - input axi_pkg::resp_t axi_b_resp_i, - input user_t axi_b_user_i, - input logic axi_b_valid_i, - output logic axi_b_ready_o, - - - output idma_pkg::idma_busy_t idma_busy_o -); - - /// Define the error handling capability - localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : - idma_pkg::NO_ERROR_HANDLING; - - // AXI4+ATOP typedefs -`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) -`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) - -`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) - -`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) -`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - - - // Meta Channel Widths - localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); - - /// Option struct: AXI4 id as well as AXI and backend options - /// - `last`: a flag can be set if this transfer is the last of a set of transfers - `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) - - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) - - /// 1D iDMA response payload: - /// - `cause`: the AXI response - /// - `err_type`: type of the error: read, write, internal, ... - /// - `burst_addr`: the burst address where the issue error occurred - `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) - - /// 1D iDMA response type: - /// - `last`: the response of the request that was marked with the `opt.last` flag - /// - `error`: 1 if an error occurred - /// - `pld`: the error payload - `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) - - - typedef struct packed { - axi_ar_chan_t ar_chan; - } axi_read_meta_channel_t; - - typedef struct packed { - axi_read_meta_channel_t axi; - } read_meta_channel_t; - - typedef struct packed { - axi_aw_chan_t aw_chan; - } axi_write_meta_channel_t; - - typedef struct packed { - axi_write_meta_channel_t axi; - } write_meta_channel_t; - - // local types - // AXI4+ATOP request and response - axi_req_t axi_read_req; - axi_rsp_t axi_read_rsp; - - axi_req_t axi_write_req; - axi_rsp_t axi_write_rsp; - - idma_req_t idma_req; - idma_rsp_t idma_rsp; - - idma_backend_rw_axi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .AxiIdWidth ( AxiIdWidth ), - .UserWidth ( UserWidth ), - .TFLenWidth ( TFLenWidth ), - .MaskInvalidData ( MaskInvalidData ), - .BufferDepth ( BufferDepth ), - .NumAxInFlight ( NumAxInFlight ), - .MemSysDepth ( MemSysDepth ), - .RAWCouplingAvail ( RAWCouplingAvail ), - .HardwareLegalizer ( HardwareLegalizer ), - .RejectZeroTransfers ( RejectZeroTransfers ), - .ErrorCap ( ErrorCap ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ) - ) i_idma_backend ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( test_i ), - .idma_req_i ( idma_req ), - .req_valid_i ( req_valid_i ), - .req_ready_o ( req_ready_o ), - .idma_rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid_o ), - .rsp_ready_i ( rsp_ready_i ), - .idma_eh_req_i ( eh_req_i ), - .eh_req_valid_i ( eh_req_valid_i ), - .eh_req_ready_o ( eh_req_ready_o ), - .axi_read_req_o ( axi_read_req ), - .axi_read_rsp_i ( axi_read_rsp ), - .axi_write_req_o ( axi_write_req ), - .axi_write_rsp_i ( axi_write_rsp ), - .busy_o ( idma_busy_o ) - ); - - // flatten structs - assign idma_req.dst_addr = req_dst_addr_i; - assign idma_req.src_addr = req_src_addr_i; - assign idma_req.length = req_length_i; - assign idma_req.opt.src_protocol = req_src_protocol_i; - assign idma_req.opt.dst_protocol = req_dst_protocol_i; - assign idma_req.opt.axi_id = req_axi_id_i; - assign idma_req.opt.dst.cache = req_dst_cache_i; - assign idma_req.opt.dst.burst = req_dst_burst_i; - assign idma_req.opt.dst.qos = req_dst_qos_i; - assign idma_req.opt.dst.lock = req_dst_lock_i; - assign idma_req.opt.dst.prot = req_dst_prot_i; - assign idma_req.opt.dst.region = req_dst_region_i; - assign idma_req.opt.src.cache = req_src_cache_i; - assign idma_req.opt.src.burst = req_src_burst_i; - assign idma_req.opt.src.qos = req_src_qos_i; - assign idma_req.opt.src.lock = req_src_lock_i; - assign idma_req.opt.src.prot = req_src_prot_i; - assign idma_req.opt.src.region = req_src_region_i; - assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; - assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; - assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; - assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; - assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; - assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; - assign idma_req.opt.last = req_last_i; - - assign rsp_cause_o = idma_rsp.pld.cause; - assign rsp_err_type_o = idma_rsp.pld.err_type; - assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; - assign rsp_error_o = idma_rsp.error; - assign rsp_last_o = idma_rsp.last; - - - // AXI4+ATOP Read - assign axi_ar_id_o = axi_read_req.ar.id; - assign axi_ar_addr_o = axi_read_req.ar.addr; - assign axi_ar_len_o = axi_read_req.ar.len; - assign axi_ar_size_o = axi_read_req.ar.size; - assign axi_ar_burst_o = axi_read_req.ar.burst; - assign axi_ar_lock_o = axi_read_req.ar.lock; - assign axi_ar_cache_o = axi_read_req.ar.cache; - assign axi_ar_prot_o = axi_read_req.ar.prot; - assign axi_ar_qos_o = axi_read_req.ar.qos; - assign axi_ar_region_o = axi_read_req.ar.region; - assign axi_ar_user_o = axi_read_req.ar.user; - assign axi_ar_valid_o = axi_read_req.ar_valid; - assign axi_r_ready_o = axi_read_req.r_ready; - - assign axi_read_rsp.ar_ready = axi_ar_ready_i; - assign axi_read_rsp.r.id = axi_r_id_i; - assign axi_read_rsp.r.data = axi_r_data_i; - assign axi_read_rsp.r.resp = axi_r_resp_i; - assign axi_read_rsp.r.last = axi_r_last_i; - assign axi_read_rsp.r.user = axi_r_user_i; - assign axi_read_rsp.r_valid = axi_r_valid_i; - - - - // AXI4+ATOP Write - assign axi_aw_id_o = axi_write_req.aw.id; - assign axi_aw_addr_o = axi_write_req.aw.addr; - assign axi_aw_len_o = axi_write_req.aw.len; - assign axi_aw_size_o = axi_write_req.aw.size; - assign axi_aw_burst_o = axi_write_req.aw.burst; - assign axi_aw_lock_o = axi_write_req.aw.lock; - assign axi_aw_cache_o = axi_write_req.aw.cache; - assign axi_aw_prot_o = axi_write_req.aw.prot; - assign axi_aw_qos_o = axi_write_req.aw.qos; - assign axi_aw_region_o = axi_write_req.aw.region; - assign axi_aw_atop_o = axi_write_req.aw.atop; - assign axi_aw_user_o = axi_write_req.aw.user; - assign axi_aw_valid_o = axi_write_req.aw_valid; - assign axi_w_data_o = axi_write_req.w.data; - assign axi_w_strb_o = axi_write_req.w.strb; - assign axi_w_last_o = axi_write_req.w.last; - assign axi_w_user_o = axi_write_req.w.user; - assign axi_w_valid_o = axi_write_req.w_valid; - assign axi_b_ready_o = axi_write_req.b_ready; - - assign axi_write_rsp.aw_ready = axi_aw_ready_i; - assign axi_write_rsp.w_ready = axi_w_ready_i; - assign axi_write_rsp.b.id = axi_b_id_i; - assign axi_write_rsp.b.resp = axi_b_resp_i; - assign axi_write_rsp.b.user = axi_b_user_i; - assign axi_write_rsp.b_valid = axi_b_valid_i; - - - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "axi_stream/typedef.svh" -`include "idma/typedef.svh" -`include "obi/typedef.svh" -`include "tilelink/typedef.svh" - -/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_r_obi_w_axi #( - /// Data width - parameter int unsigned DataWidth = 32'd32, - /// Address width - parameter int unsigned AddrWidth = 32'd32, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd3, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd32, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 0, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter bit ErrorHandling = 1'b0, - // Dependent parameters; do not override! - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth), - /// Address type (do not override!) - parameter type addr_t = logic[AddrWidth-1:0], - /// Data type (do not override!) - parameter type data_t = logic[DataWidth-1:0], - /// Strobe type (do not override!) - parameter type strb_t = logic[StrbWidth-1:0], - /// User type (do not override!) - parameter type user_t = logic[UserWidth-1:0], - /// ID type (do not override!) - parameter type id_t = logic[AxiIdWidth-1:0], - /// Transfer length type (do not override!) - parameter type tf_len_t = logic[TFLenWidth-1:0], - /// Offset type (do not override!) - parameter type offset_t = logic[OffsetWidth-1:0] -)( - input logic clk_i, - input logic rst_ni, - input logic test_i, - - input logic req_valid_i, - output logic req_ready_o, - - input tf_len_t req_length_i, - input addr_t req_src_addr_i, - input addr_t req_dst_addr_i, - input idma_pkg::protocol_e req_src_protocol_i, - input idma_pkg::protocol_e req_dst_protocol_i, - input id_t req_axi_id_i, - input axi_pkg::burst_t req_src_burst_i, - input axi_pkg::cache_t req_src_cache_i, - input logic req_src_lock_i, - input axi_pkg::prot_t req_src_prot_i, - input axi_pkg::qos_t req_src_qos_i, - input axi_pkg::region_t req_src_region_i, - input axi_pkg::burst_t req_dst_burst_i, - input axi_pkg::cache_t req_dst_cache_i, - input logic req_dst_lock_i, - input axi_pkg::prot_t req_dst_prot_i, - input axi_pkg::qos_t req_dst_qos_i, - input axi_pkg::region_t req_dst_region_i, - input logic req_decouple_aw_i, - input logic req_decouple_rw_i, - input logic [2:0] req_src_max_llen_i, - input logic [2:0] req_dst_max_llen_i, - input logic req_src_reduce_len_i, - input logic req_dst_reduce_len_i, - input logic req_last_i, - - output logic rsp_valid_o, - input logic rsp_ready_i, - - output axi_pkg::resp_t rsp_cause_o, - output idma_pkg::err_type_t rsp_err_type_o, - output addr_t rsp_burst_addr_o, - output logic rsp_error_o, - output logic rsp_last_o, - - input logic eh_req_valid_i, - output logic eh_req_ready_o, - input idma_pkg::idma_eh_req_t eh_req_i, - - output logic obi_read_req_a_req_o, - output addr_t obi_read_req_a_addr_o, - output logic obi_read_req_a_we_o, - output strb_t obi_read_req_a_be_o, - output data_t obi_read_req_a_wdata_o, - output logic obi_read_req_r_ready_o, - - input logic obi_read_rsp_a_gnt_i, - input logic obi_read_rsp_r_valid_i, - input data_t obi_read_rsp_r_rdata_i, - input id_t obi_read_rsp_r_rid_i, - input logic obi_read_rsp_r_err_i, - - - output id_t axi_aw_id_o, - output addr_t axi_aw_addr_o, - output axi_pkg::len_t axi_aw_len_o, - output axi_pkg::size_t axi_aw_size_o, - output axi_pkg::burst_t axi_aw_burst_o, - output logic axi_aw_lock_o, - output axi_pkg::cache_t axi_aw_cache_o, - output axi_pkg::prot_t axi_aw_prot_o, - output axi_pkg::qos_t axi_aw_qos_o, - output axi_pkg::region_t axi_aw_region_o, - output axi_pkg::atop_t axi_aw_atop_o, - output user_t axi_aw_user_o, - output logic axi_aw_valid_o, - input logic axi_aw_ready_i, - output data_t axi_w_data_o, - output strb_t axi_w_strb_o, - output logic axi_w_last_o, - output user_t axi_w_user_o, - output logic axi_w_valid_o, - input logic axi_w_ready_i, - input id_t axi_b_id_i, - input axi_pkg::resp_t axi_b_resp_i, - input user_t axi_b_user_i, - input logic axi_b_valid_i, - output logic axi_b_ready_o, - - - output idma_pkg::idma_busy_t idma_busy_o -); - - /// Define the error handling capability - localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : - idma_pkg::NO_ERROR_HANDLING; - - // AXI4+ATOP typedefs -`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) -`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) - -`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) - -`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) -`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - - - // OBI typedefs -`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) -`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) - -`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) -`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) - -`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) -`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) - - - // Meta Channel Widths - localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); - - /// Option struct: AXI4 id as well as AXI and backend options - /// - `last`: a flag can be set if this transfer is the last of a set of transfers - `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) - - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) - - /// 1D iDMA response payload: - /// - `cause`: the AXI response - /// - `err_type`: type of the error: read, write, internal, ... - /// - `burst_addr`: the burst address where the issue error occurred - `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) - - /// 1D iDMA response type: - /// - `last`: the response of the request that was marked with the `opt.last` flag - /// - `error`: 1 if an error occurred - /// - `pld`: the error payload - `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) - - - typedef struct packed { - obi_a_chan_t a_chan; - } obi_read_meta_channel_t; - - typedef struct packed { - obi_read_meta_channel_t obi; - } read_meta_channel_t; - - typedef struct packed { - axi_aw_chan_t aw_chan; - } axi_write_meta_channel_t; - - typedef struct packed { - axi_write_meta_channel_t axi; - } write_meta_channel_t; - - // local types - // AXI4+ATOP request and response - - axi_req_t axi_write_req; - axi_rsp_t axi_write_rsp; - - // OBI request and response - obi_req_t obi_read_req; - obi_rsp_t obi_read_rsp; - - - idma_req_t idma_req; - idma_rsp_t idma_rsp; - - idma_backend_r_obi_w_axi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .AxiIdWidth ( AxiIdWidth ), - .UserWidth ( UserWidth ), - .TFLenWidth ( TFLenWidth ), - .MaskInvalidData ( MaskInvalidData ), - .BufferDepth ( BufferDepth ), - .NumAxInFlight ( NumAxInFlight ), - .MemSysDepth ( MemSysDepth ), - .RAWCouplingAvail ( RAWCouplingAvail ), - .HardwareLegalizer ( HardwareLegalizer ), - .RejectZeroTransfers ( RejectZeroTransfers ), - .ErrorCap ( ErrorCap ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ) - ) i_idma_backend ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( test_i ), - .idma_req_i ( idma_req ), - .req_valid_i ( req_valid_i ), - .req_ready_o ( req_ready_o ), - .idma_rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid_o ), - .rsp_ready_i ( rsp_ready_i ), - .idma_eh_req_i ( eh_req_i ), - .eh_req_valid_i ( eh_req_valid_i ), - .eh_req_ready_o ( eh_req_ready_o ), - .obi_read_req_o ( obi_read_req ), - .obi_read_rsp_i ( obi_read_rsp ), - .axi_write_req_o ( axi_write_req ), - .axi_write_rsp_i ( axi_write_rsp ), - .busy_o ( idma_busy_o ) - ); - - // flatten structs - assign idma_req.dst_addr = req_dst_addr_i; - assign idma_req.src_addr = req_src_addr_i; - assign idma_req.length = req_length_i; - assign idma_req.opt.src_protocol = req_src_protocol_i; - assign idma_req.opt.dst_protocol = req_dst_protocol_i; - assign idma_req.opt.axi_id = req_axi_id_i; - assign idma_req.opt.dst.cache = req_dst_cache_i; - assign idma_req.opt.dst.burst = req_dst_burst_i; - assign idma_req.opt.dst.qos = req_dst_qos_i; - assign idma_req.opt.dst.lock = req_dst_lock_i; - assign idma_req.opt.dst.prot = req_dst_prot_i; - assign idma_req.opt.dst.region = req_dst_region_i; - assign idma_req.opt.src.cache = req_src_cache_i; - assign idma_req.opt.src.burst = req_src_burst_i; - assign idma_req.opt.src.qos = req_src_qos_i; - assign idma_req.opt.src.lock = req_src_lock_i; - assign idma_req.opt.src.prot = req_src_prot_i; - assign idma_req.opt.src.region = req_src_region_i; - assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; - assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; - assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; - assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; - assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; - assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; - assign idma_req.opt.last = req_last_i; - - assign rsp_cause_o = idma_rsp.pld.cause; - assign rsp_err_type_o = idma_rsp.pld.err_type; - assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; - assign rsp_error_o = idma_rsp.error; - assign rsp_last_o = idma_rsp.last; - - - // OBI Read - assign obi_read_req_a_req_o = obi_read_req.req; - assign obi_read_req_a_addr_o = obi_read_req.a.addr; - assign obi_read_req_a_we_o = obi_read_req.a.we; - assign obi_read_req_a_be_o = obi_read_req.a.be; - assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; - assign obi_read_req_r_ready_o = obi_read_req.rready; - - assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; - assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; - assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; - assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; - assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; - - - - // AXI4+ATOP Write - assign axi_aw_id_o = axi_write_req.aw.id; - assign axi_aw_addr_o = axi_write_req.aw.addr; - assign axi_aw_len_o = axi_write_req.aw.len; - assign axi_aw_size_o = axi_write_req.aw.size; - assign axi_aw_burst_o = axi_write_req.aw.burst; - assign axi_aw_lock_o = axi_write_req.aw.lock; - assign axi_aw_cache_o = axi_write_req.aw.cache; - assign axi_aw_prot_o = axi_write_req.aw.prot; - assign axi_aw_qos_o = axi_write_req.aw.qos; - assign axi_aw_region_o = axi_write_req.aw.region; - assign axi_aw_atop_o = axi_write_req.aw.atop; - assign axi_aw_user_o = axi_write_req.aw.user; - assign axi_aw_valid_o = axi_write_req.aw_valid; - assign axi_w_data_o = axi_write_req.w.data; - assign axi_w_strb_o = axi_write_req.w.strb; - assign axi_w_last_o = axi_write_req.w.last; - assign axi_w_user_o = axi_write_req.w.user; - assign axi_w_valid_o = axi_write_req.w_valid; - assign axi_b_ready_o = axi_write_req.b_ready; - - assign axi_write_rsp.aw_ready = axi_aw_ready_i; - assign axi_write_rsp.w_ready = axi_w_ready_i; - assign axi_write_rsp.b.id = axi_b_id_i; - assign axi_write_rsp.b.resp = axi_b_resp_i; - assign axi_write_rsp.b.user = axi_b_user_i; - assign axi_write_rsp.b_valid = axi_b_valid_i; - - - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "axi_stream/typedef.svh" -`include "idma/typedef.svh" -`include "obi/typedef.svh" -`include "tilelink/typedef.svh" - -/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_r_axi_w_obi #( - /// Data width - parameter int unsigned DataWidth = 32'd32, - /// Address width - parameter int unsigned AddrWidth = 32'd32, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd3, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd32, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 0, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter bit ErrorHandling = 1'b0, - // Dependent parameters; do not override! - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth), - /// Address type (do not override!) - parameter type addr_t = logic[AddrWidth-1:0], - /// Data type (do not override!) - parameter type data_t = logic[DataWidth-1:0], - /// Strobe type (do not override!) - parameter type strb_t = logic[StrbWidth-1:0], - /// User type (do not override!) - parameter type user_t = logic[UserWidth-1:0], - /// ID type (do not override!) - parameter type id_t = logic[AxiIdWidth-1:0], - /// Transfer length type (do not override!) - parameter type tf_len_t = logic[TFLenWidth-1:0], - /// Offset type (do not override!) - parameter type offset_t = logic[OffsetWidth-1:0] -)( - input logic clk_i, - input logic rst_ni, - input logic test_i, - - input logic req_valid_i, - output logic req_ready_o, - - input tf_len_t req_length_i, - input addr_t req_src_addr_i, - input addr_t req_dst_addr_i, - input idma_pkg::protocol_e req_src_protocol_i, - input idma_pkg::protocol_e req_dst_protocol_i, - input id_t req_axi_id_i, - input axi_pkg::burst_t req_src_burst_i, - input axi_pkg::cache_t req_src_cache_i, - input logic req_src_lock_i, - input axi_pkg::prot_t req_src_prot_i, - input axi_pkg::qos_t req_src_qos_i, - input axi_pkg::region_t req_src_region_i, - input axi_pkg::burst_t req_dst_burst_i, - input axi_pkg::cache_t req_dst_cache_i, - input logic req_dst_lock_i, - input axi_pkg::prot_t req_dst_prot_i, - input axi_pkg::qos_t req_dst_qos_i, - input axi_pkg::region_t req_dst_region_i, - input logic req_decouple_aw_i, - input logic req_decouple_rw_i, - input logic [2:0] req_src_max_llen_i, - input logic [2:0] req_dst_max_llen_i, - input logic req_src_reduce_len_i, - input logic req_dst_reduce_len_i, - input logic req_last_i, - - output logic rsp_valid_o, - input logic rsp_ready_i, - - output axi_pkg::resp_t rsp_cause_o, - output idma_pkg::err_type_t rsp_err_type_o, - output addr_t rsp_burst_addr_o, - output logic rsp_error_o, - output logic rsp_last_o, - - input logic eh_req_valid_i, - output logic eh_req_ready_o, - input idma_pkg::idma_eh_req_t eh_req_i, - - output id_t axi_ar_id_o, - output addr_t axi_ar_addr_o, - output axi_pkg::len_t axi_ar_len_o, - output axi_pkg::size_t axi_ar_size_o, - output axi_pkg::burst_t axi_ar_burst_o, - output logic axi_ar_lock_o, - output axi_pkg::cache_t axi_ar_cache_o, - output axi_pkg::prot_t axi_ar_prot_o, - output axi_pkg::qos_t axi_ar_qos_o, - output axi_pkg::region_t axi_ar_region_o, - output user_t axi_ar_user_o, - output logic axi_ar_valid_o, - input logic axi_ar_ready_i, - input id_t axi_r_id_i, - input data_t axi_r_data_i, - input axi_pkg::resp_t axi_r_resp_i, - input logic axi_r_last_i, - input user_t axi_r_user_i, - input logic axi_r_valid_i, - output logic axi_r_ready_o, - - - output logic obi_write_req_a_req_o, - output addr_t obi_write_req_a_addr_o, - output logic obi_write_req_a_we_o, - output strb_t obi_write_req_a_be_o, - output data_t obi_write_req_a_wdata_o, - output id_t obi_write_req_a_aid_o, - output logic obi_write_req_r_ready_o, - - input logic obi_write_rsp_a_gnt_i, - input logic obi_write_rsp_r_valid_i, - input data_t obi_write_rsp_r_rdata_i, - - - output idma_pkg::idma_busy_t idma_busy_o -); - - /// Define the error handling capability - localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : - idma_pkg::NO_ERROR_HANDLING; - - // AXI4+ATOP typedefs -`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) -`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) - -`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) - -`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) -`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - - - // OBI typedefs -`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) -`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) - -`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) -`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) - -`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) -`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) - - - // Meta Channel Widths - localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); - - /// Option struct: AXI4 id as well as AXI and backend options - /// - `last`: a flag can be set if this transfer is the last of a set of transfers - `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) - - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) - - /// 1D iDMA response payload: - /// - `cause`: the AXI response - /// - `err_type`: type of the error: read, write, internal, ... - /// - `burst_addr`: the burst address where the issue error occurred - `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) - - /// 1D iDMA response type: - /// - `last`: the response of the request that was marked with the `opt.last` flag - /// - `error`: 1 if an error occurred - /// - `pld`: the error payload - `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) - - - typedef struct packed { - axi_ar_chan_t ar_chan; - } axi_read_meta_channel_t; - - typedef struct packed { - axi_read_meta_channel_t axi; - } read_meta_channel_t; - - typedef struct packed { - obi_a_chan_t a_chan; - } obi_write_meta_channel_t; - - typedef struct packed { - obi_write_meta_channel_t obi; - } write_meta_channel_t; - - // local types - // AXI4+ATOP request and response - axi_req_t axi_read_req; - axi_rsp_t axi_read_rsp; - - - // OBI request and response - - obi_req_t obi_write_req; - obi_rsp_t obi_write_rsp; - - idma_req_t idma_req; - idma_rsp_t idma_rsp; - - idma_backend_r_axi_w_obi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .AxiIdWidth ( AxiIdWidth ), - .UserWidth ( UserWidth ), - .TFLenWidth ( TFLenWidth ), - .MaskInvalidData ( MaskInvalidData ), - .BufferDepth ( BufferDepth ), - .NumAxInFlight ( NumAxInFlight ), - .MemSysDepth ( MemSysDepth ), - .RAWCouplingAvail ( RAWCouplingAvail ), - .HardwareLegalizer ( HardwareLegalizer ), - .RejectZeroTransfers ( RejectZeroTransfers ), - .ErrorCap ( ErrorCap ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ) - ) i_idma_backend ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( test_i ), - .idma_req_i ( idma_req ), - .req_valid_i ( req_valid_i ), - .req_ready_o ( req_ready_o ), - .idma_rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid_o ), - .rsp_ready_i ( rsp_ready_i ), - .idma_eh_req_i ( eh_req_i ), - .eh_req_valid_i ( eh_req_valid_i ), - .eh_req_ready_o ( eh_req_ready_o ), - .axi_read_req_o ( axi_read_req ), - .axi_read_rsp_i ( axi_read_rsp ), - .obi_write_req_o ( obi_write_req ), - .obi_write_rsp_i ( obi_write_rsp ), - .busy_o ( idma_busy_o ) - ); - - // flatten structs - assign idma_req.dst_addr = req_dst_addr_i; - assign idma_req.src_addr = req_src_addr_i; - assign idma_req.length = req_length_i; - assign idma_req.opt.src_protocol = req_src_protocol_i; - assign idma_req.opt.dst_protocol = req_dst_protocol_i; - assign idma_req.opt.axi_id = req_axi_id_i; - assign idma_req.opt.dst.cache = req_dst_cache_i; - assign idma_req.opt.dst.burst = req_dst_burst_i; - assign idma_req.opt.dst.qos = req_dst_qos_i; - assign idma_req.opt.dst.lock = req_dst_lock_i; - assign idma_req.opt.dst.prot = req_dst_prot_i; - assign idma_req.opt.dst.region = req_dst_region_i; - assign idma_req.opt.src.cache = req_src_cache_i; - assign idma_req.opt.src.burst = req_src_burst_i; - assign idma_req.opt.src.qos = req_src_qos_i; - assign idma_req.opt.src.lock = req_src_lock_i; - assign idma_req.opt.src.prot = req_src_prot_i; - assign idma_req.opt.src.region = req_src_region_i; - assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; - assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; - assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; - assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; - assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; - assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; - assign idma_req.opt.last = req_last_i; - - assign rsp_cause_o = idma_rsp.pld.cause; - assign rsp_err_type_o = idma_rsp.pld.err_type; - assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; - assign rsp_error_o = idma_rsp.error; - assign rsp_last_o = idma_rsp.last; - - - // AXI4+ATOP Read - assign axi_ar_id_o = axi_read_req.ar.id; - assign axi_ar_addr_o = axi_read_req.ar.addr; - assign axi_ar_len_o = axi_read_req.ar.len; - assign axi_ar_size_o = axi_read_req.ar.size; - assign axi_ar_burst_o = axi_read_req.ar.burst; - assign axi_ar_lock_o = axi_read_req.ar.lock; - assign axi_ar_cache_o = axi_read_req.ar.cache; - assign axi_ar_prot_o = axi_read_req.ar.prot; - assign axi_ar_qos_o = axi_read_req.ar.qos; - assign axi_ar_region_o = axi_read_req.ar.region; - assign axi_ar_user_o = axi_read_req.ar.user; - assign axi_ar_valid_o = axi_read_req.ar_valid; - assign axi_r_ready_o = axi_read_req.r_ready; - - assign axi_read_rsp.ar_ready = axi_ar_ready_i; - assign axi_read_rsp.r.id = axi_r_id_i; - assign axi_read_rsp.r.data = axi_r_data_i; - assign axi_read_rsp.r.resp = axi_r_resp_i; - assign axi_read_rsp.r.last = axi_r_last_i; - assign axi_read_rsp.r.user = axi_r_user_i; - assign axi_read_rsp.r_valid = axi_r_valid_i; - - - - // OBI Write - assign obi_write_req_a_req_o = obi_write_req.req; - assign obi_write_req_a_addr_o = obi_write_req.a.addr; - assign obi_write_req_a_we_o = obi_write_req.a.we; - assign obi_write_req_a_be_o = obi_write_req.a.be; - assign obi_write_req_a_wdata_o = obi_write_req.a.wdata; - assign obi_write_req_a_aid_o = obi_write_req.a.aid; - assign obi_write_req_r_ready_o = obi_write_req.rready; - - assign obi_write_rsp.gnt = obi_write_rsp_a_gnt_i; - assign obi_write_rsp.rvalid = obi_write_rsp_r_valid_i; - assign obi_write_rsp.r.rdata = obi_write_rsp_r_rdata_i; - - - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "axi_stream/typedef.svh" -`include "idma/typedef.svh" -`include "obi/typedef.svh" -`include "tilelink/typedef.svh" - -/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_rw_axi_rw_axis #( - /// Data width - parameter int unsigned DataWidth = 32'd32, - /// Address width - parameter int unsigned AddrWidth = 32'd32, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd3, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd32, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 0, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter bit ErrorHandling = 1'b0, - // Dependent parameters; do not override! - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth), - /// Address type (do not override!) - parameter type addr_t = logic[AddrWidth-1:0], - /// Data type (do not override!) - parameter type data_t = logic[DataWidth-1:0], - /// Strobe type (do not override!) - parameter type strb_t = logic[StrbWidth-1:0], - /// User type (do not override!) - parameter type user_t = logic[UserWidth-1:0], - /// ID type (do not override!) - parameter type id_t = logic[AxiIdWidth-1:0], - /// Transfer length type (do not override!) - parameter type tf_len_t = logic[TFLenWidth-1:0], - /// Offset type (do not override!) - parameter type offset_t = logic[OffsetWidth-1:0] -)( - input logic clk_i, - input logic rst_ni, - input logic test_i, - - input logic req_valid_i, - output logic req_ready_o, - - input tf_len_t req_length_i, - input addr_t req_src_addr_i, - input addr_t req_dst_addr_i, - input idma_pkg::protocol_e req_src_protocol_i, - input idma_pkg::protocol_e req_dst_protocol_i, - input id_t req_axi_id_i, - input axi_pkg::burst_t req_src_burst_i, - input axi_pkg::cache_t req_src_cache_i, - input logic req_src_lock_i, - input axi_pkg::prot_t req_src_prot_i, - input axi_pkg::qos_t req_src_qos_i, - input axi_pkg::region_t req_src_region_i, - input axi_pkg::burst_t req_dst_burst_i, - input axi_pkg::cache_t req_dst_cache_i, - input logic req_dst_lock_i, - input axi_pkg::prot_t req_dst_prot_i, - input axi_pkg::qos_t req_dst_qos_i, - input axi_pkg::region_t req_dst_region_i, - input logic req_decouple_aw_i, - input logic req_decouple_rw_i, - input logic [2:0] req_src_max_llen_i, - input logic [2:0] req_dst_max_llen_i, - input logic req_src_reduce_len_i, - input logic req_dst_reduce_len_i, - input logic req_last_i, - - output logic rsp_valid_o, - input logic rsp_ready_i, - - output axi_pkg::resp_t rsp_cause_o, - output idma_pkg::err_type_t rsp_err_type_o, - output addr_t rsp_burst_addr_o, - output logic rsp_error_o, - output logic rsp_last_o, - - input logic eh_req_valid_i, - output logic eh_req_ready_o, - input idma_pkg::idma_eh_req_t eh_req_i, - - output id_t axi_ar_id_o, - output addr_t axi_ar_addr_o, - output axi_pkg::len_t axi_ar_len_o, - output axi_pkg::size_t axi_ar_size_o, - output axi_pkg::burst_t axi_ar_burst_o, - output logic axi_ar_lock_o, - output axi_pkg::cache_t axi_ar_cache_o, - output axi_pkg::prot_t axi_ar_prot_o, - output axi_pkg::qos_t axi_ar_qos_o, - output axi_pkg::region_t axi_ar_region_o, - output user_t axi_ar_user_o, - output logic axi_ar_valid_o, - input logic axi_ar_ready_i, - input id_t axi_r_id_i, - input data_t axi_r_data_i, - input axi_pkg::resp_t axi_r_resp_i, - input logic axi_r_last_i, - input user_t axi_r_user_i, - input logic axi_r_valid_i, - output logic axi_r_ready_o, - - - input data_t axis_read_data_i, - input strb_t axis_read_strb_i, - input strb_t axis_read_keep_i, - input logic axis_read_last_i, - input id_t axis_read_id_i, - input id_t axis_read_dest_i, - input user_t axis_read_user_i, - input logic axis_read_tvalid_i, - - output logic axis_read_tready_o, - - - output id_t axi_aw_id_o, - output addr_t axi_aw_addr_o, - output axi_pkg::len_t axi_aw_len_o, - output axi_pkg::size_t axi_aw_size_o, - output axi_pkg::burst_t axi_aw_burst_o, - output logic axi_aw_lock_o, - output axi_pkg::cache_t axi_aw_cache_o, - output axi_pkg::prot_t axi_aw_prot_o, - output axi_pkg::qos_t axi_aw_qos_o, - output axi_pkg::region_t axi_aw_region_o, - output axi_pkg::atop_t axi_aw_atop_o, - output user_t axi_aw_user_o, - output logic axi_aw_valid_o, - input logic axi_aw_ready_i, - output data_t axi_w_data_o, - output strb_t axi_w_strb_o, - output logic axi_w_last_o, - output user_t axi_w_user_o, - output logic axi_w_valid_o, - input logic axi_w_ready_i, - input id_t axi_b_id_i, - input axi_pkg::resp_t axi_b_resp_i, - input user_t axi_b_user_i, - input logic axi_b_valid_i, - output logic axi_b_ready_o, - - - output data_t axis_write_data_o, - output strb_t axis_write_strb_o, - output strb_t axis_write_keep_o, - output logic axis_write_last_o, - output id_t axis_write_id_o, - output id_t axis_write_dest_o, - output user_t axis_write_user_o, - output logic axis_write_tvalid_o, - - input logic axis_write_tready_i, - - - output idma_pkg::idma_busy_t idma_busy_o -); - - /// Define the error handling capability - localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : - idma_pkg::NO_ERROR_HANDLING; - - // AXI4+ATOP typedefs -`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) -`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) - -`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) - -`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) -`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - - - // AXI Stream typedefs -`AXI_STREAM_TYPEDEF_S_CHAN_T(axis_t_chan_t, data_t, strb_t, strb_t, id_t, id_t, user_t) - -`AXI_STREAM_TYPEDEF_REQ_T(axis_req_t, axis_t_chan_t) -`AXI_STREAM_TYPEDEF_RSP_T(axis_rsp_t) - - - // Meta Channel Widths - localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned axis_t_chan_width = $bits(axis_t_chan_t); - - /// Option struct: AXI4 id as well as AXI and backend options - /// - `last`: a flag can be set if this transfer is the last of a set of transfers - `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) - - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) - - /// 1D iDMA response payload: - /// - `cause`: the AXI response - /// - `err_type`: type of the error: read, write, internal, ... - /// - `burst_addr`: the burst address where the issue error occurred - `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) - - /// 1D iDMA response type: - /// - `last`: the response of the request that was marked with the `opt.last` flag - /// - `error`: 1 if an error occurred - /// - `pld`: the error payload - `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) - - function int unsigned max_width(input int unsigned a, b); - return (a > b) ? a : b; - endfunction - - typedef struct packed { - axi_ar_chan_t ar_chan; - logic[max_width(axi_ar_chan_width, axis_t_chan_width)-axi_ar_chan_width:0] padding; - } axi_read_ar_chan_padded_t; - - typedef struct packed { - axis_t_chan_t t_chan; - logic[max_width(axi_ar_chan_width, axis_t_chan_width)-axis_t_chan_width:0] padding; - } axis_read_t_chan_padded_t; - - typedef union packed { - axi_read_ar_chan_padded_t axi; - axis_read_t_chan_padded_t axis; - } read_meta_channel_t; - - typedef struct packed { - axi_aw_chan_t aw_chan; - logic[max_width(axi_aw_chan_width, axis_t_chan_width)-axi_aw_chan_width:0] padding; - } axi_write_aw_chan_padded_t; - - typedef struct packed { - axis_t_chan_t t_chan; - logic[max_width(axi_aw_chan_width, axis_t_chan_width)-axis_t_chan_width:0] padding; - } axis_write_t_chan_padded_t; - - typedef union packed { - axi_write_aw_chan_padded_t axi; - axis_write_t_chan_padded_t axis; - } write_meta_channel_t; - - // local types - // AXI4+ATOP request and response - axi_req_t axi_read_req; - axi_rsp_t axi_read_rsp; - - axi_req_t axi_write_req; - axi_rsp_t axi_write_rsp; - - // AXI Stream request and response - axis_req_t axis_read_req; - axis_rsp_t axis_read_rsp; - - axis_req_t axis_write_req; - axis_rsp_t axis_write_rsp; - - idma_req_t idma_req; - idma_rsp_t idma_rsp; - - idma_backend_rw_axi_rw_axis #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .AxiIdWidth ( AxiIdWidth ), - .UserWidth ( UserWidth ), - .TFLenWidth ( TFLenWidth ), - .MaskInvalidData ( MaskInvalidData ), - .BufferDepth ( BufferDepth ), - .NumAxInFlight ( NumAxInFlight ), - .MemSysDepth ( MemSysDepth ), - .RAWCouplingAvail ( RAWCouplingAvail ), - .HardwareLegalizer ( HardwareLegalizer ), - .RejectZeroTransfers ( RejectZeroTransfers ), - .ErrorCap ( ErrorCap ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .axis_req_t ( axis_req_t ), - .axis_rsp_t ( axis_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ) - ) i_idma_backend ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( test_i ), - .idma_req_i ( idma_req ), - .req_valid_i ( req_valid_i ), - .req_ready_o ( req_ready_o ), - .idma_rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid_o ), - .rsp_ready_i ( rsp_ready_i ), - .idma_eh_req_i ( eh_req_i ), - .eh_req_valid_i ( eh_req_valid_i ), - .eh_req_ready_o ( eh_req_ready_o ), - .axi_read_req_o ( axi_read_req ), - .axi_read_rsp_i ( axi_read_rsp ), - .axis_read_req_i ( axis_read_req ), - .axis_read_rsp_o ( axis_read_rsp ), - .axi_write_req_o ( axi_write_req ), - .axi_write_rsp_i ( axi_write_rsp ), - .axis_write_req_o ( axis_write_req ), - .axis_write_rsp_i ( axis_write_rsp ), - .busy_o ( idma_busy_o ) - ); - - // flatten structs - assign idma_req.dst_addr = req_dst_addr_i; - assign idma_req.src_addr = req_src_addr_i; - assign idma_req.length = req_length_i; - assign idma_req.opt.src_protocol = req_src_protocol_i; - assign idma_req.opt.dst_protocol = req_dst_protocol_i; - assign idma_req.opt.axi_id = req_axi_id_i; - assign idma_req.opt.dst.cache = req_dst_cache_i; - assign idma_req.opt.dst.burst = req_dst_burst_i; - assign idma_req.opt.dst.qos = req_dst_qos_i; - assign idma_req.opt.dst.lock = req_dst_lock_i; - assign idma_req.opt.dst.prot = req_dst_prot_i; - assign idma_req.opt.dst.region = req_dst_region_i; - assign idma_req.opt.src.cache = req_src_cache_i; - assign idma_req.opt.src.burst = req_src_burst_i; - assign idma_req.opt.src.qos = req_src_qos_i; - assign idma_req.opt.src.lock = req_src_lock_i; - assign idma_req.opt.src.prot = req_src_prot_i; - assign idma_req.opt.src.region = req_src_region_i; - assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; - assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; - assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; - assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; - assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; - assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; - assign idma_req.opt.last = req_last_i; - - assign rsp_cause_o = idma_rsp.pld.cause; - assign rsp_err_type_o = idma_rsp.pld.err_type; - assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; - assign rsp_error_o = idma_rsp.error; - assign rsp_last_o = idma_rsp.last; - - - // AXI4+ATOP Read - assign axi_ar_id_o = axi_read_req.ar.id; - assign axi_ar_addr_o = axi_read_req.ar.addr; - assign axi_ar_len_o = axi_read_req.ar.len; - assign axi_ar_size_o = axi_read_req.ar.size; - assign axi_ar_burst_o = axi_read_req.ar.burst; - assign axi_ar_lock_o = axi_read_req.ar.lock; - assign axi_ar_cache_o = axi_read_req.ar.cache; - assign axi_ar_prot_o = axi_read_req.ar.prot; - assign axi_ar_qos_o = axi_read_req.ar.qos; - assign axi_ar_region_o = axi_read_req.ar.region; - assign axi_ar_user_o = axi_read_req.ar.user; - assign axi_ar_valid_o = axi_read_req.ar_valid; - assign axi_r_ready_o = axi_read_req.r_ready; - - assign axi_read_rsp.ar_ready = axi_ar_ready_i; - assign axi_read_rsp.r.id = axi_r_id_i; - assign axi_read_rsp.r.data = axi_r_data_i; - assign axi_read_rsp.r.resp = axi_r_resp_i; - assign axi_read_rsp.r.last = axi_r_last_i; - assign axi_read_rsp.r.user = axi_r_user_i; - assign axi_read_rsp.r_valid = axi_r_valid_i; - - - - // AXI Stream Read - assign axis_read_req.t.data = axis_read_data_i; - assign axis_read_req.t.strb = axis_read_strb_i; - assign axis_read_req.t.keep = axis_read_keep_i; - assign axis_read_req.t.last = axis_read_last_i; - assign axis_read_req.t.id = axis_read_id_i; - assign axis_read_req.t.dest = axis_read_dest_i; - assign axis_read_req.t.user = axis_read_user_i; - assign axis_read_req.tvalid = axis_read_tvalid_i; - - assign axis_read_tready_o = axis_read_rsp.tready; - - - - // AXI4+ATOP Write - assign axi_aw_id_o = axi_write_req.aw.id; - assign axi_aw_addr_o = axi_write_req.aw.addr; - assign axi_aw_len_o = axi_write_req.aw.len; - assign axi_aw_size_o = axi_write_req.aw.size; - assign axi_aw_burst_o = axi_write_req.aw.burst; - assign axi_aw_lock_o = axi_write_req.aw.lock; - assign axi_aw_cache_o = axi_write_req.aw.cache; - assign axi_aw_prot_o = axi_write_req.aw.prot; - assign axi_aw_qos_o = axi_write_req.aw.qos; - assign axi_aw_region_o = axi_write_req.aw.region; - assign axi_aw_atop_o = axi_write_req.aw.atop; - assign axi_aw_user_o = axi_write_req.aw.user; - assign axi_aw_valid_o = axi_write_req.aw_valid; - assign axi_w_data_o = axi_write_req.w.data; - assign axi_w_strb_o = axi_write_req.w.strb; - assign axi_w_last_o = axi_write_req.w.last; - assign axi_w_user_o = axi_write_req.w.user; - assign axi_w_valid_o = axi_write_req.w_valid; - assign axi_b_ready_o = axi_write_req.b_ready; - - assign axi_write_rsp.aw_ready = axi_aw_ready_i; - assign axi_write_rsp.w_ready = axi_w_ready_i; - assign axi_write_rsp.b.id = axi_b_id_i; - assign axi_write_rsp.b.resp = axi_b_resp_i; - assign axi_write_rsp.b.user = axi_b_user_i; - assign axi_write_rsp.b_valid = axi_b_valid_i; - - - - // AXI Stream Write - assign axis_write_data_o = axis_write_req.t.data; - assign axis_write_strb_o = axis_write_req.t.strb; - assign axis_write_keep_o = axis_write_req.t.keep; - assign axis_write_last_o = axis_write_req.t.last; - assign axis_write_id_o = axis_write_req.t.id; - assign axis_write_dest_o = axis_write_req.t.dest; - assign axis_write_user_o = axis_write_req.t.user; - assign axis_write_tvalid_o = axis_write_req.tvalid; - - assign axis_write_rsp.tready = axis_write_tready_i; - - - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "axi_stream/typedef.svh" -`include "idma/typedef.svh" -`include "obi/typedef.svh" -`include "tilelink/typedef.svh" - -/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_r_obi_rw_init_w_axi #( - /// Data width - parameter int unsigned DataWidth = 32'd32, - /// Address width - parameter int unsigned AddrWidth = 32'd32, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd3, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd32, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 0, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter bit ErrorHandling = 1'b0, - // Dependent parameters; do not override! - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth), - /// Address type (do not override!) - parameter type addr_t = logic[AddrWidth-1:0], - /// Data type (do not override!) - parameter type data_t = logic[DataWidth-1:0], - /// Strobe type (do not override!) - parameter type strb_t = logic[StrbWidth-1:0], - /// User type (do not override!) - parameter type user_t = logic[UserWidth-1:0], - /// ID type (do not override!) - parameter type id_t = logic[AxiIdWidth-1:0], - /// Transfer length type (do not override!) - parameter type tf_len_t = logic[TFLenWidth-1:0], - /// Offset type (do not override!) - parameter type offset_t = logic[OffsetWidth-1:0] -)( - input logic clk_i, - input logic rst_ni, - input logic test_i, - - input logic req_valid_i, - output logic req_ready_o, - - input tf_len_t req_length_i, - input addr_t req_src_addr_i, - input addr_t req_dst_addr_i, - input idma_pkg::protocol_e req_src_protocol_i, - input idma_pkg::protocol_e req_dst_protocol_i, - input id_t req_axi_id_i, - input axi_pkg::burst_t req_src_burst_i, - input axi_pkg::cache_t req_src_cache_i, - input logic req_src_lock_i, - input axi_pkg::prot_t req_src_prot_i, - input axi_pkg::qos_t req_src_qos_i, - input axi_pkg::region_t req_src_region_i, - input axi_pkg::burst_t req_dst_burst_i, - input axi_pkg::cache_t req_dst_cache_i, - input logic req_dst_lock_i, - input axi_pkg::prot_t req_dst_prot_i, - input axi_pkg::qos_t req_dst_qos_i, - input axi_pkg::region_t req_dst_region_i, - input logic req_decouple_aw_i, - input logic req_decouple_rw_i, - input logic [2:0] req_src_max_llen_i, - input logic [2:0] req_dst_max_llen_i, - input logic req_src_reduce_len_i, - input logic req_dst_reduce_len_i, - input logic req_last_i, - - output logic rsp_valid_o, - input logic rsp_ready_i, - - output axi_pkg::resp_t rsp_cause_o, - output idma_pkg::err_type_t rsp_err_type_o, - output addr_t rsp_burst_addr_o, - output logic rsp_error_o, - output logic rsp_last_o, - - input logic eh_req_valid_i, - output logic eh_req_ready_o, - input idma_pkg::idma_eh_req_t eh_req_i, - - output logic init_read_req_valid_o, - output addr_t init_read_req_config_o, - input logic init_read_req_ready_i, - - input logic init_read_rsp_valid_i, - input data_t init_read_rsp_init_i, - output logic init_read_rsp_ready_o, - - - output logic obi_read_req_a_req_o, - output addr_t obi_read_req_a_addr_o, - output logic obi_read_req_a_we_o, - output strb_t obi_read_req_a_be_o, - output data_t obi_read_req_a_wdata_o, - output logic obi_read_req_r_ready_o, - - input logic obi_read_rsp_a_gnt_i, - input logic obi_read_rsp_r_valid_i, - input data_t obi_read_rsp_r_rdata_i, - input id_t obi_read_rsp_r_rid_i, - input logic obi_read_rsp_r_err_i, - - - output id_t axi_aw_id_o, - output addr_t axi_aw_addr_o, - output axi_pkg::len_t axi_aw_len_o, - output axi_pkg::size_t axi_aw_size_o, - output axi_pkg::burst_t axi_aw_burst_o, - output logic axi_aw_lock_o, - output axi_pkg::cache_t axi_aw_cache_o, - output axi_pkg::prot_t axi_aw_prot_o, - output axi_pkg::qos_t axi_aw_qos_o, - output axi_pkg::region_t axi_aw_region_o, - output axi_pkg::atop_t axi_aw_atop_o, - output user_t axi_aw_user_o, - output logic axi_aw_valid_o, - input logic axi_aw_ready_i, - output data_t axi_w_data_o, - output strb_t axi_w_strb_o, - output logic axi_w_last_o, - output user_t axi_w_user_o, - output logic axi_w_valid_o, - input logic axi_w_ready_i, - input id_t axi_b_id_i, - input axi_pkg::resp_t axi_b_resp_i, - input user_t axi_b_user_i, - input logic axi_b_valid_i, - output logic axi_b_ready_o, - - - output logic init_write_req_valid_o, - output addr_t init_write_req_cfg_o, - output data_t init_write_req_term_o, - output strb_t init_write_req_strb_o, - output id_t init_write_req_id_o, - input logic init_write_req_ready_i, - - input logic init_write_rsp_valid_i, - output logic init_write_rsp_ready_o, - - - output idma_pkg::idma_busy_t idma_busy_o -); - - /// Define the error handling capability - localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : - idma_pkg::NO_ERROR_HANDLING; - - // AXI4+ATOP typedefs -`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) -`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) - -`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) - -`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) -`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - - - // Memory Init typedefs -/// init read request -typedef struct packed { - logic [AddrWidth-1:0] cfg; - logic [DataWidth-1:0] term; - logic [StrbWidth-1:0] strb; - logic [AxiIdWidth-1:0] id; -} init_req_chan_t; - -typedef struct packed { - init_req_chan_t req_chan; - logic req_valid; - logic rsp_ready; -} init_req_t; - -typedef struct packed { - logic [DataWidth-1:0] init; -} init_rsp_chan_t; - -typedef struct packed { - init_rsp_chan_t rsp_chan; - logic rsp_valid; - logic req_ready; -} init_rsp_t; - - - // OBI typedefs -`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) -`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) - -`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) -`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) - -`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) -`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) - - - // Meta Channel Widths - localparam int unsigned axi_aw_chan_width = axi_pkg::aw_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); - localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); - - /// Option struct: AXI4 id as well as AXI and backend options - /// - `last`: a flag can be set if this transfer is the last of a set of transfers - `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) - - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) - - /// 1D iDMA response payload: - /// - `cause`: the AXI response - /// - `err_type`: type of the error: read, write, internal, ... - /// - `burst_addr`: the burst address where the issue error occurred - `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) - - /// 1D iDMA response type: - /// - `last`: the response of the request that was marked with the `opt.last` flag - /// - `error`: 1 if an error occurred - /// - `pld`: the error payload - `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) - - function int unsigned max_width(input int unsigned a, b); - return (a > b) ? a : b; - endfunction - - typedef struct packed { - init_req_chan_t req_chan; - logic[max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; - } init_read_req_chan_padded_t; - - typedef struct packed { - obi_a_chan_t a_chan; - logic[max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; - } obi_read_a_chan_padded_t; - - typedef union packed { - init_read_req_chan_padded_t init; - obi_read_a_chan_padded_t obi; - } read_meta_channel_t; - - typedef struct packed { - axi_aw_chan_t aw_chan; - logic[max_width(axi_aw_chan_width, init_req_chan_width)-axi_aw_chan_width:0] padding; - } axi_write_aw_chan_padded_t; - - typedef struct packed { - init_req_chan_t req_chan; - logic[max_width(axi_aw_chan_width, init_req_chan_width)-init_req_chan_width:0] padding; - } init_write_req_chan_padded_t; - - typedef union packed { - axi_write_aw_chan_padded_t axi; - init_write_req_chan_padded_t init; - } write_meta_channel_t; - - // local types - // AXI4+ATOP request and response - - axi_req_t axi_write_req; - axi_rsp_t axi_write_rsp; - - // Memory Init request and response - init_req_t init_read_req; - init_rsp_t init_read_rsp; - - init_req_t init_write_req; - init_rsp_t init_write_rsp; - - // OBI request and response - obi_req_t obi_read_req; - obi_rsp_t obi_read_rsp; - - - idma_req_t idma_req; - idma_rsp_t idma_rsp; - - idma_backend_r_obi_rw_init_w_axi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .AxiIdWidth ( AxiIdWidth ), - .UserWidth ( UserWidth ), - .TFLenWidth ( TFLenWidth ), - .MaskInvalidData ( MaskInvalidData ), - .BufferDepth ( BufferDepth ), - .NumAxInFlight ( NumAxInFlight ), - .MemSysDepth ( MemSysDepth ), - .RAWCouplingAvail ( RAWCouplingAvail ), - .HardwareLegalizer ( HardwareLegalizer ), - .RejectZeroTransfers ( RejectZeroTransfers ), - .ErrorCap ( ErrorCap ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .init_req_t ( init_req_t ), - .init_rsp_t ( init_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ) - ) i_idma_backend ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( test_i ), - .idma_req_i ( idma_req ), - .req_valid_i ( req_valid_i ), - .req_ready_o ( req_ready_o ), - .idma_rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid_o ), - .rsp_ready_i ( rsp_ready_i ), - .idma_eh_req_i ( eh_req_i ), - .eh_req_valid_i ( eh_req_valid_i ), - .eh_req_ready_o ( eh_req_ready_o ), - .init_read_req_o ( init_read_req ), - .init_read_rsp_i ( init_read_rsp ), - .obi_read_req_o ( obi_read_req ), - .obi_read_rsp_i ( obi_read_rsp ), - .axi_write_req_o ( axi_write_req ), - .axi_write_rsp_i ( axi_write_rsp ), - .init_write_req_o ( init_write_req ), - .init_write_rsp_i ( init_write_rsp ), - .busy_o ( idma_busy_o ) - ); - - // flatten structs - assign idma_req.dst_addr = req_dst_addr_i; - assign idma_req.src_addr = req_src_addr_i; - assign idma_req.length = req_length_i; - assign idma_req.opt.src_protocol = req_src_protocol_i; - assign idma_req.opt.dst_protocol = req_dst_protocol_i; - assign idma_req.opt.axi_id = req_axi_id_i; - assign idma_req.opt.dst.cache = req_dst_cache_i; - assign idma_req.opt.dst.burst = req_dst_burst_i; - assign idma_req.opt.dst.qos = req_dst_qos_i; - assign idma_req.opt.dst.lock = req_dst_lock_i; - assign idma_req.opt.dst.prot = req_dst_prot_i; - assign idma_req.opt.dst.region = req_dst_region_i; - assign idma_req.opt.src.cache = req_src_cache_i; - assign idma_req.opt.src.burst = req_src_burst_i; - assign idma_req.opt.src.qos = req_src_qos_i; - assign idma_req.opt.src.lock = req_src_lock_i; - assign idma_req.opt.src.prot = req_src_prot_i; - assign idma_req.opt.src.region = req_src_region_i; - assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; - assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; - assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; - assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; - assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; - assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; - assign idma_req.opt.last = req_last_i; - - assign rsp_cause_o = idma_rsp.pld.cause; - assign rsp_err_type_o = idma_rsp.pld.err_type; - assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; - assign rsp_error_o = idma_rsp.error; - assign rsp_last_o = idma_rsp.last; - - - // Memory Init Read - assign init_read_req_valid_o = init_read_req.req_valid; - assign init_read_req_config_o = init_read_req.req_chan.cfg; - assign init_read_rsp.req_ready = init_read_req_ready_i; - - assign init_read_rsp.rsp_valid = init_read_rsp_valid_i; - assign init_read_rsp.rsp_chan.init = init_read_rsp_init_i; - assign init_read_rsp_ready_o = init_read_req.rsp_ready; - - - - // OBI Read - assign obi_read_req_a_req_o = obi_read_req.req; - assign obi_read_req_a_addr_o = obi_read_req.a.addr; - assign obi_read_req_a_we_o = obi_read_req.a.we; - assign obi_read_req_a_be_o = obi_read_req.a.be; - assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; - assign obi_read_req_r_ready_o = obi_read_req.rready; - - assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; - assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; - assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; - assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; - assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; - - - - // AXI4+ATOP Write - assign axi_aw_id_o = axi_write_req.aw.id; - assign axi_aw_addr_o = axi_write_req.aw.addr; - assign axi_aw_len_o = axi_write_req.aw.len; - assign axi_aw_size_o = axi_write_req.aw.size; - assign axi_aw_burst_o = axi_write_req.aw.burst; - assign axi_aw_lock_o = axi_write_req.aw.lock; - assign axi_aw_cache_o = axi_write_req.aw.cache; - assign axi_aw_prot_o = axi_write_req.aw.prot; - assign axi_aw_qos_o = axi_write_req.aw.qos; - assign axi_aw_region_o = axi_write_req.aw.region; - assign axi_aw_atop_o = axi_write_req.aw.atop; - assign axi_aw_user_o = axi_write_req.aw.user; - assign axi_aw_valid_o = axi_write_req.aw_valid; - assign axi_w_data_o = axi_write_req.w.data; - assign axi_w_strb_o = axi_write_req.w.strb; - assign axi_w_last_o = axi_write_req.w.last; - assign axi_w_user_o = axi_write_req.w.user; - assign axi_w_valid_o = axi_write_req.w_valid; - assign axi_b_ready_o = axi_write_req.b_ready; - - assign axi_write_rsp.aw_ready = axi_aw_ready_i; - assign axi_write_rsp.w_ready = axi_w_ready_i; - assign axi_write_rsp.b.id = axi_b_id_i; - assign axi_write_rsp.b.resp = axi_b_resp_i; - assign axi_write_rsp.b.user = axi_b_user_i; - assign axi_write_rsp.b_valid = axi_b_valid_i; - - - - // Memory Init Write - assign init_write_req_valid_o = init_write_req.req_valid; - assign init_write_req_cfg_o = init_write_req.req_chan.cfg; - assign init_write_req_term_o = init_write_req.req_chan.term; - assign init_write_req_strb_o = init_write_req.req_chan.strb; - assign init_write_req_id_o = init_write_req.req_chan.id; - assign init_write_rsp.req_ready = init_write_req_ready_i; - - assign init_write_rsp.rsp_valid = init_write_rsp_valid_i; - assign init_write_rsp_ready_o = init_write_req.rsp_ready; - - - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Thomas Benz -// - Tobias Senti - -`include "axi/typedef.svh" -`include "axi_stream/typedef.svh" -`include "idma/typedef.svh" -`include "obi/typedef.svh" -`include "tilelink/typedef.svh" - -/// Synthesis wrapper for the iDMA backend. Unpacks all the interfaces to simple logic vectors -module idma_backend_synth_r_axi_rw_init_rw_obi #( - /// Data width - parameter int unsigned DataWidth = 32'd32, - /// Address width - parameter int unsigned AddrWidth = 32'd32, - /// AXI user width - parameter int unsigned UserWidth = 32'd1, - /// AXI ID width - parameter int unsigned AxiIdWidth = 32'd1, - /// Number of transaction that can be in-flight concurrently - parameter int unsigned NumAxInFlight = 32'd3, - /// The depth of the internal reorder buffer: - /// - '2': minimal possible configuration - /// - '3': efficiently handle misaligned transfers (recommended) - parameter int unsigned BufferDepth = 32'd3, - /// With of a transfer: max transfer size is `2**TFLenWidth` bytes - parameter int unsigned TFLenWidth = 32'd32, - /// The depth of the memory system the backend is attached to - parameter int unsigned MemSysDepth = 32'd0, - /// Should both data shifts be done before the dataflow element? - /// If this is enabled, then the data inserted into the dataflow element - /// will no longer be word aligned, but only a single shifter is needed - parameter bit CombinedShifter = 1'b0, - /// Mask invalid data on the manager interface - parameter bit MaskInvalidData = 1'b1, - /// Should the `R`-`AW` coupling hardware be present? (recommended) - parameter bit RAWCouplingAvail = 0, - /// Should hardware legalization be present? (recommended) - /// If not, software legalization is required to ensure the transfers are - /// AXI4-conformal - parameter bit HardwareLegalizer = 1'b1, - /// Reject zero-length transfers - parameter bit RejectZeroTransfers = 1'b1, - /// Should the error handler be present? - parameter bit ErrorHandling = 1'b0, - // Dependent parameters; do not override! - /// Strobe Width (do not override!) - parameter int unsigned StrbWidth = DataWidth / 8, - /// Offset Width (do not override!) - parameter int unsigned OffsetWidth = $clog2(StrbWidth), - /// Address type (do not override!) - parameter type addr_t = logic[AddrWidth-1:0], - /// Data type (do not override!) - parameter type data_t = logic[DataWidth-1:0], - /// Strobe type (do not override!) - parameter type strb_t = logic[StrbWidth-1:0], - /// User type (do not override!) - parameter type user_t = logic[UserWidth-1:0], - /// ID type (do not override!) - parameter type id_t = logic[AxiIdWidth-1:0], - /// Transfer length type (do not override!) - parameter type tf_len_t = logic[TFLenWidth-1:0], - /// Offset type (do not override!) - parameter type offset_t = logic[OffsetWidth-1:0] -)( - input logic clk_i, - input logic rst_ni, - input logic test_i, - - input logic req_valid_i, - output logic req_ready_o, - - input tf_len_t req_length_i, - input addr_t req_src_addr_i, - input addr_t req_dst_addr_i, - input idma_pkg::protocol_e req_src_protocol_i, - input idma_pkg::protocol_e req_dst_protocol_i, - input id_t req_axi_id_i, - input axi_pkg::burst_t req_src_burst_i, - input axi_pkg::cache_t req_src_cache_i, - input logic req_src_lock_i, - input axi_pkg::prot_t req_src_prot_i, - input axi_pkg::qos_t req_src_qos_i, - input axi_pkg::region_t req_src_region_i, - input axi_pkg::burst_t req_dst_burst_i, - input axi_pkg::cache_t req_dst_cache_i, - input logic req_dst_lock_i, - input axi_pkg::prot_t req_dst_prot_i, - input axi_pkg::qos_t req_dst_qos_i, - input axi_pkg::region_t req_dst_region_i, - input logic req_decouple_aw_i, - input logic req_decouple_rw_i, - input logic [2:0] req_src_max_llen_i, - input logic [2:0] req_dst_max_llen_i, - input logic req_src_reduce_len_i, - input logic req_dst_reduce_len_i, - input logic req_last_i, - - output logic rsp_valid_o, - input logic rsp_ready_i, - - output axi_pkg::resp_t rsp_cause_o, - output idma_pkg::err_type_t rsp_err_type_o, - output addr_t rsp_burst_addr_o, - output logic rsp_error_o, - output logic rsp_last_o, - - input logic eh_req_valid_i, - output logic eh_req_ready_o, - input idma_pkg::idma_eh_req_t eh_req_i, - - output id_t axi_ar_id_o, - output addr_t axi_ar_addr_o, - output axi_pkg::len_t axi_ar_len_o, - output axi_pkg::size_t axi_ar_size_o, - output axi_pkg::burst_t axi_ar_burst_o, - output logic axi_ar_lock_o, - output axi_pkg::cache_t axi_ar_cache_o, - output axi_pkg::prot_t axi_ar_prot_o, - output axi_pkg::qos_t axi_ar_qos_o, - output axi_pkg::region_t axi_ar_region_o, - output user_t axi_ar_user_o, - output logic axi_ar_valid_o, - input logic axi_ar_ready_i, - input id_t axi_r_id_i, - input data_t axi_r_data_i, - input axi_pkg::resp_t axi_r_resp_i, - input logic axi_r_last_i, - input user_t axi_r_user_i, - input logic axi_r_valid_i, - output logic axi_r_ready_o, - - - output logic init_read_req_valid_o, - output addr_t init_read_req_config_o, - input logic init_read_req_ready_i, - - input logic init_read_rsp_valid_i, - input data_t init_read_rsp_init_i, - output logic init_read_rsp_ready_o, - - - output logic obi_read_req_a_req_o, - output addr_t obi_read_req_a_addr_o, - output logic obi_read_req_a_we_o, - output strb_t obi_read_req_a_be_o, - output data_t obi_read_req_a_wdata_o, - output logic obi_read_req_r_ready_o, - - input logic obi_read_rsp_a_gnt_i, - input logic obi_read_rsp_r_valid_i, - input data_t obi_read_rsp_r_rdata_i, - input id_t obi_read_rsp_r_rid_i, - input logic obi_read_rsp_r_err_i, - - - output logic init_write_req_valid_o, - output addr_t init_write_req_cfg_o, - output data_t init_write_req_term_o, - output strb_t init_write_req_strb_o, - output id_t init_write_req_id_o, - input logic init_write_req_ready_i, - - input logic init_write_rsp_valid_i, - output logic init_write_rsp_ready_o, - - - output logic obi_write_req_a_req_o, - output addr_t obi_write_req_a_addr_o, - output logic obi_write_req_a_we_o, - output strb_t obi_write_req_a_be_o, - output data_t obi_write_req_a_wdata_o, - output id_t obi_write_req_a_aid_o, - output logic obi_write_req_r_ready_o, - - input logic obi_write_rsp_a_gnt_i, - input logic obi_write_rsp_r_valid_i, - input data_t obi_write_rsp_r_rdata_i, - - - output idma_pkg::idma_busy_t idma_busy_o -); - - /// Define the error handling capability - localparam idma_pkg::error_cap_e ErrorCap = ErrorHandling ? idma_pkg::ERROR_HANDLING : - idma_pkg::NO_ERROR_HANDLING; - - // AXI4+ATOP typedefs -`AXI_TYPEDEF_AW_CHAN_T(axi_aw_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_W_CHAN_T(axi_w_chan_t, data_t, strb_t, user_t) -`AXI_TYPEDEF_B_CHAN_T(axi_b_chan_t, id_t, user_t) - -`AXI_TYPEDEF_AR_CHAN_T(axi_ar_chan_t, addr_t, id_t, user_t) -`AXI_TYPEDEF_R_CHAN_T(axi_r_chan_t, data_t, id_t, user_t) - -`AXI_TYPEDEF_REQ_T(axi_req_t, axi_aw_chan_t, axi_w_chan_t, axi_ar_chan_t) -`AXI_TYPEDEF_RESP_T(axi_rsp_t, axi_b_chan_t, axi_r_chan_t) - - - // Memory Init typedefs -/// init read request -typedef struct packed { - logic [AddrWidth-1:0] cfg; - logic [DataWidth-1:0] term; - logic [StrbWidth-1:0] strb; - logic [AxiIdWidth-1:0] id; -} init_req_chan_t; - -typedef struct packed { - init_req_chan_t req_chan; - logic req_valid; - logic rsp_ready; -} init_req_t; - -typedef struct packed { - logic [DataWidth-1:0] init; -} init_rsp_chan_t; - -typedef struct packed { - init_rsp_chan_t rsp_chan; - logic rsp_valid; - logic req_ready; -} init_rsp_t; - - - // OBI typedefs -`OBI_TYPEDEF_MINIMAL_A_OPTIONAL(a_optional_t) -`OBI_TYPEDEF_MINIMAL_R_OPTIONAL(r_optional_t) - -`OBI_TYPEDEF_TYPE_A_CHAN_T(obi_a_chan_t, addr_t, data_t, strb_t, id_t, a_optional_t) -`OBI_TYPEDEF_TYPE_R_CHAN_T(obi_r_chan_t, data_t, id_t, r_optional_t) - -`OBI_TYPEDEF_REQ_T(obi_req_t, obi_a_chan_t) -`OBI_TYPEDEF_RSP_T(obi_rsp_t, obi_r_chan_t) - - - // Meta Channel Widths - localparam int unsigned axi_ar_chan_width = axi_pkg::ar_width(AddrWidth, AxiIdWidth, UserWidth); - localparam int unsigned init_req_chan_width = $bits(init_req_chan_t); - localparam int unsigned obi_a_chan_width = $bits(obi_a_chan_t); - - /// Option struct: AXI4 id as well as AXI and backend options - /// - `last`: a flag can be set if this transfer is the last of a set of transfers - `IDMA_TYPEDEF_OPTIONS_T(options_t, id_t) - - /// 1D iDMA request type: - /// - `length`: the length of the transfer in bytes - /// - `*_addr`: the source / target byte addresses of the transfer - /// - `opt`: the options field - `IDMA_TYPEDEF_REQ_T(idma_req_t, tf_len_t, addr_t, options_t) - - /// 1D iDMA response payload: - /// - `cause`: the AXI response - /// - `err_type`: type of the error: read, write, internal, ... - /// - `burst_addr`: the burst address where the issue error occurred - `IDMA_TYPEDEF_ERR_PAYLOAD_T(err_payload_t, addr_t) - - /// 1D iDMA response type: - /// - `last`: the response of the request that was marked with the `opt.last` flag - /// - `error`: 1 if an error occurred - /// - `pld`: the error payload - `IDMA_TYPEDEF_RSP_T(idma_rsp_t, err_payload_t) - - function int unsigned max_width(input int unsigned a, b); - return (a > b) ? a : b; - endfunction - - typedef struct packed { - axi_ar_chan_t ar_chan; - logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-axi_ar_chan_width:0] padding; - } axi_read_ar_chan_padded_t; - - typedef struct packed { - init_req_chan_t req_chan; - logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-init_req_chan_width:0] padding; - } init_read_req_chan_padded_t; - - typedef struct packed { - obi_a_chan_t a_chan; - logic[max_width(axi_ar_chan_width, max_width(init_req_chan_width, obi_a_chan_width))-obi_a_chan_width:0] padding; - } obi_read_a_chan_padded_t; - - typedef union packed { - axi_read_ar_chan_padded_t axi; - init_read_req_chan_padded_t init; - obi_read_a_chan_padded_t obi; - } read_meta_channel_t; - - typedef struct packed { - init_req_chan_t req_chan; - logic[max_width(init_req_chan_width, obi_a_chan_width)-init_req_chan_width:0] padding; - } init_write_req_chan_padded_t; - - typedef struct packed { - obi_a_chan_t a_chan; - logic[max_width(init_req_chan_width, obi_a_chan_width)-obi_a_chan_width:0] padding; - } obi_write_a_chan_padded_t; - - typedef union packed { - init_write_req_chan_padded_t init; - obi_write_a_chan_padded_t obi; - } write_meta_channel_t; - - // local types - // AXI4+ATOP request and response - axi_req_t axi_read_req; - axi_rsp_t axi_read_rsp; - - - // Memory Init request and response - init_req_t init_read_req; - init_rsp_t init_read_rsp; - - init_req_t init_write_req; - init_rsp_t init_write_rsp; - - // OBI request and response - obi_req_t obi_read_req; - obi_rsp_t obi_read_rsp; - - obi_req_t obi_write_req; - obi_rsp_t obi_write_rsp; - - idma_req_t idma_req; - idma_rsp_t idma_rsp; - - idma_backend_r_axi_rw_init_rw_obi #( - .CombinedShifter ( CombinedShifter ), - .DataWidth ( DataWidth ), - .AddrWidth ( AddrWidth ), - .AxiIdWidth ( AxiIdWidth ), - .UserWidth ( UserWidth ), - .TFLenWidth ( TFLenWidth ), - .MaskInvalidData ( MaskInvalidData ), - .BufferDepth ( BufferDepth ), - .NumAxInFlight ( NumAxInFlight ), - .MemSysDepth ( MemSysDepth ), - .RAWCouplingAvail ( RAWCouplingAvail ), - .HardwareLegalizer ( HardwareLegalizer ), - .RejectZeroTransfers ( RejectZeroTransfers ), - .ErrorCap ( ErrorCap ), - .idma_req_t ( idma_req_t ), - .idma_rsp_t ( idma_rsp_t ), - .idma_eh_req_t ( idma_pkg::idma_eh_req_t ), - .idma_busy_t ( idma_pkg::idma_busy_t ), - .axi_req_t ( axi_req_t ), - .axi_rsp_t ( axi_rsp_t ), - .init_req_t ( init_req_t ), - .init_rsp_t ( init_rsp_t ), - .obi_req_t ( obi_req_t ), - .obi_rsp_t ( obi_rsp_t ), - .write_meta_channel_t ( write_meta_channel_t ), - .read_meta_channel_t ( read_meta_channel_t ) - ) i_idma_backend ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .testmode_i ( test_i ), - .idma_req_i ( idma_req ), - .req_valid_i ( req_valid_i ), - .req_ready_o ( req_ready_o ), - .idma_rsp_o ( idma_rsp ), - .rsp_valid_o ( rsp_valid_o ), - .rsp_ready_i ( rsp_ready_i ), - .idma_eh_req_i ( eh_req_i ), - .eh_req_valid_i ( eh_req_valid_i ), - .eh_req_ready_o ( eh_req_ready_o ), - .axi_read_req_o ( axi_read_req ), - .axi_read_rsp_i ( axi_read_rsp ), - .init_read_req_o ( init_read_req ), - .init_read_rsp_i ( init_read_rsp ), - .obi_read_req_o ( obi_read_req ), - .obi_read_rsp_i ( obi_read_rsp ), - .init_write_req_o ( init_write_req ), - .init_write_rsp_i ( init_write_rsp ), - .obi_write_req_o ( obi_write_req ), - .obi_write_rsp_i ( obi_write_rsp ), - .busy_o ( idma_busy_o ) - ); - - // flatten structs - assign idma_req.dst_addr = req_dst_addr_i; - assign idma_req.src_addr = req_src_addr_i; - assign idma_req.length = req_length_i; - assign idma_req.opt.src_protocol = req_src_protocol_i; - assign idma_req.opt.dst_protocol = req_dst_protocol_i; - assign idma_req.opt.axi_id = req_axi_id_i; - assign idma_req.opt.dst.cache = req_dst_cache_i; - assign idma_req.opt.dst.burst = req_dst_burst_i; - assign idma_req.opt.dst.qos = req_dst_qos_i; - assign idma_req.opt.dst.lock = req_dst_lock_i; - assign idma_req.opt.dst.prot = req_dst_prot_i; - assign idma_req.opt.dst.region = req_dst_region_i; - assign idma_req.opt.src.cache = req_src_cache_i; - assign idma_req.opt.src.burst = req_src_burst_i; - assign idma_req.opt.src.qos = req_src_qos_i; - assign idma_req.opt.src.lock = req_src_lock_i; - assign idma_req.opt.src.prot = req_src_prot_i; - assign idma_req.opt.src.region = req_src_region_i; - assign idma_req.opt.beo.dst_reduce_len = req_dst_reduce_len_i; - assign idma_req.opt.beo.src_reduce_len = req_src_reduce_len_i; - assign idma_req.opt.beo.dst_max_llen = req_dst_max_llen_i; - assign idma_req.opt.beo.src_max_llen = req_src_max_llen_i; - assign idma_req.opt.beo.decouple_rw = req_decouple_rw_i; - assign idma_req.opt.beo.decouple_aw = req_decouple_aw_i; - assign idma_req.opt.last = req_last_i; - - assign rsp_cause_o = idma_rsp.pld.cause; - assign rsp_err_type_o = idma_rsp.pld.err_type; - assign rsp_burst_addr_o = idma_rsp.pld.burst_addr; - assign rsp_error_o = idma_rsp.error; - assign rsp_last_o = idma_rsp.last; - - - // AXI4+ATOP Read - assign axi_ar_id_o = axi_read_req.ar.id; - assign axi_ar_addr_o = axi_read_req.ar.addr; - assign axi_ar_len_o = axi_read_req.ar.len; - assign axi_ar_size_o = axi_read_req.ar.size; - assign axi_ar_burst_o = axi_read_req.ar.burst; - assign axi_ar_lock_o = axi_read_req.ar.lock; - assign axi_ar_cache_o = axi_read_req.ar.cache; - assign axi_ar_prot_o = axi_read_req.ar.prot; - assign axi_ar_qos_o = axi_read_req.ar.qos; - assign axi_ar_region_o = axi_read_req.ar.region; - assign axi_ar_user_o = axi_read_req.ar.user; - assign axi_ar_valid_o = axi_read_req.ar_valid; - assign axi_r_ready_o = axi_read_req.r_ready; - - assign axi_read_rsp.ar_ready = axi_ar_ready_i; - assign axi_read_rsp.r.id = axi_r_id_i; - assign axi_read_rsp.r.data = axi_r_data_i; - assign axi_read_rsp.r.resp = axi_r_resp_i; - assign axi_read_rsp.r.last = axi_r_last_i; - assign axi_read_rsp.r.user = axi_r_user_i; - assign axi_read_rsp.r_valid = axi_r_valid_i; - - - - // Memory Init Read - assign init_read_req_valid_o = init_read_req.req_valid; - assign init_read_req_config_o = init_read_req.req_chan.cfg; - assign init_read_rsp.req_ready = init_read_req_ready_i; - - assign init_read_rsp.rsp_valid = init_read_rsp_valid_i; - assign init_read_rsp.rsp_chan.init = init_read_rsp_init_i; - assign init_read_rsp_ready_o = init_read_req.rsp_ready; - - - - // OBI Read - assign obi_read_req_a_req_o = obi_read_req.req; - assign obi_read_req_a_addr_o = obi_read_req.a.addr; - assign obi_read_req_a_we_o = obi_read_req.a.we; - assign obi_read_req_a_be_o = obi_read_req.a.be; - assign obi_read_req_a_wdata_o = obi_read_req.a.wdata; - assign obi_read_req_r_ready_o = obi_read_req.rready; - - assign obi_read_rsp.gnt = obi_read_rsp_a_gnt_i; - assign obi_read_rsp.rvalid = obi_read_rsp_r_valid_i; - assign obi_read_rsp.r.rdata = obi_read_rsp_r_rdata_i; - assign obi_read_rsp.r.rid = obi_read_rsp_r_rid_i; - assign obi_read_rsp.r.err = obi_read_rsp_r_err_i; - - - - // Memory Init Write - assign init_write_req_valid_o = init_write_req.req_valid; - assign init_write_req_cfg_o = init_write_req.req_chan.cfg; - assign init_write_req_term_o = init_write_req.req_chan.term; - assign init_write_req_strb_o = init_write_req.req_chan.strb; - assign init_write_req_id_o = init_write_req.req_chan.id; - assign init_write_rsp.req_ready = init_write_req_ready_i; - - assign init_write_rsp.rsp_valid = init_write_rsp_valid_i; - assign init_write_rsp_ready_o = init_write_req.rsp_ready; - - - - // OBI Write - assign obi_write_req_a_req_o = obi_write_req.req; - assign obi_write_req_a_addr_o = obi_write_req.a.addr; - assign obi_write_req_a_we_o = obi_write_req.a.we; - assign obi_write_req_a_be_o = obi_write_req.a.be; - assign obi_write_req_a_wdata_o = obi_write_req.a.wdata; - assign obi_write_req_a_aid_o = obi_write_req.a.aid; - assign obi_write_req_r_ready_o = obi_write_req.rready; - - assign obi_write_rsp.gnt = obi_write_rsp_a_gnt_i; - assign obi_write_rsp.rvalid = obi_write_rsp_r_valid_i; - assign obi_write_rsp.r.rdata = obi_write_rsp_r_rdata_i; - - - -endmodule - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure - -package idma_desc64_reg_pkg; - - // Address widths within the block - parameter int BlockAw = 4; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - logic [63:0] q; - logic qe; - } idma_desc64_reg2hw_desc_addr_reg_t; - - typedef struct packed { - struct packed { - logic d; - logic de; - } busy; - struct packed { - logic d; - logic de; - } fifo_full; - } idma_desc64_hw2reg_status_reg_t; - - // Register -> HW type - typedef struct packed { - idma_desc64_reg2hw_desc_addr_reg_t desc_addr; // [64:0] - } idma_desc64_reg2hw_t; - - // HW -> register type - typedef struct packed { - idma_desc64_hw2reg_status_reg_t status; // [3:0] - } idma_desc64_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] IDMA_DESC64_DESC_ADDR_OFFSET = 4'h 0; - parameter logic [BlockAw-1:0] IDMA_DESC64_STATUS_OFFSET = 4'h 8; - - // Register index - typedef enum int { - IDMA_DESC64_DESC_ADDR, - IDMA_DESC64_STATUS - } idma_desc64_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] IDMA_DESC64_PERMIT [2] = '{ - 4'b 1111, // index[0] IDMA_DESC64_DESC_ADDR - 4'b 0001 // index[1] IDMA_DESC64_STATUS - }; - -endpackage - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure - -package idma_reg32_3d_reg_pkg; - - // Param list - parameter int num_dims = 3; - - // Address widths within the block - parameter int BlockAw = 9; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - struct packed { - logic q; - } decouple_aw; - struct packed { - logic q; - } decouple_rw; - struct packed { - logic q; - } src_reduce_len; - struct packed { - logic q; - } dst_reduce_len; - struct packed { - logic [2:0] q; - } src_max_llen; - struct packed { - logic [2:0] q; - } dst_max_llen; - struct packed { - logic [1:0] q; - } enable_nd; - struct packed { - logic [2:0] q; - } src_protocol; - struct packed { - logic [2:0] q; - } dst_protocol; - } idma_reg32_3d_reg2hw_conf_reg_t; - - typedef struct packed { - logic [31:0] q; - logic re; - } idma_reg32_3d_reg2hw_next_id_mreg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_dst_addr_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_src_addr_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_length_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_dst_stride_2_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_src_stride_2_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_reps_2_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_dst_stride_3_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_src_stride_3_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg32_3d_reg2hw_reps_3_low_reg_t; - - typedef struct packed { - logic [9:0] d; - } idma_reg32_3d_hw2reg_status_mreg_t; - - typedef struct packed { - logic [31:0] d; - } idma_reg32_3d_hw2reg_next_id_mreg_t; - - typedef struct packed { - logic [31:0] d; - } idma_reg32_3d_hw2reg_done_id_mreg_t; - - // Register -> HW type - typedef struct packed { - idma_reg32_3d_reg2hw_conf_reg_t conf; // [833:816] - idma_reg32_3d_reg2hw_next_id_mreg_t [15:0] next_id; // [815:288] - idma_reg32_3d_reg2hw_dst_addr_low_reg_t dst_addr_low; // [287:256] - idma_reg32_3d_reg2hw_src_addr_low_reg_t src_addr_low; // [255:224] - idma_reg32_3d_reg2hw_length_low_reg_t length_low; // [223:192] - idma_reg32_3d_reg2hw_dst_stride_2_low_reg_t dst_stride_2_low; // [191:160] - idma_reg32_3d_reg2hw_src_stride_2_low_reg_t src_stride_2_low; // [159:128] - idma_reg32_3d_reg2hw_reps_2_low_reg_t reps_2_low; // [127:96] - idma_reg32_3d_reg2hw_dst_stride_3_low_reg_t dst_stride_3_low; // [95:64] - idma_reg32_3d_reg2hw_src_stride_3_low_reg_t src_stride_3_low; // [63:32] - idma_reg32_3d_reg2hw_reps_3_low_reg_t reps_3_low; // [31:0] - } idma_reg32_3d_reg2hw_t; - - // HW -> register type - typedef struct packed { - idma_reg32_3d_hw2reg_status_mreg_t [15:0] status; // [1183:1024] - idma_reg32_3d_hw2reg_next_id_mreg_t [15:0] next_id; // [1023:512] - idma_reg32_3d_hw2reg_done_id_mreg_t [15:0] done_id; // [511:0] - } idma_reg32_3d_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] IDMA_REG32_3D_CONF_OFFSET = 9'h 0; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_0_OFFSET = 9'h 4; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_1_OFFSET = 9'h 8; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_2_OFFSET = 9'h c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_3_OFFSET = 9'h 10; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_4_OFFSET = 9'h 14; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_5_OFFSET = 9'h 18; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_6_OFFSET = 9'h 1c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_7_OFFSET = 9'h 20; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_8_OFFSET = 9'h 24; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_9_OFFSET = 9'h 28; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_10_OFFSET = 9'h 2c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_11_OFFSET = 9'h 30; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_12_OFFSET = 9'h 34; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_13_OFFSET = 9'h 38; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_14_OFFSET = 9'h 3c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_STATUS_15_OFFSET = 9'h 40; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_0_OFFSET = 9'h 44; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_1_OFFSET = 9'h 48; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_2_OFFSET = 9'h 4c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_3_OFFSET = 9'h 50; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_4_OFFSET = 9'h 54; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_5_OFFSET = 9'h 58; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_6_OFFSET = 9'h 5c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_7_OFFSET = 9'h 60; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_8_OFFSET = 9'h 64; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_9_OFFSET = 9'h 68; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_10_OFFSET = 9'h 6c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_11_OFFSET = 9'h 70; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_12_OFFSET = 9'h 74; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_13_OFFSET = 9'h 78; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_14_OFFSET = 9'h 7c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_NEXT_ID_15_OFFSET = 9'h 80; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_0_OFFSET = 9'h 84; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_1_OFFSET = 9'h 88; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_2_OFFSET = 9'h 8c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_3_OFFSET = 9'h 90; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_4_OFFSET = 9'h 94; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_5_OFFSET = 9'h 98; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_6_OFFSET = 9'h 9c; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_7_OFFSET = 9'h a0; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_8_OFFSET = 9'h a4; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_9_OFFSET = 9'h a8; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_10_OFFSET = 9'h ac; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_11_OFFSET = 9'h b0; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_12_OFFSET = 9'h b4; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_13_OFFSET = 9'h b8; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_14_OFFSET = 9'h bc; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DONE_ID_15_OFFSET = 9'h c0; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DST_ADDR_LOW_OFFSET = 9'h d0; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_SRC_ADDR_LOW_OFFSET = 9'h d8; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_LENGTH_LOW_OFFSET = 9'h e0; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DST_STRIDE_2_LOW_OFFSET = 9'h e8; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_SRC_STRIDE_2_LOW_OFFSET = 9'h f0; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_REPS_2_LOW_OFFSET = 9'h f8; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_DST_STRIDE_3_LOW_OFFSET = 9'h 100; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_SRC_STRIDE_3_LOW_OFFSET = 9'h 108; - parameter logic [BlockAw-1:0] IDMA_REG32_3D_REPS_3_LOW_OFFSET = 9'h 110; - - // Reset values for hwext registers and their fields - parameter logic [9:0] IDMA_REG32_3D_STATUS_0_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_1_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_2_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_3_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_4_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_5_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_6_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_7_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_8_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_9_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_10_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_11_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_12_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_13_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_14_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG32_3D_STATUS_15_RESVAL = 10'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_0_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_1_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_2_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_3_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_4_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_5_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_6_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_7_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_8_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_9_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_10_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_11_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_12_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_13_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_14_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_NEXT_ID_15_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_0_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_1_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_2_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_3_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_4_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_5_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_6_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_7_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_8_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_9_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_10_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_11_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_12_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_13_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_14_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG32_3D_DONE_ID_15_RESVAL = 32'h 0; - - // Register index - typedef enum int { - IDMA_REG32_3D_CONF, - IDMA_REG32_3D_STATUS_0, - IDMA_REG32_3D_STATUS_1, - IDMA_REG32_3D_STATUS_2, - IDMA_REG32_3D_STATUS_3, - IDMA_REG32_3D_STATUS_4, - IDMA_REG32_3D_STATUS_5, - IDMA_REG32_3D_STATUS_6, - IDMA_REG32_3D_STATUS_7, - IDMA_REG32_3D_STATUS_8, - IDMA_REG32_3D_STATUS_9, - IDMA_REG32_3D_STATUS_10, - IDMA_REG32_3D_STATUS_11, - IDMA_REG32_3D_STATUS_12, - IDMA_REG32_3D_STATUS_13, - IDMA_REG32_3D_STATUS_14, - IDMA_REG32_3D_STATUS_15, - IDMA_REG32_3D_NEXT_ID_0, - IDMA_REG32_3D_NEXT_ID_1, - IDMA_REG32_3D_NEXT_ID_2, - IDMA_REG32_3D_NEXT_ID_3, - IDMA_REG32_3D_NEXT_ID_4, - IDMA_REG32_3D_NEXT_ID_5, - IDMA_REG32_3D_NEXT_ID_6, - IDMA_REG32_3D_NEXT_ID_7, - IDMA_REG32_3D_NEXT_ID_8, - IDMA_REG32_3D_NEXT_ID_9, - IDMA_REG32_3D_NEXT_ID_10, - IDMA_REG32_3D_NEXT_ID_11, - IDMA_REG32_3D_NEXT_ID_12, - IDMA_REG32_3D_NEXT_ID_13, - IDMA_REG32_3D_NEXT_ID_14, - IDMA_REG32_3D_NEXT_ID_15, - IDMA_REG32_3D_DONE_ID_0, - IDMA_REG32_3D_DONE_ID_1, - IDMA_REG32_3D_DONE_ID_2, - IDMA_REG32_3D_DONE_ID_3, - IDMA_REG32_3D_DONE_ID_4, - IDMA_REG32_3D_DONE_ID_5, - IDMA_REG32_3D_DONE_ID_6, - IDMA_REG32_3D_DONE_ID_7, - IDMA_REG32_3D_DONE_ID_8, - IDMA_REG32_3D_DONE_ID_9, - IDMA_REG32_3D_DONE_ID_10, - IDMA_REG32_3D_DONE_ID_11, - IDMA_REG32_3D_DONE_ID_12, - IDMA_REG32_3D_DONE_ID_13, - IDMA_REG32_3D_DONE_ID_14, - IDMA_REG32_3D_DONE_ID_15, - IDMA_REG32_3D_DST_ADDR_LOW, - IDMA_REG32_3D_SRC_ADDR_LOW, - IDMA_REG32_3D_LENGTH_LOW, - IDMA_REG32_3D_DST_STRIDE_2_LOW, - IDMA_REG32_3D_SRC_STRIDE_2_LOW, - IDMA_REG32_3D_REPS_2_LOW, - IDMA_REG32_3D_DST_STRIDE_3_LOW, - IDMA_REG32_3D_SRC_STRIDE_3_LOW, - IDMA_REG32_3D_REPS_3_LOW - } idma_reg32_3d_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] IDMA_REG32_3D_PERMIT [58] = '{ - 4'b 0111, // index[ 0] IDMA_REG32_3D_CONF - 4'b 0011, // index[ 1] IDMA_REG32_3D_STATUS_0 - 4'b 0011, // index[ 2] IDMA_REG32_3D_STATUS_1 - 4'b 0011, // index[ 3] IDMA_REG32_3D_STATUS_2 - 4'b 0011, // index[ 4] IDMA_REG32_3D_STATUS_3 - 4'b 0011, // index[ 5] IDMA_REG32_3D_STATUS_4 - 4'b 0011, // index[ 6] IDMA_REG32_3D_STATUS_5 - 4'b 0011, // index[ 7] IDMA_REG32_3D_STATUS_6 - 4'b 0011, // index[ 8] IDMA_REG32_3D_STATUS_7 - 4'b 0011, // index[ 9] IDMA_REG32_3D_STATUS_8 - 4'b 0011, // index[10] IDMA_REG32_3D_STATUS_9 - 4'b 0011, // index[11] IDMA_REG32_3D_STATUS_10 - 4'b 0011, // index[12] IDMA_REG32_3D_STATUS_11 - 4'b 0011, // index[13] IDMA_REG32_3D_STATUS_12 - 4'b 0011, // index[14] IDMA_REG32_3D_STATUS_13 - 4'b 0011, // index[15] IDMA_REG32_3D_STATUS_14 - 4'b 0011, // index[16] IDMA_REG32_3D_STATUS_15 - 4'b 1111, // index[17] IDMA_REG32_3D_NEXT_ID_0 - 4'b 1111, // index[18] IDMA_REG32_3D_NEXT_ID_1 - 4'b 1111, // index[19] IDMA_REG32_3D_NEXT_ID_2 - 4'b 1111, // index[20] IDMA_REG32_3D_NEXT_ID_3 - 4'b 1111, // index[21] IDMA_REG32_3D_NEXT_ID_4 - 4'b 1111, // index[22] IDMA_REG32_3D_NEXT_ID_5 - 4'b 1111, // index[23] IDMA_REG32_3D_NEXT_ID_6 - 4'b 1111, // index[24] IDMA_REG32_3D_NEXT_ID_7 - 4'b 1111, // index[25] IDMA_REG32_3D_NEXT_ID_8 - 4'b 1111, // index[26] IDMA_REG32_3D_NEXT_ID_9 - 4'b 1111, // index[27] IDMA_REG32_3D_NEXT_ID_10 - 4'b 1111, // index[28] IDMA_REG32_3D_NEXT_ID_11 - 4'b 1111, // index[29] IDMA_REG32_3D_NEXT_ID_12 - 4'b 1111, // index[30] IDMA_REG32_3D_NEXT_ID_13 - 4'b 1111, // index[31] IDMA_REG32_3D_NEXT_ID_14 - 4'b 1111, // index[32] IDMA_REG32_3D_NEXT_ID_15 - 4'b 1111, // index[33] IDMA_REG32_3D_DONE_ID_0 - 4'b 1111, // index[34] IDMA_REG32_3D_DONE_ID_1 - 4'b 1111, // index[35] IDMA_REG32_3D_DONE_ID_2 - 4'b 1111, // index[36] IDMA_REG32_3D_DONE_ID_3 - 4'b 1111, // index[37] IDMA_REG32_3D_DONE_ID_4 - 4'b 1111, // index[38] IDMA_REG32_3D_DONE_ID_5 - 4'b 1111, // index[39] IDMA_REG32_3D_DONE_ID_6 - 4'b 1111, // index[40] IDMA_REG32_3D_DONE_ID_7 - 4'b 1111, // index[41] IDMA_REG32_3D_DONE_ID_8 - 4'b 1111, // index[42] IDMA_REG32_3D_DONE_ID_9 - 4'b 1111, // index[43] IDMA_REG32_3D_DONE_ID_10 - 4'b 1111, // index[44] IDMA_REG32_3D_DONE_ID_11 - 4'b 1111, // index[45] IDMA_REG32_3D_DONE_ID_12 - 4'b 1111, // index[46] IDMA_REG32_3D_DONE_ID_13 - 4'b 1111, // index[47] IDMA_REG32_3D_DONE_ID_14 - 4'b 1111, // index[48] IDMA_REG32_3D_DONE_ID_15 - 4'b 1111, // index[49] IDMA_REG32_3D_DST_ADDR_LOW - 4'b 1111, // index[50] IDMA_REG32_3D_SRC_ADDR_LOW - 4'b 1111, // index[51] IDMA_REG32_3D_LENGTH_LOW - 4'b 1111, // index[52] IDMA_REG32_3D_DST_STRIDE_2_LOW - 4'b 1111, // index[53] IDMA_REG32_3D_SRC_STRIDE_2_LOW - 4'b 1111, // index[54] IDMA_REG32_3D_REPS_2_LOW - 4'b 1111, // index[55] IDMA_REG32_3D_DST_STRIDE_3_LOW - 4'b 1111, // index[56] IDMA_REG32_3D_SRC_STRIDE_3_LOW - 4'b 1111 // index[57] IDMA_REG32_3D_REPS_3_LOW - }; - -endpackage - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure - -package idma_reg64_2d_reg_pkg; - - // Param list - parameter int num_dims = 2; - - // Address widths within the block - parameter int BlockAw = 8; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - struct packed { - logic q; - } decouple_aw; - struct packed { - logic q; - } decouple_rw; - struct packed { - logic q; - } src_reduce_len; - struct packed { - logic q; - } dst_reduce_len; - struct packed { - logic [2:0] q; - } src_max_llen; - struct packed { - logic [2:0] q; - } dst_max_llen; - struct packed { - logic q; - } enable_nd; - struct packed { - logic [2:0] q; - } src_protocol; - struct packed { - logic [2:0] q; - } dst_protocol; - } idma_reg64_2d_reg2hw_conf_reg_t; - - typedef struct packed { - logic [31:0] q; - logic re; - } idma_reg64_2d_reg2hw_next_id_mreg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_dst_addr_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_dst_addr_high_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_src_addr_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_src_addr_high_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_length_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_length_high_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_dst_stride_2_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_dst_stride_2_high_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_src_stride_2_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_src_stride_2_high_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_reps_2_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_2d_reg2hw_reps_2_high_reg_t; - - typedef struct packed { - logic [9:0] d; - } idma_reg64_2d_hw2reg_status_mreg_t; - - typedef struct packed { - logic [31:0] d; - } idma_reg64_2d_hw2reg_next_id_mreg_t; - - typedef struct packed { - logic [31:0] d; - } idma_reg64_2d_hw2reg_done_id_mreg_t; - - // Register -> HW type - typedef struct packed { - idma_reg64_2d_reg2hw_conf_reg_t conf; // [928:912] - idma_reg64_2d_reg2hw_next_id_mreg_t [15:0] next_id; // [911:384] - idma_reg64_2d_reg2hw_dst_addr_low_reg_t dst_addr_low; // [383:352] - idma_reg64_2d_reg2hw_dst_addr_high_reg_t dst_addr_high; // [351:320] - idma_reg64_2d_reg2hw_src_addr_low_reg_t src_addr_low; // [319:288] - idma_reg64_2d_reg2hw_src_addr_high_reg_t src_addr_high; // [287:256] - idma_reg64_2d_reg2hw_length_low_reg_t length_low; // [255:224] - idma_reg64_2d_reg2hw_length_high_reg_t length_high; // [223:192] - idma_reg64_2d_reg2hw_dst_stride_2_low_reg_t dst_stride_2_low; // [191:160] - idma_reg64_2d_reg2hw_dst_stride_2_high_reg_t dst_stride_2_high; // [159:128] - idma_reg64_2d_reg2hw_src_stride_2_low_reg_t src_stride_2_low; // [127:96] - idma_reg64_2d_reg2hw_src_stride_2_high_reg_t src_stride_2_high; // [95:64] - idma_reg64_2d_reg2hw_reps_2_low_reg_t reps_2_low; // [63:32] - idma_reg64_2d_reg2hw_reps_2_high_reg_t reps_2_high; // [31:0] - } idma_reg64_2d_reg2hw_t; - - // HW -> register type - typedef struct packed { - idma_reg64_2d_hw2reg_status_mreg_t [15:0] status; // [1183:1024] - idma_reg64_2d_hw2reg_next_id_mreg_t [15:0] next_id; // [1023:512] - idma_reg64_2d_hw2reg_done_id_mreg_t [15:0] done_id; // [511:0] - } idma_reg64_2d_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] IDMA_REG64_2D_CONF_OFFSET = 8'h 0; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_0_OFFSET = 8'h 4; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_1_OFFSET = 8'h 8; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_2_OFFSET = 8'h c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_3_OFFSET = 8'h 10; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_4_OFFSET = 8'h 14; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_5_OFFSET = 8'h 18; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_6_OFFSET = 8'h 1c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_7_OFFSET = 8'h 20; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_8_OFFSET = 8'h 24; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_9_OFFSET = 8'h 28; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_10_OFFSET = 8'h 2c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_11_OFFSET = 8'h 30; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_12_OFFSET = 8'h 34; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_13_OFFSET = 8'h 38; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_14_OFFSET = 8'h 3c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_STATUS_15_OFFSET = 8'h 40; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_0_OFFSET = 8'h 44; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_1_OFFSET = 8'h 48; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_2_OFFSET = 8'h 4c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_3_OFFSET = 8'h 50; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_4_OFFSET = 8'h 54; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_5_OFFSET = 8'h 58; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_6_OFFSET = 8'h 5c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_7_OFFSET = 8'h 60; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_8_OFFSET = 8'h 64; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_9_OFFSET = 8'h 68; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_10_OFFSET = 8'h 6c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_11_OFFSET = 8'h 70; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_12_OFFSET = 8'h 74; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_13_OFFSET = 8'h 78; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_14_OFFSET = 8'h 7c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_NEXT_ID_15_OFFSET = 8'h 80; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_0_OFFSET = 8'h 84; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_1_OFFSET = 8'h 88; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_2_OFFSET = 8'h 8c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_3_OFFSET = 8'h 90; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_4_OFFSET = 8'h 94; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_5_OFFSET = 8'h 98; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_6_OFFSET = 8'h 9c; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_7_OFFSET = 8'h a0; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_8_OFFSET = 8'h a4; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_9_OFFSET = 8'h a8; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_10_OFFSET = 8'h ac; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_11_OFFSET = 8'h b0; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_12_OFFSET = 8'h b4; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_13_OFFSET = 8'h b8; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_14_OFFSET = 8'h bc; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DONE_ID_15_OFFSET = 8'h c0; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DST_ADDR_LOW_OFFSET = 8'h d0; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DST_ADDR_HIGH_OFFSET = 8'h d4; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_SRC_ADDR_LOW_OFFSET = 8'h d8; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_SRC_ADDR_HIGH_OFFSET = 8'h dc; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_LENGTH_LOW_OFFSET = 8'h e0; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_LENGTH_HIGH_OFFSET = 8'h e4; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DST_STRIDE_2_LOW_OFFSET = 8'h e8; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_DST_STRIDE_2_HIGH_OFFSET = 8'h ec; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_SRC_STRIDE_2_LOW_OFFSET = 8'h f0; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_SRC_STRIDE_2_HIGH_OFFSET = 8'h f4; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_REPS_2_LOW_OFFSET = 8'h f8; - parameter logic [BlockAw-1:0] IDMA_REG64_2D_REPS_2_HIGH_OFFSET = 8'h fc; - - // Reset values for hwext registers and their fields - parameter logic [9:0] IDMA_REG64_2D_STATUS_0_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_1_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_2_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_3_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_4_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_5_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_6_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_7_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_8_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_9_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_10_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_11_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_12_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_13_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_14_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_2D_STATUS_15_RESVAL = 10'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_0_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_1_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_2_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_3_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_4_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_5_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_6_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_7_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_8_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_9_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_10_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_11_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_12_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_13_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_14_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_NEXT_ID_15_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_0_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_1_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_2_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_3_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_4_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_5_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_6_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_7_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_8_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_9_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_10_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_11_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_12_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_13_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_14_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_2D_DONE_ID_15_RESVAL = 32'h 0; - - // Register index - typedef enum int { - IDMA_REG64_2D_CONF, - IDMA_REG64_2D_STATUS_0, - IDMA_REG64_2D_STATUS_1, - IDMA_REG64_2D_STATUS_2, - IDMA_REG64_2D_STATUS_3, - IDMA_REG64_2D_STATUS_4, - IDMA_REG64_2D_STATUS_5, - IDMA_REG64_2D_STATUS_6, - IDMA_REG64_2D_STATUS_7, - IDMA_REG64_2D_STATUS_8, - IDMA_REG64_2D_STATUS_9, - IDMA_REG64_2D_STATUS_10, - IDMA_REG64_2D_STATUS_11, - IDMA_REG64_2D_STATUS_12, - IDMA_REG64_2D_STATUS_13, - IDMA_REG64_2D_STATUS_14, - IDMA_REG64_2D_STATUS_15, - IDMA_REG64_2D_NEXT_ID_0, - IDMA_REG64_2D_NEXT_ID_1, - IDMA_REG64_2D_NEXT_ID_2, - IDMA_REG64_2D_NEXT_ID_3, - IDMA_REG64_2D_NEXT_ID_4, - IDMA_REG64_2D_NEXT_ID_5, - IDMA_REG64_2D_NEXT_ID_6, - IDMA_REG64_2D_NEXT_ID_7, - IDMA_REG64_2D_NEXT_ID_8, - IDMA_REG64_2D_NEXT_ID_9, - IDMA_REG64_2D_NEXT_ID_10, - IDMA_REG64_2D_NEXT_ID_11, - IDMA_REG64_2D_NEXT_ID_12, - IDMA_REG64_2D_NEXT_ID_13, - IDMA_REG64_2D_NEXT_ID_14, - IDMA_REG64_2D_NEXT_ID_15, - IDMA_REG64_2D_DONE_ID_0, - IDMA_REG64_2D_DONE_ID_1, - IDMA_REG64_2D_DONE_ID_2, - IDMA_REG64_2D_DONE_ID_3, - IDMA_REG64_2D_DONE_ID_4, - IDMA_REG64_2D_DONE_ID_5, - IDMA_REG64_2D_DONE_ID_6, - IDMA_REG64_2D_DONE_ID_7, - IDMA_REG64_2D_DONE_ID_8, - IDMA_REG64_2D_DONE_ID_9, - IDMA_REG64_2D_DONE_ID_10, - IDMA_REG64_2D_DONE_ID_11, - IDMA_REG64_2D_DONE_ID_12, - IDMA_REG64_2D_DONE_ID_13, - IDMA_REG64_2D_DONE_ID_14, - IDMA_REG64_2D_DONE_ID_15, - IDMA_REG64_2D_DST_ADDR_LOW, - IDMA_REG64_2D_DST_ADDR_HIGH, - IDMA_REG64_2D_SRC_ADDR_LOW, - IDMA_REG64_2D_SRC_ADDR_HIGH, - IDMA_REG64_2D_LENGTH_LOW, - IDMA_REG64_2D_LENGTH_HIGH, - IDMA_REG64_2D_DST_STRIDE_2_LOW, - IDMA_REG64_2D_DST_STRIDE_2_HIGH, - IDMA_REG64_2D_SRC_STRIDE_2_LOW, - IDMA_REG64_2D_SRC_STRIDE_2_HIGH, - IDMA_REG64_2D_REPS_2_LOW, - IDMA_REG64_2D_REPS_2_HIGH - } idma_reg64_2d_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] IDMA_REG64_2D_PERMIT [61] = '{ - 4'b 0111, // index[ 0] IDMA_REG64_2D_CONF - 4'b 0011, // index[ 1] IDMA_REG64_2D_STATUS_0 - 4'b 0011, // index[ 2] IDMA_REG64_2D_STATUS_1 - 4'b 0011, // index[ 3] IDMA_REG64_2D_STATUS_2 - 4'b 0011, // index[ 4] IDMA_REG64_2D_STATUS_3 - 4'b 0011, // index[ 5] IDMA_REG64_2D_STATUS_4 - 4'b 0011, // index[ 6] IDMA_REG64_2D_STATUS_5 - 4'b 0011, // index[ 7] IDMA_REG64_2D_STATUS_6 - 4'b 0011, // index[ 8] IDMA_REG64_2D_STATUS_7 - 4'b 0011, // index[ 9] IDMA_REG64_2D_STATUS_8 - 4'b 0011, // index[10] IDMA_REG64_2D_STATUS_9 - 4'b 0011, // index[11] IDMA_REG64_2D_STATUS_10 - 4'b 0011, // index[12] IDMA_REG64_2D_STATUS_11 - 4'b 0011, // index[13] IDMA_REG64_2D_STATUS_12 - 4'b 0011, // index[14] IDMA_REG64_2D_STATUS_13 - 4'b 0011, // index[15] IDMA_REG64_2D_STATUS_14 - 4'b 0011, // index[16] IDMA_REG64_2D_STATUS_15 - 4'b 1111, // index[17] IDMA_REG64_2D_NEXT_ID_0 - 4'b 1111, // index[18] IDMA_REG64_2D_NEXT_ID_1 - 4'b 1111, // index[19] IDMA_REG64_2D_NEXT_ID_2 - 4'b 1111, // index[20] IDMA_REG64_2D_NEXT_ID_3 - 4'b 1111, // index[21] IDMA_REG64_2D_NEXT_ID_4 - 4'b 1111, // index[22] IDMA_REG64_2D_NEXT_ID_5 - 4'b 1111, // index[23] IDMA_REG64_2D_NEXT_ID_6 - 4'b 1111, // index[24] IDMA_REG64_2D_NEXT_ID_7 - 4'b 1111, // index[25] IDMA_REG64_2D_NEXT_ID_8 - 4'b 1111, // index[26] IDMA_REG64_2D_NEXT_ID_9 - 4'b 1111, // index[27] IDMA_REG64_2D_NEXT_ID_10 - 4'b 1111, // index[28] IDMA_REG64_2D_NEXT_ID_11 - 4'b 1111, // index[29] IDMA_REG64_2D_NEXT_ID_12 - 4'b 1111, // index[30] IDMA_REG64_2D_NEXT_ID_13 - 4'b 1111, // index[31] IDMA_REG64_2D_NEXT_ID_14 - 4'b 1111, // index[32] IDMA_REG64_2D_NEXT_ID_15 - 4'b 1111, // index[33] IDMA_REG64_2D_DONE_ID_0 - 4'b 1111, // index[34] IDMA_REG64_2D_DONE_ID_1 - 4'b 1111, // index[35] IDMA_REG64_2D_DONE_ID_2 - 4'b 1111, // index[36] IDMA_REG64_2D_DONE_ID_3 - 4'b 1111, // index[37] IDMA_REG64_2D_DONE_ID_4 - 4'b 1111, // index[38] IDMA_REG64_2D_DONE_ID_5 - 4'b 1111, // index[39] IDMA_REG64_2D_DONE_ID_6 - 4'b 1111, // index[40] IDMA_REG64_2D_DONE_ID_7 - 4'b 1111, // index[41] IDMA_REG64_2D_DONE_ID_8 - 4'b 1111, // index[42] IDMA_REG64_2D_DONE_ID_9 - 4'b 1111, // index[43] IDMA_REG64_2D_DONE_ID_10 - 4'b 1111, // index[44] IDMA_REG64_2D_DONE_ID_11 - 4'b 1111, // index[45] IDMA_REG64_2D_DONE_ID_12 - 4'b 1111, // index[46] IDMA_REG64_2D_DONE_ID_13 - 4'b 1111, // index[47] IDMA_REG64_2D_DONE_ID_14 - 4'b 1111, // index[48] IDMA_REG64_2D_DONE_ID_15 - 4'b 1111, // index[49] IDMA_REG64_2D_DST_ADDR_LOW - 4'b 1111, // index[50] IDMA_REG64_2D_DST_ADDR_HIGH - 4'b 1111, // index[51] IDMA_REG64_2D_SRC_ADDR_LOW - 4'b 1111, // index[52] IDMA_REG64_2D_SRC_ADDR_HIGH - 4'b 1111, // index[53] IDMA_REG64_2D_LENGTH_LOW - 4'b 1111, // index[54] IDMA_REG64_2D_LENGTH_HIGH - 4'b 1111, // index[55] IDMA_REG64_2D_DST_STRIDE_2_LOW - 4'b 1111, // index[56] IDMA_REG64_2D_DST_STRIDE_2_HIGH - 4'b 1111, // index[57] IDMA_REG64_2D_SRC_STRIDE_2_LOW - 4'b 1111, // index[58] IDMA_REG64_2D_SRC_STRIDE_2_HIGH - 4'b 1111, // index[59] IDMA_REG64_2D_REPS_2_LOW - 4'b 1111 // index[60] IDMA_REG64_2D_REPS_2_HIGH - }; - -endpackage - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Package auto-generated by `reggen` containing data structure - -package idma_reg64_1d_reg_pkg; - - // Param list - parameter int num_dims = 1; - - // Address widths within the block - parameter int BlockAw = 8; - - //////////////////////////// - // Typedefs for registers // - //////////////////////////// - - typedef struct packed { - struct packed { - logic q; - } decouple_aw; - struct packed { - logic q; - } decouple_rw; - struct packed { - logic q; - } src_reduce_len; - struct packed { - logic q; - } dst_reduce_len; - struct packed { - logic [2:0] q; - } src_max_llen; - struct packed { - logic [2:0] q; - } dst_max_llen; - struct packed { - logic q; - } enable_nd; - struct packed { - logic [2:0] q; - } src_protocol; - struct packed { - logic [2:0] q; - } dst_protocol; - } idma_reg64_1d_reg2hw_conf_reg_t; - - typedef struct packed { - logic [31:0] q; - logic re; - } idma_reg64_1d_reg2hw_next_id_mreg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_1d_reg2hw_dst_addr_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_1d_reg2hw_dst_addr_high_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_1d_reg2hw_src_addr_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_1d_reg2hw_src_addr_high_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_1d_reg2hw_length_low_reg_t; - - typedef struct packed { - logic [31:0] q; - } idma_reg64_1d_reg2hw_length_high_reg_t; - - typedef struct packed { - logic [9:0] d; - } idma_reg64_1d_hw2reg_status_mreg_t; - - typedef struct packed { - logic [31:0] d; - } idma_reg64_1d_hw2reg_next_id_mreg_t; - - typedef struct packed { - logic [31:0] d; - } idma_reg64_1d_hw2reg_done_id_mreg_t; - - // Register -> HW type - typedef struct packed { - idma_reg64_1d_reg2hw_conf_reg_t conf; // [736:720] - idma_reg64_1d_reg2hw_next_id_mreg_t [15:0] next_id; // [719:192] - idma_reg64_1d_reg2hw_dst_addr_low_reg_t dst_addr_low; // [191:160] - idma_reg64_1d_reg2hw_dst_addr_high_reg_t dst_addr_high; // [159:128] - idma_reg64_1d_reg2hw_src_addr_low_reg_t src_addr_low; // [127:96] - idma_reg64_1d_reg2hw_src_addr_high_reg_t src_addr_high; // [95:64] - idma_reg64_1d_reg2hw_length_low_reg_t length_low; // [63:32] - idma_reg64_1d_reg2hw_length_high_reg_t length_high; // [31:0] - } idma_reg64_1d_reg2hw_t; - - // HW -> register type - typedef struct packed { - idma_reg64_1d_hw2reg_status_mreg_t [15:0] status; // [1183:1024] - idma_reg64_1d_hw2reg_next_id_mreg_t [15:0] next_id; // [1023:512] - idma_reg64_1d_hw2reg_done_id_mreg_t [15:0] done_id; // [511:0] - } idma_reg64_1d_hw2reg_t; - - // Register offsets - parameter logic [BlockAw-1:0] IDMA_REG64_1D_CONF_OFFSET = 8'h 0; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_0_OFFSET = 8'h 4; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_1_OFFSET = 8'h 8; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_2_OFFSET = 8'h c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_3_OFFSET = 8'h 10; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_4_OFFSET = 8'h 14; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_5_OFFSET = 8'h 18; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_6_OFFSET = 8'h 1c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_7_OFFSET = 8'h 20; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_8_OFFSET = 8'h 24; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_9_OFFSET = 8'h 28; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_10_OFFSET = 8'h 2c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_11_OFFSET = 8'h 30; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_12_OFFSET = 8'h 34; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_13_OFFSET = 8'h 38; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_14_OFFSET = 8'h 3c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_STATUS_15_OFFSET = 8'h 40; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_0_OFFSET = 8'h 44; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_1_OFFSET = 8'h 48; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_2_OFFSET = 8'h 4c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_3_OFFSET = 8'h 50; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_4_OFFSET = 8'h 54; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_5_OFFSET = 8'h 58; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_6_OFFSET = 8'h 5c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_7_OFFSET = 8'h 60; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_8_OFFSET = 8'h 64; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_9_OFFSET = 8'h 68; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_10_OFFSET = 8'h 6c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_11_OFFSET = 8'h 70; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_12_OFFSET = 8'h 74; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_13_OFFSET = 8'h 78; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_14_OFFSET = 8'h 7c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_NEXT_ID_15_OFFSET = 8'h 80; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_0_OFFSET = 8'h 84; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_1_OFFSET = 8'h 88; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_2_OFFSET = 8'h 8c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_3_OFFSET = 8'h 90; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_4_OFFSET = 8'h 94; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_5_OFFSET = 8'h 98; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_6_OFFSET = 8'h 9c; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_7_OFFSET = 8'h a0; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_8_OFFSET = 8'h a4; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_9_OFFSET = 8'h a8; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_10_OFFSET = 8'h ac; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_11_OFFSET = 8'h b0; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_12_OFFSET = 8'h b4; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_13_OFFSET = 8'h b8; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_14_OFFSET = 8'h bc; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DONE_ID_15_OFFSET = 8'h c0; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DST_ADDR_LOW_OFFSET = 8'h d0; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_DST_ADDR_HIGH_OFFSET = 8'h d4; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_SRC_ADDR_LOW_OFFSET = 8'h d8; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_SRC_ADDR_HIGH_OFFSET = 8'h dc; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_LENGTH_LOW_OFFSET = 8'h e0; - parameter logic [BlockAw-1:0] IDMA_REG64_1D_LENGTH_HIGH_OFFSET = 8'h e4; - - // Reset values for hwext registers and their fields - parameter logic [9:0] IDMA_REG64_1D_STATUS_0_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_1_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_2_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_3_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_4_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_5_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_6_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_7_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_8_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_9_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_10_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_11_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_12_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_13_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_14_RESVAL = 10'h 0; - parameter logic [9:0] IDMA_REG64_1D_STATUS_15_RESVAL = 10'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_0_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_1_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_2_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_3_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_4_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_5_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_6_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_7_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_8_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_9_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_10_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_11_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_12_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_13_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_14_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_NEXT_ID_15_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_0_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_1_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_2_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_3_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_4_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_5_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_6_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_7_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_8_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_9_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_10_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_11_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_12_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_13_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_14_RESVAL = 32'h 0; - parameter logic [31:0] IDMA_REG64_1D_DONE_ID_15_RESVAL = 32'h 0; - - // Register index - typedef enum int { - IDMA_REG64_1D_CONF, - IDMA_REG64_1D_STATUS_0, - IDMA_REG64_1D_STATUS_1, - IDMA_REG64_1D_STATUS_2, - IDMA_REG64_1D_STATUS_3, - IDMA_REG64_1D_STATUS_4, - IDMA_REG64_1D_STATUS_5, - IDMA_REG64_1D_STATUS_6, - IDMA_REG64_1D_STATUS_7, - IDMA_REG64_1D_STATUS_8, - IDMA_REG64_1D_STATUS_9, - IDMA_REG64_1D_STATUS_10, - IDMA_REG64_1D_STATUS_11, - IDMA_REG64_1D_STATUS_12, - IDMA_REG64_1D_STATUS_13, - IDMA_REG64_1D_STATUS_14, - IDMA_REG64_1D_STATUS_15, - IDMA_REG64_1D_NEXT_ID_0, - IDMA_REG64_1D_NEXT_ID_1, - IDMA_REG64_1D_NEXT_ID_2, - IDMA_REG64_1D_NEXT_ID_3, - IDMA_REG64_1D_NEXT_ID_4, - IDMA_REG64_1D_NEXT_ID_5, - IDMA_REG64_1D_NEXT_ID_6, - IDMA_REG64_1D_NEXT_ID_7, - IDMA_REG64_1D_NEXT_ID_8, - IDMA_REG64_1D_NEXT_ID_9, - IDMA_REG64_1D_NEXT_ID_10, - IDMA_REG64_1D_NEXT_ID_11, - IDMA_REG64_1D_NEXT_ID_12, - IDMA_REG64_1D_NEXT_ID_13, - IDMA_REG64_1D_NEXT_ID_14, - IDMA_REG64_1D_NEXT_ID_15, - IDMA_REG64_1D_DONE_ID_0, - IDMA_REG64_1D_DONE_ID_1, - IDMA_REG64_1D_DONE_ID_2, - IDMA_REG64_1D_DONE_ID_3, - IDMA_REG64_1D_DONE_ID_4, - IDMA_REG64_1D_DONE_ID_5, - IDMA_REG64_1D_DONE_ID_6, - IDMA_REG64_1D_DONE_ID_7, - IDMA_REG64_1D_DONE_ID_8, - IDMA_REG64_1D_DONE_ID_9, - IDMA_REG64_1D_DONE_ID_10, - IDMA_REG64_1D_DONE_ID_11, - IDMA_REG64_1D_DONE_ID_12, - IDMA_REG64_1D_DONE_ID_13, - IDMA_REG64_1D_DONE_ID_14, - IDMA_REG64_1D_DONE_ID_15, - IDMA_REG64_1D_DST_ADDR_LOW, - IDMA_REG64_1D_DST_ADDR_HIGH, - IDMA_REG64_1D_SRC_ADDR_LOW, - IDMA_REG64_1D_SRC_ADDR_HIGH, - IDMA_REG64_1D_LENGTH_LOW, - IDMA_REG64_1D_LENGTH_HIGH - } idma_reg64_1d_id_e; - - // Register width information to check illegal writes - parameter logic [3:0] IDMA_REG64_1D_PERMIT [55] = '{ - 4'b 0111, // index[ 0] IDMA_REG64_1D_CONF - 4'b 0011, // index[ 1] IDMA_REG64_1D_STATUS_0 - 4'b 0011, // index[ 2] IDMA_REG64_1D_STATUS_1 - 4'b 0011, // index[ 3] IDMA_REG64_1D_STATUS_2 - 4'b 0011, // index[ 4] IDMA_REG64_1D_STATUS_3 - 4'b 0011, // index[ 5] IDMA_REG64_1D_STATUS_4 - 4'b 0011, // index[ 6] IDMA_REG64_1D_STATUS_5 - 4'b 0011, // index[ 7] IDMA_REG64_1D_STATUS_6 - 4'b 0011, // index[ 8] IDMA_REG64_1D_STATUS_7 - 4'b 0011, // index[ 9] IDMA_REG64_1D_STATUS_8 - 4'b 0011, // index[10] IDMA_REG64_1D_STATUS_9 - 4'b 0011, // index[11] IDMA_REG64_1D_STATUS_10 - 4'b 0011, // index[12] IDMA_REG64_1D_STATUS_11 - 4'b 0011, // index[13] IDMA_REG64_1D_STATUS_12 - 4'b 0011, // index[14] IDMA_REG64_1D_STATUS_13 - 4'b 0011, // index[15] IDMA_REG64_1D_STATUS_14 - 4'b 0011, // index[16] IDMA_REG64_1D_STATUS_15 - 4'b 1111, // index[17] IDMA_REG64_1D_NEXT_ID_0 - 4'b 1111, // index[18] IDMA_REG64_1D_NEXT_ID_1 - 4'b 1111, // index[19] IDMA_REG64_1D_NEXT_ID_2 - 4'b 1111, // index[20] IDMA_REG64_1D_NEXT_ID_3 - 4'b 1111, // index[21] IDMA_REG64_1D_NEXT_ID_4 - 4'b 1111, // index[22] IDMA_REG64_1D_NEXT_ID_5 - 4'b 1111, // index[23] IDMA_REG64_1D_NEXT_ID_6 - 4'b 1111, // index[24] IDMA_REG64_1D_NEXT_ID_7 - 4'b 1111, // index[25] IDMA_REG64_1D_NEXT_ID_8 - 4'b 1111, // index[26] IDMA_REG64_1D_NEXT_ID_9 - 4'b 1111, // index[27] IDMA_REG64_1D_NEXT_ID_10 - 4'b 1111, // index[28] IDMA_REG64_1D_NEXT_ID_11 - 4'b 1111, // index[29] IDMA_REG64_1D_NEXT_ID_12 - 4'b 1111, // index[30] IDMA_REG64_1D_NEXT_ID_13 - 4'b 1111, // index[31] IDMA_REG64_1D_NEXT_ID_14 - 4'b 1111, // index[32] IDMA_REG64_1D_NEXT_ID_15 - 4'b 1111, // index[33] IDMA_REG64_1D_DONE_ID_0 - 4'b 1111, // index[34] IDMA_REG64_1D_DONE_ID_1 - 4'b 1111, // index[35] IDMA_REG64_1D_DONE_ID_2 - 4'b 1111, // index[36] IDMA_REG64_1D_DONE_ID_3 - 4'b 1111, // index[37] IDMA_REG64_1D_DONE_ID_4 - 4'b 1111, // index[38] IDMA_REG64_1D_DONE_ID_5 - 4'b 1111, // index[39] IDMA_REG64_1D_DONE_ID_6 - 4'b 1111, // index[40] IDMA_REG64_1D_DONE_ID_7 - 4'b 1111, // index[41] IDMA_REG64_1D_DONE_ID_8 - 4'b 1111, // index[42] IDMA_REG64_1D_DONE_ID_9 - 4'b 1111, // index[43] IDMA_REG64_1D_DONE_ID_10 - 4'b 1111, // index[44] IDMA_REG64_1D_DONE_ID_11 - 4'b 1111, // index[45] IDMA_REG64_1D_DONE_ID_12 - 4'b 1111, // index[46] IDMA_REG64_1D_DONE_ID_13 - 4'b 1111, // index[47] IDMA_REG64_1D_DONE_ID_14 - 4'b 1111, // index[48] IDMA_REG64_1D_DONE_ID_15 - 4'b 1111, // index[49] IDMA_REG64_1D_DST_ADDR_LOW - 4'b 1111, // index[50] IDMA_REG64_1D_DST_ADDR_HIGH - 4'b 1111, // index[51] IDMA_REG64_1D_SRC_ADDR_LOW - 4'b 1111, // index[52] IDMA_REG64_1D_SRC_ADDR_HIGH - 4'b 1111, // index[53] IDMA_REG64_1D_LENGTH_LOW - 4'b 1111 // index[54] IDMA_REG64_1D_LENGTH_HIGH - }; - -endpackage - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module idma_desc64_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 4 -) ( - input logic clk_i, - input logic rst_ni, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - // To HW - output idma_desc64_reg_pkg::idma_desc64_reg2hw_t reg2hw, // Write - input idma_desc64_reg_pkg::idma_desc64_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import idma_desc64_reg_pkg::* ; - - localparam int DW = 64; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [BlockAw-1:0] reg_addr; - logic [DW-1:0] reg_wdata; - logic [DBW-1:0] reg_be; - logic [DW-1:0] reg_rdata; - logic reg_error; - - logic addrmiss, wr_err; - - logic [DW-1:0] reg_rdata_next; - - // Below register interface can be changed - reg_req_t reg_intf_req; - reg_rsp_t reg_intf_rsp; - - - assign reg_intf_req = reg_req_i; - assign reg_rsp_o = reg_intf_rsp; - - - assign reg_we = reg_intf_req.valid & reg_intf_req.write; - assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; - assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; - assign reg_wdata = reg_intf_req.wdata; - assign reg_be = reg_intf_req.wstrb; - assign reg_intf_rsp.rdata = reg_rdata; - assign reg_intf_rsp.error = reg_error; - assign reg_intf_rsp.ready = 1'b1; - - assign reg_rdata = reg_rdata_next ; - assign reg_error = (devmode_i & addrmiss) | wr_err; - - - // Define SW related signals - // Format: __{wd|we|qs} - // or _{wd|we|qs} if field == 1 or 0 - logic [63:0] desc_addr_wd; - logic desc_addr_we; - logic status_busy_qs; - logic status_fifo_full_qs; - - // Register instances - // R[desc_addr]: V(False) - - prim_subreg #( - .DW (64), - .SWACCESS("WO"), - .RESVAL (64'hffffffffffffffff) - ) u_desc_addr ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (desc_addr_we), - .wd (desc_addr_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (reg2hw.desc_addr.qe), - .q (reg2hw.desc_addr.q ), - - .qs () - ); - - - // R[status]: V(False) - - // F[busy]: 0:0 - prim_subreg #( - .DW (1), - .SWACCESS("RO"), - .RESVAL (1'h0) - ) u_status_busy ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - .we (1'b0), - .wd ('0 ), - - // from internal hardware - .de (hw2reg.status.busy.de), - .d (hw2reg.status.busy.d ), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (status_busy_qs) - ); - - - // F[fifo_full]: 1:1 - prim_subreg #( - .DW (1), - .SWACCESS("RO"), - .RESVAL (1'h0) - ) u_status_fifo_full ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - .we (1'b0), - .wd ('0 ), - - // from internal hardware - .de (hw2reg.status.fifo_full.de), - .d (hw2reg.status.fifo_full.d ), - - // to internal hardware - .qe (), - .q (), - - // to register interface (read) - .qs (status_fifo_full_qs) - ); - - - - - logic [1:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[0] = (reg_addr == IDMA_DESC64_DESC_ADDR_OFFSET); - addr_hit[1] = (reg_addr == IDMA_DESC64_STATUS_OFFSET); - end - - assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; - - // Check sub-word write is permitted - always_comb begin - wr_err = (reg_we & - ((addr_hit[0] & (|(IDMA_DESC64_PERMIT[0] & ~reg_be))) | - (addr_hit[1] & (|(IDMA_DESC64_PERMIT[1] & ~reg_be))))); - end - - assign desc_addr_we = addr_hit[0] & reg_we & !reg_error; - assign desc_addr_wd = reg_wdata[63:0]; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[63:0] = '0; - end - - addr_hit[1]: begin - reg_rdata_next[0] = status_busy_qs; - reg_rdata_next[1] = status_fifo_full_qs; - end - - default: begin - reg_rdata_next = '1; - end - endcase - end - - // Unused signal tieoff - - // wdata / byte enable are not always fully used - // add a blanket unused statement to handle lint waivers - logic unused_wdata; - logic unused_be; - assign unused_wdata = ^reg_wdata; - assign unused_be = ^reg_be; - - // Assertions for Register Interface - `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) - -endmodule - -module idma_desc64_reg_top_intf -#( - parameter int AW = 4, - localparam int DW = 64 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output idma_desc64_reg_pkg::idma_desc64_reg2hw_t reg2hw, // Write - input idma_desc64_reg_pkg::idma_desc64_hw2reg_t hw2reg, // Read - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - localparam int unsigned STRB_WIDTH = DW/8; - -`include "register_interface/typedef.svh" -`include "register_interface/assign.svh" - - // Define structs for reg_bus - typedef logic [AW-1:0] addr_t; - typedef logic [DW-1:0] data_t; - typedef logic [STRB_WIDTH-1:0] strb_t; - `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) - - reg_bus_req_t s_reg_req; - reg_bus_rsp_t s_reg_rsp; - - // Assign SV interface to structs - `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) - `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) - - - - idma_desc64_reg_top #( - .reg_req_t(reg_bus_req_t), - .reg_rsp_t(reg_bus_rsp_t), - .AW(AW) - ) i_regs ( - .clk_i, - .rst_ni, - .reg_req_i(s_reg_req), - .reg_rsp_o(s_reg_rsp), - .reg2hw, // Write - .hw2reg, // Read - .devmode_i - ); - -endmodule - - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module idma_reg32_3d_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 9 -) ( - input logic clk_i, - input logic rst_ni, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - // To HW - output idma_reg32_3d_reg_pkg::idma_reg32_3d_reg2hw_t reg2hw, // Write - input idma_reg32_3d_reg_pkg::idma_reg32_3d_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import idma_reg32_3d_reg_pkg::* ; - - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [BlockAw-1:0] reg_addr; - logic [DW-1:0] reg_wdata; - logic [DBW-1:0] reg_be; - logic [DW-1:0] reg_rdata; - logic reg_error; - - logic addrmiss, wr_err; - - logic [DW-1:0] reg_rdata_next; - - // Below register interface can be changed - reg_req_t reg_intf_req; - reg_rsp_t reg_intf_rsp; - - - assign reg_intf_req = reg_req_i; - assign reg_rsp_o = reg_intf_rsp; - - - assign reg_we = reg_intf_req.valid & reg_intf_req.write; - assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; - assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; - assign reg_wdata = reg_intf_req.wdata; - assign reg_be = reg_intf_req.wstrb; - assign reg_intf_rsp.rdata = reg_rdata; - assign reg_intf_rsp.error = reg_error; - assign reg_intf_rsp.ready = 1'b1; - - assign reg_rdata = reg_rdata_next ; - assign reg_error = (devmode_i & addrmiss) | wr_err; - - - // Define SW related signals - // Format: __{wd|we|qs} - // or _{wd|we|qs} if field == 1 or 0 - logic conf_decouple_aw_qs; - logic conf_decouple_aw_wd; - logic conf_decouple_aw_we; - logic conf_decouple_rw_qs; - logic conf_decouple_rw_wd; - logic conf_decouple_rw_we; - logic conf_src_reduce_len_qs; - logic conf_src_reduce_len_wd; - logic conf_src_reduce_len_we; - logic conf_dst_reduce_len_qs; - logic conf_dst_reduce_len_wd; - logic conf_dst_reduce_len_we; - logic [2:0] conf_src_max_llen_qs; - logic [2:0] conf_src_max_llen_wd; - logic conf_src_max_llen_we; - logic [2:0] conf_dst_max_llen_qs; - logic [2:0] conf_dst_max_llen_wd; - logic conf_dst_max_llen_we; - logic [1:0] conf_enable_nd_qs; - logic [1:0] conf_enable_nd_wd; - logic conf_enable_nd_we; - logic [2:0] conf_src_protocol_qs; - logic [2:0] conf_src_protocol_wd; - logic conf_src_protocol_we; - logic [2:0] conf_dst_protocol_qs; - logic [2:0] conf_dst_protocol_wd; - logic conf_dst_protocol_we; - logic [9:0] status_0_qs; - logic status_0_re; - logic [9:0] status_1_qs; - logic status_1_re; - logic [9:0] status_2_qs; - logic status_2_re; - logic [9:0] status_3_qs; - logic status_3_re; - logic [9:0] status_4_qs; - logic status_4_re; - logic [9:0] status_5_qs; - logic status_5_re; - logic [9:0] status_6_qs; - logic status_6_re; - logic [9:0] status_7_qs; - logic status_7_re; - logic [9:0] status_8_qs; - logic status_8_re; - logic [9:0] status_9_qs; - logic status_9_re; - logic [9:0] status_10_qs; - logic status_10_re; - logic [9:0] status_11_qs; - logic status_11_re; - logic [9:0] status_12_qs; - logic status_12_re; - logic [9:0] status_13_qs; - logic status_13_re; - logic [9:0] status_14_qs; - logic status_14_re; - logic [9:0] status_15_qs; - logic status_15_re; - logic [31:0] next_id_0_qs; - logic next_id_0_re; - logic [31:0] next_id_1_qs; - logic next_id_1_re; - logic [31:0] next_id_2_qs; - logic next_id_2_re; - logic [31:0] next_id_3_qs; - logic next_id_3_re; - logic [31:0] next_id_4_qs; - logic next_id_4_re; - logic [31:0] next_id_5_qs; - logic next_id_5_re; - logic [31:0] next_id_6_qs; - logic next_id_6_re; - logic [31:0] next_id_7_qs; - logic next_id_7_re; - logic [31:0] next_id_8_qs; - logic next_id_8_re; - logic [31:0] next_id_9_qs; - logic next_id_9_re; - logic [31:0] next_id_10_qs; - logic next_id_10_re; - logic [31:0] next_id_11_qs; - logic next_id_11_re; - logic [31:0] next_id_12_qs; - logic next_id_12_re; - logic [31:0] next_id_13_qs; - logic next_id_13_re; - logic [31:0] next_id_14_qs; - logic next_id_14_re; - logic [31:0] next_id_15_qs; - logic next_id_15_re; - logic [31:0] done_id_0_qs; - logic done_id_0_re; - logic [31:0] done_id_1_qs; - logic done_id_1_re; - logic [31:0] done_id_2_qs; - logic done_id_2_re; - logic [31:0] done_id_3_qs; - logic done_id_3_re; - logic [31:0] done_id_4_qs; - logic done_id_4_re; - logic [31:0] done_id_5_qs; - logic done_id_5_re; - logic [31:0] done_id_6_qs; - logic done_id_6_re; - logic [31:0] done_id_7_qs; - logic done_id_7_re; - logic [31:0] done_id_8_qs; - logic done_id_8_re; - logic [31:0] done_id_9_qs; - logic done_id_9_re; - logic [31:0] done_id_10_qs; - logic done_id_10_re; - logic [31:0] done_id_11_qs; - logic done_id_11_re; - logic [31:0] done_id_12_qs; - logic done_id_12_re; - logic [31:0] done_id_13_qs; - logic done_id_13_re; - logic [31:0] done_id_14_qs; - logic done_id_14_re; - logic [31:0] done_id_15_qs; - logic done_id_15_re; - logic [31:0] dst_addr_low_qs; - logic [31:0] dst_addr_low_wd; - logic dst_addr_low_we; - logic [31:0] src_addr_low_qs; - logic [31:0] src_addr_low_wd; - logic src_addr_low_we; - logic [31:0] length_low_qs; - logic [31:0] length_low_wd; - logic length_low_we; - logic [31:0] dst_stride_2_low_qs; - logic [31:0] dst_stride_2_low_wd; - logic dst_stride_2_low_we; - logic [31:0] src_stride_2_low_qs; - logic [31:0] src_stride_2_low_wd; - logic src_stride_2_low_we; - logic [31:0] reps_2_low_qs; - logic [31:0] reps_2_low_wd; - logic reps_2_low_we; - logic [31:0] dst_stride_3_low_qs; - logic [31:0] dst_stride_3_low_wd; - logic dst_stride_3_low_we; - logic [31:0] src_stride_3_low_qs; - logic [31:0] src_stride_3_low_wd; - logic src_stride_3_low_we; - logic [31:0] reps_3_low_qs; - logic [31:0] reps_3_low_wd; - logic reps_3_low_we; - - // Register instances - // R[conf]: V(False) - - // F[decouple_aw]: 0:0 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_decouple_aw ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_decouple_aw_we), - .wd (conf_decouple_aw_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.decouple_aw.q ), - - // to register interface (read) - .qs (conf_decouple_aw_qs) - ); - - - // F[decouple_rw]: 1:1 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_decouple_rw ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_decouple_rw_we), - .wd (conf_decouple_rw_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.decouple_rw.q ), - - // to register interface (read) - .qs (conf_decouple_rw_qs) - ); - - - // F[src_reduce_len]: 2:2 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_src_reduce_len ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_reduce_len_we), - .wd (conf_src_reduce_len_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_reduce_len.q ), - - // to register interface (read) - .qs (conf_src_reduce_len_qs) - ); - - - // F[dst_reduce_len]: 3:3 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_dst_reduce_len ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_reduce_len_we), - .wd (conf_dst_reduce_len_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_reduce_len.q ), - - // to register interface (read) - .qs (conf_dst_reduce_len_qs) - ); - - - // F[src_max_llen]: 6:4 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_src_max_llen ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_max_llen_we), - .wd (conf_src_max_llen_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_max_llen.q ), - - // to register interface (read) - .qs (conf_src_max_llen_qs) - ); - - - // F[dst_max_llen]: 9:7 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_dst_max_llen ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_max_llen_we), - .wd (conf_dst_max_llen_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_max_llen.q ), - - // to register interface (read) - .qs (conf_dst_max_llen_qs) - ); - - - // F[enable_nd]: 11:10 - prim_subreg #( - .DW (2), - .SWACCESS("RW"), - .RESVAL (2'h0) - ) u_conf_enable_nd ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_enable_nd_we), - .wd (conf_enable_nd_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.enable_nd.q ), - - // to register interface (read) - .qs (conf_enable_nd_qs) - ); - - - // F[src_protocol]: 14:12 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_src_protocol ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_protocol_we), - .wd (conf_src_protocol_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_protocol.q ), - - // to register interface (read) - .qs (conf_src_protocol_qs) - ); - - - // F[dst_protocol]: 17:15 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_dst_protocol ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_protocol_we), - .wd (conf_dst_protocol_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_protocol.q ), - - // to register interface (read) - .qs (conf_dst_protocol_qs) - ); - - - - // Subregister 0 of Multireg status - // R[status_0]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_0 ( - .re (status_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[0].d), - .qre (), - .qe (), - .q (), - .qs (status_0_qs) - ); - - // Subregister 1 of Multireg status - // R[status_1]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_1 ( - .re (status_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[1].d), - .qre (), - .qe (), - .q (), - .qs (status_1_qs) - ); - - // Subregister 2 of Multireg status - // R[status_2]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_2 ( - .re (status_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[2].d), - .qre (), - .qe (), - .q (), - .qs (status_2_qs) - ); - - // Subregister 3 of Multireg status - // R[status_3]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_3 ( - .re (status_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[3].d), - .qre (), - .qe (), - .q (), - .qs (status_3_qs) - ); - - // Subregister 4 of Multireg status - // R[status_4]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_4 ( - .re (status_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[4].d), - .qre (), - .qe (), - .q (), - .qs (status_4_qs) - ); - - // Subregister 5 of Multireg status - // R[status_5]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_5 ( - .re (status_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[5].d), - .qre (), - .qe (), - .q (), - .qs (status_5_qs) - ); - - // Subregister 6 of Multireg status - // R[status_6]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_6 ( - .re (status_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[6].d), - .qre (), - .qe (), - .q (), - .qs (status_6_qs) - ); - - // Subregister 7 of Multireg status - // R[status_7]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_7 ( - .re (status_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[7].d), - .qre (), - .qe (), - .q (), - .qs (status_7_qs) - ); - - // Subregister 8 of Multireg status - // R[status_8]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_8 ( - .re (status_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[8].d), - .qre (), - .qe (), - .q (), - .qs (status_8_qs) - ); - - // Subregister 9 of Multireg status - // R[status_9]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_9 ( - .re (status_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[9].d), - .qre (), - .qe (), - .q (), - .qs (status_9_qs) - ); - - // Subregister 10 of Multireg status - // R[status_10]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_10 ( - .re (status_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[10].d), - .qre (), - .qe (), - .q (), - .qs (status_10_qs) - ); - - // Subregister 11 of Multireg status - // R[status_11]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_11 ( - .re (status_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[11].d), - .qre (), - .qe (), - .q (), - .qs (status_11_qs) - ); - - // Subregister 12 of Multireg status - // R[status_12]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_12 ( - .re (status_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[12].d), - .qre (), - .qe (), - .q (), - .qs (status_12_qs) - ); - - // Subregister 13 of Multireg status - // R[status_13]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_13 ( - .re (status_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[13].d), - .qre (), - .qe (), - .q (), - .qs (status_13_qs) - ); - - // Subregister 14 of Multireg status - // R[status_14]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_14 ( - .re (status_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[14].d), - .qre (), - .qe (), - .q (), - .qs (status_14_qs) - ); - - // Subregister 15 of Multireg status - // R[status_15]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_15 ( - .re (status_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[15].d), - .qre (), - .qe (), - .q (), - .qs (status_15_qs) - ); - - - - // Subregister 0 of Multireg next_id - // R[next_id_0]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_0 ( - .re (next_id_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[0].d), - .qre (reg2hw.next_id[0].re), - .qe (), - .q (reg2hw.next_id[0].q ), - .qs (next_id_0_qs) - ); - - // Subregister 1 of Multireg next_id - // R[next_id_1]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_1 ( - .re (next_id_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[1].d), - .qre (reg2hw.next_id[1].re), - .qe (), - .q (reg2hw.next_id[1].q ), - .qs (next_id_1_qs) - ); - - // Subregister 2 of Multireg next_id - // R[next_id_2]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_2 ( - .re (next_id_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[2].d), - .qre (reg2hw.next_id[2].re), - .qe (), - .q (reg2hw.next_id[2].q ), - .qs (next_id_2_qs) - ); - - // Subregister 3 of Multireg next_id - // R[next_id_3]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_3 ( - .re (next_id_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[3].d), - .qre (reg2hw.next_id[3].re), - .qe (), - .q (reg2hw.next_id[3].q ), - .qs (next_id_3_qs) - ); - - // Subregister 4 of Multireg next_id - // R[next_id_4]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_4 ( - .re (next_id_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[4].d), - .qre (reg2hw.next_id[4].re), - .qe (), - .q (reg2hw.next_id[4].q ), - .qs (next_id_4_qs) - ); - - // Subregister 5 of Multireg next_id - // R[next_id_5]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_5 ( - .re (next_id_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[5].d), - .qre (reg2hw.next_id[5].re), - .qe (), - .q (reg2hw.next_id[5].q ), - .qs (next_id_5_qs) - ); - - // Subregister 6 of Multireg next_id - // R[next_id_6]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_6 ( - .re (next_id_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[6].d), - .qre (reg2hw.next_id[6].re), - .qe (), - .q (reg2hw.next_id[6].q ), - .qs (next_id_6_qs) - ); - - // Subregister 7 of Multireg next_id - // R[next_id_7]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_7 ( - .re (next_id_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[7].d), - .qre (reg2hw.next_id[7].re), - .qe (), - .q (reg2hw.next_id[7].q ), - .qs (next_id_7_qs) - ); - - // Subregister 8 of Multireg next_id - // R[next_id_8]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_8 ( - .re (next_id_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[8].d), - .qre (reg2hw.next_id[8].re), - .qe (), - .q (reg2hw.next_id[8].q ), - .qs (next_id_8_qs) - ); - - // Subregister 9 of Multireg next_id - // R[next_id_9]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_9 ( - .re (next_id_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[9].d), - .qre (reg2hw.next_id[9].re), - .qe (), - .q (reg2hw.next_id[9].q ), - .qs (next_id_9_qs) - ); - - // Subregister 10 of Multireg next_id - // R[next_id_10]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_10 ( - .re (next_id_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[10].d), - .qre (reg2hw.next_id[10].re), - .qe (), - .q (reg2hw.next_id[10].q ), - .qs (next_id_10_qs) - ); - - // Subregister 11 of Multireg next_id - // R[next_id_11]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_11 ( - .re (next_id_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[11].d), - .qre (reg2hw.next_id[11].re), - .qe (), - .q (reg2hw.next_id[11].q ), - .qs (next_id_11_qs) - ); - - // Subregister 12 of Multireg next_id - // R[next_id_12]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_12 ( - .re (next_id_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[12].d), - .qre (reg2hw.next_id[12].re), - .qe (), - .q (reg2hw.next_id[12].q ), - .qs (next_id_12_qs) - ); - - // Subregister 13 of Multireg next_id - // R[next_id_13]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_13 ( - .re (next_id_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[13].d), - .qre (reg2hw.next_id[13].re), - .qe (), - .q (reg2hw.next_id[13].q ), - .qs (next_id_13_qs) - ); - - // Subregister 14 of Multireg next_id - // R[next_id_14]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_14 ( - .re (next_id_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[14].d), - .qre (reg2hw.next_id[14].re), - .qe (), - .q (reg2hw.next_id[14].q ), - .qs (next_id_14_qs) - ); - - // Subregister 15 of Multireg next_id - // R[next_id_15]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_15 ( - .re (next_id_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[15].d), - .qre (reg2hw.next_id[15].re), - .qe (), - .q (reg2hw.next_id[15].q ), - .qs (next_id_15_qs) - ); - - - - // Subregister 0 of Multireg done_id - // R[done_id_0]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_0 ( - .re (done_id_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[0].d), - .qre (), - .qe (), - .q (), - .qs (done_id_0_qs) - ); - - // Subregister 1 of Multireg done_id - // R[done_id_1]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_1 ( - .re (done_id_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[1].d), - .qre (), - .qe (), - .q (), - .qs (done_id_1_qs) - ); - - // Subregister 2 of Multireg done_id - // R[done_id_2]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_2 ( - .re (done_id_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[2].d), - .qre (), - .qe (), - .q (), - .qs (done_id_2_qs) - ); - - // Subregister 3 of Multireg done_id - // R[done_id_3]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_3 ( - .re (done_id_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[3].d), - .qre (), - .qe (), - .q (), - .qs (done_id_3_qs) - ); - - // Subregister 4 of Multireg done_id - // R[done_id_4]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_4 ( - .re (done_id_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[4].d), - .qre (), - .qe (), - .q (), - .qs (done_id_4_qs) - ); - - // Subregister 5 of Multireg done_id - // R[done_id_5]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_5 ( - .re (done_id_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[5].d), - .qre (), - .qe (), - .q (), - .qs (done_id_5_qs) - ); - - // Subregister 6 of Multireg done_id - // R[done_id_6]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_6 ( - .re (done_id_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[6].d), - .qre (), - .qe (), - .q (), - .qs (done_id_6_qs) - ); - - // Subregister 7 of Multireg done_id - // R[done_id_7]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_7 ( - .re (done_id_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[7].d), - .qre (), - .qe (), - .q (), - .qs (done_id_7_qs) - ); - - // Subregister 8 of Multireg done_id - // R[done_id_8]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_8 ( - .re (done_id_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[8].d), - .qre (), - .qe (), - .q (), - .qs (done_id_8_qs) - ); - - // Subregister 9 of Multireg done_id - // R[done_id_9]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_9 ( - .re (done_id_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[9].d), - .qre (), - .qe (), - .q (), - .qs (done_id_9_qs) - ); - - // Subregister 10 of Multireg done_id - // R[done_id_10]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_10 ( - .re (done_id_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[10].d), - .qre (), - .qe (), - .q (), - .qs (done_id_10_qs) - ); - - // Subregister 11 of Multireg done_id - // R[done_id_11]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_11 ( - .re (done_id_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[11].d), - .qre (), - .qe (), - .q (), - .qs (done_id_11_qs) - ); - - // Subregister 12 of Multireg done_id - // R[done_id_12]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_12 ( - .re (done_id_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[12].d), - .qre (), - .qe (), - .q (), - .qs (done_id_12_qs) - ); - - // Subregister 13 of Multireg done_id - // R[done_id_13]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_13 ( - .re (done_id_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[13].d), - .qre (), - .qe (), - .q (), - .qs (done_id_13_qs) - ); - - // Subregister 14 of Multireg done_id - // R[done_id_14]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_14 ( - .re (done_id_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[14].d), - .qre (), - .qe (), - .q (), - .qs (done_id_14_qs) - ); - - // Subregister 15 of Multireg done_id - // R[done_id_15]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_15 ( - .re (done_id_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[15].d), - .qre (), - .qe (), - .q (), - .qs (done_id_15_qs) - ); - - - // R[dst_addr_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_addr_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_addr_low_we), - .wd (dst_addr_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_addr_low.q ), - - // to register interface (read) - .qs (dst_addr_low_qs) - ); - - - // R[src_addr_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_addr_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_addr_low_we), - .wd (src_addr_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_addr_low.q ), - - // to register interface (read) - .qs (src_addr_low_qs) - ); - - - // R[length_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_length_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (length_low_we), - .wd (length_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.length_low.q ), - - // to register interface (read) - .qs (length_low_qs) - ); - - - // R[dst_stride_2_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_stride_2_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_stride_2_low_we), - .wd (dst_stride_2_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_stride_2_low.q ), - - // to register interface (read) - .qs (dst_stride_2_low_qs) - ); - - - // R[src_stride_2_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_stride_2_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_stride_2_low_we), - .wd (src_stride_2_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_stride_2_low.q ), - - // to register interface (read) - .qs (src_stride_2_low_qs) - ); - - - // R[reps_2_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_reps_2_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (reps_2_low_we), - .wd (reps_2_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.reps_2_low.q ), - - // to register interface (read) - .qs (reps_2_low_qs) - ); - - - // R[dst_stride_3_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_stride_3_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_stride_3_low_we), - .wd (dst_stride_3_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_stride_3_low.q ), - - // to register interface (read) - .qs (dst_stride_3_low_qs) - ); - - - // R[src_stride_3_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_stride_3_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_stride_3_low_we), - .wd (src_stride_3_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_stride_3_low.q ), - - // to register interface (read) - .qs (src_stride_3_low_qs) - ); - - - // R[reps_3_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_reps_3_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (reps_3_low_we), - .wd (reps_3_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.reps_3_low.q ), - - // to register interface (read) - .qs (reps_3_low_qs) - ); - - - - - logic [57:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[ 0] = (reg_addr == IDMA_REG32_3D_CONF_OFFSET); - addr_hit[ 1] = (reg_addr == IDMA_REG32_3D_STATUS_0_OFFSET); - addr_hit[ 2] = (reg_addr == IDMA_REG32_3D_STATUS_1_OFFSET); - addr_hit[ 3] = (reg_addr == IDMA_REG32_3D_STATUS_2_OFFSET); - addr_hit[ 4] = (reg_addr == IDMA_REG32_3D_STATUS_3_OFFSET); - addr_hit[ 5] = (reg_addr == IDMA_REG32_3D_STATUS_4_OFFSET); - addr_hit[ 6] = (reg_addr == IDMA_REG32_3D_STATUS_5_OFFSET); - addr_hit[ 7] = (reg_addr == IDMA_REG32_3D_STATUS_6_OFFSET); - addr_hit[ 8] = (reg_addr == IDMA_REG32_3D_STATUS_7_OFFSET); - addr_hit[ 9] = (reg_addr == IDMA_REG32_3D_STATUS_8_OFFSET); - addr_hit[10] = (reg_addr == IDMA_REG32_3D_STATUS_9_OFFSET); - addr_hit[11] = (reg_addr == IDMA_REG32_3D_STATUS_10_OFFSET); - addr_hit[12] = (reg_addr == IDMA_REG32_3D_STATUS_11_OFFSET); - addr_hit[13] = (reg_addr == IDMA_REG32_3D_STATUS_12_OFFSET); - addr_hit[14] = (reg_addr == IDMA_REG32_3D_STATUS_13_OFFSET); - addr_hit[15] = (reg_addr == IDMA_REG32_3D_STATUS_14_OFFSET); - addr_hit[16] = (reg_addr == IDMA_REG32_3D_STATUS_15_OFFSET); - addr_hit[17] = (reg_addr == IDMA_REG32_3D_NEXT_ID_0_OFFSET); - addr_hit[18] = (reg_addr == IDMA_REG32_3D_NEXT_ID_1_OFFSET); - addr_hit[19] = (reg_addr == IDMA_REG32_3D_NEXT_ID_2_OFFSET); - addr_hit[20] = (reg_addr == IDMA_REG32_3D_NEXT_ID_3_OFFSET); - addr_hit[21] = (reg_addr == IDMA_REG32_3D_NEXT_ID_4_OFFSET); - addr_hit[22] = (reg_addr == IDMA_REG32_3D_NEXT_ID_5_OFFSET); - addr_hit[23] = (reg_addr == IDMA_REG32_3D_NEXT_ID_6_OFFSET); - addr_hit[24] = (reg_addr == IDMA_REG32_3D_NEXT_ID_7_OFFSET); - addr_hit[25] = (reg_addr == IDMA_REG32_3D_NEXT_ID_8_OFFSET); - addr_hit[26] = (reg_addr == IDMA_REG32_3D_NEXT_ID_9_OFFSET); - addr_hit[27] = (reg_addr == IDMA_REG32_3D_NEXT_ID_10_OFFSET); - addr_hit[28] = (reg_addr == IDMA_REG32_3D_NEXT_ID_11_OFFSET); - addr_hit[29] = (reg_addr == IDMA_REG32_3D_NEXT_ID_12_OFFSET); - addr_hit[30] = (reg_addr == IDMA_REG32_3D_NEXT_ID_13_OFFSET); - addr_hit[31] = (reg_addr == IDMA_REG32_3D_NEXT_ID_14_OFFSET); - addr_hit[32] = (reg_addr == IDMA_REG32_3D_NEXT_ID_15_OFFSET); - addr_hit[33] = (reg_addr == IDMA_REG32_3D_DONE_ID_0_OFFSET); - addr_hit[34] = (reg_addr == IDMA_REG32_3D_DONE_ID_1_OFFSET); - addr_hit[35] = (reg_addr == IDMA_REG32_3D_DONE_ID_2_OFFSET); - addr_hit[36] = (reg_addr == IDMA_REG32_3D_DONE_ID_3_OFFSET); - addr_hit[37] = (reg_addr == IDMA_REG32_3D_DONE_ID_4_OFFSET); - addr_hit[38] = (reg_addr == IDMA_REG32_3D_DONE_ID_5_OFFSET); - addr_hit[39] = (reg_addr == IDMA_REG32_3D_DONE_ID_6_OFFSET); - addr_hit[40] = (reg_addr == IDMA_REG32_3D_DONE_ID_7_OFFSET); - addr_hit[41] = (reg_addr == IDMA_REG32_3D_DONE_ID_8_OFFSET); - addr_hit[42] = (reg_addr == IDMA_REG32_3D_DONE_ID_9_OFFSET); - addr_hit[43] = (reg_addr == IDMA_REG32_3D_DONE_ID_10_OFFSET); - addr_hit[44] = (reg_addr == IDMA_REG32_3D_DONE_ID_11_OFFSET); - addr_hit[45] = (reg_addr == IDMA_REG32_3D_DONE_ID_12_OFFSET); - addr_hit[46] = (reg_addr == IDMA_REG32_3D_DONE_ID_13_OFFSET); - addr_hit[47] = (reg_addr == IDMA_REG32_3D_DONE_ID_14_OFFSET); - addr_hit[48] = (reg_addr == IDMA_REG32_3D_DONE_ID_15_OFFSET); - addr_hit[49] = (reg_addr == IDMA_REG32_3D_DST_ADDR_LOW_OFFSET); - addr_hit[50] = (reg_addr == IDMA_REG32_3D_SRC_ADDR_LOW_OFFSET); - addr_hit[51] = (reg_addr == IDMA_REG32_3D_LENGTH_LOW_OFFSET); - addr_hit[52] = (reg_addr == IDMA_REG32_3D_DST_STRIDE_2_LOW_OFFSET); - addr_hit[53] = (reg_addr == IDMA_REG32_3D_SRC_STRIDE_2_LOW_OFFSET); - addr_hit[54] = (reg_addr == IDMA_REG32_3D_REPS_2_LOW_OFFSET); - addr_hit[55] = (reg_addr == IDMA_REG32_3D_DST_STRIDE_3_LOW_OFFSET); - addr_hit[56] = (reg_addr == IDMA_REG32_3D_SRC_STRIDE_3_LOW_OFFSET); - addr_hit[57] = (reg_addr == IDMA_REG32_3D_REPS_3_LOW_OFFSET); - end - - assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; - - // Check sub-word write is permitted - always_comb begin - wr_err = (reg_we & - ((addr_hit[ 0] & (|(IDMA_REG32_3D_PERMIT[ 0] & ~reg_be))) | - (addr_hit[ 1] & (|(IDMA_REG32_3D_PERMIT[ 1] & ~reg_be))) | - (addr_hit[ 2] & (|(IDMA_REG32_3D_PERMIT[ 2] & ~reg_be))) | - (addr_hit[ 3] & (|(IDMA_REG32_3D_PERMIT[ 3] & ~reg_be))) | - (addr_hit[ 4] & (|(IDMA_REG32_3D_PERMIT[ 4] & ~reg_be))) | - (addr_hit[ 5] & (|(IDMA_REG32_3D_PERMIT[ 5] & ~reg_be))) | - (addr_hit[ 6] & (|(IDMA_REG32_3D_PERMIT[ 6] & ~reg_be))) | - (addr_hit[ 7] & (|(IDMA_REG32_3D_PERMIT[ 7] & ~reg_be))) | - (addr_hit[ 8] & (|(IDMA_REG32_3D_PERMIT[ 8] & ~reg_be))) | - (addr_hit[ 9] & (|(IDMA_REG32_3D_PERMIT[ 9] & ~reg_be))) | - (addr_hit[10] & (|(IDMA_REG32_3D_PERMIT[10] & ~reg_be))) | - (addr_hit[11] & (|(IDMA_REG32_3D_PERMIT[11] & ~reg_be))) | - (addr_hit[12] & (|(IDMA_REG32_3D_PERMIT[12] & ~reg_be))) | - (addr_hit[13] & (|(IDMA_REG32_3D_PERMIT[13] & ~reg_be))) | - (addr_hit[14] & (|(IDMA_REG32_3D_PERMIT[14] & ~reg_be))) | - (addr_hit[15] & (|(IDMA_REG32_3D_PERMIT[15] & ~reg_be))) | - (addr_hit[16] & (|(IDMA_REG32_3D_PERMIT[16] & ~reg_be))) | - (addr_hit[17] & (|(IDMA_REG32_3D_PERMIT[17] & ~reg_be))) | - (addr_hit[18] & (|(IDMA_REG32_3D_PERMIT[18] & ~reg_be))) | - (addr_hit[19] & (|(IDMA_REG32_3D_PERMIT[19] & ~reg_be))) | - (addr_hit[20] & (|(IDMA_REG32_3D_PERMIT[20] & ~reg_be))) | - (addr_hit[21] & (|(IDMA_REG32_3D_PERMIT[21] & ~reg_be))) | - (addr_hit[22] & (|(IDMA_REG32_3D_PERMIT[22] & ~reg_be))) | - (addr_hit[23] & (|(IDMA_REG32_3D_PERMIT[23] & ~reg_be))) | - (addr_hit[24] & (|(IDMA_REG32_3D_PERMIT[24] & ~reg_be))) | - (addr_hit[25] & (|(IDMA_REG32_3D_PERMIT[25] & ~reg_be))) | - (addr_hit[26] & (|(IDMA_REG32_3D_PERMIT[26] & ~reg_be))) | - (addr_hit[27] & (|(IDMA_REG32_3D_PERMIT[27] & ~reg_be))) | - (addr_hit[28] & (|(IDMA_REG32_3D_PERMIT[28] & ~reg_be))) | - (addr_hit[29] & (|(IDMA_REG32_3D_PERMIT[29] & ~reg_be))) | - (addr_hit[30] & (|(IDMA_REG32_3D_PERMIT[30] & ~reg_be))) | - (addr_hit[31] & (|(IDMA_REG32_3D_PERMIT[31] & ~reg_be))) | - (addr_hit[32] & (|(IDMA_REG32_3D_PERMIT[32] & ~reg_be))) | - (addr_hit[33] & (|(IDMA_REG32_3D_PERMIT[33] & ~reg_be))) | - (addr_hit[34] & (|(IDMA_REG32_3D_PERMIT[34] & ~reg_be))) | - (addr_hit[35] & (|(IDMA_REG32_3D_PERMIT[35] & ~reg_be))) | - (addr_hit[36] & (|(IDMA_REG32_3D_PERMIT[36] & ~reg_be))) | - (addr_hit[37] & (|(IDMA_REG32_3D_PERMIT[37] & ~reg_be))) | - (addr_hit[38] & (|(IDMA_REG32_3D_PERMIT[38] & ~reg_be))) | - (addr_hit[39] & (|(IDMA_REG32_3D_PERMIT[39] & ~reg_be))) | - (addr_hit[40] & (|(IDMA_REG32_3D_PERMIT[40] & ~reg_be))) | - (addr_hit[41] & (|(IDMA_REG32_3D_PERMIT[41] & ~reg_be))) | - (addr_hit[42] & (|(IDMA_REG32_3D_PERMIT[42] & ~reg_be))) | - (addr_hit[43] & (|(IDMA_REG32_3D_PERMIT[43] & ~reg_be))) | - (addr_hit[44] & (|(IDMA_REG32_3D_PERMIT[44] & ~reg_be))) | - (addr_hit[45] & (|(IDMA_REG32_3D_PERMIT[45] & ~reg_be))) | - (addr_hit[46] & (|(IDMA_REG32_3D_PERMIT[46] & ~reg_be))) | - (addr_hit[47] & (|(IDMA_REG32_3D_PERMIT[47] & ~reg_be))) | - (addr_hit[48] & (|(IDMA_REG32_3D_PERMIT[48] & ~reg_be))) | - (addr_hit[49] & (|(IDMA_REG32_3D_PERMIT[49] & ~reg_be))) | - (addr_hit[50] & (|(IDMA_REG32_3D_PERMIT[50] & ~reg_be))) | - (addr_hit[51] & (|(IDMA_REG32_3D_PERMIT[51] & ~reg_be))) | - (addr_hit[52] & (|(IDMA_REG32_3D_PERMIT[52] & ~reg_be))) | - (addr_hit[53] & (|(IDMA_REG32_3D_PERMIT[53] & ~reg_be))) | - (addr_hit[54] & (|(IDMA_REG32_3D_PERMIT[54] & ~reg_be))) | - (addr_hit[55] & (|(IDMA_REG32_3D_PERMIT[55] & ~reg_be))) | - (addr_hit[56] & (|(IDMA_REG32_3D_PERMIT[56] & ~reg_be))) | - (addr_hit[57] & (|(IDMA_REG32_3D_PERMIT[57] & ~reg_be))))); - end - - assign conf_decouple_aw_we = addr_hit[0] & reg_we & !reg_error; - assign conf_decouple_aw_wd = reg_wdata[0]; - - assign conf_decouple_rw_we = addr_hit[0] & reg_we & !reg_error; - assign conf_decouple_rw_wd = reg_wdata[1]; - - assign conf_src_reduce_len_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_reduce_len_wd = reg_wdata[2]; - - assign conf_dst_reduce_len_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_reduce_len_wd = reg_wdata[3]; - - assign conf_src_max_llen_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_max_llen_wd = reg_wdata[6:4]; - - assign conf_dst_max_llen_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_max_llen_wd = reg_wdata[9:7]; - - assign conf_enable_nd_we = addr_hit[0] & reg_we & !reg_error; - assign conf_enable_nd_wd = reg_wdata[11:10]; - - assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_protocol_wd = reg_wdata[14:12]; - - assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_protocol_wd = reg_wdata[17:15]; - - assign status_0_re = addr_hit[1] & reg_re & !reg_error; - - assign status_1_re = addr_hit[2] & reg_re & !reg_error; - - assign status_2_re = addr_hit[3] & reg_re & !reg_error; - - assign status_3_re = addr_hit[4] & reg_re & !reg_error; - - assign status_4_re = addr_hit[5] & reg_re & !reg_error; - - assign status_5_re = addr_hit[6] & reg_re & !reg_error; - - assign status_6_re = addr_hit[7] & reg_re & !reg_error; - - assign status_7_re = addr_hit[8] & reg_re & !reg_error; - - assign status_8_re = addr_hit[9] & reg_re & !reg_error; - - assign status_9_re = addr_hit[10] & reg_re & !reg_error; - - assign status_10_re = addr_hit[11] & reg_re & !reg_error; - - assign status_11_re = addr_hit[12] & reg_re & !reg_error; - - assign status_12_re = addr_hit[13] & reg_re & !reg_error; - - assign status_13_re = addr_hit[14] & reg_re & !reg_error; - - assign status_14_re = addr_hit[15] & reg_re & !reg_error; - - assign status_15_re = addr_hit[16] & reg_re & !reg_error; - - assign next_id_0_re = addr_hit[17] & reg_re & !reg_error; - - assign next_id_1_re = addr_hit[18] & reg_re & !reg_error; - - assign next_id_2_re = addr_hit[19] & reg_re & !reg_error; - - assign next_id_3_re = addr_hit[20] & reg_re & !reg_error; - - assign next_id_4_re = addr_hit[21] & reg_re & !reg_error; - - assign next_id_5_re = addr_hit[22] & reg_re & !reg_error; - - assign next_id_6_re = addr_hit[23] & reg_re & !reg_error; - - assign next_id_7_re = addr_hit[24] & reg_re & !reg_error; - - assign next_id_8_re = addr_hit[25] & reg_re & !reg_error; - - assign next_id_9_re = addr_hit[26] & reg_re & !reg_error; - - assign next_id_10_re = addr_hit[27] & reg_re & !reg_error; - - assign next_id_11_re = addr_hit[28] & reg_re & !reg_error; - - assign next_id_12_re = addr_hit[29] & reg_re & !reg_error; - - assign next_id_13_re = addr_hit[30] & reg_re & !reg_error; - - assign next_id_14_re = addr_hit[31] & reg_re & !reg_error; - - assign next_id_15_re = addr_hit[32] & reg_re & !reg_error; - - assign done_id_0_re = addr_hit[33] & reg_re & !reg_error; - - assign done_id_1_re = addr_hit[34] & reg_re & !reg_error; - - assign done_id_2_re = addr_hit[35] & reg_re & !reg_error; - - assign done_id_3_re = addr_hit[36] & reg_re & !reg_error; - - assign done_id_4_re = addr_hit[37] & reg_re & !reg_error; - - assign done_id_5_re = addr_hit[38] & reg_re & !reg_error; - - assign done_id_6_re = addr_hit[39] & reg_re & !reg_error; - - assign done_id_7_re = addr_hit[40] & reg_re & !reg_error; - - assign done_id_8_re = addr_hit[41] & reg_re & !reg_error; - - assign done_id_9_re = addr_hit[42] & reg_re & !reg_error; - - assign done_id_10_re = addr_hit[43] & reg_re & !reg_error; - - assign done_id_11_re = addr_hit[44] & reg_re & !reg_error; - - assign done_id_12_re = addr_hit[45] & reg_re & !reg_error; - - assign done_id_13_re = addr_hit[46] & reg_re & !reg_error; - - assign done_id_14_re = addr_hit[47] & reg_re & !reg_error; - - assign done_id_15_re = addr_hit[48] & reg_re & !reg_error; - - assign dst_addr_low_we = addr_hit[49] & reg_we & !reg_error; - assign dst_addr_low_wd = reg_wdata[31:0]; - - assign src_addr_low_we = addr_hit[50] & reg_we & !reg_error; - assign src_addr_low_wd = reg_wdata[31:0]; - - assign length_low_we = addr_hit[51] & reg_we & !reg_error; - assign length_low_wd = reg_wdata[31:0]; - - assign dst_stride_2_low_we = addr_hit[52] & reg_we & !reg_error; - assign dst_stride_2_low_wd = reg_wdata[31:0]; - - assign src_stride_2_low_we = addr_hit[53] & reg_we & !reg_error; - assign src_stride_2_low_wd = reg_wdata[31:0]; - - assign reps_2_low_we = addr_hit[54] & reg_we & !reg_error; - assign reps_2_low_wd = reg_wdata[31:0]; - - assign dst_stride_3_low_we = addr_hit[55] & reg_we & !reg_error; - assign dst_stride_3_low_wd = reg_wdata[31:0]; - - assign src_stride_3_low_we = addr_hit[56] & reg_we & !reg_error; - assign src_stride_3_low_wd = reg_wdata[31:0]; - - assign reps_3_low_we = addr_hit[57] & reg_we & !reg_error; - assign reps_3_low_wd = reg_wdata[31:0]; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[0] = conf_decouple_aw_qs; - reg_rdata_next[1] = conf_decouple_rw_qs; - reg_rdata_next[2] = conf_src_reduce_len_qs; - reg_rdata_next[3] = conf_dst_reduce_len_qs; - reg_rdata_next[6:4] = conf_src_max_llen_qs; - reg_rdata_next[9:7] = conf_dst_max_llen_qs; - reg_rdata_next[11:10] = conf_enable_nd_qs; - reg_rdata_next[14:12] = conf_src_protocol_qs; - reg_rdata_next[17:15] = conf_dst_protocol_qs; - end - - addr_hit[1]: begin - reg_rdata_next[9:0] = status_0_qs; - end - - addr_hit[2]: begin - reg_rdata_next[9:0] = status_1_qs; - end - - addr_hit[3]: begin - reg_rdata_next[9:0] = status_2_qs; - end - - addr_hit[4]: begin - reg_rdata_next[9:0] = status_3_qs; - end - - addr_hit[5]: begin - reg_rdata_next[9:0] = status_4_qs; - end - - addr_hit[6]: begin - reg_rdata_next[9:0] = status_5_qs; - end - - addr_hit[7]: begin - reg_rdata_next[9:0] = status_6_qs; - end - - addr_hit[8]: begin - reg_rdata_next[9:0] = status_7_qs; - end - - addr_hit[9]: begin - reg_rdata_next[9:0] = status_8_qs; - end - - addr_hit[10]: begin - reg_rdata_next[9:0] = status_9_qs; - end - - addr_hit[11]: begin - reg_rdata_next[9:0] = status_10_qs; - end - - addr_hit[12]: begin - reg_rdata_next[9:0] = status_11_qs; - end - - addr_hit[13]: begin - reg_rdata_next[9:0] = status_12_qs; - end - - addr_hit[14]: begin - reg_rdata_next[9:0] = status_13_qs; - end - - addr_hit[15]: begin - reg_rdata_next[9:0] = status_14_qs; - end - - addr_hit[16]: begin - reg_rdata_next[9:0] = status_15_qs; - end - - addr_hit[17]: begin - reg_rdata_next[31:0] = next_id_0_qs; - end - - addr_hit[18]: begin - reg_rdata_next[31:0] = next_id_1_qs; - end - - addr_hit[19]: begin - reg_rdata_next[31:0] = next_id_2_qs; - end - - addr_hit[20]: begin - reg_rdata_next[31:0] = next_id_3_qs; - end - - addr_hit[21]: begin - reg_rdata_next[31:0] = next_id_4_qs; - end - - addr_hit[22]: begin - reg_rdata_next[31:0] = next_id_5_qs; - end - - addr_hit[23]: begin - reg_rdata_next[31:0] = next_id_6_qs; - end - - addr_hit[24]: begin - reg_rdata_next[31:0] = next_id_7_qs; - end - - addr_hit[25]: begin - reg_rdata_next[31:0] = next_id_8_qs; - end - - addr_hit[26]: begin - reg_rdata_next[31:0] = next_id_9_qs; - end - - addr_hit[27]: begin - reg_rdata_next[31:0] = next_id_10_qs; - end - - addr_hit[28]: begin - reg_rdata_next[31:0] = next_id_11_qs; - end - - addr_hit[29]: begin - reg_rdata_next[31:0] = next_id_12_qs; - end - - addr_hit[30]: begin - reg_rdata_next[31:0] = next_id_13_qs; - end - - addr_hit[31]: begin - reg_rdata_next[31:0] = next_id_14_qs; - end - - addr_hit[32]: begin - reg_rdata_next[31:0] = next_id_15_qs; - end - - addr_hit[33]: begin - reg_rdata_next[31:0] = done_id_0_qs; - end - - addr_hit[34]: begin - reg_rdata_next[31:0] = done_id_1_qs; - end - - addr_hit[35]: begin - reg_rdata_next[31:0] = done_id_2_qs; - end - - addr_hit[36]: begin - reg_rdata_next[31:0] = done_id_3_qs; - end - - addr_hit[37]: begin - reg_rdata_next[31:0] = done_id_4_qs; - end - - addr_hit[38]: begin - reg_rdata_next[31:0] = done_id_5_qs; - end - - addr_hit[39]: begin - reg_rdata_next[31:0] = done_id_6_qs; - end - - addr_hit[40]: begin - reg_rdata_next[31:0] = done_id_7_qs; - end - - addr_hit[41]: begin - reg_rdata_next[31:0] = done_id_8_qs; - end - - addr_hit[42]: begin - reg_rdata_next[31:0] = done_id_9_qs; - end - - addr_hit[43]: begin - reg_rdata_next[31:0] = done_id_10_qs; - end - - addr_hit[44]: begin - reg_rdata_next[31:0] = done_id_11_qs; - end - - addr_hit[45]: begin - reg_rdata_next[31:0] = done_id_12_qs; - end - - addr_hit[46]: begin - reg_rdata_next[31:0] = done_id_13_qs; - end - - addr_hit[47]: begin - reg_rdata_next[31:0] = done_id_14_qs; - end - - addr_hit[48]: begin - reg_rdata_next[31:0] = done_id_15_qs; - end - - addr_hit[49]: begin - reg_rdata_next[31:0] = dst_addr_low_qs; - end - - addr_hit[50]: begin - reg_rdata_next[31:0] = src_addr_low_qs; - end - - addr_hit[51]: begin - reg_rdata_next[31:0] = length_low_qs; - end - - addr_hit[52]: begin - reg_rdata_next[31:0] = dst_stride_2_low_qs; - end - - addr_hit[53]: begin - reg_rdata_next[31:0] = src_stride_2_low_qs; - end - - addr_hit[54]: begin - reg_rdata_next[31:0] = reps_2_low_qs; - end - - addr_hit[55]: begin - reg_rdata_next[31:0] = dst_stride_3_low_qs; - end - - addr_hit[56]: begin - reg_rdata_next[31:0] = src_stride_3_low_qs; - end - - addr_hit[57]: begin - reg_rdata_next[31:0] = reps_3_low_qs; - end - - default: begin - reg_rdata_next = '1; - end - endcase - end - - // Unused signal tieoff - - // wdata / byte enable are not always fully used - // add a blanket unused statement to handle lint waivers - logic unused_wdata; - logic unused_be; - assign unused_wdata = ^reg_wdata; - assign unused_be = ^reg_be; - - // Assertions for Register Interface - `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) - -endmodule - -module idma_reg32_3d_reg_top_intf -#( - parameter int AW = 9, - localparam int DW = 32 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output idma_reg32_3d_reg_pkg::idma_reg32_3d_reg2hw_t reg2hw, // Write - input idma_reg32_3d_reg_pkg::idma_reg32_3d_hw2reg_t hw2reg, // Read - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - localparam int unsigned STRB_WIDTH = DW/8; - -`include "register_interface/typedef.svh" -`include "register_interface/assign.svh" - - // Define structs for reg_bus - typedef logic [AW-1:0] addr_t; - typedef logic [DW-1:0] data_t; - typedef logic [STRB_WIDTH-1:0] strb_t; - `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) - - reg_bus_req_t s_reg_req; - reg_bus_rsp_t s_reg_rsp; - - // Assign SV interface to structs - `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) - `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) - - - - idma_reg32_3d_reg_top #( - .reg_req_t(reg_bus_req_t), - .reg_rsp_t(reg_bus_rsp_t), - .AW(AW) - ) i_regs ( - .clk_i, - .rst_ni, - .reg_req_i(s_reg_req), - .reg_rsp_o(s_reg_rsp), - .reg2hw, // Write - .hw2reg, // Read - .devmode_i - ); - -endmodule - - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module idma_reg64_2d_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 8 -) ( - input logic clk_i, - input logic rst_ni, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - // To HW - output idma_reg64_2d_reg_pkg::idma_reg64_2d_reg2hw_t reg2hw, // Write - input idma_reg64_2d_reg_pkg::idma_reg64_2d_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import idma_reg64_2d_reg_pkg::* ; - - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [BlockAw-1:0] reg_addr; - logic [DW-1:0] reg_wdata; - logic [DBW-1:0] reg_be; - logic [DW-1:0] reg_rdata; - logic reg_error; - - logic addrmiss, wr_err; - - logic [DW-1:0] reg_rdata_next; - - // Below register interface can be changed - reg_req_t reg_intf_req; - reg_rsp_t reg_intf_rsp; - - - assign reg_intf_req = reg_req_i; - assign reg_rsp_o = reg_intf_rsp; - - - assign reg_we = reg_intf_req.valid & reg_intf_req.write; - assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; - assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; - assign reg_wdata = reg_intf_req.wdata; - assign reg_be = reg_intf_req.wstrb; - assign reg_intf_rsp.rdata = reg_rdata; - assign reg_intf_rsp.error = reg_error; - assign reg_intf_rsp.ready = 1'b1; - - assign reg_rdata = reg_rdata_next ; - assign reg_error = (devmode_i & addrmiss) | wr_err; - - - // Define SW related signals - // Format: __{wd|we|qs} - // or _{wd|we|qs} if field == 1 or 0 - logic conf_decouple_aw_qs; - logic conf_decouple_aw_wd; - logic conf_decouple_aw_we; - logic conf_decouple_rw_qs; - logic conf_decouple_rw_wd; - logic conf_decouple_rw_we; - logic conf_src_reduce_len_qs; - logic conf_src_reduce_len_wd; - logic conf_src_reduce_len_we; - logic conf_dst_reduce_len_qs; - logic conf_dst_reduce_len_wd; - logic conf_dst_reduce_len_we; - logic [2:0] conf_src_max_llen_qs; - logic [2:0] conf_src_max_llen_wd; - logic conf_src_max_llen_we; - logic [2:0] conf_dst_max_llen_qs; - logic [2:0] conf_dst_max_llen_wd; - logic conf_dst_max_llen_we; - logic conf_enable_nd_qs; - logic conf_enable_nd_wd; - logic conf_enable_nd_we; - logic [2:0] conf_src_protocol_qs; - logic [2:0] conf_src_protocol_wd; - logic conf_src_protocol_we; - logic [2:0] conf_dst_protocol_qs; - logic [2:0] conf_dst_protocol_wd; - logic conf_dst_protocol_we; - logic [9:0] status_0_qs; - logic status_0_re; - logic [9:0] status_1_qs; - logic status_1_re; - logic [9:0] status_2_qs; - logic status_2_re; - logic [9:0] status_3_qs; - logic status_3_re; - logic [9:0] status_4_qs; - logic status_4_re; - logic [9:0] status_5_qs; - logic status_5_re; - logic [9:0] status_6_qs; - logic status_6_re; - logic [9:0] status_7_qs; - logic status_7_re; - logic [9:0] status_8_qs; - logic status_8_re; - logic [9:0] status_9_qs; - logic status_9_re; - logic [9:0] status_10_qs; - logic status_10_re; - logic [9:0] status_11_qs; - logic status_11_re; - logic [9:0] status_12_qs; - logic status_12_re; - logic [9:0] status_13_qs; - logic status_13_re; - logic [9:0] status_14_qs; - logic status_14_re; - logic [9:0] status_15_qs; - logic status_15_re; - logic [31:0] next_id_0_qs; - logic next_id_0_re; - logic [31:0] next_id_1_qs; - logic next_id_1_re; - logic [31:0] next_id_2_qs; - logic next_id_2_re; - logic [31:0] next_id_3_qs; - logic next_id_3_re; - logic [31:0] next_id_4_qs; - logic next_id_4_re; - logic [31:0] next_id_5_qs; - logic next_id_5_re; - logic [31:0] next_id_6_qs; - logic next_id_6_re; - logic [31:0] next_id_7_qs; - logic next_id_7_re; - logic [31:0] next_id_8_qs; - logic next_id_8_re; - logic [31:0] next_id_9_qs; - logic next_id_9_re; - logic [31:0] next_id_10_qs; - logic next_id_10_re; - logic [31:0] next_id_11_qs; - logic next_id_11_re; - logic [31:0] next_id_12_qs; - logic next_id_12_re; - logic [31:0] next_id_13_qs; - logic next_id_13_re; - logic [31:0] next_id_14_qs; - logic next_id_14_re; - logic [31:0] next_id_15_qs; - logic next_id_15_re; - logic [31:0] done_id_0_qs; - logic done_id_0_re; - logic [31:0] done_id_1_qs; - logic done_id_1_re; - logic [31:0] done_id_2_qs; - logic done_id_2_re; - logic [31:0] done_id_3_qs; - logic done_id_3_re; - logic [31:0] done_id_4_qs; - logic done_id_4_re; - logic [31:0] done_id_5_qs; - logic done_id_5_re; - logic [31:0] done_id_6_qs; - logic done_id_6_re; - logic [31:0] done_id_7_qs; - logic done_id_7_re; - logic [31:0] done_id_8_qs; - logic done_id_8_re; - logic [31:0] done_id_9_qs; - logic done_id_9_re; - logic [31:0] done_id_10_qs; - logic done_id_10_re; - logic [31:0] done_id_11_qs; - logic done_id_11_re; - logic [31:0] done_id_12_qs; - logic done_id_12_re; - logic [31:0] done_id_13_qs; - logic done_id_13_re; - logic [31:0] done_id_14_qs; - logic done_id_14_re; - logic [31:0] done_id_15_qs; - logic done_id_15_re; - logic [31:0] dst_addr_low_qs; - logic [31:0] dst_addr_low_wd; - logic dst_addr_low_we; - logic [31:0] dst_addr_high_qs; - logic [31:0] dst_addr_high_wd; - logic dst_addr_high_we; - logic [31:0] src_addr_low_qs; - logic [31:0] src_addr_low_wd; - logic src_addr_low_we; - logic [31:0] src_addr_high_qs; - logic [31:0] src_addr_high_wd; - logic src_addr_high_we; - logic [31:0] length_low_qs; - logic [31:0] length_low_wd; - logic length_low_we; - logic [31:0] length_high_qs; - logic [31:0] length_high_wd; - logic length_high_we; - logic [31:0] dst_stride_2_low_qs; - logic [31:0] dst_stride_2_low_wd; - logic dst_stride_2_low_we; - logic [31:0] dst_stride_2_high_qs; - logic [31:0] dst_stride_2_high_wd; - logic dst_stride_2_high_we; - logic [31:0] src_stride_2_low_qs; - logic [31:0] src_stride_2_low_wd; - logic src_stride_2_low_we; - logic [31:0] src_stride_2_high_qs; - logic [31:0] src_stride_2_high_wd; - logic src_stride_2_high_we; - logic [31:0] reps_2_low_qs; - logic [31:0] reps_2_low_wd; - logic reps_2_low_we; - logic [31:0] reps_2_high_qs; - logic [31:0] reps_2_high_wd; - logic reps_2_high_we; - - // Register instances - // R[conf]: V(False) - - // F[decouple_aw]: 0:0 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_decouple_aw ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_decouple_aw_we), - .wd (conf_decouple_aw_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.decouple_aw.q ), - - // to register interface (read) - .qs (conf_decouple_aw_qs) - ); - - - // F[decouple_rw]: 1:1 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_decouple_rw ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_decouple_rw_we), - .wd (conf_decouple_rw_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.decouple_rw.q ), - - // to register interface (read) - .qs (conf_decouple_rw_qs) - ); - - - // F[src_reduce_len]: 2:2 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_src_reduce_len ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_reduce_len_we), - .wd (conf_src_reduce_len_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_reduce_len.q ), - - // to register interface (read) - .qs (conf_src_reduce_len_qs) - ); - - - // F[dst_reduce_len]: 3:3 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_dst_reduce_len ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_reduce_len_we), - .wd (conf_dst_reduce_len_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_reduce_len.q ), - - // to register interface (read) - .qs (conf_dst_reduce_len_qs) - ); - - - // F[src_max_llen]: 6:4 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_src_max_llen ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_max_llen_we), - .wd (conf_src_max_llen_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_max_llen.q ), - - // to register interface (read) - .qs (conf_src_max_llen_qs) - ); - - - // F[dst_max_llen]: 9:7 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_dst_max_llen ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_max_llen_we), - .wd (conf_dst_max_llen_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_max_llen.q ), - - // to register interface (read) - .qs (conf_dst_max_llen_qs) - ); - - - // F[enable_nd]: 10:10 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_enable_nd ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_enable_nd_we), - .wd (conf_enable_nd_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.enable_nd.q ), - - // to register interface (read) - .qs (conf_enable_nd_qs) - ); - - - // F[src_protocol]: 13:11 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_src_protocol ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_protocol_we), - .wd (conf_src_protocol_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_protocol.q ), - - // to register interface (read) - .qs (conf_src_protocol_qs) - ); - - - // F[dst_protocol]: 16:14 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_dst_protocol ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_protocol_we), - .wd (conf_dst_protocol_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_protocol.q ), - - // to register interface (read) - .qs (conf_dst_protocol_qs) - ); - - - - // Subregister 0 of Multireg status - // R[status_0]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_0 ( - .re (status_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[0].d), - .qre (), - .qe (), - .q (), - .qs (status_0_qs) - ); - - // Subregister 1 of Multireg status - // R[status_1]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_1 ( - .re (status_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[1].d), - .qre (), - .qe (), - .q (), - .qs (status_1_qs) - ); - - // Subregister 2 of Multireg status - // R[status_2]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_2 ( - .re (status_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[2].d), - .qre (), - .qe (), - .q (), - .qs (status_2_qs) - ); - - // Subregister 3 of Multireg status - // R[status_3]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_3 ( - .re (status_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[3].d), - .qre (), - .qe (), - .q (), - .qs (status_3_qs) - ); - - // Subregister 4 of Multireg status - // R[status_4]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_4 ( - .re (status_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[4].d), - .qre (), - .qe (), - .q (), - .qs (status_4_qs) - ); - - // Subregister 5 of Multireg status - // R[status_5]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_5 ( - .re (status_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[5].d), - .qre (), - .qe (), - .q (), - .qs (status_5_qs) - ); - - // Subregister 6 of Multireg status - // R[status_6]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_6 ( - .re (status_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[6].d), - .qre (), - .qe (), - .q (), - .qs (status_6_qs) - ); - - // Subregister 7 of Multireg status - // R[status_7]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_7 ( - .re (status_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[7].d), - .qre (), - .qe (), - .q (), - .qs (status_7_qs) - ); - - // Subregister 8 of Multireg status - // R[status_8]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_8 ( - .re (status_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[8].d), - .qre (), - .qe (), - .q (), - .qs (status_8_qs) - ); - - // Subregister 9 of Multireg status - // R[status_9]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_9 ( - .re (status_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[9].d), - .qre (), - .qe (), - .q (), - .qs (status_9_qs) - ); - - // Subregister 10 of Multireg status - // R[status_10]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_10 ( - .re (status_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[10].d), - .qre (), - .qe (), - .q (), - .qs (status_10_qs) - ); - - // Subregister 11 of Multireg status - // R[status_11]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_11 ( - .re (status_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[11].d), - .qre (), - .qe (), - .q (), - .qs (status_11_qs) - ); - - // Subregister 12 of Multireg status - // R[status_12]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_12 ( - .re (status_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[12].d), - .qre (), - .qe (), - .q (), - .qs (status_12_qs) - ); - - // Subregister 13 of Multireg status - // R[status_13]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_13 ( - .re (status_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[13].d), - .qre (), - .qe (), - .q (), - .qs (status_13_qs) - ); - - // Subregister 14 of Multireg status - // R[status_14]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_14 ( - .re (status_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[14].d), - .qre (), - .qe (), - .q (), - .qs (status_14_qs) - ); - - // Subregister 15 of Multireg status - // R[status_15]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_15 ( - .re (status_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[15].d), - .qre (), - .qe (), - .q (), - .qs (status_15_qs) - ); - - - - // Subregister 0 of Multireg next_id - // R[next_id_0]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_0 ( - .re (next_id_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[0].d), - .qre (reg2hw.next_id[0].re), - .qe (), - .q (reg2hw.next_id[0].q ), - .qs (next_id_0_qs) - ); - - // Subregister 1 of Multireg next_id - // R[next_id_1]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_1 ( - .re (next_id_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[1].d), - .qre (reg2hw.next_id[1].re), - .qe (), - .q (reg2hw.next_id[1].q ), - .qs (next_id_1_qs) - ); - - // Subregister 2 of Multireg next_id - // R[next_id_2]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_2 ( - .re (next_id_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[2].d), - .qre (reg2hw.next_id[2].re), - .qe (), - .q (reg2hw.next_id[2].q ), - .qs (next_id_2_qs) - ); - - // Subregister 3 of Multireg next_id - // R[next_id_3]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_3 ( - .re (next_id_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[3].d), - .qre (reg2hw.next_id[3].re), - .qe (), - .q (reg2hw.next_id[3].q ), - .qs (next_id_3_qs) - ); - - // Subregister 4 of Multireg next_id - // R[next_id_4]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_4 ( - .re (next_id_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[4].d), - .qre (reg2hw.next_id[4].re), - .qe (), - .q (reg2hw.next_id[4].q ), - .qs (next_id_4_qs) - ); - - // Subregister 5 of Multireg next_id - // R[next_id_5]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_5 ( - .re (next_id_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[5].d), - .qre (reg2hw.next_id[5].re), - .qe (), - .q (reg2hw.next_id[5].q ), - .qs (next_id_5_qs) - ); - - // Subregister 6 of Multireg next_id - // R[next_id_6]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_6 ( - .re (next_id_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[6].d), - .qre (reg2hw.next_id[6].re), - .qe (), - .q (reg2hw.next_id[6].q ), - .qs (next_id_6_qs) - ); - - // Subregister 7 of Multireg next_id - // R[next_id_7]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_7 ( - .re (next_id_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[7].d), - .qre (reg2hw.next_id[7].re), - .qe (), - .q (reg2hw.next_id[7].q ), - .qs (next_id_7_qs) - ); - - // Subregister 8 of Multireg next_id - // R[next_id_8]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_8 ( - .re (next_id_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[8].d), - .qre (reg2hw.next_id[8].re), - .qe (), - .q (reg2hw.next_id[8].q ), - .qs (next_id_8_qs) - ); - - // Subregister 9 of Multireg next_id - // R[next_id_9]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_9 ( - .re (next_id_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[9].d), - .qre (reg2hw.next_id[9].re), - .qe (), - .q (reg2hw.next_id[9].q ), - .qs (next_id_9_qs) - ); - - // Subregister 10 of Multireg next_id - // R[next_id_10]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_10 ( - .re (next_id_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[10].d), - .qre (reg2hw.next_id[10].re), - .qe (), - .q (reg2hw.next_id[10].q ), - .qs (next_id_10_qs) - ); - - // Subregister 11 of Multireg next_id - // R[next_id_11]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_11 ( - .re (next_id_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[11].d), - .qre (reg2hw.next_id[11].re), - .qe (), - .q (reg2hw.next_id[11].q ), - .qs (next_id_11_qs) - ); - - // Subregister 12 of Multireg next_id - // R[next_id_12]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_12 ( - .re (next_id_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[12].d), - .qre (reg2hw.next_id[12].re), - .qe (), - .q (reg2hw.next_id[12].q ), - .qs (next_id_12_qs) - ); - - // Subregister 13 of Multireg next_id - // R[next_id_13]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_13 ( - .re (next_id_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[13].d), - .qre (reg2hw.next_id[13].re), - .qe (), - .q (reg2hw.next_id[13].q ), - .qs (next_id_13_qs) - ); - - // Subregister 14 of Multireg next_id - // R[next_id_14]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_14 ( - .re (next_id_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[14].d), - .qre (reg2hw.next_id[14].re), - .qe (), - .q (reg2hw.next_id[14].q ), - .qs (next_id_14_qs) - ); - - // Subregister 15 of Multireg next_id - // R[next_id_15]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_15 ( - .re (next_id_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[15].d), - .qre (reg2hw.next_id[15].re), - .qe (), - .q (reg2hw.next_id[15].q ), - .qs (next_id_15_qs) - ); - - - - // Subregister 0 of Multireg done_id - // R[done_id_0]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_0 ( - .re (done_id_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[0].d), - .qre (), - .qe (), - .q (), - .qs (done_id_0_qs) - ); - - // Subregister 1 of Multireg done_id - // R[done_id_1]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_1 ( - .re (done_id_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[1].d), - .qre (), - .qe (), - .q (), - .qs (done_id_1_qs) - ); - - // Subregister 2 of Multireg done_id - // R[done_id_2]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_2 ( - .re (done_id_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[2].d), - .qre (), - .qe (), - .q (), - .qs (done_id_2_qs) - ); - - // Subregister 3 of Multireg done_id - // R[done_id_3]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_3 ( - .re (done_id_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[3].d), - .qre (), - .qe (), - .q (), - .qs (done_id_3_qs) - ); - - // Subregister 4 of Multireg done_id - // R[done_id_4]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_4 ( - .re (done_id_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[4].d), - .qre (), - .qe (), - .q (), - .qs (done_id_4_qs) - ); - - // Subregister 5 of Multireg done_id - // R[done_id_5]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_5 ( - .re (done_id_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[5].d), - .qre (), - .qe (), - .q (), - .qs (done_id_5_qs) - ); - - // Subregister 6 of Multireg done_id - // R[done_id_6]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_6 ( - .re (done_id_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[6].d), - .qre (), - .qe (), - .q (), - .qs (done_id_6_qs) - ); - - // Subregister 7 of Multireg done_id - // R[done_id_7]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_7 ( - .re (done_id_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[7].d), - .qre (), - .qe (), - .q (), - .qs (done_id_7_qs) - ); - - // Subregister 8 of Multireg done_id - // R[done_id_8]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_8 ( - .re (done_id_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[8].d), - .qre (), - .qe (), - .q (), - .qs (done_id_8_qs) - ); - - // Subregister 9 of Multireg done_id - // R[done_id_9]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_9 ( - .re (done_id_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[9].d), - .qre (), - .qe (), - .q (), - .qs (done_id_9_qs) - ); - - // Subregister 10 of Multireg done_id - // R[done_id_10]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_10 ( - .re (done_id_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[10].d), - .qre (), - .qe (), - .q (), - .qs (done_id_10_qs) - ); - - // Subregister 11 of Multireg done_id - // R[done_id_11]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_11 ( - .re (done_id_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[11].d), - .qre (), - .qe (), - .q (), - .qs (done_id_11_qs) - ); - - // Subregister 12 of Multireg done_id - // R[done_id_12]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_12 ( - .re (done_id_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[12].d), - .qre (), - .qe (), - .q (), - .qs (done_id_12_qs) - ); - - // Subregister 13 of Multireg done_id - // R[done_id_13]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_13 ( - .re (done_id_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[13].d), - .qre (), - .qe (), - .q (), - .qs (done_id_13_qs) - ); - - // Subregister 14 of Multireg done_id - // R[done_id_14]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_14 ( - .re (done_id_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[14].d), - .qre (), - .qe (), - .q (), - .qs (done_id_14_qs) - ); - - // Subregister 15 of Multireg done_id - // R[done_id_15]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_15 ( - .re (done_id_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[15].d), - .qre (), - .qe (), - .q (), - .qs (done_id_15_qs) - ); - - - // R[dst_addr_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_addr_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_addr_low_we), - .wd (dst_addr_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_addr_low.q ), - - // to register interface (read) - .qs (dst_addr_low_qs) - ); - - - // R[dst_addr_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_addr_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_addr_high_we), - .wd (dst_addr_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_addr_high.q ), - - // to register interface (read) - .qs (dst_addr_high_qs) - ); - - - // R[src_addr_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_addr_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_addr_low_we), - .wd (src_addr_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_addr_low.q ), - - // to register interface (read) - .qs (src_addr_low_qs) - ); - - - // R[src_addr_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_addr_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_addr_high_we), - .wd (src_addr_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_addr_high.q ), - - // to register interface (read) - .qs (src_addr_high_qs) - ); - - - // R[length_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_length_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (length_low_we), - .wd (length_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.length_low.q ), - - // to register interface (read) - .qs (length_low_qs) - ); - - - // R[length_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_length_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (length_high_we), - .wd (length_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.length_high.q ), - - // to register interface (read) - .qs (length_high_qs) - ); - - - // R[dst_stride_2_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_stride_2_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_stride_2_low_we), - .wd (dst_stride_2_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_stride_2_low.q ), - - // to register interface (read) - .qs (dst_stride_2_low_qs) - ); - - - // R[dst_stride_2_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_stride_2_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_stride_2_high_we), - .wd (dst_stride_2_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_stride_2_high.q ), - - // to register interface (read) - .qs (dst_stride_2_high_qs) - ); - - - // R[src_stride_2_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_stride_2_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_stride_2_low_we), - .wd (src_stride_2_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_stride_2_low.q ), - - // to register interface (read) - .qs (src_stride_2_low_qs) - ); - - - // R[src_stride_2_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_stride_2_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_stride_2_high_we), - .wd (src_stride_2_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_stride_2_high.q ), - - // to register interface (read) - .qs (src_stride_2_high_qs) - ); - - - // R[reps_2_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_reps_2_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (reps_2_low_we), - .wd (reps_2_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.reps_2_low.q ), - - // to register interface (read) - .qs (reps_2_low_qs) - ); - - - // R[reps_2_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_reps_2_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (reps_2_high_we), - .wd (reps_2_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.reps_2_high.q ), - - // to register interface (read) - .qs (reps_2_high_qs) - ); - - - - - logic [60:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[ 0] = (reg_addr == IDMA_REG64_2D_CONF_OFFSET); - addr_hit[ 1] = (reg_addr == IDMA_REG64_2D_STATUS_0_OFFSET); - addr_hit[ 2] = (reg_addr == IDMA_REG64_2D_STATUS_1_OFFSET); - addr_hit[ 3] = (reg_addr == IDMA_REG64_2D_STATUS_2_OFFSET); - addr_hit[ 4] = (reg_addr == IDMA_REG64_2D_STATUS_3_OFFSET); - addr_hit[ 5] = (reg_addr == IDMA_REG64_2D_STATUS_4_OFFSET); - addr_hit[ 6] = (reg_addr == IDMA_REG64_2D_STATUS_5_OFFSET); - addr_hit[ 7] = (reg_addr == IDMA_REG64_2D_STATUS_6_OFFSET); - addr_hit[ 8] = (reg_addr == IDMA_REG64_2D_STATUS_7_OFFSET); - addr_hit[ 9] = (reg_addr == IDMA_REG64_2D_STATUS_8_OFFSET); - addr_hit[10] = (reg_addr == IDMA_REG64_2D_STATUS_9_OFFSET); - addr_hit[11] = (reg_addr == IDMA_REG64_2D_STATUS_10_OFFSET); - addr_hit[12] = (reg_addr == IDMA_REG64_2D_STATUS_11_OFFSET); - addr_hit[13] = (reg_addr == IDMA_REG64_2D_STATUS_12_OFFSET); - addr_hit[14] = (reg_addr == IDMA_REG64_2D_STATUS_13_OFFSET); - addr_hit[15] = (reg_addr == IDMA_REG64_2D_STATUS_14_OFFSET); - addr_hit[16] = (reg_addr == IDMA_REG64_2D_STATUS_15_OFFSET); - addr_hit[17] = (reg_addr == IDMA_REG64_2D_NEXT_ID_0_OFFSET); - addr_hit[18] = (reg_addr == IDMA_REG64_2D_NEXT_ID_1_OFFSET); - addr_hit[19] = (reg_addr == IDMA_REG64_2D_NEXT_ID_2_OFFSET); - addr_hit[20] = (reg_addr == IDMA_REG64_2D_NEXT_ID_3_OFFSET); - addr_hit[21] = (reg_addr == IDMA_REG64_2D_NEXT_ID_4_OFFSET); - addr_hit[22] = (reg_addr == IDMA_REG64_2D_NEXT_ID_5_OFFSET); - addr_hit[23] = (reg_addr == IDMA_REG64_2D_NEXT_ID_6_OFFSET); - addr_hit[24] = (reg_addr == IDMA_REG64_2D_NEXT_ID_7_OFFSET); - addr_hit[25] = (reg_addr == IDMA_REG64_2D_NEXT_ID_8_OFFSET); - addr_hit[26] = (reg_addr == IDMA_REG64_2D_NEXT_ID_9_OFFSET); - addr_hit[27] = (reg_addr == IDMA_REG64_2D_NEXT_ID_10_OFFSET); - addr_hit[28] = (reg_addr == IDMA_REG64_2D_NEXT_ID_11_OFFSET); - addr_hit[29] = (reg_addr == IDMA_REG64_2D_NEXT_ID_12_OFFSET); - addr_hit[30] = (reg_addr == IDMA_REG64_2D_NEXT_ID_13_OFFSET); - addr_hit[31] = (reg_addr == IDMA_REG64_2D_NEXT_ID_14_OFFSET); - addr_hit[32] = (reg_addr == IDMA_REG64_2D_NEXT_ID_15_OFFSET); - addr_hit[33] = (reg_addr == IDMA_REG64_2D_DONE_ID_0_OFFSET); - addr_hit[34] = (reg_addr == IDMA_REG64_2D_DONE_ID_1_OFFSET); - addr_hit[35] = (reg_addr == IDMA_REG64_2D_DONE_ID_2_OFFSET); - addr_hit[36] = (reg_addr == IDMA_REG64_2D_DONE_ID_3_OFFSET); - addr_hit[37] = (reg_addr == IDMA_REG64_2D_DONE_ID_4_OFFSET); - addr_hit[38] = (reg_addr == IDMA_REG64_2D_DONE_ID_5_OFFSET); - addr_hit[39] = (reg_addr == IDMA_REG64_2D_DONE_ID_6_OFFSET); - addr_hit[40] = (reg_addr == IDMA_REG64_2D_DONE_ID_7_OFFSET); - addr_hit[41] = (reg_addr == IDMA_REG64_2D_DONE_ID_8_OFFSET); - addr_hit[42] = (reg_addr == IDMA_REG64_2D_DONE_ID_9_OFFSET); - addr_hit[43] = (reg_addr == IDMA_REG64_2D_DONE_ID_10_OFFSET); - addr_hit[44] = (reg_addr == IDMA_REG64_2D_DONE_ID_11_OFFSET); - addr_hit[45] = (reg_addr == IDMA_REG64_2D_DONE_ID_12_OFFSET); - addr_hit[46] = (reg_addr == IDMA_REG64_2D_DONE_ID_13_OFFSET); - addr_hit[47] = (reg_addr == IDMA_REG64_2D_DONE_ID_14_OFFSET); - addr_hit[48] = (reg_addr == IDMA_REG64_2D_DONE_ID_15_OFFSET); - addr_hit[49] = (reg_addr == IDMA_REG64_2D_DST_ADDR_LOW_OFFSET); - addr_hit[50] = (reg_addr == IDMA_REG64_2D_DST_ADDR_HIGH_OFFSET); - addr_hit[51] = (reg_addr == IDMA_REG64_2D_SRC_ADDR_LOW_OFFSET); - addr_hit[52] = (reg_addr == IDMA_REG64_2D_SRC_ADDR_HIGH_OFFSET); - addr_hit[53] = (reg_addr == IDMA_REG64_2D_LENGTH_LOW_OFFSET); - addr_hit[54] = (reg_addr == IDMA_REG64_2D_LENGTH_HIGH_OFFSET); - addr_hit[55] = (reg_addr == IDMA_REG64_2D_DST_STRIDE_2_LOW_OFFSET); - addr_hit[56] = (reg_addr == IDMA_REG64_2D_DST_STRIDE_2_HIGH_OFFSET); - addr_hit[57] = (reg_addr == IDMA_REG64_2D_SRC_STRIDE_2_LOW_OFFSET); - addr_hit[58] = (reg_addr == IDMA_REG64_2D_SRC_STRIDE_2_HIGH_OFFSET); - addr_hit[59] = (reg_addr == IDMA_REG64_2D_REPS_2_LOW_OFFSET); - addr_hit[60] = (reg_addr == IDMA_REG64_2D_REPS_2_HIGH_OFFSET); - end - - assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; - - // Check sub-word write is permitted - always_comb begin - wr_err = (reg_we & - ((addr_hit[ 0] & (|(IDMA_REG64_2D_PERMIT[ 0] & ~reg_be))) | - (addr_hit[ 1] & (|(IDMA_REG64_2D_PERMIT[ 1] & ~reg_be))) | - (addr_hit[ 2] & (|(IDMA_REG64_2D_PERMIT[ 2] & ~reg_be))) | - (addr_hit[ 3] & (|(IDMA_REG64_2D_PERMIT[ 3] & ~reg_be))) | - (addr_hit[ 4] & (|(IDMA_REG64_2D_PERMIT[ 4] & ~reg_be))) | - (addr_hit[ 5] & (|(IDMA_REG64_2D_PERMIT[ 5] & ~reg_be))) | - (addr_hit[ 6] & (|(IDMA_REG64_2D_PERMIT[ 6] & ~reg_be))) | - (addr_hit[ 7] & (|(IDMA_REG64_2D_PERMIT[ 7] & ~reg_be))) | - (addr_hit[ 8] & (|(IDMA_REG64_2D_PERMIT[ 8] & ~reg_be))) | - (addr_hit[ 9] & (|(IDMA_REG64_2D_PERMIT[ 9] & ~reg_be))) | - (addr_hit[10] & (|(IDMA_REG64_2D_PERMIT[10] & ~reg_be))) | - (addr_hit[11] & (|(IDMA_REG64_2D_PERMIT[11] & ~reg_be))) | - (addr_hit[12] & (|(IDMA_REG64_2D_PERMIT[12] & ~reg_be))) | - (addr_hit[13] & (|(IDMA_REG64_2D_PERMIT[13] & ~reg_be))) | - (addr_hit[14] & (|(IDMA_REG64_2D_PERMIT[14] & ~reg_be))) | - (addr_hit[15] & (|(IDMA_REG64_2D_PERMIT[15] & ~reg_be))) | - (addr_hit[16] & (|(IDMA_REG64_2D_PERMIT[16] & ~reg_be))) | - (addr_hit[17] & (|(IDMA_REG64_2D_PERMIT[17] & ~reg_be))) | - (addr_hit[18] & (|(IDMA_REG64_2D_PERMIT[18] & ~reg_be))) | - (addr_hit[19] & (|(IDMA_REG64_2D_PERMIT[19] & ~reg_be))) | - (addr_hit[20] & (|(IDMA_REG64_2D_PERMIT[20] & ~reg_be))) | - (addr_hit[21] & (|(IDMA_REG64_2D_PERMIT[21] & ~reg_be))) | - (addr_hit[22] & (|(IDMA_REG64_2D_PERMIT[22] & ~reg_be))) | - (addr_hit[23] & (|(IDMA_REG64_2D_PERMIT[23] & ~reg_be))) | - (addr_hit[24] & (|(IDMA_REG64_2D_PERMIT[24] & ~reg_be))) | - (addr_hit[25] & (|(IDMA_REG64_2D_PERMIT[25] & ~reg_be))) | - (addr_hit[26] & (|(IDMA_REG64_2D_PERMIT[26] & ~reg_be))) | - (addr_hit[27] & (|(IDMA_REG64_2D_PERMIT[27] & ~reg_be))) | - (addr_hit[28] & (|(IDMA_REG64_2D_PERMIT[28] & ~reg_be))) | - (addr_hit[29] & (|(IDMA_REG64_2D_PERMIT[29] & ~reg_be))) | - (addr_hit[30] & (|(IDMA_REG64_2D_PERMIT[30] & ~reg_be))) | - (addr_hit[31] & (|(IDMA_REG64_2D_PERMIT[31] & ~reg_be))) | - (addr_hit[32] & (|(IDMA_REG64_2D_PERMIT[32] & ~reg_be))) | - (addr_hit[33] & (|(IDMA_REG64_2D_PERMIT[33] & ~reg_be))) | - (addr_hit[34] & (|(IDMA_REG64_2D_PERMIT[34] & ~reg_be))) | - (addr_hit[35] & (|(IDMA_REG64_2D_PERMIT[35] & ~reg_be))) | - (addr_hit[36] & (|(IDMA_REG64_2D_PERMIT[36] & ~reg_be))) | - (addr_hit[37] & (|(IDMA_REG64_2D_PERMIT[37] & ~reg_be))) | - (addr_hit[38] & (|(IDMA_REG64_2D_PERMIT[38] & ~reg_be))) | - (addr_hit[39] & (|(IDMA_REG64_2D_PERMIT[39] & ~reg_be))) | - (addr_hit[40] & (|(IDMA_REG64_2D_PERMIT[40] & ~reg_be))) | - (addr_hit[41] & (|(IDMA_REG64_2D_PERMIT[41] & ~reg_be))) | - (addr_hit[42] & (|(IDMA_REG64_2D_PERMIT[42] & ~reg_be))) | - (addr_hit[43] & (|(IDMA_REG64_2D_PERMIT[43] & ~reg_be))) | - (addr_hit[44] & (|(IDMA_REG64_2D_PERMIT[44] & ~reg_be))) | - (addr_hit[45] & (|(IDMA_REG64_2D_PERMIT[45] & ~reg_be))) | - (addr_hit[46] & (|(IDMA_REG64_2D_PERMIT[46] & ~reg_be))) | - (addr_hit[47] & (|(IDMA_REG64_2D_PERMIT[47] & ~reg_be))) | - (addr_hit[48] & (|(IDMA_REG64_2D_PERMIT[48] & ~reg_be))) | - (addr_hit[49] & (|(IDMA_REG64_2D_PERMIT[49] & ~reg_be))) | - (addr_hit[50] & (|(IDMA_REG64_2D_PERMIT[50] & ~reg_be))) | - (addr_hit[51] & (|(IDMA_REG64_2D_PERMIT[51] & ~reg_be))) | - (addr_hit[52] & (|(IDMA_REG64_2D_PERMIT[52] & ~reg_be))) | - (addr_hit[53] & (|(IDMA_REG64_2D_PERMIT[53] & ~reg_be))) | - (addr_hit[54] & (|(IDMA_REG64_2D_PERMIT[54] & ~reg_be))) | - (addr_hit[55] & (|(IDMA_REG64_2D_PERMIT[55] & ~reg_be))) | - (addr_hit[56] & (|(IDMA_REG64_2D_PERMIT[56] & ~reg_be))) | - (addr_hit[57] & (|(IDMA_REG64_2D_PERMIT[57] & ~reg_be))) | - (addr_hit[58] & (|(IDMA_REG64_2D_PERMIT[58] & ~reg_be))) | - (addr_hit[59] & (|(IDMA_REG64_2D_PERMIT[59] & ~reg_be))) | - (addr_hit[60] & (|(IDMA_REG64_2D_PERMIT[60] & ~reg_be))))); - end - - assign conf_decouple_aw_we = addr_hit[0] & reg_we & !reg_error; - assign conf_decouple_aw_wd = reg_wdata[0]; - - assign conf_decouple_rw_we = addr_hit[0] & reg_we & !reg_error; - assign conf_decouple_rw_wd = reg_wdata[1]; - - assign conf_src_reduce_len_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_reduce_len_wd = reg_wdata[2]; - - assign conf_dst_reduce_len_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_reduce_len_wd = reg_wdata[3]; - - assign conf_src_max_llen_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_max_llen_wd = reg_wdata[6:4]; - - assign conf_dst_max_llen_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_max_llen_wd = reg_wdata[9:7]; - - assign conf_enable_nd_we = addr_hit[0] & reg_we & !reg_error; - assign conf_enable_nd_wd = reg_wdata[10]; - - assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_protocol_wd = reg_wdata[13:11]; - - assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_protocol_wd = reg_wdata[16:14]; - - assign status_0_re = addr_hit[1] & reg_re & !reg_error; - - assign status_1_re = addr_hit[2] & reg_re & !reg_error; - - assign status_2_re = addr_hit[3] & reg_re & !reg_error; - - assign status_3_re = addr_hit[4] & reg_re & !reg_error; - - assign status_4_re = addr_hit[5] & reg_re & !reg_error; - - assign status_5_re = addr_hit[6] & reg_re & !reg_error; - - assign status_6_re = addr_hit[7] & reg_re & !reg_error; - - assign status_7_re = addr_hit[8] & reg_re & !reg_error; - - assign status_8_re = addr_hit[9] & reg_re & !reg_error; - - assign status_9_re = addr_hit[10] & reg_re & !reg_error; - - assign status_10_re = addr_hit[11] & reg_re & !reg_error; - - assign status_11_re = addr_hit[12] & reg_re & !reg_error; - - assign status_12_re = addr_hit[13] & reg_re & !reg_error; - - assign status_13_re = addr_hit[14] & reg_re & !reg_error; - - assign status_14_re = addr_hit[15] & reg_re & !reg_error; - - assign status_15_re = addr_hit[16] & reg_re & !reg_error; - - assign next_id_0_re = addr_hit[17] & reg_re & !reg_error; - - assign next_id_1_re = addr_hit[18] & reg_re & !reg_error; - - assign next_id_2_re = addr_hit[19] & reg_re & !reg_error; - - assign next_id_3_re = addr_hit[20] & reg_re & !reg_error; - - assign next_id_4_re = addr_hit[21] & reg_re & !reg_error; - - assign next_id_5_re = addr_hit[22] & reg_re & !reg_error; - - assign next_id_6_re = addr_hit[23] & reg_re & !reg_error; - - assign next_id_7_re = addr_hit[24] & reg_re & !reg_error; - - assign next_id_8_re = addr_hit[25] & reg_re & !reg_error; - - assign next_id_9_re = addr_hit[26] & reg_re & !reg_error; - - assign next_id_10_re = addr_hit[27] & reg_re & !reg_error; - - assign next_id_11_re = addr_hit[28] & reg_re & !reg_error; - - assign next_id_12_re = addr_hit[29] & reg_re & !reg_error; - - assign next_id_13_re = addr_hit[30] & reg_re & !reg_error; - - assign next_id_14_re = addr_hit[31] & reg_re & !reg_error; - - assign next_id_15_re = addr_hit[32] & reg_re & !reg_error; - - assign done_id_0_re = addr_hit[33] & reg_re & !reg_error; - - assign done_id_1_re = addr_hit[34] & reg_re & !reg_error; - - assign done_id_2_re = addr_hit[35] & reg_re & !reg_error; - - assign done_id_3_re = addr_hit[36] & reg_re & !reg_error; - - assign done_id_4_re = addr_hit[37] & reg_re & !reg_error; - - assign done_id_5_re = addr_hit[38] & reg_re & !reg_error; - - assign done_id_6_re = addr_hit[39] & reg_re & !reg_error; - - assign done_id_7_re = addr_hit[40] & reg_re & !reg_error; - - assign done_id_8_re = addr_hit[41] & reg_re & !reg_error; - - assign done_id_9_re = addr_hit[42] & reg_re & !reg_error; - - assign done_id_10_re = addr_hit[43] & reg_re & !reg_error; - - assign done_id_11_re = addr_hit[44] & reg_re & !reg_error; - - assign done_id_12_re = addr_hit[45] & reg_re & !reg_error; - - assign done_id_13_re = addr_hit[46] & reg_re & !reg_error; - - assign done_id_14_re = addr_hit[47] & reg_re & !reg_error; - - assign done_id_15_re = addr_hit[48] & reg_re & !reg_error; - - assign dst_addr_low_we = addr_hit[49] & reg_we & !reg_error; - assign dst_addr_low_wd = reg_wdata[31:0]; - - assign dst_addr_high_we = addr_hit[50] & reg_we & !reg_error; - assign dst_addr_high_wd = reg_wdata[31:0]; - - assign src_addr_low_we = addr_hit[51] & reg_we & !reg_error; - assign src_addr_low_wd = reg_wdata[31:0]; - - assign src_addr_high_we = addr_hit[52] & reg_we & !reg_error; - assign src_addr_high_wd = reg_wdata[31:0]; - - assign length_low_we = addr_hit[53] & reg_we & !reg_error; - assign length_low_wd = reg_wdata[31:0]; - - assign length_high_we = addr_hit[54] & reg_we & !reg_error; - assign length_high_wd = reg_wdata[31:0]; - - assign dst_stride_2_low_we = addr_hit[55] & reg_we & !reg_error; - assign dst_stride_2_low_wd = reg_wdata[31:0]; - - assign dst_stride_2_high_we = addr_hit[56] & reg_we & !reg_error; - assign dst_stride_2_high_wd = reg_wdata[31:0]; - - assign src_stride_2_low_we = addr_hit[57] & reg_we & !reg_error; - assign src_stride_2_low_wd = reg_wdata[31:0]; - - assign src_stride_2_high_we = addr_hit[58] & reg_we & !reg_error; - assign src_stride_2_high_wd = reg_wdata[31:0]; - - assign reps_2_low_we = addr_hit[59] & reg_we & !reg_error; - assign reps_2_low_wd = reg_wdata[31:0]; - - assign reps_2_high_we = addr_hit[60] & reg_we & !reg_error; - assign reps_2_high_wd = reg_wdata[31:0]; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[0] = conf_decouple_aw_qs; - reg_rdata_next[1] = conf_decouple_rw_qs; - reg_rdata_next[2] = conf_src_reduce_len_qs; - reg_rdata_next[3] = conf_dst_reduce_len_qs; - reg_rdata_next[6:4] = conf_src_max_llen_qs; - reg_rdata_next[9:7] = conf_dst_max_llen_qs; - reg_rdata_next[10] = conf_enable_nd_qs; - reg_rdata_next[13:11] = conf_src_protocol_qs; - reg_rdata_next[16:14] = conf_dst_protocol_qs; - end - - addr_hit[1]: begin - reg_rdata_next[9:0] = status_0_qs; - end - - addr_hit[2]: begin - reg_rdata_next[9:0] = status_1_qs; - end - - addr_hit[3]: begin - reg_rdata_next[9:0] = status_2_qs; - end - - addr_hit[4]: begin - reg_rdata_next[9:0] = status_3_qs; - end - - addr_hit[5]: begin - reg_rdata_next[9:0] = status_4_qs; - end - - addr_hit[6]: begin - reg_rdata_next[9:0] = status_5_qs; - end - - addr_hit[7]: begin - reg_rdata_next[9:0] = status_6_qs; - end - - addr_hit[8]: begin - reg_rdata_next[9:0] = status_7_qs; - end - - addr_hit[9]: begin - reg_rdata_next[9:0] = status_8_qs; - end - - addr_hit[10]: begin - reg_rdata_next[9:0] = status_9_qs; - end - - addr_hit[11]: begin - reg_rdata_next[9:0] = status_10_qs; - end - - addr_hit[12]: begin - reg_rdata_next[9:0] = status_11_qs; - end - - addr_hit[13]: begin - reg_rdata_next[9:0] = status_12_qs; - end - - addr_hit[14]: begin - reg_rdata_next[9:0] = status_13_qs; - end - - addr_hit[15]: begin - reg_rdata_next[9:0] = status_14_qs; - end - - addr_hit[16]: begin - reg_rdata_next[9:0] = status_15_qs; - end - - addr_hit[17]: begin - reg_rdata_next[31:0] = next_id_0_qs; - end - - addr_hit[18]: begin - reg_rdata_next[31:0] = next_id_1_qs; - end - - addr_hit[19]: begin - reg_rdata_next[31:0] = next_id_2_qs; - end - - addr_hit[20]: begin - reg_rdata_next[31:0] = next_id_3_qs; - end - - addr_hit[21]: begin - reg_rdata_next[31:0] = next_id_4_qs; - end - - addr_hit[22]: begin - reg_rdata_next[31:0] = next_id_5_qs; - end - - addr_hit[23]: begin - reg_rdata_next[31:0] = next_id_6_qs; - end - - addr_hit[24]: begin - reg_rdata_next[31:0] = next_id_7_qs; - end - - addr_hit[25]: begin - reg_rdata_next[31:0] = next_id_8_qs; - end - - addr_hit[26]: begin - reg_rdata_next[31:0] = next_id_9_qs; - end - - addr_hit[27]: begin - reg_rdata_next[31:0] = next_id_10_qs; - end - - addr_hit[28]: begin - reg_rdata_next[31:0] = next_id_11_qs; - end - - addr_hit[29]: begin - reg_rdata_next[31:0] = next_id_12_qs; - end - - addr_hit[30]: begin - reg_rdata_next[31:0] = next_id_13_qs; - end - - addr_hit[31]: begin - reg_rdata_next[31:0] = next_id_14_qs; - end - - addr_hit[32]: begin - reg_rdata_next[31:0] = next_id_15_qs; - end - - addr_hit[33]: begin - reg_rdata_next[31:0] = done_id_0_qs; - end - - addr_hit[34]: begin - reg_rdata_next[31:0] = done_id_1_qs; - end - - addr_hit[35]: begin - reg_rdata_next[31:0] = done_id_2_qs; - end - - addr_hit[36]: begin - reg_rdata_next[31:0] = done_id_3_qs; - end - - addr_hit[37]: begin - reg_rdata_next[31:0] = done_id_4_qs; - end - - addr_hit[38]: begin - reg_rdata_next[31:0] = done_id_5_qs; - end - - addr_hit[39]: begin - reg_rdata_next[31:0] = done_id_6_qs; - end - - addr_hit[40]: begin - reg_rdata_next[31:0] = done_id_7_qs; - end - - addr_hit[41]: begin - reg_rdata_next[31:0] = done_id_8_qs; - end - - addr_hit[42]: begin - reg_rdata_next[31:0] = done_id_9_qs; - end - - addr_hit[43]: begin - reg_rdata_next[31:0] = done_id_10_qs; - end - - addr_hit[44]: begin - reg_rdata_next[31:0] = done_id_11_qs; - end - - addr_hit[45]: begin - reg_rdata_next[31:0] = done_id_12_qs; - end - - addr_hit[46]: begin - reg_rdata_next[31:0] = done_id_13_qs; - end - - addr_hit[47]: begin - reg_rdata_next[31:0] = done_id_14_qs; - end - - addr_hit[48]: begin - reg_rdata_next[31:0] = done_id_15_qs; - end - - addr_hit[49]: begin - reg_rdata_next[31:0] = dst_addr_low_qs; - end - - addr_hit[50]: begin - reg_rdata_next[31:0] = dst_addr_high_qs; - end - - addr_hit[51]: begin - reg_rdata_next[31:0] = src_addr_low_qs; - end - - addr_hit[52]: begin - reg_rdata_next[31:0] = src_addr_high_qs; - end - - addr_hit[53]: begin - reg_rdata_next[31:0] = length_low_qs; - end - - addr_hit[54]: begin - reg_rdata_next[31:0] = length_high_qs; - end - - addr_hit[55]: begin - reg_rdata_next[31:0] = dst_stride_2_low_qs; - end - - addr_hit[56]: begin - reg_rdata_next[31:0] = dst_stride_2_high_qs; - end - - addr_hit[57]: begin - reg_rdata_next[31:0] = src_stride_2_low_qs; - end - - addr_hit[58]: begin - reg_rdata_next[31:0] = src_stride_2_high_qs; - end - - addr_hit[59]: begin - reg_rdata_next[31:0] = reps_2_low_qs; - end - - addr_hit[60]: begin - reg_rdata_next[31:0] = reps_2_high_qs; - end - - default: begin - reg_rdata_next = '1; - end - endcase - end - - // Unused signal tieoff - - // wdata / byte enable are not always fully used - // add a blanket unused statement to handle lint waivers - logic unused_wdata; - logic unused_be; - assign unused_wdata = ^reg_wdata; - assign unused_be = ^reg_be; - - // Assertions for Register Interface - `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) - -endmodule - -module idma_reg64_2d_reg_top_intf -#( - parameter int AW = 8, - localparam int DW = 32 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output idma_reg64_2d_reg_pkg::idma_reg64_2d_reg2hw_t reg2hw, // Write - input idma_reg64_2d_reg_pkg::idma_reg64_2d_hw2reg_t hw2reg, // Read - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - localparam int unsigned STRB_WIDTH = DW/8; - -`include "register_interface/typedef.svh" -`include "register_interface/assign.svh" - - // Define structs for reg_bus - typedef logic [AW-1:0] addr_t; - typedef logic [DW-1:0] data_t; - typedef logic [STRB_WIDTH-1:0] strb_t; - `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) - - reg_bus_req_t s_reg_req; - reg_bus_rsp_t s_reg_rsp; - - // Assign SV interface to structs - `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) - `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) - - - - idma_reg64_2d_reg_top #( - .reg_req_t(reg_bus_req_t), - .reg_rsp_t(reg_bus_rsp_t), - .AW(AW) - ) i_regs ( - .clk_i, - .rst_ni, - .reg_req_i(s_reg_req), - .reg_rsp_o(s_reg_rsp), - .reg2hw, // Write - .hw2reg, // Read - .devmode_i - ); - -endmodule - - -// Copyright lowRISC contributors. -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 -// -// Register Top module auto-generated by `reggen` - - -`include "common_cells/assertions.svh" - -module idma_reg64_1d_reg_top #( - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic, - parameter int AW = 8 -) ( - input logic clk_i, - input logic rst_ni, - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - // To HW - output idma_reg64_1d_reg_pkg::idma_reg64_1d_reg2hw_t reg2hw, // Write - input idma_reg64_1d_reg_pkg::idma_reg64_1d_hw2reg_t hw2reg, // Read - - - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - - import idma_reg64_1d_reg_pkg::* ; - - localparam int DW = 32; - localparam int DBW = DW/8; // Byte Width - - // register signals - logic reg_we; - logic reg_re; - logic [BlockAw-1:0] reg_addr; - logic [DW-1:0] reg_wdata; - logic [DBW-1:0] reg_be; - logic [DW-1:0] reg_rdata; - logic reg_error; - - logic addrmiss, wr_err; - - logic [DW-1:0] reg_rdata_next; - - // Below register interface can be changed - reg_req_t reg_intf_req; - reg_rsp_t reg_intf_rsp; - - - assign reg_intf_req = reg_req_i; - assign reg_rsp_o = reg_intf_rsp; - - - assign reg_we = reg_intf_req.valid & reg_intf_req.write; - assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; - assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; - assign reg_wdata = reg_intf_req.wdata; - assign reg_be = reg_intf_req.wstrb; - assign reg_intf_rsp.rdata = reg_rdata; - assign reg_intf_rsp.error = reg_error; - assign reg_intf_rsp.ready = 1'b1; - - assign reg_rdata = reg_rdata_next ; - assign reg_error = (devmode_i & addrmiss) | wr_err; - - - // Define SW related signals - // Format: __{wd|we|qs} - // or _{wd|we|qs} if field == 1 or 0 - logic conf_decouple_aw_qs; - logic conf_decouple_aw_wd; - logic conf_decouple_aw_we; - logic conf_decouple_rw_qs; - logic conf_decouple_rw_wd; - logic conf_decouple_rw_we; - logic conf_src_reduce_len_qs; - logic conf_src_reduce_len_wd; - logic conf_src_reduce_len_we; - logic conf_dst_reduce_len_qs; - logic conf_dst_reduce_len_wd; - logic conf_dst_reduce_len_we; - logic [2:0] conf_src_max_llen_qs; - logic [2:0] conf_src_max_llen_wd; - logic conf_src_max_llen_we; - logic [2:0] conf_dst_max_llen_qs; - logic [2:0] conf_dst_max_llen_wd; - logic conf_dst_max_llen_we; - logic conf_enable_nd_qs; - logic conf_enable_nd_wd; - logic conf_enable_nd_we; - logic [2:0] conf_src_protocol_qs; - logic [2:0] conf_src_protocol_wd; - logic conf_src_protocol_we; - logic [2:0] conf_dst_protocol_qs; - logic [2:0] conf_dst_protocol_wd; - logic conf_dst_protocol_we; - logic [9:0] status_0_qs; - logic status_0_re; - logic [9:0] status_1_qs; - logic status_1_re; - logic [9:0] status_2_qs; - logic status_2_re; - logic [9:0] status_3_qs; - logic status_3_re; - logic [9:0] status_4_qs; - logic status_4_re; - logic [9:0] status_5_qs; - logic status_5_re; - logic [9:0] status_6_qs; - logic status_6_re; - logic [9:0] status_7_qs; - logic status_7_re; - logic [9:0] status_8_qs; - logic status_8_re; - logic [9:0] status_9_qs; - logic status_9_re; - logic [9:0] status_10_qs; - logic status_10_re; - logic [9:0] status_11_qs; - logic status_11_re; - logic [9:0] status_12_qs; - logic status_12_re; - logic [9:0] status_13_qs; - logic status_13_re; - logic [9:0] status_14_qs; - logic status_14_re; - logic [9:0] status_15_qs; - logic status_15_re; - logic [31:0] next_id_0_qs; - logic next_id_0_re; - logic [31:0] next_id_1_qs; - logic next_id_1_re; - logic [31:0] next_id_2_qs; - logic next_id_2_re; - logic [31:0] next_id_3_qs; - logic next_id_3_re; - logic [31:0] next_id_4_qs; - logic next_id_4_re; - logic [31:0] next_id_5_qs; - logic next_id_5_re; - logic [31:0] next_id_6_qs; - logic next_id_6_re; - logic [31:0] next_id_7_qs; - logic next_id_7_re; - logic [31:0] next_id_8_qs; - logic next_id_8_re; - logic [31:0] next_id_9_qs; - logic next_id_9_re; - logic [31:0] next_id_10_qs; - logic next_id_10_re; - logic [31:0] next_id_11_qs; - logic next_id_11_re; - logic [31:0] next_id_12_qs; - logic next_id_12_re; - logic [31:0] next_id_13_qs; - logic next_id_13_re; - logic [31:0] next_id_14_qs; - logic next_id_14_re; - logic [31:0] next_id_15_qs; - logic next_id_15_re; - logic [31:0] done_id_0_qs; - logic done_id_0_re; - logic [31:0] done_id_1_qs; - logic done_id_1_re; - logic [31:0] done_id_2_qs; - logic done_id_2_re; - logic [31:0] done_id_3_qs; - logic done_id_3_re; - logic [31:0] done_id_4_qs; - logic done_id_4_re; - logic [31:0] done_id_5_qs; - logic done_id_5_re; - logic [31:0] done_id_6_qs; - logic done_id_6_re; - logic [31:0] done_id_7_qs; - logic done_id_7_re; - logic [31:0] done_id_8_qs; - logic done_id_8_re; - logic [31:0] done_id_9_qs; - logic done_id_9_re; - logic [31:0] done_id_10_qs; - logic done_id_10_re; - logic [31:0] done_id_11_qs; - logic done_id_11_re; - logic [31:0] done_id_12_qs; - logic done_id_12_re; - logic [31:0] done_id_13_qs; - logic done_id_13_re; - logic [31:0] done_id_14_qs; - logic done_id_14_re; - logic [31:0] done_id_15_qs; - logic done_id_15_re; - logic [31:0] dst_addr_low_qs; - logic [31:0] dst_addr_low_wd; - logic dst_addr_low_we; - logic [31:0] dst_addr_high_qs; - logic [31:0] dst_addr_high_wd; - logic dst_addr_high_we; - logic [31:0] src_addr_low_qs; - logic [31:0] src_addr_low_wd; - logic src_addr_low_we; - logic [31:0] src_addr_high_qs; - logic [31:0] src_addr_high_wd; - logic src_addr_high_we; - logic [31:0] length_low_qs; - logic [31:0] length_low_wd; - logic length_low_we; - logic [31:0] length_high_qs; - logic [31:0] length_high_wd; - logic length_high_we; - - // Register instances - // R[conf]: V(False) - - // F[decouple_aw]: 0:0 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_decouple_aw ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_decouple_aw_we), - .wd (conf_decouple_aw_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.decouple_aw.q ), - - // to register interface (read) - .qs (conf_decouple_aw_qs) - ); - - - // F[decouple_rw]: 1:1 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_decouple_rw ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_decouple_rw_we), - .wd (conf_decouple_rw_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.decouple_rw.q ), - - // to register interface (read) - .qs (conf_decouple_rw_qs) - ); - - - // F[src_reduce_len]: 2:2 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_src_reduce_len ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_reduce_len_we), - .wd (conf_src_reduce_len_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_reduce_len.q ), - - // to register interface (read) - .qs (conf_src_reduce_len_qs) - ); - - - // F[dst_reduce_len]: 3:3 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_dst_reduce_len ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_reduce_len_we), - .wd (conf_dst_reduce_len_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_reduce_len.q ), - - // to register interface (read) - .qs (conf_dst_reduce_len_qs) - ); - - - // F[src_max_llen]: 6:4 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_src_max_llen ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_max_llen_we), - .wd (conf_src_max_llen_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_max_llen.q ), - - // to register interface (read) - .qs (conf_src_max_llen_qs) - ); - - - // F[dst_max_llen]: 9:7 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_dst_max_llen ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_max_llen_we), - .wd (conf_dst_max_llen_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_max_llen.q ), - - // to register interface (read) - .qs (conf_dst_max_llen_qs) - ); - - - // F[enable_nd]: 10:10 - prim_subreg #( - .DW (1), - .SWACCESS("RW"), - .RESVAL (1'h0) - ) u_conf_enable_nd ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_enable_nd_we), - .wd (conf_enable_nd_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.enable_nd.q ), - - // to register interface (read) - .qs (conf_enable_nd_qs) - ); - - - // F[src_protocol]: 13:11 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_src_protocol ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_src_protocol_we), - .wd (conf_src_protocol_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.src_protocol.q ), - - // to register interface (read) - .qs (conf_src_protocol_qs) - ); - - - // F[dst_protocol]: 16:14 - prim_subreg #( - .DW (3), - .SWACCESS("RW"), - .RESVAL (3'h0) - ) u_conf_dst_protocol ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (conf_dst_protocol_we), - .wd (conf_dst_protocol_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.conf.dst_protocol.q ), - - // to register interface (read) - .qs (conf_dst_protocol_qs) - ); - - - - // Subregister 0 of Multireg status - // R[status_0]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_0 ( - .re (status_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[0].d), - .qre (), - .qe (), - .q (), - .qs (status_0_qs) - ); - - // Subregister 1 of Multireg status - // R[status_1]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_1 ( - .re (status_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[1].d), - .qre (), - .qe (), - .q (), - .qs (status_1_qs) - ); - - // Subregister 2 of Multireg status - // R[status_2]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_2 ( - .re (status_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[2].d), - .qre (), - .qe (), - .q (), - .qs (status_2_qs) - ); - - // Subregister 3 of Multireg status - // R[status_3]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_3 ( - .re (status_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[3].d), - .qre (), - .qe (), - .q (), - .qs (status_3_qs) - ); - - // Subregister 4 of Multireg status - // R[status_4]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_4 ( - .re (status_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[4].d), - .qre (), - .qe (), - .q (), - .qs (status_4_qs) - ); - - // Subregister 5 of Multireg status - // R[status_5]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_5 ( - .re (status_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[5].d), - .qre (), - .qe (), - .q (), - .qs (status_5_qs) - ); - - // Subregister 6 of Multireg status - // R[status_6]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_6 ( - .re (status_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[6].d), - .qre (), - .qe (), - .q (), - .qs (status_6_qs) - ); - - // Subregister 7 of Multireg status - // R[status_7]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_7 ( - .re (status_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[7].d), - .qre (), - .qe (), - .q (), - .qs (status_7_qs) - ); - - // Subregister 8 of Multireg status - // R[status_8]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_8 ( - .re (status_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[8].d), - .qre (), - .qe (), - .q (), - .qs (status_8_qs) - ); - - // Subregister 9 of Multireg status - // R[status_9]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_9 ( - .re (status_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[9].d), - .qre (), - .qe (), - .q (), - .qs (status_9_qs) - ); - - // Subregister 10 of Multireg status - // R[status_10]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_10 ( - .re (status_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[10].d), - .qre (), - .qe (), - .q (), - .qs (status_10_qs) - ); - - // Subregister 11 of Multireg status - // R[status_11]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_11 ( - .re (status_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[11].d), - .qre (), - .qe (), - .q (), - .qs (status_11_qs) - ); - - // Subregister 12 of Multireg status - // R[status_12]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_12 ( - .re (status_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[12].d), - .qre (), - .qe (), - .q (), - .qs (status_12_qs) - ); - - // Subregister 13 of Multireg status - // R[status_13]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_13 ( - .re (status_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[13].d), - .qre (), - .qe (), - .q (), - .qs (status_13_qs) - ); - - // Subregister 14 of Multireg status - // R[status_14]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_14 ( - .re (status_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[14].d), - .qre (), - .qe (), - .q (), - .qs (status_14_qs) - ); - - // Subregister 15 of Multireg status - // R[status_15]: V(True) - - prim_subreg_ext #( - .DW (10) - ) u_status_15 ( - .re (status_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.status[15].d), - .qre (), - .qe (), - .q (), - .qs (status_15_qs) - ); - - - - // Subregister 0 of Multireg next_id - // R[next_id_0]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_0 ( - .re (next_id_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[0].d), - .qre (reg2hw.next_id[0].re), - .qe (), - .q (reg2hw.next_id[0].q ), - .qs (next_id_0_qs) - ); - - // Subregister 1 of Multireg next_id - // R[next_id_1]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_1 ( - .re (next_id_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[1].d), - .qre (reg2hw.next_id[1].re), - .qe (), - .q (reg2hw.next_id[1].q ), - .qs (next_id_1_qs) - ); - - // Subregister 2 of Multireg next_id - // R[next_id_2]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_2 ( - .re (next_id_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[2].d), - .qre (reg2hw.next_id[2].re), - .qe (), - .q (reg2hw.next_id[2].q ), - .qs (next_id_2_qs) - ); - - // Subregister 3 of Multireg next_id - // R[next_id_3]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_3 ( - .re (next_id_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[3].d), - .qre (reg2hw.next_id[3].re), - .qe (), - .q (reg2hw.next_id[3].q ), - .qs (next_id_3_qs) - ); - - // Subregister 4 of Multireg next_id - // R[next_id_4]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_4 ( - .re (next_id_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[4].d), - .qre (reg2hw.next_id[4].re), - .qe (), - .q (reg2hw.next_id[4].q ), - .qs (next_id_4_qs) - ); - - // Subregister 5 of Multireg next_id - // R[next_id_5]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_5 ( - .re (next_id_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[5].d), - .qre (reg2hw.next_id[5].re), - .qe (), - .q (reg2hw.next_id[5].q ), - .qs (next_id_5_qs) - ); - - // Subregister 6 of Multireg next_id - // R[next_id_6]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_6 ( - .re (next_id_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[6].d), - .qre (reg2hw.next_id[6].re), - .qe (), - .q (reg2hw.next_id[6].q ), - .qs (next_id_6_qs) - ); - - // Subregister 7 of Multireg next_id - // R[next_id_7]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_7 ( - .re (next_id_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[7].d), - .qre (reg2hw.next_id[7].re), - .qe (), - .q (reg2hw.next_id[7].q ), - .qs (next_id_7_qs) - ); - - // Subregister 8 of Multireg next_id - // R[next_id_8]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_8 ( - .re (next_id_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[8].d), - .qre (reg2hw.next_id[8].re), - .qe (), - .q (reg2hw.next_id[8].q ), - .qs (next_id_8_qs) - ); - - // Subregister 9 of Multireg next_id - // R[next_id_9]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_9 ( - .re (next_id_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[9].d), - .qre (reg2hw.next_id[9].re), - .qe (), - .q (reg2hw.next_id[9].q ), - .qs (next_id_9_qs) - ); - - // Subregister 10 of Multireg next_id - // R[next_id_10]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_10 ( - .re (next_id_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[10].d), - .qre (reg2hw.next_id[10].re), - .qe (), - .q (reg2hw.next_id[10].q ), - .qs (next_id_10_qs) - ); - - // Subregister 11 of Multireg next_id - // R[next_id_11]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_11 ( - .re (next_id_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[11].d), - .qre (reg2hw.next_id[11].re), - .qe (), - .q (reg2hw.next_id[11].q ), - .qs (next_id_11_qs) - ); - - // Subregister 12 of Multireg next_id - // R[next_id_12]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_12 ( - .re (next_id_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[12].d), - .qre (reg2hw.next_id[12].re), - .qe (), - .q (reg2hw.next_id[12].q ), - .qs (next_id_12_qs) - ); - - // Subregister 13 of Multireg next_id - // R[next_id_13]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_13 ( - .re (next_id_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[13].d), - .qre (reg2hw.next_id[13].re), - .qe (), - .q (reg2hw.next_id[13].q ), - .qs (next_id_13_qs) - ); - - // Subregister 14 of Multireg next_id - // R[next_id_14]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_14 ( - .re (next_id_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[14].d), - .qre (reg2hw.next_id[14].re), - .qe (), - .q (reg2hw.next_id[14].q ), - .qs (next_id_14_qs) - ); - - // Subregister 15 of Multireg next_id - // R[next_id_15]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_next_id_15 ( - .re (next_id_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.next_id[15].d), - .qre (reg2hw.next_id[15].re), - .qe (), - .q (reg2hw.next_id[15].q ), - .qs (next_id_15_qs) - ); - - - - // Subregister 0 of Multireg done_id - // R[done_id_0]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_0 ( - .re (done_id_0_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[0].d), - .qre (), - .qe (), - .q (), - .qs (done_id_0_qs) - ); - - // Subregister 1 of Multireg done_id - // R[done_id_1]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_1 ( - .re (done_id_1_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[1].d), - .qre (), - .qe (), - .q (), - .qs (done_id_1_qs) - ); - - // Subregister 2 of Multireg done_id - // R[done_id_2]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_2 ( - .re (done_id_2_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[2].d), - .qre (), - .qe (), - .q (), - .qs (done_id_2_qs) - ); - - // Subregister 3 of Multireg done_id - // R[done_id_3]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_3 ( - .re (done_id_3_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[3].d), - .qre (), - .qe (), - .q (), - .qs (done_id_3_qs) - ); - - // Subregister 4 of Multireg done_id - // R[done_id_4]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_4 ( - .re (done_id_4_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[4].d), - .qre (), - .qe (), - .q (), - .qs (done_id_4_qs) - ); - - // Subregister 5 of Multireg done_id - // R[done_id_5]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_5 ( - .re (done_id_5_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[5].d), - .qre (), - .qe (), - .q (), - .qs (done_id_5_qs) - ); - - // Subregister 6 of Multireg done_id - // R[done_id_6]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_6 ( - .re (done_id_6_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[6].d), - .qre (), - .qe (), - .q (), - .qs (done_id_6_qs) - ); - - // Subregister 7 of Multireg done_id - // R[done_id_7]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_7 ( - .re (done_id_7_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[7].d), - .qre (), - .qe (), - .q (), - .qs (done_id_7_qs) - ); - - // Subregister 8 of Multireg done_id - // R[done_id_8]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_8 ( - .re (done_id_8_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[8].d), - .qre (), - .qe (), - .q (), - .qs (done_id_8_qs) - ); - - // Subregister 9 of Multireg done_id - // R[done_id_9]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_9 ( - .re (done_id_9_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[9].d), - .qre (), - .qe (), - .q (), - .qs (done_id_9_qs) - ); - - // Subregister 10 of Multireg done_id - // R[done_id_10]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_10 ( - .re (done_id_10_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[10].d), - .qre (), - .qe (), - .q (), - .qs (done_id_10_qs) - ); - - // Subregister 11 of Multireg done_id - // R[done_id_11]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_11 ( - .re (done_id_11_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[11].d), - .qre (), - .qe (), - .q (), - .qs (done_id_11_qs) - ); - - // Subregister 12 of Multireg done_id - // R[done_id_12]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_12 ( - .re (done_id_12_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[12].d), - .qre (), - .qe (), - .q (), - .qs (done_id_12_qs) - ); - - // Subregister 13 of Multireg done_id - // R[done_id_13]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_13 ( - .re (done_id_13_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[13].d), - .qre (), - .qe (), - .q (), - .qs (done_id_13_qs) - ); - - // Subregister 14 of Multireg done_id - // R[done_id_14]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_14 ( - .re (done_id_14_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[14].d), - .qre (), - .qe (), - .q (), - .qs (done_id_14_qs) - ); - - // Subregister 15 of Multireg done_id - // R[done_id_15]: V(True) - - prim_subreg_ext #( - .DW (32) - ) u_done_id_15 ( - .re (done_id_15_re), - .we (1'b0), - .wd ('0), - .d (hw2reg.done_id[15].d), - .qre (), - .qe (), - .q (), - .qs (done_id_15_qs) - ); - - - // R[dst_addr_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_addr_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_addr_low_we), - .wd (dst_addr_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_addr_low.q ), - - // to register interface (read) - .qs (dst_addr_low_qs) - ); - - - // R[dst_addr_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_dst_addr_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (dst_addr_high_we), - .wd (dst_addr_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.dst_addr_high.q ), - - // to register interface (read) - .qs (dst_addr_high_qs) - ); - - - // R[src_addr_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_addr_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_addr_low_we), - .wd (src_addr_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_addr_low.q ), - - // to register interface (read) - .qs (src_addr_low_qs) - ); - - - // R[src_addr_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_src_addr_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (src_addr_high_we), - .wd (src_addr_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.src_addr_high.q ), - - // to register interface (read) - .qs (src_addr_high_qs) - ); - - - // R[length_low]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_length_low ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (length_low_we), - .wd (length_low_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.length_low.q ), - - // to register interface (read) - .qs (length_low_qs) - ); - - - // R[length_high]: V(False) - - prim_subreg #( - .DW (32), - .SWACCESS("RW"), - .RESVAL (32'h0) - ) u_length_high ( - .clk_i (clk_i ), - .rst_ni (rst_ni ), - - // from register interface - .we (length_high_we), - .wd (length_high_wd), - - // from internal hardware - .de (1'b0), - .d ('0 ), - - // to internal hardware - .qe (), - .q (reg2hw.length_high.q ), - - // to register interface (read) - .qs (length_high_qs) - ); - - - - - logic [54:0] addr_hit; - always_comb begin - addr_hit = '0; - addr_hit[ 0] = (reg_addr == IDMA_REG64_1D_CONF_OFFSET); - addr_hit[ 1] = (reg_addr == IDMA_REG64_1D_STATUS_0_OFFSET); - addr_hit[ 2] = (reg_addr == IDMA_REG64_1D_STATUS_1_OFFSET); - addr_hit[ 3] = (reg_addr == IDMA_REG64_1D_STATUS_2_OFFSET); - addr_hit[ 4] = (reg_addr == IDMA_REG64_1D_STATUS_3_OFFSET); - addr_hit[ 5] = (reg_addr == IDMA_REG64_1D_STATUS_4_OFFSET); - addr_hit[ 6] = (reg_addr == IDMA_REG64_1D_STATUS_5_OFFSET); - addr_hit[ 7] = (reg_addr == IDMA_REG64_1D_STATUS_6_OFFSET); - addr_hit[ 8] = (reg_addr == IDMA_REG64_1D_STATUS_7_OFFSET); - addr_hit[ 9] = (reg_addr == IDMA_REG64_1D_STATUS_8_OFFSET); - addr_hit[10] = (reg_addr == IDMA_REG64_1D_STATUS_9_OFFSET); - addr_hit[11] = (reg_addr == IDMA_REG64_1D_STATUS_10_OFFSET); - addr_hit[12] = (reg_addr == IDMA_REG64_1D_STATUS_11_OFFSET); - addr_hit[13] = (reg_addr == IDMA_REG64_1D_STATUS_12_OFFSET); - addr_hit[14] = (reg_addr == IDMA_REG64_1D_STATUS_13_OFFSET); - addr_hit[15] = (reg_addr == IDMA_REG64_1D_STATUS_14_OFFSET); - addr_hit[16] = (reg_addr == IDMA_REG64_1D_STATUS_15_OFFSET); - addr_hit[17] = (reg_addr == IDMA_REG64_1D_NEXT_ID_0_OFFSET); - addr_hit[18] = (reg_addr == IDMA_REG64_1D_NEXT_ID_1_OFFSET); - addr_hit[19] = (reg_addr == IDMA_REG64_1D_NEXT_ID_2_OFFSET); - addr_hit[20] = (reg_addr == IDMA_REG64_1D_NEXT_ID_3_OFFSET); - addr_hit[21] = (reg_addr == IDMA_REG64_1D_NEXT_ID_4_OFFSET); - addr_hit[22] = (reg_addr == IDMA_REG64_1D_NEXT_ID_5_OFFSET); - addr_hit[23] = (reg_addr == IDMA_REG64_1D_NEXT_ID_6_OFFSET); - addr_hit[24] = (reg_addr == IDMA_REG64_1D_NEXT_ID_7_OFFSET); - addr_hit[25] = (reg_addr == IDMA_REG64_1D_NEXT_ID_8_OFFSET); - addr_hit[26] = (reg_addr == IDMA_REG64_1D_NEXT_ID_9_OFFSET); - addr_hit[27] = (reg_addr == IDMA_REG64_1D_NEXT_ID_10_OFFSET); - addr_hit[28] = (reg_addr == IDMA_REG64_1D_NEXT_ID_11_OFFSET); - addr_hit[29] = (reg_addr == IDMA_REG64_1D_NEXT_ID_12_OFFSET); - addr_hit[30] = (reg_addr == IDMA_REG64_1D_NEXT_ID_13_OFFSET); - addr_hit[31] = (reg_addr == IDMA_REG64_1D_NEXT_ID_14_OFFSET); - addr_hit[32] = (reg_addr == IDMA_REG64_1D_NEXT_ID_15_OFFSET); - addr_hit[33] = (reg_addr == IDMA_REG64_1D_DONE_ID_0_OFFSET); - addr_hit[34] = (reg_addr == IDMA_REG64_1D_DONE_ID_1_OFFSET); - addr_hit[35] = (reg_addr == IDMA_REG64_1D_DONE_ID_2_OFFSET); - addr_hit[36] = (reg_addr == IDMA_REG64_1D_DONE_ID_3_OFFSET); - addr_hit[37] = (reg_addr == IDMA_REG64_1D_DONE_ID_4_OFFSET); - addr_hit[38] = (reg_addr == IDMA_REG64_1D_DONE_ID_5_OFFSET); - addr_hit[39] = (reg_addr == IDMA_REG64_1D_DONE_ID_6_OFFSET); - addr_hit[40] = (reg_addr == IDMA_REG64_1D_DONE_ID_7_OFFSET); - addr_hit[41] = (reg_addr == IDMA_REG64_1D_DONE_ID_8_OFFSET); - addr_hit[42] = (reg_addr == IDMA_REG64_1D_DONE_ID_9_OFFSET); - addr_hit[43] = (reg_addr == IDMA_REG64_1D_DONE_ID_10_OFFSET); - addr_hit[44] = (reg_addr == IDMA_REG64_1D_DONE_ID_11_OFFSET); - addr_hit[45] = (reg_addr == IDMA_REG64_1D_DONE_ID_12_OFFSET); - addr_hit[46] = (reg_addr == IDMA_REG64_1D_DONE_ID_13_OFFSET); - addr_hit[47] = (reg_addr == IDMA_REG64_1D_DONE_ID_14_OFFSET); - addr_hit[48] = (reg_addr == IDMA_REG64_1D_DONE_ID_15_OFFSET); - addr_hit[49] = (reg_addr == IDMA_REG64_1D_DST_ADDR_LOW_OFFSET); - addr_hit[50] = (reg_addr == IDMA_REG64_1D_DST_ADDR_HIGH_OFFSET); - addr_hit[51] = (reg_addr == IDMA_REG64_1D_SRC_ADDR_LOW_OFFSET); - addr_hit[52] = (reg_addr == IDMA_REG64_1D_SRC_ADDR_HIGH_OFFSET); - addr_hit[53] = (reg_addr == IDMA_REG64_1D_LENGTH_LOW_OFFSET); - addr_hit[54] = (reg_addr == IDMA_REG64_1D_LENGTH_HIGH_OFFSET); - end - - assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; - - // Check sub-word write is permitted - always_comb begin - wr_err = (reg_we & - ((addr_hit[ 0] & (|(IDMA_REG64_1D_PERMIT[ 0] & ~reg_be))) | - (addr_hit[ 1] & (|(IDMA_REG64_1D_PERMIT[ 1] & ~reg_be))) | - (addr_hit[ 2] & (|(IDMA_REG64_1D_PERMIT[ 2] & ~reg_be))) | - (addr_hit[ 3] & (|(IDMA_REG64_1D_PERMIT[ 3] & ~reg_be))) | - (addr_hit[ 4] & (|(IDMA_REG64_1D_PERMIT[ 4] & ~reg_be))) | - (addr_hit[ 5] & (|(IDMA_REG64_1D_PERMIT[ 5] & ~reg_be))) | - (addr_hit[ 6] & (|(IDMA_REG64_1D_PERMIT[ 6] & ~reg_be))) | - (addr_hit[ 7] & (|(IDMA_REG64_1D_PERMIT[ 7] & ~reg_be))) | - (addr_hit[ 8] & (|(IDMA_REG64_1D_PERMIT[ 8] & ~reg_be))) | - (addr_hit[ 9] & (|(IDMA_REG64_1D_PERMIT[ 9] & ~reg_be))) | - (addr_hit[10] & (|(IDMA_REG64_1D_PERMIT[10] & ~reg_be))) | - (addr_hit[11] & (|(IDMA_REG64_1D_PERMIT[11] & ~reg_be))) | - (addr_hit[12] & (|(IDMA_REG64_1D_PERMIT[12] & ~reg_be))) | - (addr_hit[13] & (|(IDMA_REG64_1D_PERMIT[13] & ~reg_be))) | - (addr_hit[14] & (|(IDMA_REG64_1D_PERMIT[14] & ~reg_be))) | - (addr_hit[15] & (|(IDMA_REG64_1D_PERMIT[15] & ~reg_be))) | - (addr_hit[16] & (|(IDMA_REG64_1D_PERMIT[16] & ~reg_be))) | - (addr_hit[17] & (|(IDMA_REG64_1D_PERMIT[17] & ~reg_be))) | - (addr_hit[18] & (|(IDMA_REG64_1D_PERMIT[18] & ~reg_be))) | - (addr_hit[19] & (|(IDMA_REG64_1D_PERMIT[19] & ~reg_be))) | - (addr_hit[20] & (|(IDMA_REG64_1D_PERMIT[20] & ~reg_be))) | - (addr_hit[21] & (|(IDMA_REG64_1D_PERMIT[21] & ~reg_be))) | - (addr_hit[22] & (|(IDMA_REG64_1D_PERMIT[22] & ~reg_be))) | - (addr_hit[23] & (|(IDMA_REG64_1D_PERMIT[23] & ~reg_be))) | - (addr_hit[24] & (|(IDMA_REG64_1D_PERMIT[24] & ~reg_be))) | - (addr_hit[25] & (|(IDMA_REG64_1D_PERMIT[25] & ~reg_be))) | - (addr_hit[26] & (|(IDMA_REG64_1D_PERMIT[26] & ~reg_be))) | - (addr_hit[27] & (|(IDMA_REG64_1D_PERMIT[27] & ~reg_be))) | - (addr_hit[28] & (|(IDMA_REG64_1D_PERMIT[28] & ~reg_be))) | - (addr_hit[29] & (|(IDMA_REG64_1D_PERMIT[29] & ~reg_be))) | - (addr_hit[30] & (|(IDMA_REG64_1D_PERMIT[30] & ~reg_be))) | - (addr_hit[31] & (|(IDMA_REG64_1D_PERMIT[31] & ~reg_be))) | - (addr_hit[32] & (|(IDMA_REG64_1D_PERMIT[32] & ~reg_be))) | - (addr_hit[33] & (|(IDMA_REG64_1D_PERMIT[33] & ~reg_be))) | - (addr_hit[34] & (|(IDMA_REG64_1D_PERMIT[34] & ~reg_be))) | - (addr_hit[35] & (|(IDMA_REG64_1D_PERMIT[35] & ~reg_be))) | - (addr_hit[36] & (|(IDMA_REG64_1D_PERMIT[36] & ~reg_be))) | - (addr_hit[37] & (|(IDMA_REG64_1D_PERMIT[37] & ~reg_be))) | - (addr_hit[38] & (|(IDMA_REG64_1D_PERMIT[38] & ~reg_be))) | - (addr_hit[39] & (|(IDMA_REG64_1D_PERMIT[39] & ~reg_be))) | - (addr_hit[40] & (|(IDMA_REG64_1D_PERMIT[40] & ~reg_be))) | - (addr_hit[41] & (|(IDMA_REG64_1D_PERMIT[41] & ~reg_be))) | - (addr_hit[42] & (|(IDMA_REG64_1D_PERMIT[42] & ~reg_be))) | - (addr_hit[43] & (|(IDMA_REG64_1D_PERMIT[43] & ~reg_be))) | - (addr_hit[44] & (|(IDMA_REG64_1D_PERMIT[44] & ~reg_be))) | - (addr_hit[45] & (|(IDMA_REG64_1D_PERMIT[45] & ~reg_be))) | - (addr_hit[46] & (|(IDMA_REG64_1D_PERMIT[46] & ~reg_be))) | - (addr_hit[47] & (|(IDMA_REG64_1D_PERMIT[47] & ~reg_be))) | - (addr_hit[48] & (|(IDMA_REG64_1D_PERMIT[48] & ~reg_be))) | - (addr_hit[49] & (|(IDMA_REG64_1D_PERMIT[49] & ~reg_be))) | - (addr_hit[50] & (|(IDMA_REG64_1D_PERMIT[50] & ~reg_be))) | - (addr_hit[51] & (|(IDMA_REG64_1D_PERMIT[51] & ~reg_be))) | - (addr_hit[52] & (|(IDMA_REG64_1D_PERMIT[52] & ~reg_be))) | - (addr_hit[53] & (|(IDMA_REG64_1D_PERMIT[53] & ~reg_be))) | - (addr_hit[54] & (|(IDMA_REG64_1D_PERMIT[54] & ~reg_be))))); - end - - assign conf_decouple_aw_we = addr_hit[0] & reg_we & !reg_error; - assign conf_decouple_aw_wd = reg_wdata[0]; - - assign conf_decouple_rw_we = addr_hit[0] & reg_we & !reg_error; - assign conf_decouple_rw_wd = reg_wdata[1]; - - assign conf_src_reduce_len_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_reduce_len_wd = reg_wdata[2]; - - assign conf_dst_reduce_len_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_reduce_len_wd = reg_wdata[3]; - - assign conf_src_max_llen_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_max_llen_wd = reg_wdata[6:4]; - - assign conf_dst_max_llen_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_max_llen_wd = reg_wdata[9:7]; - - assign conf_enable_nd_we = addr_hit[0] & reg_we & !reg_error; - assign conf_enable_nd_wd = reg_wdata[10]; - - assign conf_src_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_src_protocol_wd = reg_wdata[13:11]; - - assign conf_dst_protocol_we = addr_hit[0] & reg_we & !reg_error; - assign conf_dst_protocol_wd = reg_wdata[16:14]; - - assign status_0_re = addr_hit[1] & reg_re & !reg_error; - - assign status_1_re = addr_hit[2] & reg_re & !reg_error; - - assign status_2_re = addr_hit[3] & reg_re & !reg_error; - - assign status_3_re = addr_hit[4] & reg_re & !reg_error; - - assign status_4_re = addr_hit[5] & reg_re & !reg_error; - - assign status_5_re = addr_hit[6] & reg_re & !reg_error; - - assign status_6_re = addr_hit[7] & reg_re & !reg_error; - - assign status_7_re = addr_hit[8] & reg_re & !reg_error; - - assign status_8_re = addr_hit[9] & reg_re & !reg_error; - - assign status_9_re = addr_hit[10] & reg_re & !reg_error; - - assign status_10_re = addr_hit[11] & reg_re & !reg_error; - - assign status_11_re = addr_hit[12] & reg_re & !reg_error; - - assign status_12_re = addr_hit[13] & reg_re & !reg_error; - - assign status_13_re = addr_hit[14] & reg_re & !reg_error; - - assign status_14_re = addr_hit[15] & reg_re & !reg_error; - - assign status_15_re = addr_hit[16] & reg_re & !reg_error; - - assign next_id_0_re = addr_hit[17] & reg_re & !reg_error; - - assign next_id_1_re = addr_hit[18] & reg_re & !reg_error; - - assign next_id_2_re = addr_hit[19] & reg_re & !reg_error; - - assign next_id_3_re = addr_hit[20] & reg_re & !reg_error; - - assign next_id_4_re = addr_hit[21] & reg_re & !reg_error; - - assign next_id_5_re = addr_hit[22] & reg_re & !reg_error; - - assign next_id_6_re = addr_hit[23] & reg_re & !reg_error; - - assign next_id_7_re = addr_hit[24] & reg_re & !reg_error; - - assign next_id_8_re = addr_hit[25] & reg_re & !reg_error; - - assign next_id_9_re = addr_hit[26] & reg_re & !reg_error; - - assign next_id_10_re = addr_hit[27] & reg_re & !reg_error; - - assign next_id_11_re = addr_hit[28] & reg_re & !reg_error; - - assign next_id_12_re = addr_hit[29] & reg_re & !reg_error; - - assign next_id_13_re = addr_hit[30] & reg_re & !reg_error; - - assign next_id_14_re = addr_hit[31] & reg_re & !reg_error; - - assign next_id_15_re = addr_hit[32] & reg_re & !reg_error; - - assign done_id_0_re = addr_hit[33] & reg_re & !reg_error; - - assign done_id_1_re = addr_hit[34] & reg_re & !reg_error; - - assign done_id_2_re = addr_hit[35] & reg_re & !reg_error; - - assign done_id_3_re = addr_hit[36] & reg_re & !reg_error; - - assign done_id_4_re = addr_hit[37] & reg_re & !reg_error; - - assign done_id_5_re = addr_hit[38] & reg_re & !reg_error; - - assign done_id_6_re = addr_hit[39] & reg_re & !reg_error; - - assign done_id_7_re = addr_hit[40] & reg_re & !reg_error; - - assign done_id_8_re = addr_hit[41] & reg_re & !reg_error; - - assign done_id_9_re = addr_hit[42] & reg_re & !reg_error; - - assign done_id_10_re = addr_hit[43] & reg_re & !reg_error; - - assign done_id_11_re = addr_hit[44] & reg_re & !reg_error; - - assign done_id_12_re = addr_hit[45] & reg_re & !reg_error; - - assign done_id_13_re = addr_hit[46] & reg_re & !reg_error; - - assign done_id_14_re = addr_hit[47] & reg_re & !reg_error; - - assign done_id_15_re = addr_hit[48] & reg_re & !reg_error; - - assign dst_addr_low_we = addr_hit[49] & reg_we & !reg_error; - assign dst_addr_low_wd = reg_wdata[31:0]; - - assign dst_addr_high_we = addr_hit[50] & reg_we & !reg_error; - assign dst_addr_high_wd = reg_wdata[31:0]; - - assign src_addr_low_we = addr_hit[51] & reg_we & !reg_error; - assign src_addr_low_wd = reg_wdata[31:0]; - - assign src_addr_high_we = addr_hit[52] & reg_we & !reg_error; - assign src_addr_high_wd = reg_wdata[31:0]; - - assign length_low_we = addr_hit[53] & reg_we & !reg_error; - assign length_low_wd = reg_wdata[31:0]; - - assign length_high_we = addr_hit[54] & reg_we & !reg_error; - assign length_high_wd = reg_wdata[31:0]; - - // Read data return - always_comb begin - reg_rdata_next = '0; - unique case (1'b1) - addr_hit[0]: begin - reg_rdata_next[0] = conf_decouple_aw_qs; - reg_rdata_next[1] = conf_decouple_rw_qs; - reg_rdata_next[2] = conf_src_reduce_len_qs; - reg_rdata_next[3] = conf_dst_reduce_len_qs; - reg_rdata_next[6:4] = conf_src_max_llen_qs; - reg_rdata_next[9:7] = conf_dst_max_llen_qs; - reg_rdata_next[10] = conf_enable_nd_qs; - reg_rdata_next[13:11] = conf_src_protocol_qs; - reg_rdata_next[16:14] = conf_dst_protocol_qs; - end - - addr_hit[1]: begin - reg_rdata_next[9:0] = status_0_qs; - end - - addr_hit[2]: begin - reg_rdata_next[9:0] = status_1_qs; - end - - addr_hit[3]: begin - reg_rdata_next[9:0] = status_2_qs; - end - - addr_hit[4]: begin - reg_rdata_next[9:0] = status_3_qs; - end - - addr_hit[5]: begin - reg_rdata_next[9:0] = status_4_qs; - end - - addr_hit[6]: begin - reg_rdata_next[9:0] = status_5_qs; - end - - addr_hit[7]: begin - reg_rdata_next[9:0] = status_6_qs; - end - - addr_hit[8]: begin - reg_rdata_next[9:0] = status_7_qs; - end - - addr_hit[9]: begin - reg_rdata_next[9:0] = status_8_qs; - end - - addr_hit[10]: begin - reg_rdata_next[9:0] = status_9_qs; - end - - addr_hit[11]: begin - reg_rdata_next[9:0] = status_10_qs; - end - - addr_hit[12]: begin - reg_rdata_next[9:0] = status_11_qs; - end - - addr_hit[13]: begin - reg_rdata_next[9:0] = status_12_qs; - end - - addr_hit[14]: begin - reg_rdata_next[9:0] = status_13_qs; - end - - addr_hit[15]: begin - reg_rdata_next[9:0] = status_14_qs; - end - - addr_hit[16]: begin - reg_rdata_next[9:0] = status_15_qs; - end - - addr_hit[17]: begin - reg_rdata_next[31:0] = next_id_0_qs; - end - - addr_hit[18]: begin - reg_rdata_next[31:0] = next_id_1_qs; - end - - addr_hit[19]: begin - reg_rdata_next[31:0] = next_id_2_qs; - end - - addr_hit[20]: begin - reg_rdata_next[31:0] = next_id_3_qs; - end - - addr_hit[21]: begin - reg_rdata_next[31:0] = next_id_4_qs; - end - - addr_hit[22]: begin - reg_rdata_next[31:0] = next_id_5_qs; - end - - addr_hit[23]: begin - reg_rdata_next[31:0] = next_id_6_qs; - end - - addr_hit[24]: begin - reg_rdata_next[31:0] = next_id_7_qs; - end - - addr_hit[25]: begin - reg_rdata_next[31:0] = next_id_8_qs; - end - - addr_hit[26]: begin - reg_rdata_next[31:0] = next_id_9_qs; - end - - addr_hit[27]: begin - reg_rdata_next[31:0] = next_id_10_qs; - end - - addr_hit[28]: begin - reg_rdata_next[31:0] = next_id_11_qs; - end - - addr_hit[29]: begin - reg_rdata_next[31:0] = next_id_12_qs; - end - - addr_hit[30]: begin - reg_rdata_next[31:0] = next_id_13_qs; - end - - addr_hit[31]: begin - reg_rdata_next[31:0] = next_id_14_qs; - end - - addr_hit[32]: begin - reg_rdata_next[31:0] = next_id_15_qs; - end - - addr_hit[33]: begin - reg_rdata_next[31:0] = done_id_0_qs; - end - - addr_hit[34]: begin - reg_rdata_next[31:0] = done_id_1_qs; - end - - addr_hit[35]: begin - reg_rdata_next[31:0] = done_id_2_qs; - end - - addr_hit[36]: begin - reg_rdata_next[31:0] = done_id_3_qs; - end - - addr_hit[37]: begin - reg_rdata_next[31:0] = done_id_4_qs; - end - - addr_hit[38]: begin - reg_rdata_next[31:0] = done_id_5_qs; - end - - addr_hit[39]: begin - reg_rdata_next[31:0] = done_id_6_qs; - end - - addr_hit[40]: begin - reg_rdata_next[31:0] = done_id_7_qs; - end - - addr_hit[41]: begin - reg_rdata_next[31:0] = done_id_8_qs; - end - - addr_hit[42]: begin - reg_rdata_next[31:0] = done_id_9_qs; - end - - addr_hit[43]: begin - reg_rdata_next[31:0] = done_id_10_qs; - end - - addr_hit[44]: begin - reg_rdata_next[31:0] = done_id_11_qs; - end - - addr_hit[45]: begin - reg_rdata_next[31:0] = done_id_12_qs; - end - - addr_hit[46]: begin - reg_rdata_next[31:0] = done_id_13_qs; - end - - addr_hit[47]: begin - reg_rdata_next[31:0] = done_id_14_qs; - end - - addr_hit[48]: begin - reg_rdata_next[31:0] = done_id_15_qs; - end - - addr_hit[49]: begin - reg_rdata_next[31:0] = dst_addr_low_qs; - end - - addr_hit[50]: begin - reg_rdata_next[31:0] = dst_addr_high_qs; - end - - addr_hit[51]: begin - reg_rdata_next[31:0] = src_addr_low_qs; - end - - addr_hit[52]: begin - reg_rdata_next[31:0] = src_addr_high_qs; - end - - addr_hit[53]: begin - reg_rdata_next[31:0] = length_low_qs; - end - - addr_hit[54]: begin - reg_rdata_next[31:0] = length_high_qs; - end - - default: begin - reg_rdata_next = '1; - end - endcase - end - - // Unused signal tieoff - - // wdata / byte enable are not always fully used - // add a blanket unused statement to handle lint waivers - logic unused_wdata; - logic unused_be; - assign unused_wdata = ^reg_wdata; - assign unused_be = ^reg_be; - - // Assertions for Register Interface - `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) - -endmodule - -module idma_reg64_1d_reg_top_intf -#( - parameter int AW = 8, - localparam int DW = 32 -) ( - input logic clk_i, - input logic rst_ni, - REG_BUS.in regbus_slave, - // To HW - output idma_reg64_1d_reg_pkg::idma_reg64_1d_reg2hw_t reg2hw, // Write - input idma_reg64_1d_reg_pkg::idma_reg64_1d_hw2reg_t hw2reg, // Read - // Config - input devmode_i // If 1, explicit error return for unmapped register access -); - localparam int unsigned STRB_WIDTH = DW/8; - -`include "register_interface/typedef.svh" -`include "register_interface/assign.svh" - - // Define structs for reg_bus - typedef logic [AW-1:0] addr_t; - typedef logic [DW-1:0] data_t; - typedef logic [STRB_WIDTH-1:0] strb_t; - `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) - - reg_bus_req_t s_reg_req; - reg_bus_rsp_t s_reg_rsp; - - // Assign SV interface to structs - `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) - `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) - - - - idma_reg64_1d_reg_top #( - .reg_req_t(reg_bus_req_t), - .reg_rsp_t(reg_bus_rsp_t), - .AW(AW) - ) i_regs ( - .clk_i, - .rst_ni, - .reg_req_i(s_reg_req), - .reg_rsp_o(s_reg_rsp), - .reg2hw, // Write - .hw2reg, // Read - .devmode_i - ); - -endmodule - - - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Michael Rogenmoser -// - Thomas Benz - -/// Description: Register-based front-end for iDMA -module idma_reg32_3d #( - /// Number of configuration register ports - parameter int unsigned NumRegs = 32'd1, - /// Number of streams (max 16) - parameter int unsigned NumStreams = 32'd1, - /// Width of the transfer id (max 32-bit) - parameter int unsigned IdCounterWidth = 32'd32, - /// Dependent parameter: Stream Idx - parameter int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams), - /// Register_interface request type - parameter type reg_req_t = logic, - /// Register_interface response type - parameter type reg_rsp_t = logic, - /// DMA 1d or ND burst request type - parameter type dma_req_t = logic, - /// Dependent type for IdCounterWidth - parameter type cnt_width_t = logic [IdCounterWidth-1:0], - /// Dependent type for StreamWidth - parameter type stream_t = logic [StreamWidth-1:0] -) ( - input logic clk_i, - input logic rst_ni, - /// Register interface control slave - input reg_req_t [NumRegs-1:0] dma_ctrl_req_i, - output reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, - /// Request signals - output dma_req_t dma_req_o, - output logic req_valid_o, - input logic req_ready_i, - input cnt_width_t next_id_i, - output stream_t stream_idx_o, - /// Status signals - input cnt_width_t [NumStreams-1:0] done_id_i, - input idma_pkg::idma_busy_t [NumStreams-1:0] busy_i, - input logic [NumStreams-1:0] midend_busy_i -); - - /// Maximum number of streams is set to 16. It can be enlarged, but the register file - /// needs to be adapted too. - localparam int unsigned MaxNumStreams = 32'd16; - - // register connections - idma_reg32_3d_reg_pkg::idma_reg32_3d_reg2hw_t [NumRegs-1:0] dma_reg2hw; - idma_reg32_3d_reg_pkg::idma_reg32_3d_hw2reg_t [NumRegs-1:0] dma_hw2reg; - - // arbitration output - dma_req_t [NumRegs-1:0] arb_dma_req; - logic [NumRegs-1:0] arb_valid; - logic [NumRegs-1:0] arb_ready; - - // register signals - reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; - - always_comb begin - stream_idx_o = '0; - for (int r = 0; r < NumRegs; r++) begin - for (int c = 0; c < NumStreams; c++) begin - if (dma_reg2hw[r].next_id[c].re) begin - stream_idx_o = c; - end - end - end - end - - // generate the registers - for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs - - idma_reg32_3d_reg_top #( - .reg_req_t ( reg_req_t ), - .reg_rsp_t ( reg_rsp_t ) - ) i_idma_reg32_3d_reg_top ( - .clk_i, - .rst_ni, - .reg_req_i ( dma_ctrl_req_i [i] ), - .reg_rsp_o ( dma_ctrl_rsp [i] ), - .reg2hw ( dma_reg2hw [i] ), - .hw2reg ( dma_hw2reg [i] ), - .devmode_i ( 1'b1 ) - ); - - logic read_happens; - // DMA backpressure - always_comb begin : proc_dma_backpressure - // ready signal - dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; - dma_ctrl_rsp_o[i].ready = read_happens ? arb_ready[i] : dma_ctrl_rsp[i]; - end - - // valid signals - - always_comb begin : proc_launch - read_happens = 1'b0; - for (int c = 0; c < NumStreams; c++) begin - read_happens |= dma_reg2hw[i].next_id[c].re; - end - arb_valid[i] = read_happens; - end - - // assign request struct - always_comb begin : proc_hw_req_conv - // all fields are zero per default - arb_dma_req[i] = '0; - - // address and length - arb_dma_req[i].burst_req.length = dma_reg2hw[i].length_low.q; - arb_dma_req[i].burst_req.src_addr = dma_reg2hw[i].src_addr_low.q; - arb_dma_req[i].burst_req.dst_addr = dma_reg2hw[i].dst_addr_low.q; - - // Protocols - arb_dma_req[i].burst_req.opt.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); - arb_dma_req[i].burst_req.opt.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); - - // Current backend only supports incremental burst - arb_dma_req[i].burst_req.opt.src.burst = axi_pkg::BURST_INCR; - arb_dma_req[i].burst_req.opt.dst.burst = axi_pkg::BURST_INCR; - // this frontend currently does not support cache variations - arb_dma_req[i].burst_req.opt.src.cache = axi_pkg::CACHE_MODIFIABLE; - arb_dma_req[i].burst_req.opt.dst.cache = axi_pkg::CACHE_MODIFIABLE; - - // Backend options - arb_dma_req[i].burst_req.opt.beo.decouple_aw = dma_reg2hw[i].conf.decouple_aw.q; - arb_dma_req[i].burst_req.opt.beo.decouple_rw = dma_reg2hw[i].conf.decouple_rw.q; - arb_dma_req[i].burst_req.opt.beo.src_max_llen = dma_reg2hw[i].conf.src_max_llen.q; - arb_dma_req[i].burst_req.opt.beo.dst_max_llen = dma_reg2hw[i].conf.dst_max_llen.q; - arb_dma_req[i].burst_req.opt.beo.src_reduce_len = dma_reg2hw[i].conf.src_reduce_len.q; - arb_dma_req[i].burst_req.opt.beo.dst_reduce_len = dma_reg2hw[i].conf.dst_reduce_len.q; - - // ND connections - arb_dma_req[i].d_req[0].reps = dma_reg2hw[i].reps_2_low.q; - arb_dma_req[i].d_req[0].src_strides = dma_reg2hw[i].src_stride_2_low.q; - arb_dma_req[i].d_req[0].dst_strides = dma_reg2hw[i].dst_stride_2_low.q; - arb_dma_req[i].d_req[1].reps = dma_reg2hw[i].reps_3_low.q; - arb_dma_req[i].d_req[1].src_strides = dma_reg2hw[i].src_stride_3_low.q; - arb_dma_req[i].d_req[1].dst_strides = dma_reg2hw[i].dst_stride_3_low.q; - - // Disable higher dimensions - if ( dma_reg2hw[i].conf.enable_nd.q == 0) begin - arb_dma_req[i].d_req[0].reps = '0; - arb_dma_req[i].d_req[1].reps = 'd1; - end - else if ( dma_reg2hw[i].conf.enable_nd.q == 1) begin - arb_dma_req[i].d_req[1].reps = 'd1; - end - end - - // observational registers - for (genvar c = 0; c < NumStreams; c++) begin - assign dma_hw2reg[i].status[c] = {midend_busy_i[c], busy_i[c]}; - assign dma_hw2reg[i].next_id[c] = next_id_i; - assign dma_hw2reg[i].done_id[c] = done_id_i[c]; - end - - // tie-off unused channels - for (genvar c = NumStreams; c < MaxNumStreams; c++) begin - assign dma_hw2reg[i].status[c] = '0; - assign dma_hw2reg[i].next_id[c] = '0; - assign dma_hw2reg[i].done_id[c] = '0; - end - - end - - // arbitration - rr_arb_tree #( - .NumIn ( NumRegs ), - .DataType ( dma_req_t ), - .ExtPrio ( 0 ), - .AxiVldRdy ( 1 ), - .LockIn ( 1 ) - ) i_rr_arb_tree ( - .clk_i, - .rst_ni, - .flush_i ( 1'b0 ), - .rr_i ( '0 ), - .req_i ( arb_valid ), - .gnt_o ( arb_ready ), - .data_i ( arb_dma_req ), - .gnt_i ( req_ready_i ), - .req_o ( req_valid_o ), - .data_o ( dma_req_o ), - .idx_o ( /* NC */ ) - ); - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Michael Rogenmoser -// - Thomas Benz - -/// Description: Register-based front-end for iDMA -module idma_reg64_2d #( - /// Number of configuration register ports - parameter int unsigned NumRegs = 32'd1, - /// Number of streams (max 16) - parameter int unsigned NumStreams = 32'd1, - /// Width of the transfer id (max 32-bit) - parameter int unsigned IdCounterWidth = 32'd32, - /// Dependent parameter: Stream Idx - parameter int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams), - /// Register_interface request type - parameter type reg_req_t = logic, - /// Register_interface response type - parameter type reg_rsp_t = logic, - /// DMA 1d or ND burst request type - parameter type dma_req_t = logic, - /// Dependent type for IdCounterWidth - parameter type cnt_width_t = logic [IdCounterWidth-1:0], - /// Dependent type for StreamWidth - parameter type stream_t = logic [StreamWidth-1:0] -) ( - input logic clk_i, - input logic rst_ni, - /// Register interface control slave - input reg_req_t [NumRegs-1:0] dma_ctrl_req_i, - output reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, - /// Request signals - output dma_req_t dma_req_o, - output logic req_valid_o, - input logic req_ready_i, - input cnt_width_t next_id_i, - output stream_t stream_idx_o, - /// Status signals - input cnt_width_t [NumStreams-1:0] done_id_i, - input idma_pkg::idma_busy_t [NumStreams-1:0] busy_i, - input logic [NumStreams-1:0] midend_busy_i -); - - /// Maximum number of streams is set to 16. It can be enlarged, but the register file - /// needs to be adapted too. - localparam int unsigned MaxNumStreams = 32'd16; - - // register connections - idma_reg64_2d_reg_pkg::idma_reg64_2d_reg2hw_t [NumRegs-1:0] dma_reg2hw; - idma_reg64_2d_reg_pkg::idma_reg64_2d_hw2reg_t [NumRegs-1:0] dma_hw2reg; - - // arbitration output - dma_req_t [NumRegs-1:0] arb_dma_req; - logic [NumRegs-1:0] arb_valid; - logic [NumRegs-1:0] arb_ready; - - // register signals - reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; - - always_comb begin - stream_idx_o = '0; - for (int r = 0; r < NumRegs; r++) begin - for (int c = 0; c < NumStreams; c++) begin - if (dma_reg2hw[r].next_id[c].re) begin - stream_idx_o = c; - end - end - end - end - - // generate the registers - for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs - - idma_reg64_2d_reg_top #( - .reg_req_t ( reg_req_t ), - .reg_rsp_t ( reg_rsp_t ) - ) i_idma_reg64_2d_reg_top ( - .clk_i, - .rst_ni, - .reg_req_i ( dma_ctrl_req_i [i] ), - .reg_rsp_o ( dma_ctrl_rsp [i] ), - .reg2hw ( dma_reg2hw [i] ), - .hw2reg ( dma_hw2reg [i] ), - .devmode_i ( 1'b1 ) - ); - - logic read_happens; - // DMA backpressure - always_comb begin : proc_dma_backpressure - // ready signal - dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; - dma_ctrl_rsp_o[i].ready = read_happens ? arb_ready[i] : dma_ctrl_rsp[i]; - end - - // valid signals - - always_comb begin : proc_launch - read_happens = 1'b0; - for (int c = 0; c < NumStreams; c++) begin - read_happens |= dma_reg2hw[i].next_id[c].re; - end - arb_valid[i] = read_happens; - end - - // assign request struct - always_comb begin : proc_hw_req_conv - // all fields are zero per default - arb_dma_req[i] = '0; - - // address and length - arb_dma_req[i].burst_req.length = {dma_reg2hw[i].length_high.q, dma_reg2hw[i].length_low.q}; - arb_dma_req[i].burst_req.src_addr = {dma_reg2hw[i].src_addr_high.q, dma_reg2hw[i].src_addr_low.q}; - arb_dma_req[i].burst_req.dst_addr = {dma_reg2hw[i].dst_addr_high.q, dma_reg2hw[i].dst_addr_low.q}; - - // Protocols - arb_dma_req[i].burst_req.opt.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); - arb_dma_req[i].burst_req.opt.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); - - // Current backend only supports incremental burst - arb_dma_req[i].burst_req.opt.src.burst = axi_pkg::BURST_INCR; - arb_dma_req[i].burst_req.opt.dst.burst = axi_pkg::BURST_INCR; - // this frontend currently does not support cache variations - arb_dma_req[i].burst_req.opt.src.cache = axi_pkg::CACHE_MODIFIABLE; - arb_dma_req[i].burst_req.opt.dst.cache = axi_pkg::CACHE_MODIFIABLE; - - // Backend options - arb_dma_req[i].burst_req.opt.beo.decouple_aw = dma_reg2hw[i].conf.decouple_aw.q; - arb_dma_req[i].burst_req.opt.beo.decouple_rw = dma_reg2hw[i].conf.decouple_rw.q; - arb_dma_req[i].burst_req.opt.beo.src_max_llen = dma_reg2hw[i].conf.src_max_llen.q; - arb_dma_req[i].burst_req.opt.beo.dst_max_llen = dma_reg2hw[i].conf.dst_max_llen.q; - arb_dma_req[i].burst_req.opt.beo.src_reduce_len = dma_reg2hw[i].conf.src_reduce_len.q; - arb_dma_req[i].burst_req.opt.beo.dst_reduce_len = dma_reg2hw[i].conf.dst_reduce_len.q; - - // ND connections - arb_dma_req[i].d_req[0].reps = {dma_reg2hw[i].reps_2_high.q, - dma_reg2hw[i].reps_2_low.q }; - arb_dma_req[i].d_req[0].src_strides = {dma_reg2hw[i].src_stride_2_high.q, - dma_reg2hw[i].src_stride_2_low.q}; - arb_dma_req[i].d_req[0].dst_strides = {dma_reg2hw[i].dst_stride_2_high.q, - dma_reg2hw[i].dst_stride_2_low.q}; - - // Disable higher dimensions - if ( dma_reg2hw[i].conf.enable_nd.q == 0) begin - arb_dma_req[i].d_req[0].reps = 'd1; - end - end - - // observational registers - for (genvar c = 0; c < NumStreams; c++) begin - assign dma_hw2reg[i].status[c] = {midend_busy_i[c], busy_i[c]}; - assign dma_hw2reg[i].next_id[c] = next_id_i; - assign dma_hw2reg[i].done_id[c] = done_id_i[c]; - end - - // tie-off unused channels - for (genvar c = NumStreams; c < MaxNumStreams; c++) begin - assign dma_hw2reg[i].status[c] = '0; - assign dma_hw2reg[i].next_id[c] = '0; - assign dma_hw2reg[i].done_id[c] = '0; - end - - end - - // arbitration - rr_arb_tree #( - .NumIn ( NumRegs ), - .DataType ( dma_req_t ), - .ExtPrio ( 0 ), - .AxiVldRdy ( 1 ), - .LockIn ( 1 ) - ) i_rr_arb_tree ( - .clk_i, - .rst_ni, - .flush_i ( 1'b0 ), - .rr_i ( '0 ), - .req_i ( arb_valid ), - .gnt_o ( arb_ready ), - .data_i ( arb_dma_req ), - .gnt_i ( req_ready_i ), - .req_o ( req_valid_o ), - .data_o ( dma_req_o ), - .idx_o ( /* NC */ ) - ); - -endmodule - -// Copyright 2023 ETH Zurich and University of Bologna. -// Solderpad Hardware License, Version 0.51, see LICENSE for details. -// SPDX-License-Identifier: SHL-0.51 - -// Authors: -// - Michael Rogenmoser -// - Thomas Benz - -/// Description: Register-based front-end for iDMA -module idma_reg64_1d #( - /// Number of configuration register ports - parameter int unsigned NumRegs = 32'd1, - /// Number of streams (max 16) - parameter int unsigned NumStreams = 32'd1, - /// Width of the transfer id (max 32-bit) - parameter int unsigned IdCounterWidth = 32'd32, - /// Dependent parameter: Stream Idx - parameter int unsigned StreamWidth = cf_math_pkg::idx_width(NumStreams), - /// Register_interface request type - parameter type reg_req_t = logic, - /// Register_interface response type - parameter type reg_rsp_t = logic, - /// DMA 1d or ND burst request type - parameter type dma_req_t = logic, - /// Dependent type for IdCounterWidth - parameter type cnt_width_t = logic [IdCounterWidth-1:0], - /// Dependent type for StreamWidth - parameter type stream_t = logic [StreamWidth-1:0] -) ( - input logic clk_i, - input logic rst_ni, - /// Register interface control slave - input reg_req_t [NumRegs-1:0] dma_ctrl_req_i, - output reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp_o, - /// Request signals - output dma_req_t dma_req_o, - output logic req_valid_o, - input logic req_ready_i, - input cnt_width_t next_id_i, - output stream_t stream_idx_o, - /// Status signals - input cnt_width_t [NumStreams-1:0] done_id_i, - input idma_pkg::idma_busy_t [NumStreams-1:0] busy_i, - input logic [NumStreams-1:0] midend_busy_i -); - - /// Maximum number of streams is set to 16. It can be enlarged, but the register file - /// needs to be adapted too. - localparam int unsigned MaxNumStreams = 32'd16; - - // register connections - idma_reg64_1d_reg_pkg::idma_reg64_1d_reg2hw_t [NumRegs-1:0] dma_reg2hw; - idma_reg64_1d_reg_pkg::idma_reg64_1d_hw2reg_t [NumRegs-1:0] dma_hw2reg; - - // arbitration output - dma_req_t [NumRegs-1:0] arb_dma_req; - logic [NumRegs-1:0] arb_valid; - logic [NumRegs-1:0] arb_ready; - - // register signals - reg_rsp_t [NumRegs-1:0] dma_ctrl_rsp; - - always_comb begin - stream_idx_o = '0; - for (int r = 0; r < NumRegs; r++) begin - for (int c = 0; c < NumStreams; c++) begin - if (dma_reg2hw[r].next_id[c].re) begin - stream_idx_o = c; - end - end - end - end - - // generate the registers - for (genvar i = 0; i < NumRegs; i++) begin : gen_core_regs - - idma_reg64_1d_reg_top #( - .reg_req_t ( reg_req_t ), - .reg_rsp_t ( reg_rsp_t ) - ) i_idma_reg64_1d_reg_top ( - .clk_i, - .rst_ni, - .reg_req_i ( dma_ctrl_req_i [i] ), - .reg_rsp_o ( dma_ctrl_rsp [i] ), - .reg2hw ( dma_reg2hw [i] ), - .hw2reg ( dma_hw2reg [i] ), - .devmode_i ( 1'b1 ) - ); - - logic read_happens; - // DMA backpressure - always_comb begin : proc_dma_backpressure - // ready signal - dma_ctrl_rsp_o[i] = dma_ctrl_rsp[i]; - dma_ctrl_rsp_o[i].ready = read_happens ? arb_ready[i] : dma_ctrl_rsp[i]; - end - - // valid signals - - always_comb begin : proc_launch - read_happens = 1'b0; - for (int c = 0; c < NumStreams; c++) begin - read_happens |= dma_reg2hw[i].next_id[c].re; - end - arb_valid[i] = read_happens; - end - - // assign request struct - always_comb begin : proc_hw_req_conv - // all fields are zero per default - arb_dma_req[i] = '0; - - // address and length - arb_dma_req[i].length = {dma_reg2hw[i].length_high.q, dma_reg2hw[i].length_low.q}; - arb_dma_req[i].src_addr = {dma_reg2hw[i].src_addr_high.q, dma_reg2hw[i].src_addr_low.q}; - arb_dma_req[i].dst_addr = {dma_reg2hw[i].dst_addr_high.q, dma_reg2hw[i].dst_addr_low.q}; - - // Protocols - arb_dma_req[i].opt.src_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.src_protocol); - arb_dma_req[i].opt.dst_protocol = idma_pkg::protocol_e'(dma_reg2hw[i].conf.dst_protocol); - - // Current backend only supports incremental burst - arb_dma_req[i].opt.src.burst = axi_pkg::BURST_INCR; - arb_dma_req[i].opt.dst.burst = axi_pkg::BURST_INCR; - // this frontend currently does not support cache variations - arb_dma_req[i].opt.src.cache = axi_pkg::CACHE_MODIFIABLE; - arb_dma_req[i].opt.dst.cache = axi_pkg::CACHE_MODIFIABLE; - - // Backend options - arb_dma_req[i].opt.beo.decouple_aw = dma_reg2hw[i].conf.decouple_aw.q; - arb_dma_req[i].opt.beo.decouple_rw = dma_reg2hw[i].conf.decouple_rw.q; - arb_dma_req[i].opt.beo.src_max_llen = dma_reg2hw[i].conf.src_max_llen.q; - arb_dma_req[i].opt.beo.dst_max_llen = dma_reg2hw[i].conf.dst_max_llen.q; - arb_dma_req[i].opt.beo.src_reduce_len = dma_reg2hw[i].conf.src_reduce_len.q; - arb_dma_req[i].opt.beo.dst_reduce_len = dma_reg2hw[i].conf.dst_reduce_len.q; - - end - - // observational registers - for (genvar c = 0; c < NumStreams; c++) begin - assign dma_hw2reg[i].status[c] = {midend_busy_i[c], busy_i[c]}; - assign dma_hw2reg[i].next_id[c] = next_id_i; - assign dma_hw2reg[i].done_id[c] = done_id_i[c]; - end - - // tie-off unused channels - for (genvar c = NumStreams; c < MaxNumStreams; c++) begin - assign dma_hw2reg[i].status[c] = '0; - assign dma_hw2reg[i].next_id[c] = '0; - assign dma_hw2reg[i].done_id[c] = '0; - end - - end - - // arbitration - rr_arb_tree #( - .NumIn ( NumRegs ), - .DataType ( dma_req_t ), - .ExtPrio ( 0 ), - .AxiVldRdy ( 1 ), - .LockIn ( 1 ) - ) i_rr_arb_tree ( - .clk_i, - .rst_ni, - .flush_i ( 1'b0 ), - .rr_i ( '0 ), - .req_i ( arb_valid ), - .gnt_o ( arb_ready ), - .data_i ( arb_dma_req ), - .gnt_i ( req_ready_i ), - .req_o ( req_valid_o ), - .data_o ( dma_req_o ), - .idx_o ( /* NC */ ) - ); - -endmodule - diff --git a/util/mario/legalizer.py b/util/mario/legalizer.py index c1a00364..77dee207 100644 --- a/util/mario/legalizer.py +++ b/util/mario/legalizer.py @@ -56,7 +56,7 @@ def render_legalizer(prot_ids: dict, db: dict, tpl_file: str) -> str: data_path = indent_block(db[wp]['legalizer_write_data_path'], 3 - swp, 4) db[wp]['legalizer_write_data_path'] = data_path - + has_page_read_bursting = eval_key(used_read_prots, 'bursts', 'split_at_page_boundary', db) has_pow2_read_bursting = eval_key(used_read_prots, 'bursts', 'only_pow2', db) has_read_bursting = has_page_read_bursting or has_pow2_read_bursting