diff --git a/src/axi_id_serialize.sv b/src/axi_id_serialize.sv index 9a787dd25..0d1553b99 100644 --- a/src/axi_id_serialize.sv +++ b/src/axi_id_serialize.sv @@ -12,6 +12,7 @@ // Authors: // - Andreas Kurth // - Paul Scheffler +// - Michael Rogenmoser `include "axi/assign.svh" `include "axi/typedef.svh" @@ -29,9 +30,6 @@ module axi_id_serialize #( /// ID width of the AXI4+ATOP slave port parameter int unsigned AxiSlvPortIdWidth = 32'd0, - /// Maximum number of transactions that can be in flight at the slave port. Reads and writes are - /// counted separately (except for ATOPs, which count as both read and write). - parameter int unsigned AxiSlvPortMaxTxns = 32'd0, /// ID width of the AXI4+ATOP master port parameter int unsigned AxiMstPortIdWidth = 32'd0, /// Maximum number of different IDs that can be in flight at the master port. Reads and writes @@ -41,14 +39,6 @@ module axi_id_serialize #( parameter int unsigned AxiMstPortMaxUniqIds = 32'd0, /// Maximum number of in-flight transactions with the same ID at the master port. parameter int unsigned AxiMstPortMaxTxnsPerId = 32'd0, - /// Address width of both AXI4+ATOP ports - parameter int unsigned AxiAddrWidth = 32'd0, - /// Data width of both AXI4+ATOP ports - parameter int unsigned AxiDataWidth = 32'd0, - /// User width of both AXI4+ATOP ports - parameter int unsigned AxiUserWidth = 32'd0, - /// Enable support for AXI4+ATOP atomics - parameter bit AtopSupport = 1'b1, /// Request struct type of the AXI4+ATOP slave port parameter type slv_req_t = logic, /// Response struct type of the AXI4+ATOP slave port @@ -66,7 +56,13 @@ module axi_id_serialize #( /// Number of Entries in the explicit ID map (default: None) parameter int unsigned IdMapNumEntries = 32'd0, /// Explicit ID map; index [0] in each entry is the input ID to match, index [1] the output ID. - parameter int unsigned IdMap [IdMapNumEntries-1:0][0:1] = '{default: {32'b0, 32'b0}} + parameter int unsigned IdMap [IdMapNumEntries-1:0][0:1] = '{default: {32'b0, 32'b0}}, + // unused parameters, no longer needed, left for backwards-compatibility + parameter int unsigned AxiSlvPortMaxTxns = 32'd0, // unused + parameter int unsigned AxiAddrWidth = 32'd0, + parameter int unsigned AxiDataWidth = 32'd0, + parameter int unsigned AxiUserWidth = 32'd0, + parameter bit AtopSupport = 1'b1 ) ( /// Rising-edge clock of both ports input logic clk_i, @@ -87,73 +83,9 @@ module axi_id_serialize #( /// Slice of slave port IDs that determines the master port ID typedef logic [SelectWidth-1:0] select_t; - /// ID width after the multiplexer - localparam int unsigned MuxIdWidth = (AxiMstPortMaxUniqIds > 32'd1) ? SelectWidth + 32'd1 : 32'd1; - - /// ID after serializer (i.e., with a constant value of zero) - typedef logic [0:0] ser_id_t; - /// ID after the multiplexer - typedef logic [MuxIdWidth-1:0] mux_id_t; - /// ID at the slave port - typedef logic [AxiSlvPortIdWidth-1:0] slv_id_t; /// ID at the master port typedef logic [AxiMstPortIdWidth-1:0] mst_id_t; - /// Address in any AXI channel - typedef logic [AxiAddrWidth-1:0] addr_t; - /// Data in any AXI channel - typedef logic [AxiDataWidth-1:0] data_t; - /// Strobe in any AXI channel - typedef logic [AxiDataWidth/8-1:0] strb_t; - /// User signal in any AXI channel - typedef logic [AxiUserWidth-1:0] user_t; - - /// W channel at any interface - `AXI_TYPEDEF_W_CHAN_T(w_t, data_t, strb_t, user_t) - - /// AW channel at slave port - `AXI_TYPEDEF_AW_CHAN_T(slv_aw_t, addr_t, slv_id_t, user_t) - /// B channel at slave port - `AXI_TYPEDEF_B_CHAN_T(slv_b_t, slv_id_t, user_t) - /// AR channel at slave port - `AXI_TYPEDEF_AR_CHAN_T(slv_ar_t, addr_t, slv_id_t, user_t) - /// R channel at slave port - `AXI_TYPEDEF_R_CHAN_T(slv_r_t, data_t, slv_id_t, user_t) - - /// AW channel after serializer - `AXI_TYPEDEF_AW_CHAN_T(ser_aw_t, addr_t, ser_id_t, user_t) - /// B channel after serializer - `AXI_TYPEDEF_B_CHAN_T(ser_b_t, ser_id_t, user_t) - /// AR channel after serializer - `AXI_TYPEDEF_AR_CHAN_T(ser_ar_t, addr_t, ser_id_t, user_t) - /// R channel after serializer - `AXI_TYPEDEF_R_CHAN_T(ser_r_t, data_t, ser_id_t, user_t) - /// AXI Requests from serializer - `AXI_TYPEDEF_REQ_T(ser_req_t, ser_aw_t, w_t, ser_ar_t) - /// AXI responses to serializer - `AXI_TYPEDEF_RESP_T(ser_resp_t, ser_b_t, ser_r_t) - - /// AW channel after the multiplexer - `AXI_TYPEDEF_AW_CHAN_T(mux_aw_t, addr_t, mux_id_t, user_t) - /// B channel after the multiplexer - `AXI_TYPEDEF_B_CHAN_T(mux_b_t, mux_id_t, user_t) - /// AR channel after the multiplexer - `AXI_TYPEDEF_AR_CHAN_T(mux_ar_t, addr_t, mux_id_t, user_t) - /// R channel after the multiplexer - `AXI_TYPEDEF_R_CHAN_T(mux_r_t, data_t, mux_id_t, user_t) - /// AXI requests from the multiplexer - `AXI_TYPEDEF_REQ_T(mux_req_t, mux_aw_t, w_t, mux_ar_t) - /// AXI responses to the multiplexer - `AXI_TYPEDEF_RESP_T(mux_resp_t, mux_b_t, mux_r_t) - - /// AW channel at master port - `AXI_TYPEDEF_AW_CHAN_T(mst_aw_t, addr_t, mst_id_t, user_t) - /// B channel at master port - `AXI_TYPEDEF_B_CHAN_T(mst_b_t, mst_id_t, user_t) - /// AR channel at master port - `AXI_TYPEDEF_AR_CHAN_T(mst_ar_t, addr_t, mst_id_t, user_t) - /// R channel at master port - `AXI_TYPEDEF_R_CHAN_T(mst_r_t, data_t, mst_id_t, user_t) - + /// Type for slave ID map typedef mst_id_t [2**AxiSlvPortIdWidth-1:0] slv_id_map_t; @@ -172,49 +104,70 @@ module axi_id_serialize #( /// Input-to-output ID map used localparam slv_id_map_t SlvIdMap = map_slv_ids(); - select_t slv_aw_select, slv_ar_select; + select_t slv_aw_select, slv_ar_select, slv_b_select, slv_r_select; assign slv_aw_select = select_t'(SlvIdMap[slv_req_i.aw.id]); assign slv_ar_select = select_t'(SlvIdMap[slv_req_i.ar.id]); slv_req_t [AxiMstPortMaxUniqIds-1:0] to_serializer_reqs; slv_resp_t [AxiMstPortMaxUniqIds-1:0] to_serializer_resps; - axi_demux #( - .AxiIdWidth ( AxiSlvPortIdWidth ), - .aw_chan_t ( slv_aw_t ), - .w_chan_t ( w_t ), - .b_chan_t ( slv_b_t ), - .ar_chan_t ( slv_ar_t ), - .r_chan_t ( slv_r_t ), - .axi_req_t ( slv_req_t ), - .axi_resp_t ( slv_resp_t ), - .NoMstPorts ( AxiMstPortMaxUniqIds ), - .MaxTrans ( AxiSlvPortMaxTxns ), - .AxiLookBits ( AxiSlvPortIdWidth ), - .AtopSupport ( AtopSupport ), - .SpillAw ( 1'b1 ), - .SpillW ( 1'b0 ), - .SpillB ( 1'b0 ), - .SpillAr ( 1'b1 ), - .SpillR ( 1'b0 ) - ) i_axi_demux ( - .clk_i, - .rst_ni, - .test_i ( 1'b0 ), - .slv_req_i ( slv_req_i ), - .slv_aw_select_i ( slv_aw_select ), - .slv_ar_select_i ( slv_ar_select ), - .slv_resp_o ( slv_resp_o ), - .mst_reqs_o ( to_serializer_reqs ), - .mst_resps_i ( to_serializer_resps ) + logic [AxiMstPortMaxUniqIds-1:0] to_serializer_resps_b_valid, + to_serializer_resps_r_valid; + + onehot_to_bin #( + .ONEHOT_WIDTH( AxiMstPortMaxUniqIds ) + ) i_slv_b_select ( + .onehot(to_serializer_resps_b_valid), + .bin (slv_b_select) ); + onehot_to_bin #( + .ONEHOT_WIDTH( AxiMstPortMaxUniqIds ) + ) i_slv_r_select ( + .onehot(to_serializer_resps_r_valid), + .bin (slv_r_select) + ); + + for (genvar i = 0; i < AxiMstPortMaxUniqIds; i++) begin + assign to_serializer_resps_b_valid[i] = to_serializer_resps[i].b_valid; + assign to_serializer_resps_r_valid[i] = to_serializer_resps[i].r_valid; + end + + // Due to static ID mapping, ID consistency checking is not needed. + always_comb begin + // AW, W, AR + for (int unsigned i = 0; i < AxiMstPortMaxUniqIds; i++) begin + to_serializer_reqs[i] = slv_req_i; // .aw, .w, .ar + to_serializer_reqs[i].aw_valid = '0; + to_serializer_reqs[i].w_valid = '0; + to_serializer_reqs[i].ar_valid = '0; + end + to_serializer_reqs[slv_aw_select].aw_valid = slv_req_i.aw_valid; + slv_resp_o.aw_ready = to_serializer_resps[slv_aw_select].aw_ready; + + slv_resp_o.w_ready = mst_resp_i.w_ready; + + to_serializer_reqs[slv_ar_select].ar_valid = slv_req_i.ar_valid; + slv_resp_o.ar_ready = to_serializer_resps[slv_ar_select].ar_ready; + + // B, R (these are passed through or both gated inside the serializer) + slv_resp_o.b_valid = |to_serializer_resps_b_valid; + slv_resp_o.b = to_serializer_resps[slv_b_select].b; + slv_resp_o.r_valid = |to_serializer_resps_r_valid; + slv_resp_o.r = to_serializer_resps[slv_r_select].r; + for (int unsigned i = 0; i < AxiMstPortMaxUniqIds; i++) begin + to_serializer_reqs[i].b_ready = slv_req_i.b_ready; + to_serializer_reqs[i].r_ready = slv_req_i.r_ready; + end + end + slv_req_t [AxiMstPortMaxUniqIds-1:0] tmp_serializer_reqs; slv_resp_t [AxiMstPortMaxUniqIds-1:0] tmp_serializer_resps; - ser_req_t [AxiMstPortMaxUniqIds-1:0] from_serializer_reqs; - ser_resp_t [AxiMstPortMaxUniqIds-1:0] from_serializer_resps; + mst_req_t [AxiMstPortMaxUniqIds-1:0] from_serializer_reqs; + mst_resp_t [AxiMstPortMaxUniqIds-1:0] from_serializer_resps; for (genvar i = 0; i < AxiMstPortMaxUniqIds; i++) begin : gen_serializers + // serializer takes care to ensure unique IDs for ATOPs axi_serializer #( .MaxReadTxns ( AxiMstPortMaxTxnsPerId ), .MaxWriteTxns ( AxiMstPortMaxTxnsPerId ), @@ -231,110 +184,65 @@ module axi_id_serialize #( ); always_comb begin `AXI_SET_REQ_STRUCT(from_serializer_reqs[i], tmp_serializer_reqs[i]) - // Truncate to ID width 1 as all requests have ID '0. - from_serializer_reqs[i].aw.id = tmp_serializer_reqs[i].aw.id[0]; - from_serializer_reqs[i].ar.id = tmp_serializer_reqs[i].ar.id[0]; + from_serializer_reqs[i].aw.id = i; + from_serializer_reqs[i].ar.id = i; `AXI_SET_RESP_STRUCT(tmp_serializer_resps[i], from_serializer_resps[i]) // Zero-extend response IDs. - tmp_serializer_resps[i].b.id = {{AxiSlvPortIdWidth-1{1'b0}}, from_serializer_resps[i].b.id}; - tmp_serializer_resps[i].r.id = {{AxiSlvPortIdWidth-1{1'b0}}, from_serializer_resps[i].r.id}; + tmp_serializer_resps[i].b.id = '0; + tmp_serializer_resps[i].r.id = '0; end end - mux_req_t axi_mux_req; - mux_resp_t axi_mux_resp; - - axi_mux #( - .SlvAxiIDWidth ( 32'd1 ), - .slv_aw_chan_t ( ser_aw_t ), - .mst_aw_chan_t ( mux_aw_t ), - .w_chan_t ( w_t ), - .slv_b_chan_t ( ser_b_t ), - .mst_b_chan_t ( mux_b_t ), - .slv_ar_chan_t ( ser_ar_t ), - .mst_ar_chan_t ( mux_ar_t ), - .slv_r_chan_t ( ser_r_t ), - .mst_r_chan_t ( mux_r_t ), - .slv_req_t ( ser_req_t ), - .slv_resp_t ( ser_resp_t ), - .mst_req_t ( mux_req_t ), - .mst_resp_t ( mux_resp_t ), - .NoSlvPorts ( AxiMstPortMaxUniqIds ), - .MaxWTrans ( AxiMstPortMaxTxnsPerId ), - .FallThrough ( 1'b0 ), - .SpillAw ( 1'b1 ), - .SpillW ( 1'b0 ), - .SpillB ( 1'b0 ), - .SpillAr ( 1'b1 ), - .SpillR ( 1'b0 ) - ) i_axi_mux ( - .clk_i, - .rst_ni, - .test_i ( 1'b0 ), - .slv_reqs_i ( from_serializer_reqs ), - .slv_resps_o ( from_serializer_resps ), - .mst_req_o ( axi_mux_req ), - .mst_resp_i ( axi_mux_resp ) + logic [AxiMstPortMaxUniqIds-1:0] from_serializer_reqs_aw_valid, + from_serializer_reqs_ar_valid, + from_serializer_reqs_b_ready, + from_serializer_reqs_r_ready; + + select_t mst_aw_select, mst_ar_select; + + onehot_to_bin #( + .ONEHOT_WIDTH( AxiMstPortMaxUniqIds ) + ) i_mst_aw_select ( + .onehot(from_serializer_reqs_aw_valid), + .bin (mst_aw_select) ); - // Shift the ID one down if needed, as mux prepends IDs - if (MuxIdWidth > 32'd1) begin : gen_id_shift - always_comb begin - `AXI_SET_REQ_STRUCT(mst_req_o, axi_mux_req) - mst_req_o.aw.id = mst_id_t'(axi_mux_req.aw.id >> 32'd1); - mst_req_o.ar.id = mst_id_t'(axi_mux_req.ar.id >> 32'd1); - `AXI_SET_RESP_STRUCT(axi_mux_resp, mst_resp_i) - axi_mux_resp.b.id = mux_id_t'(mst_resp_i.b.id << 32'd1); - axi_mux_resp.r.id = mux_id_t'(mst_resp_i.r.id << 32'd1); + onehot_to_bin #( + .ONEHOT_WIDTH( AxiMstPortMaxUniqIds ) + ) i_mst_ar_select ( + .onehot(from_serializer_reqs_ar_valid), + .bin (mst_ar_select) + ); + + for (genvar i = 0; i < AxiMstPortMaxUniqIds; i++) begin + assign from_serializer_reqs_aw_valid[i] = from_serializer_reqs[i].aw_valid; + assign from_serializer_reqs_ar_valid[i] = from_serializer_reqs[i].ar_valid; + end + + always_comb begin + mst_req_o.aw_valid = |from_serializer_reqs_aw_valid; + mst_req_o.aw = from_serializer_reqs[mst_aw_select].aw; + mst_req_o.w_valid = slv_req_i.w_valid; + mst_req_o.w = slv_req_i.w; + mst_req_o.ar_valid = |from_serializer_reqs_ar_valid; + mst_req_o.ar = from_serializer_reqs[mst_ar_select].ar; + for (int unsigned i = 0; i < AxiMstPortMaxUniqIds; i++) begin + from_serializer_resps[i].aw_ready = mst_resp_i.aw_ready; + from_serializer_resps[i].ar_ready = mst_resp_i.ar_ready; end - end else begin : gen_no_id_shift - axi_id_prepend #( - .NoBus ( 32'd1 ), - .AxiIdWidthSlvPort ( MuxIdWidth ), - .AxiIdWidthMstPort ( AxiMstPortIdWidth ), - .slv_aw_chan_t ( mux_aw_t ), - .slv_w_chan_t ( w_t ), - .slv_b_chan_t ( mux_b_t ), - .slv_ar_chan_t ( mux_ar_t ), - .slv_r_chan_t ( mux_r_t ), - .mst_aw_chan_t ( mst_aw_t ), - .mst_w_chan_t ( w_t ), - .mst_b_chan_t ( mst_b_t ), - .mst_ar_chan_t ( mst_ar_t ), - .mst_r_chan_t ( mst_r_t ) - ) i_axi_id_prepend ( - .pre_id_i ( '0 ), - .slv_aw_chans_i ( axi_mux_req.aw ), - .slv_aw_valids_i ( axi_mux_req.aw_valid ), - .slv_aw_readies_o ( axi_mux_resp.aw_ready ), - .slv_w_chans_i ( axi_mux_req.w ), - .slv_w_valids_i ( axi_mux_req.w_valid ), - .slv_w_readies_o ( axi_mux_resp.w_ready ), - .slv_b_chans_o ( axi_mux_resp.b ), - .slv_b_valids_o ( axi_mux_resp.b_valid ), - .slv_b_readies_i ( axi_mux_req.b_ready ), - .slv_ar_chans_i ( axi_mux_req.ar ), - .slv_ar_valids_i ( axi_mux_req.ar_valid ), - .slv_ar_readies_o ( axi_mux_resp.ar_ready ), - .slv_r_chans_o ( axi_mux_resp.r ), - .slv_r_valids_o ( axi_mux_resp.r_valid ), - .slv_r_readies_i ( axi_mux_req.r_ready ), - .mst_aw_chans_o ( mst_req_o.aw ), - .mst_aw_valids_o ( mst_req_o.aw_valid ), - .mst_aw_readies_i ( mst_resp_i.aw_ready ), - .mst_w_chans_o ( mst_req_o.w ), - .mst_w_valids_o ( mst_req_o.w_valid ), - .mst_w_readies_i ( mst_resp_i.w_ready ), - .mst_b_chans_i ( mst_resp_i.b ), - .mst_b_valids_i ( mst_resp_i.b_valid ), - .mst_b_readies_o ( mst_req_o.b_ready ), - .mst_ar_chans_o ( mst_req_o.ar ), - .mst_ar_valids_o ( mst_req_o.ar_valid ), - .mst_ar_readies_i ( mst_resp_i.ar_ready ), - .mst_r_chans_i ( mst_resp_i.r ), - .mst_r_valids_i ( mst_resp_i.r_valid ), - .mst_r_readies_o ( mst_req_o.r_ready ) - ); + + for (int unsigned i = 0; i < AxiMstPortMaxUniqIds; i++) begin + from_serializer_reqs_b_ready[i] = from_serializer_reqs[i].b_ready; + from_serializer_reqs_r_ready[i] = from_serializer_reqs[i].r_ready; + from_serializer_resps[i].b_valid = '0; + from_serializer_resps[i].r_valid = '0; + from_serializer_resps[i].b = mst_resp_i.b; + from_serializer_resps[i].r = mst_resp_i.r; + end + from_serializer_resps[mst_resp_i.b.id].b_valid = mst_resp_i.b_valid; + mst_req_o.b_ready = from_serializer_reqs[mst_resp_i.b.id].b_ready; + from_serializer_resps[mst_resp_i.r.id].r_valid = mst_resp_i.r_valid; + mst_req_o.r_ready = from_serializer_reqs[mst_resp_i.r.id].r_ready; end // pragma translate_off