Skip to content

Commit 6e625f3

Browse files
committed
axi_mcast_xbar: Allow multiple outstanding multicast transactions
Multiple outstanding multicast transactions are allowed only if the slaves selected by these transactions are the same.
1 parent 49bcf7c commit 6e625f3

File tree

1 file changed

+29
-20
lines changed

1 file changed

+29
-20
lines changed

src/axi_mcast_demux.sv

+29-20
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ module axi_mcast_demux #(
6262
parameter int unsigned NoAddrRules = 32'd0,
6363
parameter int unsigned NoMulticastRules = 32'd0,
6464
parameter int unsigned NoMulticastPorts = 32'd0,
65+
parameter int unsigned MaxMcastTrans = 32'd7,
6566
// Dependent parameters, DO NOT OVERRIDE!
6667
parameter int unsigned DecodeIdxWidth = ((NoMstPorts - 1) > 32'd1) ? $clog2(NoMstPorts - 1) : 32'd1,
6768
parameter int unsigned IdxSelectWidth = (NoMstPorts > 32'd1) ? $clog2(NoMstPorts) : 32'd1,
@@ -89,6 +90,9 @@ module axi_mcast_demux #(
8990
localparam int unsigned IdCounterWidth = cf_math_pkg::idx_width(MaxTrans);
9091
typedef logic [IdCounterWidth-1:0] id_cnt_t;
9192

93+
localparam int unsigned McastCounterWidth = (MaxMcastTrans > 32'd1) ? $clog2(MaxMcastTrans+1) : 32'd1;
94+
typedef logic [McastCounterWidth-1:0] mcast_cnt_t;
95+
9296
typedef struct packed {
9397
int unsigned idx;
9498
aw_addr_t addr;
@@ -199,15 +203,14 @@ module axi_mcast_demux #(
199203
idx_select_t lookup_aw_select;
200204
logic aw_select_occupied, aw_id_cnt_full;
201205
logic aw_any_outstanding_unicast_trx;
202-
logic aw_any_outstanding_trx;
203206
// Upon an ATOP load, inject IDs from the AW into the AR channel
204207
logic atop_inject;
205208
// Multicast logic
206209
logic aw_is_multicast;
207210
logic outstanding_multicast;
208211
logic multicast_stall;
209212
mask_select_t multicast_select_q, multicast_select_d;
210-
logic multicast_select_load;
213+
mcast_cnt_t outstanding_mcast_cnt_q, outstanding_mcast_cnt_d;
211214
logic [$clog2(NoMstPorts)+1-1:0] aw_select_popcount;
212215
logic accept_aw;
213216
logic mcast_aw_hs_in_progress;
@@ -452,31 +455,37 @@ module axi_mcast_demux #(
452455
// of a multicast. This means stall an AW request if:
453456
// - there is an outstanding multicast transaction or
454457
// - if the request is a multicast, until there are no more outstanding transactions
455-
assign aw_is_multicast = aw_select_popcount > 1;
456-
assign outstanding_multicast = |multicast_select_q;
457-
assign aw_any_outstanding_trx = aw_any_outstanding_unicast_trx || outstanding_multicast;
458-
assign multicast_stall = outstanding_multicast || (aw_is_multicast && aw_any_outstanding_trx);
458+
// We can slightly loosen this constraint, in the case of successive multicast
459+
// requests going to the same slaves. In this case, we don't need to buffer any
460+
// additional select signals.
461+
assign aw_is_multicast = aw_select_popcount > 1;
462+
assign outstanding_multicast = outstanding_mcast_cnt_q != '0;
463+
assign multicast_stall = (outstanding_multicast && (slv_aw_select_mask != multicast_select_q)) ||
464+
(aw_is_multicast && aw_any_outstanding_unicast_trx) ||
465+
(outstanding_mcast_cnt_q == MaxMcastTrans);
459466
// We can send this signal to all slaves since we will only have one outstanding aw
460467
assign mst_is_mcast_o = {NoMstPorts{aw_is_multicast}};
461468

462469
// Keep track of which B responses need to be returned to complete the multicast
463-
`FFLARN(multicast_select_q, multicast_select_d, multicast_select_load, '0, clk_i, rst_ni)
470+
`FFARN(multicast_select_q, multicast_select_d, '0, clk_i, rst_ni)
471+
`FFARN(outstanding_mcast_cnt_q, outstanding_mcast_cnt_d, '0, clk_i, rst_ni)
464472

465-
// Logic to update multicast_select_q. Loads the register upon the AW handshake
466-
// of a multicast transaction. Successively clears it upon the "joined" B handshake
473+
// Logic to update number of outstanding multicast transactions and current multicast
474+
// transactions' select mask. Counter is incremented upon the AW handshake of a multicast
475+
// transaction and decremented upon the "joined" B handshake.
467476
always_comb begin
468477
multicast_select_d = multicast_select_q;
469-
multicast_select_load = 1'b0;
470-
471-
unique if (aw_is_multicast && aw_valid && aw_ready) begin
472-
multicast_select_d = slv_aw_select_mask;
473-
multicast_select_load = 1'b1;
474-
end else if (outstanding_multicast && slv_b_valid && slv_b_ready) begin
475-
multicast_select_d = '0;
476-
multicast_select_load = 1'b1;
477-
end else begin
478-
multicast_select_d = multicast_select_q;
479-
multicast_select_load = 1'b0;
478+
outstanding_mcast_cnt_d = outstanding_mcast_cnt_q;
479+
480+
// Written as separate if statements as they may both be valid at the same time
481+
// For the same reason the right hand side uses outstanding_mcast_cnt_d
482+
// instead of outstanding_mcast_cnt_q
483+
if (aw_is_multicast && aw_valid && aw_ready) begin
484+
outstanding_mcast_cnt_d = outstanding_mcast_cnt_d + (|slv_aw_select_mask);
485+
multicast_select_d = slv_aw_select_mask;
486+
end
487+
if (outstanding_multicast && slv_b_valid && slv_b_ready) begin
488+
outstanding_mcast_cnt_d = outstanding_mcast_cnt_d - 1;
480489
end
481490
end
482491

0 commit comments

Comments
 (0)