@@ -207,8 +207,8 @@ module axi_mcast_demux_mapped #(
207207 // -----------------
208208
209209 // AW decoder inputs
210- mask_rule_t [NoMulticastRules- 1 : 0 ] multicast_rules;
211- mask_rule_t default_rule;
210+ mask_rule_t [axi_pkg :: iomsb ( NoMulticastRules) : 0 ] multicast_rules;
211+ mask_rule_t default_rule;
212212
213213 // AW unicast decoder outputs
214214 idx_select_t dec_aw_unicast_select_idx;
@@ -228,16 +228,6 @@ module axi_mcast_demux_mapped #(
228228 addr_t [NoMstPortsExt- 1 : 0 ] dec_aw_addr;
229229 addr_t [NoMstPortsExt- 1 : 0 ] dec_aw_mask;
230230
231- // Convert multicast rules to mask (NAPOT) form, see https://arxiv.org/pdf/2502.19215
232- for (genvar i = 0 ; i < NoMulticastRules; i++ ) begin : g_multicast_rules
233- assign multicast_rules[i].idx = addr_map_i[i].idx;
234- assign multicast_rules[i].mask = addr_map_i[i].end_addr - addr_map_i[i].start_addr - 1 ;
235- assign multicast_rules[i].addr = addr_map_i[i].start_addr;
236- end
237- assign default_rule.idx = default_mst_port_i.idx;
238- assign default_rule.mask = default_mst_port_i.end_addr - default_mst_port_i.start_addr - 1 ;
239- assign default_rule.addr = default_mst_port_i.start_addr;
240-
241231 // Address decoding for unicast requests
242232 addr_decode # (
243233 .NoIndices (NoMstPorts),
@@ -257,40 +247,53 @@ module axi_mcast_demux_mapped #(
257247 // Generate the output mask from the index
258248 assign dec_aw_unicast_select_mask = 1'b1 << dec_aw_unicast_select_idx;
259249
260- // Address decoding for multicast requests
261- if (NoMulticastRules > 0 ) begin : gen_multicast_decoding
262- multiaddr_decode # (
263- .NoIndices (NoMulticastPorts),
264- .NoRules (NoMulticastRules),
265- .addr_t (addr_t),
266- .rule_t (mask_rule_t)
267- ) i_axi_aw_multicast_decode (
268- .addr_map_i (multicast_rules),
269- .addr_i (slv_req_cut.aw.addr),
270- .mask_i (slv_req_cut.aw.user.collective_mask),
271- .select_o (dec_aw_multicast_select_mask),
272- .addr_o (dec_aw_multicast_addr),
273- .mask_o (dec_aw_multicast_mask),
274- .dec_valid_o (dec_aw_multicast_valid),
275- .dec_error_o (dec_aw_multicast_error),
276- .en_default_idx_i (en_default_mst_port_i),
277- .default_idx_i (default_rule)
278- );
279- end else begin : gen_no_multicast_decoding
280- assign dec_aw_multicast_select_mask = '0 ;
281- assign dec_aw_multicast_addr = '0 ;
282- assign dec_aw_multicast_mask = '0 ;
283- assign dec_aw_multicast_valid = '0 ;
284- assign dec_aw_multicast_error = '0 ;
285- end
286-
287250 // If the address decoding doesn't produce any match, the request
288251 // is routed to the error slave, which lies at the highest index.
289252 mask_select_t select_error_slave;
290253 assign select_error_slave = 1'b1 << NoMstPorts;
291254
292- // Mux the multicast and unicast decoding outputs
293- if (NoMulticastRules > 0 ) begin : gen_decoding_mux
255+ // Disable multicast only if NoMulticastPorts == 0. In some instances you may want to
256+ // match the multicast decoder's default port, even if NoMulticastRules == 0.
257+ if (NoMulticastPorts > 0 ) begin : gen_multicast
258+
259+ // Convert multicast rules to mask (NAPOT) form, see https://arxiv.org/pdf/2502.19215
260+ for (genvar i = 0 ; i < NoMulticastRules; i++ ) begin : gen_multicast_rules
261+ assign multicast_rules[i].idx = addr_map_i[i].idx;
262+ assign multicast_rules[i].mask = addr_map_i[i].end_addr - addr_map_i[i].start_addr - 1 ;
263+ assign multicast_rules[i].addr = addr_map_i[i].start_addr;
264+ end
265+ assign default_rule.idx = default_mst_port_i.idx;
266+ assign default_rule.mask = default_mst_port_i.end_addr - default_mst_port_i.start_addr - 1 ;
267+ assign default_rule.addr = default_mst_port_i.start_addr;
268+
269+ if (NoMulticastRules > 0 ) begin : gen_multiaddr_decode
270+ // Address decoding for multicast requests.
271+ multiaddr_decode # (
272+ .NoIndices (NoMulticastPorts),
273+ .NoRules (NoMulticastRules),
274+ .addr_t (addr_t),
275+ .rule_t (mask_rule_t)
276+ ) i_axi_aw_multicast_decode (
277+ .addr_map_i (multicast_rules),
278+ .addr_i (slv_req_cut.aw.addr),
279+ .mask_i (slv_req_cut.aw.user.collective_mask),
280+ .select_o (dec_aw_multicast_select_mask),
281+ .addr_o (dec_aw_multicast_addr),
282+ .mask_o (dec_aw_multicast_mask),
283+ .dec_valid_o (dec_aw_multicast_valid),
284+ .dec_error_o (dec_aw_multicast_error),
285+ .en_default_idx_i (en_default_mst_port_i),
286+ .default_idx_i (default_rule)
287+ );
288+ end else begin : gen_no_multiaddr_decode
289+ assign dec_aw_multicast_select_mask = 1'b1 << default_rule.idx;
290+ assign dec_aw_multicast_addr = slv_req_cut.aw.addr;
291+ assign dec_aw_multicast_mask = slv_req_cut.aw.user.collective_mask;
292+ assign dec_aw_multicast_valid = 1'b1 ;
293+ assign dec_aw_multicast_error = 1'b0 ;
294+ end
295+
296+ // Mux the multicast and unicast decoding outputs.
294297 always_comb begin
295298 dec_aw_select_mask = '0 ;
296299 dec_aw_addr = '0 ;
@@ -313,7 +316,8 @@ module axi_mcast_demux_mapped #(
313316 end
314317 end
315318 end
316- end else begin
319+
320+ end else begin : gen_no_multicast
317321 assign dec_aw_addr = { '0 , { NoMstPorts{ slv_req_cut.aw.addr}}} ;
318322 assign dec_aw_mask = '0 ;
319323 assign dec_aw_select_mask = (dec_aw_unicast_error) ? select_error_slave :
@@ -396,7 +400,7 @@ module axi_mcast_demux_mapped #(
396400 i, addr_map_i[i].start_addr, size))
397401 end
398402 // Default rule is only converted to mask form if there are any other multicast rules
399- if (NoMulticastRules > 0 ) begin : gen_multicast_default_rule_assertion
403+ if (NoMulticastPorts > 0 ) begin : gen_multicast_default_rule_assertion
400404 addr_t size;
401405 assign size = default_mst_port_i.end_addr - default_mst_port_i.start_addr;
402406 `ASSERT (DefaultRuleSize,
0 commit comments