Skip to content

Commit 3d4586b

Browse files
committed
hw/reqrsp: Add generic reqrsp-like interface cut and mux
1 parent 8640752 commit 3d4586b

File tree

7 files changed

+269
-135
lines changed

7 files changed

+269
-135
lines changed

Bender.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ sources:
4141
# reqrsp_interface
4242
- files:
4343
# Level 0
44+
- hw/reqrsp_interface/src/generic_reqrsp_cut.sv
45+
- hw/reqrsp_interface/src/generic_reqrsp_mux.sv
4446
- hw/reqrsp_interface/src/reqrsp_pkg.sv
4547
# Level 1
4648
- hw/reqrsp_interface/src/reqrsp_intf.sv

hw/reqrsp_interface/include/reqrsp_interface/assign.svh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44

55
// Author: Florian Zaruba <[email protected]>
66
// Author: Fabian Schuiki <[email protected]>
7+
// Author: Luca Colagrande <[email protected]>
78

89
// Macros to assign reqrsp Interfaces and Structs
910

1011
`ifndef REQRSP_ASSIGN_SVH_
1112
`define REQRSP_ASSIGN_SVH_
1213

14+
// Tie off a generic reqrsp-like interface
15+
`define REQRSP_TIE_OFF_REQ(__if) \
16+
assign ``__if``.q = '0; \
17+
assign ``__if``.q_valid = 1'b0; \
18+
assign ``__if``.p_ready = 1'b0;
19+
`define REQRSP_TIE_OFF_RSP(__if) \
20+
assign ``__if``.p = '0; \
21+
assign ``__if``.p_valid = 1'b0; \
22+
assign ``__if``.q_ready = 1'b0;
23+
1324
// Assign an reqrsp handshake.
1425
`define REQRSP_ASSIGN_VALID(__opt_as, __dst, __src, __chan) \
1526
__opt_as ``__dst``.``__chan``_valid = ``__src``.``__chan``_valid;

hw/reqrsp_interface/include/reqrsp_interface/typedef.svh

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,34 @@
2525
logic error; \
2626
} __rsp_chan_t;
2727

28+
`define GENERIC_REQRSP_REQ_STRUCT(__req_chan_t) \
29+
struct packed { \
30+
__req_chan_t q; \
31+
logic q_valid; \
32+
logic p_ready; \
33+
}
34+
35+
`define GENERIC_REQRSP_RSP_STRUCT(__rsp_chan_t) \
36+
struct packed { \
37+
__rsp_chan_t p; \
38+
logic p_valid; \
39+
logic q_ready; \
40+
}
41+
2842
`define REQRSP_TYPEDEF_REQ_T(__req_t, __req_chan_t) \
29-
typedef struct packed { \
30-
__req_chan_t q; \
31-
logic q_valid; \
32-
logic p_ready; \
33-
} __req_t;
43+
typedef `GENERIC_REQRSP_REQ_STRUCT(__req_chan_t) __req_t;
3444

3545
`define REQRSP_TYPEDEF_RSP_T(__rsp_t, __rsp_chan_t) \
36-
typedef struct packed { \
37-
__rsp_chan_t p; \
38-
logic p_valid; \
39-
logic q_ready; \
40-
} __rsp_t;
46+
typedef `GENERIC_REQRSP_RSP_STRUCT(__rsp_chan_t) __rsp_t;
4147

4248
`define REQRSP_TYPEDEF_ALL(__name, __addr_t, __data_t, __strb_t, __user_t) \
4349
`REQRSP_TYPEDEF_REQ_CHAN_T(__name``_req_chan_t, __addr_t, __data_t, __strb_t, __user_t) \
4450
`REQRSP_TYPEDEF_RSP_CHAN_T(__name``_rsp_chan_t, __data_t) \
4551
`REQRSP_TYPEDEF_REQ_T(__name``_req_t, __name``_req_chan_t) \
4652
`REQRSP_TYPEDEF_RSP_T(__name``_rsp_t, __name``_rsp_chan_t)
4753

