@@ -62,6 +62,7 @@ module axi_mcast_demux #(
62
62
parameter int unsigned NoAddrRules = 32'd0 ,
63
63
parameter int unsigned NoMulticastRules = 32'd0 ,
64
64
parameter int unsigned NoMulticastPorts = 32'd0 ,
65
+ parameter int unsigned MaxMcastTrans = 32'd7 ,
65
66
// Dependent parameters, DO NOT OVERRIDE!
66
67
parameter int unsigned DecodeIdxWidth = ((NoMstPorts - 1 ) > 32'd1 ) ? $clog2(NoMstPorts - 1 ) : 32'd1 ,
67
68
parameter int unsigned IdxSelectWidth = (NoMstPorts > 32'd1 ) ? $clog2(NoMstPorts) : 32'd1 ,
@@ -89,6 +90,9 @@ module axi_mcast_demux #(
89
90
localparam int unsigned IdCounterWidth = cf_math_pkg :: idx_width (MaxTrans);
90
91
typedef logic [IdCounterWidth- 1 : 0 ] id_cnt_t ;
91
92
93
+ localparam int unsigned McastCounterWidth = (MaxMcastTrans > 32'd1 ) ? $clog2 (MaxMcastTrans+ 1 ) : 32'd1 ;
94
+ typedef logic [McastCounterWidth- 1 : 0 ] mcast_cnt_t ;
95
+
92
96
typedef struct packed {
93
97
int unsigned idx;
94
98
aw_addr_t addr;
@@ -199,15 +203,14 @@ module axi_mcast_demux #(
199
203
idx_select_t lookup_aw_select;
200
204
logic aw_select_occupied, aw_id_cnt_full;
201
205
logic aw_any_outstanding_unicast_trx;
202
- logic aw_any_outstanding_trx;
203
206
// Upon an ATOP load, inject IDs from the AW into the AR channel
204
207
logic atop_inject;
205
208
// Multicast logic
206
209
logic aw_is_multicast;
207
210
logic outstanding_multicast;
208
211
logic multicast_stall;
209
212
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 ;
211
214
logic [$clog2 (NoMstPorts)+ 1 - 1 : 0 ] aw_select_popcount;
212
215
logic accept_aw;
213
216
logic mcast_aw_hs_in_progress;
@@ -452,31 +455,37 @@ module axi_mcast_demux #(
452
455
// of a multicast. This means stall an AW request if:
453
456
// - there is an outstanding multicast transaction or
454
457
// - 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);
459
466
// We can send this signal to all slaves since we will only have one outstanding aw
460
467
assign mst_is_mcast_o = { NoMstPorts{ aw_is_multicast}} ;
461
468
462
469
// 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)
464
472
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.
467
476
always_comb begin
468
477
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 ;
480
489
end
481
490
end
482
491
0 commit comments