From 74412f0bed059c344d683e884a53312db859fa03 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Wed, 22 May 2024 17:52:57 +0200 Subject: [PATCH] Rewrite simpler axi_id_serializer Removes demux and mux inside --- src/axi_id_serialize.sv | 254 ++++++++++++++++++++-------------------- 1 file changed, 129 insertions(+), 125 deletions(-) diff --git a/src/axi_id_serialize.sv b/src/axi_id_serialize.sv index 9a787dd25..67585a337 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" @@ -172,49 +173,89 @@ 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_w_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 ( + logic [AxiMstPortMaxUniqIds-1:0] to_serializer_resps_b_valid, to_serializer_resps_r_valid; + + logic no_w_route, no_w_space; + + 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) + ); + + // 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 & ~no_w_space; + slv_resp_o.aw_ready = to_serializer_resps[slv_aw_select].aw_ready & ~no_w_space; + + to_serializer_reqs[slv_w_select].w_valid = slv_req_i.w_valid & ~no_w_route; + slv_resp_o.w_ready = to_serializer_resps[slv_w_select].w_ready & ~no_w_route; + + 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_resps_b_valid[i] = to_serializer_resps[i].b_valid; + to_serializer_resps_r_valid[i] = to_serializer_resps[i].r_valid; + + to_serializer_reqs[i].b_ready = slv_req_i.b_ready; + to_serializer_reqs[i].r_ready = slv_req_i.r_ready; + end + end + + fifo_v3 #( + .FALL_THROUGH(1'b1), + .DEPTH (AxiSlvPortMaxTxns), + .dtype (select_t) + ) i_w_sel_fifo ( .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 ) + .flush_i ('0), + .testmode_i('0), + .full_o (no_w_space), + .empty_o (no_w_route), + .usage_o (), + .data_i (slv_aw_select), + .push_i (slv_req_i.aw_valid), + .data_o (slv_w_select), + .pop_i (slv_req_i.w_valid & slv_req_i.w_ready & slv_req_i.w.last) ); 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 +272,73 @@ 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_w_valid, + from_serializer_reqs_ar_valid, + from_serializer_reqs_b_ready, + from_serializer_reqs_r_ready; + + select_t mst_aw_select, mst_w_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_w_select ( + .onehot(from_serializer_reqs_w_valid), + .bin (mst_w_select) + ); + + onehot_to_bin #( + .ONEHOT_WIDTH( AxiMstPortMaxUniqIds ) + ) i_mst_ar_select ( + .onehot(from_serializer_reqs_ar_valid), + .bin (mst_ar_select) + ); + + 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 = |from_serializer_reqs_w_valid; + mst_req_o.w = from_serializer_reqs[mst_w_select].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_reqs_aw_valid[i] = from_serializer_reqs[i].aw_valid; + from_serializer_reqs_w_valid[i] = from_serializer_reqs[i].w_valid; + from_serializer_reqs_ar_valid[i] = from_serializer_reqs[i].ar_valid; + + from_serializer_resps.aw_ready [i] = mst_resp_i.aw_ready; + from_serializer_resps.w_ready [i] = mst_resp_i.w_ready; + from_serializer_resps.ar_ready [i] = 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_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_r_ready; end // pragma translate_off