54+
`define GENERIC_REQRSP_TYPEDEF_ALL(__name, __req_chan_t, __rsp_chan_t) \
55+
`REQRSP_TYPEDEF_REQ_T(__name``_req_t, __req_chan_t) \
56+
`REQRSP_TYPEDEF_RSP_T(__name``_rsp_t, __rsp_chan_t)
57+
4858
`endif
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2025 ETH Zurich and University of Bologna.
2+
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
3+
// SPDX-License-Identifier: SHL-0.51
4+
5+
// Author: Luca Colagrande <[email protected]>
6+
7+
`include "reqrsp_interface/typedef.svh"
8+
9+
/// Cut all combinatorial paths through a generic `reqrsp`-like interface.
10+
module generic_reqrsp_cut #(
11+
/// Request type.
12+
parameter type req_chan_t = logic,
13+
/// Response type.
14+
parameter type rsp_chan_t = logic,
15+
/// Bypass request channel.
16+
parameter bit BypassReq = 0,
17+
/// Bypass Response channel.
18+
parameter bit BypassRsp = 0,
19+
/// Derived parameters *do not override*
20+
localparam type req_t = `GENERIC_REQRSP_REQ_STRUCT(req_chan_t),
21+
localparam type rsp_t = `GENERIC_REQRSP_RSP_STRUCT(rsp_chan_t)
22+
) (
23+
input logic clk_i,
24+
input logic rst_ni,
25+
input req_t slv_req_i,
26+
output rsp_t slv_rsp_o,
27+
output req_t mst_req_o,
28+
input rsp_t mst_rsp_i
29+
);
30+
31+
spill_register #(
32+
.T (req_chan_t),
33+
.Bypass(BypassReq)
34+
) i_spill_register_q (
35+
.clk_i,
36+
.rst_ni,
37+
.valid_i(slv_req_i.q_valid),
38+
.ready_o(slv_rsp_o.q_ready),
39+
.data_i (slv_req_i.q),
40+
.valid_o(mst_req_o.q_valid),
41+
.ready_i(mst_rsp_i.q_ready),
42+
.data_o (mst_req_o.q)
43+
);
44+
45+
spill_register #(
46+
.T (rsp_chan_t),
47+
.Bypass(BypassRsp)
48+
) i_spill_register_p (
49+
.clk_i,
50+
.rst_ni,
51+
.valid_i(mst_rsp_i.p_valid),
52+
.ready_o(mst_req_o.p_ready),
53+
.data_i (mst_rsp_i.p),
54+
.valid_o(slv_rsp_o.p_valid),
55+
.ready_i(slv_req_i.p_ready),
56+
.data_o (slv_rsp_o.p)
57+
);
58+
59+
endmodule
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Copyright 2025 ETH Zurich and University of Bologna.
2+
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
3+
// SPDX-License-Identifier: SHL-0.51
4+
5+
// Author: Luca Colagrande <[email protected]>
6+
7+
`include "reqrsp_interface/typedef.svh"
8+
9+
/// Multiplex multiple generic `reqrsp`-like ports onto one, based on arbitration.
10+
module generic_reqrsp_mux #(
11+
/// Number of input ports.
12+
parameter int unsigned NrPorts = 2,
13+
/// Request channel type.
14+
parameter type req_chan_t = logic,
15+
/// Response channel type.
16+
parameter type rsp_chan_t = logic,
17+
/// Amount of outstanding responses. Determines the FIFO size.
18+
parameter int unsigned RspDepth = 8,
19+
/// Cut timing paths on the request path. Incurs a cycle additional latency.
20+
/// Registers are inserted at the slave side.
21+
parameter bit [NrPorts-1:0] RegisterReq = '0,
22+
/// Externally provide routing information for responses. Can be used when
23+
/// storing response routes externally, e.g. as a source tag passed along a
24+
/// pipeline, i.e. when RspDepth == 0.
25+
parameter bit ExtRspRoute = 1'b0,
26+
/// Dependent parameters *do not override*
27+
/// Width of the arbitrated index.
28+
localparam int unsigned IdxWidth = cf_math_pkg::idx_width(NrPorts),
29+
localparam type req_t = `GENERIC_REQRSP_REQ_STRUCT(req_chan_t),
30+
localparam type rsp_t = `GENERIC_REQRSP_RSP_STRUCT(rsp_chan_t)
31+
) (
32+
input logic clk_i,
33+
input logic rst_ni,
34+
input req_t [NrPorts-1:0] slv_req_i,
35+
output rsp_t [NrPorts-1:0] slv_rsp_o,
36+
output req_t mst_req_o,
37+
input rsp_t mst_rsp_i,
38+
// Route responses should follow when using external routing.
39+
input logic [IdxWidth-1:0] rsp_route_i,
40+
// Request port select by the arbitration logic.
41+
output logic [IdxWidth-1:0] idx_o
42+
);
43+
44+
logic [NrPorts-1:0] req_valid_masked, req_ready_masked;
45+
logic [IdxWidth-1:0] idx, idx_rsp;
46+
logic full;
47+
48+
req_chan_t [NrPorts-1:0] req_payload_q;
49+
logic [NrPorts-1:0] req_valid_q, req_ready_q;
50+
51+
// Unforunately we need this signal otherwise the simulator complains about
52+
// multiple driven signals, because some other signals are driven from an
53+
// `always_comb` block.
54+
logic [NrPorts-1:0] slv_rsp_q_ready;
55+
56+
// Optionally cut the incoming paths
57+
for (genvar i = 0; i < NrPorts; i++) begin : gen_cuts
58+
spill_register #(
59+
.T (req_chan_t),
60+
.Bypass (!RegisterReq[i])
61+
) i_spill_register_req (
62+
.clk_i,
63+
.rst_ni,
64+
.valid_i (slv_req_i[i].q_valid),
65+
.ready_o (slv_rsp_q_ready[i]),
66+
.data_i (slv_req_i[i].q),
67+
.valid_o (req_valid_q[i]),
68+
.ready_i (req_ready_masked[i]),
69+
.data_o (req_payload_q[i])
70+
);
71+
end
72+
73+
// We need to silence the handshake in case the fifo is full and we can't
74+
// accept more transactions.
75+
for (genvar i = 0; i < NrPorts; i++) begin : gen_req_valid_masked
76+
assign req_valid_masked[i] = req_valid_q[i] & ~full;
77+
assign req_ready_masked[i] = req_ready_q[i] & ~full;
78+
end
79+
80+
/// Arbitrate requests
81+
rr_arb_tree #(
82+
.NumIn (NrPorts),
83+
.DataType (req_chan_t),
84+
.AxiVldRdy (1'b1),
85+
.LockIn (1'b1)
86+
) i_q_mux (
87+
.clk_i,
88+
.rst_ni,
89+
.flush_i (1'b0),
90+
.rr_i ('0),
91+
.req_i (req_valid_masked),
92+
.gnt_o (req_ready_q),
93+
.data_i (req_payload_q),
94+
.gnt_i (mst_rsp_i.q_ready),
95+
.req_o (mst_req_o.q_valid),
96+
.data_o (mst_req_o.q),
97+
.idx_o (idx_o)
98+
);
99+
100+
// De-generate version does not need a fifo. We always know where to route
101+
// back the responses.
102+
if (NrPorts == 1) begin : gen_single_port
103+
assign idx_rsp = 0;
104+
assign full = 1'b0;
105+
end else begin : gen_multi_port
106+
if (ExtRspRoute) begin : gen_no_rsp_fifo
107+
// Alternatively select route based on externally provided information.
108+
assign idx_rsp = rsp_route_i;
109+
assign full = 1'b0;
110+
end else begin : gen_rsp_fifo
111+
// For the "normal" case we need to save the arbitration decision. We do so
112+
// by converting the handshake into a binary signal which we save for
113+
// response routing.
114+
onehot_to_bin #(
115+
.ONEHOT_WIDTH (NrPorts)
116+
) i_onehot_to_bin (
117+
.onehot (req_valid_q & req_ready_q),
118+
.bin (idx)
119+
);
120+
// Save the arbitration decision.
121+
fifo_v3 #(
122+
.DATA_WIDTH (IdxWidth),
123+
.DEPTH (RspDepth)
124+
) i_rsp_fifo (
125+
.clk_i,
126+
.rst_ni,
127+
.flush_i (1'b0),
128+
.testmode_i (1'b0),
129+
.full_o (full),
130+
.empty_o (),
131+
.usage_o (),
132+
.data_i (idx),
133+
.push_i (mst_req_o.q_valid & mst_rsp_i.q_ready),
134+
.data_o (idx_rsp),
135+
.pop_i (mst_req_o.p_ready & mst_rsp_i.p_valid)
136+
);
137+
end
138+
end
139+
140+
// Output Mux
141+
always_comb begin
142+
for (int i = 0; i < NrPorts; i++) begin
143+
slv_rsp_o[i].p_valid = '0;
144+
slv_rsp_o[i].q_ready = slv_rsp_q_ready[i];
145+
slv_rsp_o[i].p = mst_rsp_i.p;
146+
end
147+
slv_rsp_o[idx_rsp].p_valid = mst_rsp_i.p_valid;
148+
end
149+
150+
assign mst_req_o.p_ready = slv_req_i[idx_rsp].p_ready;
151+
152+
endmodule

hw/reqrsp_interface/src/reqrsp_cut.sv

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,32 +38,18 @@ module reqrsp_cut #(
3838

3939
`REQRSP_TYPEDEF_ALL(reqrsp, addr_t, data_t, strb_t, user_t)
4040

41-
spill_register #(
42-
.T (reqrsp_req_chan_t),
43-
.Bypass ( BypassReq )
44-
) i_spill_register_q (
45-
.clk_i,
46-
.rst_ni,
47-
.valid_i (slv_req_i.q_valid) ,
48-
.ready_o (slv_rsp_o.q_ready) ,
49-
.data_i (slv_req_i.q),
50-
.valid_o (mst_req_o.q_valid),
51-
.ready_i (mst_rsp_i.q_ready),
52-
.data_o (mst_req_o.q)
53-
);
54-
55-
spill_register #(
56-
.T (reqrsp_rsp_chan_t),
57-
.Bypass ( BypassRsp )
58-
) i_spill_register_p (
41+
generic_reqrsp_cut #(
42+
.req_chan_t(reqrsp_req_chan_t),
43+
.rsp_chan_t(reqrsp_rsp_chan_t),
44+
.BypassReq (BypassReq),
45+
.BypassRsp (BypassRsp)
46+
) i_generic_reqrsp_cut (
5947
.clk_i,
6048
.rst_ni,
61-
.valid_i (mst_rsp_i.p_valid) ,
62-
.ready_o (mst_req_o.p_ready) ,
63-
.data_i (mst_rsp_i.p),
64-
.valid_o (slv_rsp_o.p_valid),
65-
.ready_i (slv_req_i.p_ready),
66-
.data_o (slv_rsp_o.p)
49+
.slv_req_i (slv_req_i),
50+
.slv_rsp_o (slv_rsp_o),
51+
.mst_req_o (mst_req_o),
52+
.mst_rsp_i (mst_rsp_i)
6753
);
6854

6955
endmodule

0 commit comments

Comments
 (0)