From be8892800467e2e62e3ce13b7bd80cf5670b35e5 Mon Sep 17 00:00:00 2001
From: Luca Colagrande <luca.colagrande3@gmail.com>
Date: Thu, 7 Dec 2023 12:18:20 +0100
Subject: [PATCH] axi_mcast_xbar: Add default port mechanism for multicast
 transactions

---
 src/axi_mcast_demux.sv | 20 +++++++++++++++-----
 src/axi_mcast_xbar.sv  | 21 +++++++--------------
 2 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/src/axi_mcast_demux.sv b/src/axi_mcast_demux.sv
index a38780a1a..2c60cdaf5 100644
--- a/src/axi_mcast_demux.sv
+++ b/src/axi_mcast_demux.sv
@@ -75,7 +75,7 @@ module axi_mcast_demux #(
   input  logic                       test_i,
   input  rule_t    [NoAddrRules-1:0] addr_map_i,
   input  logic                       en_default_mst_port_i,
-  input  decode_idx_t                default_mst_port_i,
+  input  rule_t                      default_mst_port_i,
   // Slave Port
   input  axi_req_t                   slv_req_i,
   input  idx_select_t                slv_ar_select_i,
@@ -186,6 +186,7 @@ module axi_mcast_demux #(
 
     // AW address decoder
     mask_rule_t [NoMulticastRules-1:0] multicast_rules;
+    mask_rule_t                        default_rule;
     decode_idx_t                       dec_aw_idx;
     logic                              dec_aw_idx_valid, dec_aw_idx_error;
     logic       [NoMulticastPorts-1:0] dec_aw_select_partial;
@@ -311,9 +312,9 @@ module axi_mcast_demux #(
         .default_idx_i   ('0)
       );
     end else begin : g_no_aw_idx_decode
-      assign dec_aw_idx_valid = en_default_mst_port_i & dec_aw_select_error;
-      assign dec_aw_idx_error = !en_default_mst_port_i;
-      assign dec_aw_idx = default_mst_port_i;
+      assign dec_aw_idx_valid = 1'b0;
+      assign dec_aw_idx_error = 1'b1;
+      assign dec_aw_idx = '0;
     end
 
     // Convert multicast rules to mask (NAPOT) form
@@ -326,6 +327,9 @@ module axi_mcast_demux #(
       assign multicast_rules[i].mask = addr_map_i[i].end_addr - addr_map_i[i].start_addr - 1;
       assign multicast_rules[i].addr = addr_map_i[i].start_addr;
     end
+    assign default_rule.idx = default_mst_port_i.idx;
+    assign default_rule.mask = default_mst_port_i.end_addr - default_mst_port_i.start_addr - 1;
+    assign default_rule.addr = default_mst_port_i.start_addr;
 
     // Compare request against {addr, mask} rules
     multiaddr_decode #(
@@ -341,7 +345,9 @@ module axi_mcast_demux #(
       .addr_o     (dec_aw_addr),
       .mask_o     (dec_aw_mask),
       .dec_valid_o(),
-      .dec_error_o(dec_aw_select_error)
+      .dec_error_o(dec_aw_select_error),
+      .en_default_idx_i(en_default_mst_port_i),
+      .default_idx_i   (default_rule)
     );
 
     // Combine output from the two address decoders
@@ -1115,6 +1121,8 @@ module axi_mcast_demux_intf #(
   input  logic    test_i,                // Testmode enable
   input  rule_t [NO_MST_PORTS-2:0] addr_map_i,
   input  idx_select_t  slv_ar_select_i,  // has to be stable, when ar_valid
+  input  logic    en_default_mst_port_i,
+  input  rule_t   default_mst_port_i,
   AXI_BUS.Slave   slv,                   // slave port
   AXI_BUS.Master  mst [NO_MST_PORTS-1:0] // master ports
 );
@@ -1170,6 +1178,8 @@ module axi_mcast_demux_intf #(
     .rst_ni,  // Asynchronous reset active low
     .test_i,  // Testmode enable
     .addr_map_i      ( addr_map_i      ),
