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

hw: Add AW cuts to chimneys #89

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ sources:
- hw/test/axi_reorder_remap_compare.sv
- hw/test/axi_bw_monitor.sv
- hw/test/floo_hbm_model.sv
- hw/test/axi_aw_w_sync.sv
# Level 2
- hw/tb/tb_floo_axi_chimney.sv
- hw/tb/tb_floo_nw_chimney.sv
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- The `ReorderBufferSize` parameters was shortened to `RoBSize`.
- All testbenches were adapted to all changes.
- All verification IPs were adapted to the new configuration structs.
- Added spill registers for outgoing AW requests in the chimneys. This is necessary since AXI allows to wait for AW *and* W to be valid before asserting the ready. Since, the AW and W beats are sent over the same channel, this might cause a deadlock if there there are no buffers downstream.

#### FlooGen
- The link typedefs are now renderd with the macros in `typedef.svh` instead of rendering them in pure SystemVerilog.
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ MKFILE_DIR := $(dir $(MKFILE_PATH))

.PHONY: all clean compile-sim run-sim run-sim-batch
all: compile-sim
clean: clean-sim clean-spyglass clean-jobs clean-sources clean-vcs
clean: clean-vsim clean-spyglass clean-jobs clean-sources clean-vcs
compile-sim: compile-vsim
run-sim: run-vsim
run-sim-batch: run-vsim-batch
Expand Down
40 changes: 36 additions & 4 deletions hw/floo_axi_chimney.sv
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,15 @@ module floo_axi_chimney #(

typedef logic [AxiCfg.AddrWidth-1:0] axi_addr_t;
typedef logic [AxiCfg.InIdWidth-1:0] axi_in_id_t;
typedef logic [AxiCfg.OutIdWidth-1:0] axi_out_id_t;
typedef logic [AxiCfg.UserWidth-1:0] axi_user_t;
typedef logic [AxiCfg.DataWidth-1:0] axi_data_t;
typedef logic [AxiCfg.DataWidth/8-1:0] axi_strb_t;

