Skip to content

Commit

Permalink
Add axi_xbar_unmuxed: Partial crossbar with unmultiplexed mst_ports
Browse files Browse the repository at this point in the history
  • Loading branch information
micprog committed Jul 3, 2024
1 parent 9402c8a commit b17cd7a
Show file tree
Hide file tree
Showing 4 changed files with 402 additions and 183 deletions.
4 changes: 3 additions & 1 deletion Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,13 @@ sources:
- src/axi_interleaved_xbar.sv
- src/axi_iw_converter.sv
- src/axi_lite_xbar.sv
- src/axi_xbar.sv
- src/axi_xbar_unmuxed.sv
- src/axi_to_mem_banked.sv
- src/axi_to_mem_interleaved.sv
- src/axi_to_mem_split.sv
# Level 5
- src/axi_xbar.sv
# Level 6
- src/axi_xp.sv

- target: synth_test
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.


## Unreleased
### Added
- Add `axi_xbar_unmuxed`: Partial crossbar with unmultiplexed mst_ports.

## 0.39.3 - 2024-05-08
### Added
Expand Down
206 changes: 24 additions & 182 deletions src/axi_xbar.sv
Original file line number Diff line number Diff line change
Expand Up @@ -99,192 +99,34 @@ import cf_math_pkg::idx_width;
`endif
);

// Address tpye for inidvidual address signals
typedef logic [Cfg.AxiAddrWidth-1:0] addr_t;
// to account for the decoding error slave
`ifdef VCS
localparam int unsigned MstPortsIdxWidthOne =
(Cfg.NoMstPorts == 32'd1) ? 32'd1 : unsigned'($clog2(Cfg.NoMstPorts + 1));
typedef logic [MstPortsIdxWidthOne-1:0] mst_port_idx_t;
`else
typedef logic [idx_width(Cfg.NoMstPorts + 1)-1:0] mst_port_idx_t;
`endif

// signals from the axi_demuxes, one index more for decode error
slv_req_t [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts:0] slv_reqs;
slv_resp_t [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts:0] slv_resps;

// workaround for issue #133 (problem with vsim 10.6c)
localparam int unsigned cfg_NoMstPorts = Cfg.NoMstPorts;

// signals into the axi_muxes, are of type slave as the multiplexer extends the ID
slv_req_t [Cfg.NoMstPorts-1:0][Cfg.NoSlvPorts-1:0] mst_reqs;
slv_resp_t [Cfg.NoMstPorts-1:0][Cfg.NoSlvPorts-1:0] mst_resps;

for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_slv_port_demux
`ifdef VCS
logic [MstPortsIdxWidth-1:0] dec_aw, dec_ar;
`else
logic [idx_width(Cfg.NoMstPorts)-1:0] dec_aw, dec_ar;
`endif
mst_port_idx_t slv_aw_select, slv_ar_select;
logic dec_aw_valid, dec_aw_error;
logic dec_ar_valid, dec_ar_error;

addr_decode #(
.NoIndices ( Cfg.NoMstPorts ),
.NoRules ( Cfg.NoAddrRules ),
.addr_t ( addr_t ),
.rule_t ( rule_t )
) i_axi_aw_decode (
.addr_i ( slv_ports_req_i[i].aw.addr ),
.addr_map_i ( addr_map_i ),
.idx_o ( dec_aw ),
.dec_valid_o ( dec_aw_valid ),
.dec_error_o ( dec_aw_error ),
.en_default_idx_i ( en_default_mst_port_i[i] ),
.default_idx_i ( default_mst_port_i[i] )
);

addr_decode #(
.NoIndices ( Cfg.NoMstPorts ),
.addr_t ( addr_t ),
.NoRules ( Cfg.NoAddrRules ),
.rule_t ( rule_t )
) i_axi_ar_decode (
.addr_i ( slv_ports_req_i[i].ar.addr ),
.addr_map_i ( addr_map_i ),
.idx_o ( dec_ar ),
.dec_valid_o ( dec_ar_valid ),
.dec_error_o ( dec_ar_error ),
.en_default_idx_i ( en_default_mst_port_i[i] ),
.default_idx_i ( default_mst_port_i[i] )
);

assign slv_aw_select = (dec_aw_error) ?
mst_port_idx_t'(Cfg.NoMstPorts) : mst_port_idx_t'(dec_aw);
assign slv_ar_select = (dec_ar_error) ?
mst_port_idx_t'(Cfg.NoMstPorts) : mst_port_idx_t'(dec_ar);

// make sure that the default slave does not get changed, if there is an unserved Ax
// pragma translate_off
`ifndef VERILATOR
`ifndef XSIM
default disable iff (~rst_ni);
default_aw_mst_port_en: assert property(
@(posedge clk_i) (slv_ports_req_i[i].aw_valid && !slv_ports_resp_o[i].aw_ready)
|=> $stable(en_default_mst_port_i[i]))
else $fatal (1, $sformatf("It is not allowed to change the default mst port\
enable, when there is an unserved Aw beat. Slave Port: %0d", i));
default_aw_mst_port: assert property(
@(posedge clk_i) (slv_ports_req_i[i].aw_valid && !slv_ports_resp_o[i].aw_ready)
|=> $stable(default_mst_port_i[i]))
else $fatal (1, $sformatf("It is not allowed to change the default mst port\
when there is an unserved Aw beat. Slave Port: %0d", i));
default_ar_mst_port_en: assert property(
@(posedge clk_i) (slv_ports_req_i[i].ar_valid && !slv_ports_resp_o[i].ar_ready)
|=> $stable(en_default_mst_port_i[i]))
else $fatal (1, $sformatf("It is not allowed to change the enable, when\
there is an unserved Ar beat. Slave Port: %0d", i));
default_ar_mst_port: assert property(
@(posedge clk_i) (slv_ports_req_i[i].ar_valid && !slv_ports_resp_o[i].ar_ready)
|=> $stable(default_mst_port_i[i]))
else $fatal (1, $sformatf("It is not allowed to change the default mst port\
when there is an unserved Ar beat. Slave Port: %0d", i));
`endif
`endif
// pragma translate_on
axi_demux #(
.AxiIdWidth ( Cfg.AxiIdWidthSlvPorts ), // ID Width
.AtopSupport ( ATOPs ),
.aw_chan_t ( slv_aw_chan_t ), // AW Channel Type
.w_chan_t ( w_chan_t ), // W Channel Type
.b_chan_t ( slv_b_chan_t ), // B Channel Type
.ar_chan_t ( slv_ar_chan_t ), // AR Channel Type
.r_chan_t ( slv_r_chan_t ), // R Channel Type
.axi_req_t ( slv_req_t ),
.axi_resp_t ( slv_resp_t ),
.NoMstPorts ( Cfg.NoMstPorts + 1 ),
.MaxTrans ( Cfg.MaxMstTrans ),
.AxiLookBits ( Cfg.AxiIdUsedSlvPorts ),
.UniqueIds ( Cfg.UniqueIds ),
.SpillAw ( Cfg.LatencyMode[9] ),
.SpillW ( Cfg.LatencyMode[8] ),
.SpillB ( Cfg.LatencyMode[7] ),
.SpillAr ( Cfg.LatencyMode[6] ),
.SpillR ( Cfg.LatencyMode[5] )
) i_axi_demux (
.clk_i, // Clock
.rst_ni, // Asynchronous reset active low
.test_i, // Testmode enable
.slv_req_i ( slv_ports_req_i[i] ),
.slv_aw_select_i ( slv_aw_select ),
.slv_ar_select_i ( slv_ar_select ),
.slv_resp_o ( slv_ports_resp_o[i] ),
.mst_reqs_o ( slv_reqs[i] ),
.mst_resps_i ( slv_resps[i] )
);

axi_err_slv #(
.AxiIdWidth ( Cfg.AxiIdWidthSlvPorts ),
.axi_req_t ( slv_req_t ),
.axi_resp_t ( slv_resp_t ),
.Resp ( axi_pkg::RESP_DECERR ),
.ATOPs ( ATOPs ),
.MaxTrans ( 4 ) // Transactions terminate at this slave, so minimize
// resource consumption by accepting only a few
// transactions at a time.
) i_axi_err_slv (
.clk_i, // Clock
.rst_ni, // Asynchronous reset active low
.test_i, // Testmode enable
// slave port
.slv_req_i ( slv_reqs[i][Cfg.NoMstPorts] ),
.slv_resp_o ( slv_resps[i][cfg_NoMstPorts] )
);
end

// cross all channels
for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_xbar_slv_cross
for (genvar j = 0; j < Cfg.NoMstPorts; j++) begin : gen_xbar_mst_cross
if (Connectivity[i][j]) begin : gen_connection
axi_multicut #(
.NoCuts ( Cfg.PipelineStages ),
.aw_chan_t ( slv_aw_chan_t ),
.w_chan_t ( w_chan_t ),
.b_chan_t ( slv_b_chan_t ),
.ar_chan_t ( slv_ar_chan_t ),
.r_chan_t ( slv_r_chan_t ),
.axi_req_t ( slv_req_t ),
.axi_resp_t ( slv_resp_t )
) i_axi_multicut_xbar_pipeline (
.clk_i,
.rst_ni,
.slv_req_i ( slv_reqs[i][j] ),
.slv_resp_o ( slv_resps[i][j] ),
.mst_req_o ( mst_reqs[j][i] ),
.mst_resp_i ( mst_resps[j][i] )
);

end else begin : gen_no_connection
assign mst_reqs[j][i] = '0;
axi_err_slv #(
.AxiIdWidth ( Cfg.AxiIdWidthSlvPorts ),
.axi_req_t ( slv_req_t ),
.axi_resp_t ( slv_resp_t ),
.Resp ( axi_pkg::RESP_DECERR ),
.ATOPs ( ATOPs ),
.MaxTrans ( 1 )
) i_axi_err_slv (
.clk_i,
.rst_ni,
.test_i,
.slv_req_i ( slv_reqs[i][j] ),
.slv_resp_o ( slv_resps[i][j] )
);
end
end
end
axi_xbar_unmuxed #(
.Cfg (Cfg),
.ATOPs (ATOPs),
.Connectivity (Connectivity),
.aw_chan_t (slv_aw_chan_t),
.w_chan_t (w_chan_t),
.b_chan_t (slv_b_chan_t),
.ar_chan_t (slv_ar_chan_t),
.r_chan_t (slv_r_chan_t),
.req_t (slv_req_t),
.resp_t (slv_resp_t),
.rule_t (rule_t)
) i_xbar_unmuxed (
.clk_i,
.rst_ni,
.test_i,
.slv_ports_req_i,
.slv_ports_resp_o,
.mst_ports_req_o (mst_reqs),
.mst_ports_resp_i (mst_resps),
.addr_map_i,
.en_default_mst_port_i,
.default_mst_port_i
);

for (genvar i = 0; i < Cfg.NoMstPorts; i++) begin : gen_mst_port_mux
axi_mux #(
Expand Down
Loading

0 comments on commit b17cd7a

Please sign in to comment.