@@ -228,11 +228,7 @@ 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
232- // - mask = {'0, {log2(end_addr - start_addr){1'b1}}}
233- // - addr = start_addr / (end_addr - start_addr)
234- // More info in `multiaddr_decode` module
235- // TODO colluca: add checks on conversion feasibility
231+ // Convert multicast rules to mask (NAPOT) form, see https://arxiv.org/pdf/2502.19215
236232 for (genvar i = 0 ; i < NoMulticastRules; i++ ) begin : g_multicast_rules
237233 assign multicast_rules[i].idx = addr_map_i[i].idx;
238234 assign multicast_rules[i].mask = addr_map_i[i].end_addr - addr_map_i[i].start_addr - 1 ;
@@ -378,6 +374,36 @@ module axi_mcast_demux_mapped #(
378374 .slv_resp_o ( errslv_resp )
379375 );
380376
377+ // -----------------
378+ // Assertions
379+ // -----------------
380+
381+ // Check that multicast address map rules expressed in interval form can be converted to
382+ // mask form, see https://arxiv.org/pdf/2502.19215
383+ for (genvar i = 0 ; i < NoMulticastRules; i++ ) begin : gen_multicast_rule_assertion
384+ addr_t size;
385+ assign size = addr_map_i[i].end_addr - addr_map_i[i].start_addr;
386+ `ASSERT (MulticastRuleSize,
387+ ((size & (size - 1 )) == 0 ), clk_i, ! rst_ni,
388+ $sformatf (" Size %d of rule %d is not a power of 2" , size, i))
389+ `ASSERT (MulticastRuleAlignment,
390+ (addr_map_i[i].start_addr % size) == 0 , clk_i, ! rst_ni,
391+ $sformatf (" Rule %d , starting at 0x%x , is not aligned to its size (%d )" ,
392+ addr_map_i[i].start_addr, i, size))
393+ end
394+ // Default rule is only converted to mask form if there are any other multicast rules
395+ if (NoMulticastRules > 0 ) begin : gen_multicast_default_rule_assertion
396+ addr_t size;
397+ assign size = default_mst_port_i.end_addr - default_mst_port_i.start_addr;
398+ `ASSERT (DefaultRuleSize,
399+ ! en_default_mst_port_i || ((size & (size - 1 )) == 0 ), clk_i, ! rst_ni,
400+ $sformatf (" Size %d of default rule is not a power of 2" , size))
401+ `ASSERT (DefaultRuleAlignment,
402+ ! en_default_mst_port_i || ((default_mst_port_i.start_addr % size) == 0 ), clk_i, ! rst_ni,
403+ $sformatf (" Default rule, starting at 0x%x , is not aligned to its size (%d )" ,
404+ default_mst_port_i.start_addr, size))
405+ end
406+
381407endmodule
382408
383409// interface wrapper
0 commit comments