// (Re-) definitons of `axi_in` and `floo` types, for transport
`AXI_TYPEDEF_ALL_CT(axi, axi_req_t, axi_rsp_t, axi_addr_t, axi_in_id_t,
axi_data_t, axi_strb_t, axi_user_t)
`AXI_TYPEDEF_AW_CHAN_T(axi_out_aw_chan_t, axi_addr_t, axi_out_id_t, axi_user_t)
`FLOO_TYPEDEF_AXI_CHAN_ALL(axi, req, rsp, axi, AxiCfg, hdr_t)

// Duplicate AXI port signals to degenerate ports
Expand Down Expand Up @@ -138,6 +140,8 @@ module floo_axi_chimney #(
// Meta Buffer
axi_req_t meta_buf_req_in;
axi_rsp_t meta_buf_rsp_out;
axi_out_req_t meta_buf_req_out;
axi_out_rsp_t meta_buf_rsp_in;

// Flit arbitration
typedef enum logic {SelAw, SelW} aw_w_sel_e;
Expand Down Expand Up @@ -202,6 +206,7 @@ module floo_axi_chimney #(
assign axi_ar_queue_valid_out = axi_in_req_i.ar_valid;
assign axi_rsp_out.ar_ready = axi_ar_queue_ready_in;
end

end else begin : gen_err_slv_port
axi_err_slv #(
.AxiIdWidth ( AxiCfg.InIdWidth ),
Expand Down Expand Up @@ -257,6 +262,34 @@ module floo_axi_chimney #(
assign floo_rsp_o.ready = floo_rsp_out_ready;
end


logic aw_out_queue_valid, aw_out_queue_ready;
axi_out_aw_chan_t axi_aw_queue_out;

// Since AW and W are transferred over the same link, it can happen that
// a downstream module does not accept the AW until the W is valid.
// Therefore, we need to add a spill register for the AW channel.
spill_register #(
.T (axi_out_aw_chan_t)
) i_aw_out_queue (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( meta_buf_req_out.aw_valid ),
.ready_o ( aw_out_queue_ready ),
.data_i ( meta_buf_req_out.aw ),
.valid_o ( aw_out_queue_valid ),
.ready_i ( axi_out_rsp_i.aw_ready ),
.data_o ( axi_aw_queue_out )
);

always_comb begin
axi_out_req_o = meta_buf_req_out;
axi_out_req_o.aw_valid = aw_out_queue_valid;
axi_out_req_o.aw = axi_aw_queue_out;
meta_buf_rsp_in = axi_out_rsp_i;
meta_buf_rsp_in.aw_ready = aw_out_queue_ready;
end

///////////////////////
// Reorder Buffers //
///////////////////////
Expand Down Expand Up @@ -663,8 +696,8 @@ module floo_axi_chimney #(
.test_enable_i,
.axi_req_i ( meta_buf_req_in ),
.axi_rsp_o ( meta_buf_rsp_out ),
.axi_req_o ( axi_out_req_o ),
.axi_rsp_i ( axi_out_rsp_i ),
.axi_req_o ( meta_buf_req_out ),
.axi_rsp_i ( meta_buf_rsp_in ),
.aw_buf_i ( aw_out_hdr_in ),
.ar_buf_i ( ar_out_hdr_in ),
.r_buf_o ( ar_out_hdr_out ),
Expand All @@ -683,8 +716,7 @@ module floo_axi_chimney #(
.slv_req_i ( meta_buf_req_in ),
.slv_resp_o ( meta_buf_rsp_out )
);

assign axi_out_req_o = '0;
assign meta_buf_req_out = '0;
assign ar_out_hdr_out = '0;
assign aw_out_hdr_out = '0;
end
Expand Down
69 changes: 63 additions & 6 deletions hw/floo_nw_chimney.sv
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@ module floo_nw_chimney #(

typedef logic [AxiCfgN.AddrWidth-1:0] axi_addr_t;
typedef logic [AxiCfgN.InIdWidth-1:0] axi_narrow_in_id_t;
typedef logic [AxiCfgN.OutIdWidth-1:0] axi_narrow_out_id_t;
typedef logic [AxiCfgN.UserWidth-1:0] axi_narrow_user_t;
typedef logic [AxiCfgN.DataWidth-1:0] axi_narrow_data_t;
typedef logic [AxiCfgN.DataWidth/8-1:0] axi_narrow_strb_t;
typedef logic [AxiCfgW.InIdWidth-1:0] axi_wide_in_id_t;
typedef logic [AxiCfgW.OutIdWidth-1:0] axi_wide_out_id_t;
typedef logic [AxiCfgW.UserWidth-1:0] axi_wide_user_t;
typedef logic [AxiCfgW.DataWidth-1:0] axi_wide_data_t;
typedef logic [AxiCfgW.DataWidth/8-1:0] axi_wide_strb_t;
Expand All @@ -122,6 +124,9 @@ module floo_nw_chimney #(
axi_narrow_in_id_t, axi_narrow_data_t, axi_narrow_strb_t, axi_narrow_user_t)
`AXI_TYPEDEF_ALL_CT(axi_wide, axi_wide_req_t, axi_wide_rsp_t, axi_addr_t,
axi_wide_in_id_t, axi_wide_data_t, axi_wide_strb_t, axi_wide_user_t)
`AXI_TYPEDEF_AW_CHAN_T(axi_wide_out_aw_chan_t, axi_addr_t, axi_wide_out_id_t, axi_wide_user_t)
`AXI_TYPEDEF_AW_CHAN_T(axi_narrow_out_aw_chan_t, axi_addr_t,
axi_narrow_out_id_t, axi_narrow_user_t)
`FLOO_TYPEDEF_NW_CHAN_ALL(axi, req, rsp, wide, axi_narrow, axi_wide, AxiCfgN, AxiCfgW, hdr_t)

// Duplicate AXI port signals to degenerate ports
Expand Down Expand Up @@ -191,8 +196,12 @@ module floo_nw_chimney #(
// Meta Buffers
axi_narrow_in_req_t axi_narrow_meta_buf_req_in;
axi_narrow_in_rsp_t axi_narrow_meta_buf_rsp_out;
axi_narrow_out_req_t axi_narrow_meta_buf_req_out;
axi_narrow_out_rsp_t axi_narrow_meta_buf_rsp_in;
axi_wide_in_req_t axi_wide_meta_buf_req_in;
axi_wide_in_rsp_t axi_wide_meta_buf_rsp_out;
axi_wide_out_req_t axi_wide_meta_buf_req_out;
axi_wide_out_rsp_t axi_wide_meta_buf_rsp_in;

// ID tracking
typedef struct packed {
Expand Down Expand Up @@ -321,6 +330,7 @@ module floo_nw_chimney #(
assign axi_wide_ar_queue_valid_out = axi_wide_in_req_i.ar_valid;
assign axi_wide_rsp_out.ar_ready = axi_wide_ar_queue_ready_in;
end

end else begin : gen_wide_err_slv_port
axi_err_slv #(
.AxiIdWidth ( AxiCfgW.InIdWidth ),
Expand Down Expand Up @@ -393,6 +403,53 @@ module floo_nw_chimney #(
assign floo_wide_o.ready = floo_wide_out_ready;
end

logic narrow_aw_out_queue_valid, narrow_aw_out_queue_ready;
logic wide_aw_out_queue_valid, wide_aw_out_queue_ready;
axi_narrow_out_aw_chan_t axi_narrow_aw_queue_out;
axi_wide_out_aw_chan_t axi_wide_aw_queue_out;

// Since AW and W are transferred over the same link, it can happen that
// a downstream module does not accept the AW until the W is valid.
// Therefore, we need to add a spill register for the AW channel.
spill_register #(
.T (axi_narrow_out_aw_chan_t)
) i_aw_narrow_out_queue (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( axi_narrow_meta_buf_req_out.aw_valid ),
.ready_o ( narrow_aw_out_queue_ready ),
.data_i ( axi_narrow_meta_buf_req_out.aw ),
.valid_o ( narrow_aw_out_queue_valid ),
.ready_i ( axi_narrow_out_rsp_i.aw_ready ),
.data_o ( axi_narrow_aw_queue_out )
);

spill_register #(
.T (axi_wide_out_aw_chan_t)
) i_aw_out_queue (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.valid_i ( axi_wide_meta_buf_req_out.aw_valid ),
.ready_o ( wide_aw_out_queue_ready ),
.data_i ( axi_wide_meta_buf_req_out.aw ),
.valid_o ( wide_aw_out_queue_valid ),
.ready_i ( axi_wide_out_rsp_i.aw_ready ),
.data_o ( axi_wide_aw_queue_out )
);

always_comb begin
axi_narrow_out_req_o = axi_narrow_meta_buf_req_out;
axi_narrow_out_req_o.aw_valid = narrow_aw_out_queue_valid;
axi_narrow_out_req_o.aw = axi_narrow_aw_queue_out;
axi_narrow_meta_buf_rsp_in = axi_narrow_out_rsp_i;
axi_narrow_meta_buf_rsp_in.aw_ready = narrow_aw_out_queue_ready;
axi_wide_out_req_o = axi_wide_meta_buf_req_out;
axi_wide_out_req_o.aw_valid = wide_aw_out_queue_valid;
axi_wide_out_req_o.aw = axi_wide_aw_queue_out;
axi_wide_meta_buf_rsp_in = axi_wide_out_rsp_i;
axi_wide_meta_buf_rsp_in.aw_ready = wide_aw_out_queue_ready;
end

///////////////////////
// Reorder Buffers //
///////////////////////
Expand Down Expand Up @@ -1106,8 +1163,8 @@ module floo_nw_chimney #(
.test_enable_i,
.axi_req_i ( axi_narrow_meta_buf_req_in ),
.axi_rsp_o ( axi_narrow_meta_buf_rsp_out ),
.axi_req_o ( axi_narrow_out_req_o ),
.axi_rsp_i ( axi_narrow_out_rsp_i ),
.axi_req_o ( axi_narrow_meta_buf_req_out ),
.axi_rsp_i ( axi_narrow_meta_buf_rsp_in ),
.aw_buf_i ( narrow_aw_buf_hdr_in ),
.ar_buf_i ( narrow_ar_buf_hdr_in ),
.r_buf_o ( narrow_ar_buf_hdr_out ),
Expand All @@ -1126,7 +1183,7 @@ module floo_nw_chimney #(
.slv_req_i ( axi_narrow_meta_buf_req_in ),
.slv_resp_o ( axi_narrow_meta_buf_rsp_out )
);
assign axi_narrow_out_req_o = '0;
assign axi_narrow_meta_buf_req_out = '0;
assign narrow_ar_buf_hdr_out = '0;
assign narrow_aw_buf_hdr_out = '0;
end
Expand All @@ -1150,8 +1207,8 @@ module floo_nw_chimney #(
.test_enable_i,
.axi_req_i ( axi_wide_meta_buf_req_in ),
.axi_rsp_o ( axi_wide_meta_buf_rsp_out ),
.axi_req_o ( axi_wide_out_req_o ),
.axi_rsp_i ( axi_wide_out_rsp_i ),
.axi_req_o ( axi_wide_meta_buf_req_out ),
.axi_rsp_i ( axi_wide_meta_buf_rsp_in ),
.aw_buf_i ( wide_aw_buf_hdr_in ),
.ar_buf_i ( wide_ar_buf_hdr_in ),
.r_buf_o ( wide_ar_buf_hdr_out ),
Expand All @@ -1170,7 +1227,7 @@ module floo_nw_chimney #(
.slv_req_i ( axi_wide_meta_buf_req_in ),
.slv_resp_o ( axi_wide_meta_buf_rsp_out )
);
assign axi_wide_out_req_o = '0;
assign axi_wide_meta_buf_req_out = '0;
assign wide_ar_buf_hdr_out = '0;
assign wide_aw_buf_hdr_out = '0;
end
Expand Down
60 changes: 42 additions & 18 deletions hw/tb/tb_floo_axi_chimney.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ module tb_floo_axi_chimney;
axi_in_req_t [NumTargets-1:0] node_man_req;
axi_in_rsp_t [NumTargets-1:0] node_man_rsp;

axi_out_req_t [NumTargets-1:0] node_sub_req;
axi_out_rsp_t [NumTargets-1:0] node_sub_rsp;
axi_out_req_t [NumTargets-1:0] node_sub_req, node_sub_req_sync;
axi_out_rsp_t [NumTargets-1:0] node_sub_rsp, node_sub_rsp_sync;

axi_in_req_t [NumTargets-1:0] sub_req_id_assign;
axi_in_rsp_t [NumTargets-1:0] sub_rsp_id_assign;

for (genvar i = 0; i < NumTargets; i++) begin : gen_axi_assign
`AXI_ASSIGN_REQ_STRUCT(sub_req_id_assign[i], node_sub_req[i])
`AXI_ASSIGN_RESP_STRUCT(sub_rsp_id_assign[i], node_sub_rsp[i])
`AXI_ASSIGN_REQ_STRUCT(sub_req_id_assign[i], node_sub_req_sync[i])
`AXI_ASSIGN_RESP_STRUCT(sub_rsp_id_assign[i], node_sub_rsp_sync[i])
end

floo_req_t [NumTargets-1:0] chimney_req;
Expand Down Expand Up @@ -83,13 +83,13 @@ module tb_floo_axi_chimney;
.NumReads ( NumReads0 ),
.NumWrites ( NumWrites0 )
) i_test_node_0 (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.mst_port_req_o ( node_man_req[0] ),
.mst_port_rsp_i ( node_man_rsp[0] ),
.slv_port_req_i ( node_sub_req[0] ),
.slv_port_rsp_o ( node_sub_rsp[0] ),
.end_of_sim ( end_of_sim[0] )
.clk_i ( clk ),
.rst_ni ( rst_n ),
.mst_port_req_o ( node_man_req[0] ),
.mst_port_rsp_i ( node_man_rsp[0] ),
.slv_port_req_i ( node_sub_req_sync[0] ),
.slv_port_rsp_o ( node_sub_rsp_sync[0] ),
.end_of_sim ( end_of_sim[0] )
);

axi_reorder_remap_compare #(
Expand All @@ -111,6 +111,18 @@ module tb_floo_axi_chimney;
.end_of_sim_o ( end_of_sim[1] )
);

axi_aw_w_sync #(
.axi_req_t ( axi_out_req_t ),
.axi_resp_t ( axi_out_rsp_t )
) i_axi_aw_w_sync_0 (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.slv_req_i ( node_sub_req[0] ),
.slv_resp_o ( node_sub_rsp[0] ),
.mst_req_o ( node_sub_req_sync[0] ),
.mst_resp_i ( node_sub_rsp_sync[0] )
);

floo_axi_chimney #(
.AxiCfg ( floo_test_pkg::AxiCfg ),
.ChimneyCfg ( floo_test_pkg::ChimneyCfg ),
Expand Down Expand Up @@ -173,6 +185,18 @@ module tb_floo_axi_chimney;
.floo_rsp_i ( chimney_rsp[0] )
);

axi_aw_w_sync #(
.axi_req_t ( axi_out_req_t ),
.axi_resp_t ( axi_out_rsp_t )
) i_axi_aw_w_sync_1 (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.slv_req_i ( node_sub_req[1] ),
.slv_resp_o ( node_sub_rsp[1] ),
.mst_req_o ( node_sub_req_sync[1] ),
.mst_resp_i ( node_sub_rsp_sync[1] )
);

axi_reorder_remap_compare #(
.AxiInIdWidth ( floo_test_pkg::AxiCfg.InIdWidth ),
.AxiOutIdWidth ( floo_test_pkg::AxiCfg.OutIdWidth ),
Expand Down Expand Up @@ -207,13 +231,13 @@ module tb_floo_axi_chimney;
.NumReads ( NumReads1 ),
.NumWrites ( NumWrites1 )
) i_test_node_1 (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.mst_port_req_o ( node_man_req[1] ),
.mst_port_rsp_i ( node_man_rsp[1] ),
.slv_port_req_i ( node_sub_req[1] ),
.slv_port_rsp_o ( node_sub_rsp[1] ),
.end_of_sim ( end_of_sim[3] )
.clk_i ( clk ),
.rst_ni ( rst_n ),
.mst_port_req_o ( node_man_req[1] ),
.mst_port_rsp_i ( node_man_rsp[1] ),
.slv_port_req_i ( node_sub_req_sync[1] ),
.slv_port_rsp_o ( node_sub_rsp_sync[1] ),
.end_of_sim ( end_of_sim[3] )
);

axi_bw_monitor #(
Expand Down
Loading
Loading