Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add axi_xbar_unmuxed: Partial crossbar with unmultiplexed mst_ports #343

Merged
merged 3 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `axi_sim_mem`: Increase number of request ports, add multiport interface variant.
- `axi_bus_compare`: Optionally consider AXI `size` field to only compare used data.
- `AXI_BUS_DV`: Add property checking that bursts do not cross 4KiB page boundaries.
- Add `axi_xbar_unmuxed`: Partial crossbar with unmultiplexed mst_ports.

### Fixed
- `axi_bus_compare`: Fix mismatch detection.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ In addition to the documents linked in the following table, we are setting up [d
| [`axi_to_axi_lite`](src/axi_to_axi_lite.sv) | AXI4 to AXI4-Lite protocol converter. | |
| [`axi_to_mem`](src/axi_to_mem.sv) | AXI4 to memory protocol (req, gnt, rvalid) converter. Additional banked, interleaved, split variant. | |
| [`axi_xbar`](src/axi_xbar.sv) | Fully-connected AXI4+ATOP crossbar with an arbitrary number of slave and master ports. | [Doc](doc/axi_xbar.md) |
| [`axi_xbar_unmuxed`](src/axi_xbar_unmuxed.sv) | Demux side of fully-connected AXI4+ATOP crossbar with an arbitrary number of slave and master ports. | [Doc](doc/axi_xbar.md) |
| [`axi_xp`](src/axi_xp.sv) | AXI Crosspoint (XP) with homomorphous slave and master ports. | |
| [`axi_zero_mem`](src/axi_zero_mem.sv) | AXI-attached /dev/zero. All reads will be zero, writes are absorbed. | |

Expand Down
4 changes: 3 additions & 1 deletion axi.core
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ filesets:
- 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
Expand All @@ -73,6 +73,8 @@ filesets:
- src/axi_sim_mem.sv
- src/axi_test.sv
# Level 5
- src/axi_xbar.sv
# Level 6
- src/axi_xp.sv
file_type : systemVerilogSource
depend :
Expand Down
2 changes: 1 addition & 1 deletion src/axi_interleaved_xbar.sv
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,10 @@ endmodule : axi_interleaved_xbar
module axi_interleaved_xbar_intf
import cf_math_pkg::idx_width;
#(
parameter axi_pkg::xbar_cfg_t Cfg = '0,
parameter int unsigned AXI_USER_WIDTH = 0,
parameter bit ATOPS = 1'b1,
parameter bit [Cfg.NoSlvPorts-1:0][Cfg.NoMstPorts-1:0] CONNECTIVITY = '1,
parameter axi_pkg::xbar_cfg_t Cfg = '0,
parameter type rule_t = axi_pkg::xbar_rule_64_t
`ifdef VCS
, localparam int unsigned MstPortsIdxWidth =
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
Loading