+    .en_default_mst_port_i ( en_default_mst_port_i ),
+    .default_mst_port_i ( default_mst_port_i ),
     // slave port
     .slv_req_i       ( slv_req         ),
     .slv_ar_select_i ( slv_ar_select_i ),
diff --git a/src/axi_mcast_xbar.sv b/src/axi_mcast_xbar.sv
index 4195255be..1797adff8 100644
--- a/src/axi_mcast_xbar.sv
+++ b/src/axi_mcast_xbar.sv
@@ -82,17 +82,10 @@ import cf_math_pkg::idx_width;
   input  rule_t [Cfg.NoAddrRules-1:0]                                   addr_map_i,
   /// Enable default master port.
   input  logic      [Cfg.NoSlvPorts-1:0]                                en_default_mst_port_i,
-`ifdef VCS
-  /// Enables a default master port for each slave port. When this is enabled unmapped
-  /// transactions get issued at the master port given by `default_mst_port_i`.
-  /// When not used, tie to `'0`.
-  input  logic      [Cfg.NoSlvPorts-1:0][MstPortsIdxWidth-1:0]          default_mst_port_i
-`else
   /// Enables a default master port for each slave port. When this is enabled unmapped
   /// transactions get issued at the master port given by `default_mst_port_i`.
   /// When not used, tie to `'0`.
-  input  logic      [Cfg.NoSlvPorts-1:0][idx_width(Cfg.NoMstPorts)-1:0] default_mst_port_i
-`endif
+  input  rule_t     [Cfg.NoSlvPorts-1:0]                                default_mst_port_i
 );
 
   // Address type for individual address signals
@@ -101,9 +94,13 @@ import cf_math_pkg::idx_width;
 `ifdef VCS
   localparam int unsigned MstPortsIdxWidthOne =
       (Cfg.NoMstPorts == 32'd1) ? 32'd1 : unsigned'($clog2(Cfg.NoMstPorts + 1));
+  localparam int unsigned MstPortsIdxWidth =
+      (Cfg.NoMstPorts == 32'd1) ? 32'd1 : unsigned'($clog2(Cfg.NoMstPorts));
   typedef logic [MstPortsIdxWidthOne-1:0]           mst_port_idx_t;
+  typedef logic [MstPortsIdxWidth-1:0]              mst_port_idx_m1_t;
 `else
   typedef logic [idx_width(Cfg.NoMstPorts + 1)-1:0] mst_port_idx_t;
+  typedef logic [idx_width(Cfg.NoMstPorts)-1:0]     mst_port_idx_m1_t;
 `endif
 
   // signals from the axi_demuxes, one index more for decode error
@@ -122,11 +119,7 @@ import cf_math_pkg::idx_width;
   slv_resp_t [Cfg.NoMstPorts-1:0][Cfg.NoSlvPorts-1:0] mst_resps;
 
   for (genvar i = 0; i < Cfg.NoSlvPorts; i++) begin : gen_slv_port_demux
-`ifdef VCS
-    logic [MstPortsIdxWidth-1:0]          dec_ar_select;
-`else
-    logic [idx_width(Cfg.NoMstPorts)-1:0] dec_ar_select;
-`endif
+    mst_port_idx_m1_t           dec_ar_select;
     logic                       dec_ar_valid,  dec_ar_error;
     mst_port_idx_t              slv_ar_select;
 
@@ -142,7 +135,7 @@ import cf_math_pkg::idx_width;
       .dec_valid_o      ( dec_ar_valid               ),
       .dec_error_o      ( dec_ar_error               ),
       .en_default_idx_i ( en_default_mst_port_i[i]   ),
-      .default_idx_i    ( default_mst_port_i[i]      )
+      .default_idx_i    ( mst_port_idx_m1_t'(default_mst_port_i[i].idx)  )
     );
     assign slv_ar_select = (dec_ar_error) ?
         mst_port_idx_t'(Cfg.NoMstPorts) : mst_port_idx_t'(dec_ar_select);