Skip to content

Commit 8e04779

Browse files
committed
axi_mcast_demux_mapped: Allow multicast XBAR with NoMulticastRules == 0
1 parent 6544830 commit 8e04779

File tree

1 file changed

+47
-43
lines changed

1 file changed

+47
-43
lines changed

src/axi_mcast_demux_mapped.sv

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)