-
Notifications
You must be signed in to change notification settings - Fork 272
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Removes demux and mux inside
- Loading branch information
Showing
1 changed file
with
112 additions
and
204 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
// Authors: | ||
// - Andreas Kurth <[email protected]> | ||
// - Paul Scheffler <[email protected]> | ||
// - Michael Rogenmoser <[email protected]> | ||
|
||
`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 | ||
|