begin axi_rab to nmigen conversion
authorTobias Platen <tplaten@posteo.de>
Thu, 23 Jan 2020 09:44:44 +0000 (10:44 +0100)
committerTobias Platen <tplaten@posteo.de>
Thu, 23 Jan 2020 09:44:44 +0000 (10:44 +0100)
src/iommu/axi_rab/axi4_ar_buffer.py [new file with mode: 0644]
src/iommu/axi_rab/rab_core.py [new file with mode: 0644]

diff --git a/src/iommu/axi_rab/axi4_ar_buffer.py b/src/iommu/axi_rab/axi4_ar_buffer.py
new file mode 100644 (file)
index 0000000..1f3a5ff
--- /dev/null
@@ -0,0 +1,135 @@
+# Copyright 2018 ETH Zurich and University of Bologna.
+# Copyright and related rights are licensed under the Solderpad Hardware
+# License, Version 0.51 (the "License"); you may not use this file except in
+# compliance with the License.  You may obtain a copy of the License at
+# http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+# or agreed to in writing, software, hardware and materials distributed under
+# this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations under the License.
+
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+# module axi4_ar_buffer
+#  #(
+#    parameter AXI_ID_WIDTH   = 4,
+#    parameter AXI_USER_WIDTH = 4
+#  )
+#  (
+#    input  logic                      axi4_aclk,
+#    input  logic                      axi4_arstn,
+#
+#    input  logic   [AXI_ID_WIDTH-1:0] s_axi4_arid,
+#    input  logic               [31:0] s_axi4_araddr,
+#    input  logic                      s_axi4_arvalid,
+#    output logic                      s_axi4_arready,
+#    input  logic                [7:0] s_axi4_arlen,
+#    input  logic                [2:0] s_axi4_arsize,
+#    input  logic                [1:0] s_axi4_arburst,
+#    input  logic                      s_axi4_arlock,
+#    input  logic                [2:0] s_axi4_arprot,
+#    input  logic                [3:0] s_axi4_arcache,
+#    input  logic [AXI_USER_WIDTH-1:0] s_axi4_aruser,
+#
+#    output logic   [AXI_ID_WIDTH-1:0] m_axi4_arid,
+#    output logic               [31:0] m_axi4_araddr,
+#    output logic                      m_axi4_arvalid,
+#    input  logic                      m_axi4_arready,
+#    output logic                [7:0] m_axi4_arlen,
+#    output logic                [2:0] m_axi4_arsize,
+#    output logic                [1:0] m_axi4_arburst,
+#    output logic                      m_axi4_arlock,
+#    output logic                [2:0] m_axi4_arprot,
+#    output logic                [3:0] m_axi4_arcache,
+#    output logic [AXI_USER_WIDTH-1:0] m_axi4_aruser
+#  );
+
+
+class axi4_ar_buffer(Elaboratable):
+
+    def __init__(self):
+        # self.axi4_aclk = Signal() # input
+        # self.axi4_arstn = Signal() # input
+        self.s_axi4_arid = Signal(AXI_ID_WIDTH)  # input
+        self.s_axi4_araddr = Signal(32)  # input
+        self.s_axi4_arvalid = Signal()  # input
+        self.s_axi4_arready = Signal()  # output
+        self.s_axi4_arlen = Signal(8)  # input
+        self.s_axi4_arsize = Signal(3)  # input
+        self.s_axi4_arburst = Signal(2)  # input
+        self.s_axi4_arlock = Signal()  # input
+        self.s_axi4_arprot = Signal(3)  # input
+        self.s_axi4_arcache = Signal(4)  # input
+        self.s_axi4_aruser = Signal(AXI_USER_WIDTH)  # input
+        self.m_axi4_arid = Signal(AXI_ID_WIDTH)  # output
+        self.m_axi4_araddr = Signal(32)  # output
+        self.m_axi4_arvalid = Signal()  # output
+        self.m_axi4_arready = Signal()  # input
+        self.m_axi4_arlen = Signal(8)  # output
+        self.m_axi4_arsize = Signal(3)  # output
+        self.m_axi4_arburst = Signal(2)  # output
+        self.m_axi4_arlock = Signal()  # output
+        self.m_axi4_arprot = Signal(3)  # output
+        self.m_axi4_arcache = Signal(4)  # output
+        self.m_axi4_aruser = Signal(AXI_USER_WIDTH)  # output
+
+    def elaborate(self, platform=None):
+        m = Module()
+        #  #TODO use record types here
+        #  wire [AXI_ID_WIDTH+AXI_USER_WIDTH+52:0] data_in;
+        #  wire [AXI_ID_WIDTH+AXI_USER_WIDTH+52:0] data_out;
+
+        # assign data_in                                           [3:0] = s_axi4_arcache;
+        # assign data_in                                           [6:4] = s_axi4_arprot;
+        # assign data_in                                             [7] = s_axi4_arlock;
+        # assign data_in                                           [9:8] = s_axi4_arburst;
+        # assign data_in                                         [12:10] = s_axi4_arsize;
+        # assign data_in                                         [20:13] = s_axi4_arlen;
+        # assign data_in                                         [52:21] = s_axi4_araddr;
+        # assign data_in                            [52+AXI_ID_WIDTH:53] = s_axi4_arid;
+        # assign data_in[52+AXI_ID_WIDTH+AXI_USER_WIDTH:53+AXI_ID_WIDTH] = s_axi4_aruser;
+        #
+        # assign m_axi4_arcache = data_out[3:0];
+        # assign m_axi4_arprot  = data_out[6:4];
+        # assign m_axi4_arlock  = data_out[7];
+        # assign m_axi4_arburst = data_out[9:8];
+        # assign m_axi4_arsize  = data_out[12:10];
+        # assign m_axi4_arlen   = data_out[20:13];
+        # assign m_axi4_araddr  = data_out[52:21];
+        # assign m_axi4_arid    = data_out[52+AXI_ID_WIDTH:53];
+        # assign m_axi4_aruser  = data_out[52+AXI_ID_WIDTH+AXI_USER_WIDTH:53+AXI_ID_WIDTH];
+
+        # m.d.comb += self.m_axi4_arcache.eq(..)
+        # m.d.comb += self.m_axi4_arprot.eq(..)
+        # m.d.comb += self.m_axi4_arlock.eq(..)
+        # m.d.comb += self.m_axi4_arburst.eq(..)
+        # m.d.comb += self.m_axi4_arsize.eq(..)
+        # m.d.comb += self.m_axi4_arlen.eq(..)
+        # m.d.comb += self.m_axi4_araddr.eq(..)
+        # m.d.comb += self.m_axi4_arid.eq(..)
+        # m.d.comb += self.m_axi4_aruser.eq(..)
+        return m
+
+# TODO convert axi_buffer_rab.sv
+#
+#  axi_buffer_rab
+#    #(
+#      .DATA_WIDTH   ( AXI_ID_WIDTH+AXI_USER_WIDTH+53  ),
+#      .BUFFER_DEPTH ( 4                               )
+#      )
+#    u_buffer
+#    (
+#      .clk       ( axi4_aclk      ),
+#      .rstn      ( axi4_arstn     ),
+#      .valid_out ( m_axi4_arvalid ),
+#      .data_out  ( data_out       ),
+#      .ready_in  ( m_axi4_arready ),
+#      .valid_in  ( s_axi4_arvalid ),
+#      .data_in   ( data_in        ),
+#      .ready_out ( s_axi4_arready )
+#    );
+#
+
+# endmodule
diff --git a/src/iommu/axi_rab/rab_core.py b/src/iommu/axi_rab/rab_core.py
new file mode 100644 (file)
index 0000000..7d7494a
--- /dev/null
@@ -0,0 +1,539 @@
+# // Copyright 2018 ETH Zurich and University of Bologna.
+# // Copyright and related rights are licensed under the Solderpad Hardware
+# // License, Version 0.51 (the "License"); you may not use this file except in
+# // compliance with the License.  You may obtain a copy of the License at
+# // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+# // or agreed to in writing, software, hardware and materials distributed under
+# // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+# // CONDITIONS OF ANY KIND, either express or implied. See the License for the
+# // specific language governing permissions and limitations under the License.
+
+# this file has been generated by sv2nmigen
+
+#
+# //`include "pulp_soc_defines.sv"
+#
+# ////import CfMath::log2;
+#
+# //`define MY_ARRAY_SUM(MY_ARRAY,ARRAY_SIZE) ( (ARRAY_SIZE==1) ? MY_ARRAY[0] : (ARRAY_SIZE==2) ? MY_ARRAY[0] + MY_ARRAY[1] : (ARRAY_SIZE==3) ? MY_ARRAY[0] + MY_ARRAY[1] + MY_ARRAY[2] : (ARRAY_SIZE==4) ? MY_ARRAY[0] + MY_ARRAY[1] + MY_ARRAY[2] + MY_ARRAY[3] : 0 )
+#
+
+# module rab_core
+#  #(
+#    parameter N_PORTS             =  3,
+#    parameter N_L2_SETS           = 32,
+#    parameter N_L2_SET_ENTRIES    = 32,
+#    parameter AXI_DATA_WIDTH      = 64,
+#    parameter AXI_S_ADDR_WIDTH    = 32,
+#    parameter AXI_M_ADDR_WIDTH    = 40,
+#    parameter AXI_LITE_DATA_WIDTH = 64,
+#    parameter AXI_LITE_ADDR_WIDTH = 32,
+#    parameter AXI_ID_WIDTH        =  8,
+#    parameter AXI_USER_WIDTH      =  6,
+#    parameter MH_FIFO_DEPTH       = 16
+#    )
+#   (
+#    input  logic                                         Clk_CI,
+#    input  logic                                         Rst_RBI,
+#
+#    input  logic               [AXI_LITE_ADDR_WIDTH-1:0] s_axi_awaddr,
+#    input  logic                                         s_axi_awvalid,
+#    output logic                                         s_axi_awready,
+#
+#    input  logic               [AXI_LITE_DATA_WIDTH-1:0] s_axi_wdata,
+#    input  logic             [AXI_LITE_DATA_WIDTH/8-1:0] s_axi_wstrb,
+#    input  logic                                         s_axi_wvalid,
+#    output logic                                         s_axi_wready,
+#
+#    input  logic               [AXI_LITE_ADDR_WIDTH-1:0] s_axi_araddr,
+#    input  logic                                         s_axi_arvalid,
+#    output logic                                         s_axi_arready,
+#
+#    input  logic                                         s_axi_rready,
+#    output logic               [AXI_LITE_DATA_WIDTH-1:0] s_axi_rdata,
+#    output logic                                   [1:0] s_axi_rresp,
+#    output logic                                         s_axi_rvalid,
+#
+#    output logic                                   [1:0] s_axi_bresp,
+#    output logic                                         s_axi_bvalid,
+#    input  logic                                         s_axi_bready,
+#
+#    output logic [N_PORTS-1:0]                           int_miss,
+#    output logic [N_PORTS-1:0]                           int_prot,
+#    output logic [N_PORTS-1:0]                           int_multi,
+#    output logic [N_PORTS-1:0]                           int_prefetch,
+#    output logic                                         int_mhf_full,
+#
+#    output logic [N_PORTS-1:0]    [AXI_S_ADDR_WIDTH-1:0] int_axaddr_o,
+#    output logic [N_PORTS-1:0]        [AXI_ID_WIDTH-1:0] int_axid_o,
+#    output logic [N_PORTS-1:0]                     [7:0] int_axlen_o,
+#    output logic [N_PORTS-1:0]      [AXI_USER_WIDTH-1:0] int_axuser_o,
+#
+#    input  logic [N_PORTS-1:0]    [AXI_S_ADDR_WIDTH-1:0] port1_addr,
+#    input  logic [N_PORTS-1:0]        [AXI_ID_WIDTH-1:0] port1_id,
+#    input  logic [N_PORTS-1:0]                     [7:0] port1_len,
+#    input  logic [N_PORTS-1:0]                     [2:0] port1_size,
+#    input  logic [N_PORTS-1:0]                           port1_addr_valid,
+#    input  logic [N_PORTS-1:0]                           port1_type,
+#    input  logic [N_PORTS-1:0]      [AXI_USER_WIDTH-1:0] port1_user,
+#    input  logic [N_PORTS-1:0]                           port1_sent,
+#    output logic [N_PORTS-1:0]    [AXI_M_ADDR_WIDTH-1:0] port1_out_addr,
+#    output logic [N_PORTS-1:0]                           port1_cache_coherent,
+#    output logic [N_PORTS-1:0]                           port1_accept,
+#    output logic [N_PORTS-1:0]                           port1_drop,
+#    output logic [N_PORTS-1:0]                           port1_miss,
+#
+#    input  logic [N_PORTS-1:0]    [AXI_S_ADDR_WIDTH-1:0] port2_addr,
+#    input  logic [N_PORTS-1:0]        [AXI_ID_WIDTH-1:0] port2_id,
+#    input  logic [N_PORTS-1:0]                     [7:0] port2_len,
+#    input  logic [N_PORTS-1:0]                     [2:0] port2_size,
+#    input  logic [N_PORTS-1:0]                           port2_addr_valid,
+#    input  logic [N_PORTS-1:0]                           port2_type,
+#    input  logic [N_PORTS-1:0]      [AXI_USER_WIDTH-1:0] port2_user,
+#    input  logic [N_PORTS-1:0]                           port2_sent,
+#    output logic [N_PORTS-1:0]    [AXI_M_ADDR_WIDTH-1:0] port2_out_addr,
+#    output logic [N_PORTS-1:0]                           port2_cache_coherent,
+#    output logic [N_PORTS-1:0]                           port2_accept,
+#    output logic [N_PORTS-1:0]                           port2_drop,
+#    output logic [N_PORTS-1:0]                           port2_miss,
+#
+#    input  logic [N_PORTS-1:0]                           miss_l2_i,
+#    input  logic [N_PORTS-1:0]    [AXI_S_ADDR_WIDTH-1:0] miss_l2_addr_i,
+#    input  logic [N_PORTS-1:0]        [AXI_ID_WIDTH-1:0] miss_l2_id_i,
+#    input  logic [N_PORTS-1:0]      [AXI_USER_WIDTH-1:0] miss_l2_user_i,
+#
+#    output logic [N_PORTS-1:0] [AXI_LITE_DATA_WIDTH-1:0] wdata_l2_o,
+#    output logic [N_PORTS-1:0] [AXI_LITE_ADDR_WIDTH-1:0] waddr_l2_o,
+#    output logic [N_PORTS-1:0]                           wren_l2_o
+#    );
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class rab_core(Elaboratable):
+
+    def __init__(self):
+        self.s_axi_awaddr = Signal(AXI_LITE_ADDR_WIDTH)  # input
+        self.s_axi_awvalid = Signal()  # input
+        self.s_axi_awready = Signal()  # output
+        self.s_axi_wdata = Signal(AXI_LITE_DATA_WIDTH)  # input
+        self.s_axi_wstrb = Signal(FIXME)  # input
+        self.s_axi_wvalid = Signal()  # input
+        self.s_axi_wready = Signal()  # output
+        self.s_axi_araddr = Signal(AXI_LITE_ADDR_WIDTH)  # input
+        self.s_axi_arvalid = Signal()  # input
+        self.s_axi_arready = Signal()  # output
+        self.s_axi_rready = Signal()  # input
+        self.s_axi_rdata = Signal(AXI_LITE_DATA_WIDTH)  # output
+        self.s_axi_rresp = Signal(2)  # output
+        self.s_axi_rvalid = Signal()  # output
+        self.s_axi_bresp = Signal(2)  # output
+        self.s_axi_bvalid = Signal()  # output
+        self.s_axi_bready = Signal()  # input
+        self.int_miss = Signal(N_PORTS)  # output
+        self.int_prot = Signal(N_PORTS)  # output
+        self.int_multi = Signal(N_PORTS)  # output
+        self.int_prefetch = Signal(N_PORTS)  # output
+        self.int_mhf_full = Signal()  # output
+        self.int_axaddr_o = Signal()  # output
+        self.int_axid_o = Signal()  # output
+        self.int_axlen_o = Signal()  # output
+        self.int_axuser_o = Signal()  # output
+        self.port1_addr = Signal()  # input
+        self.port1_id = Signal()  # input
+        self.port1_len = Signal()  # input
+        self.port1_size = Signal()  # input
+        self.port1_addr_valid = Signal(N_PORTS)  # input
+        self.port1_type = Signal(N_PORTS)  # input
+        self.port1_user = Signal()  # input
+        self.port1_sent = Signal(N_PORTS)  # input
+        self.port1_out_addr = Signal()  # output
+        self.port1_cache_coherent = Signal(N_PORTS)  # output
+        self.port1_accept = Signal(N_PORTS)  # output
+        self.port1_drop = Signal(N_PORTS)  # output
+        self.port1_miss = Signal(N_PORTS)  # output
+        self.port2_addr = Signal()  # input
+        self.port2_id = Signal()  # input
+        self.port2_len = Signal()  # input
+        self.port2_size = Signal()  # input
+        self.port2_addr_valid = Signal(N_PORTS)  # input
+        self.port2_type = Signal(N_PORTS)  # input
+        self.port2_user = Signal()  # input
+        self.port2_sent = Signal(N_PORTS)  # input
+        self.port2_out_addr = Signal()  # output
+        self.port2_cache_coherent = Signal(N_PORTS)  # output
+        self.port2_accept = Signal(N_PORTS)  # output
+        self.port2_drop = Signal(N_PORTS)  # output
+        self.port2_miss = Signal(N_PORTS)  # output
+        self.miss_l2_i = Signal(N_PORTS)  # input
+        self.miss_l2_addr_i = Signal()  # input
+        self.miss_l2_id_i = Signal()  # input
+        self.miss_l2_user_i = Signal()  # input
+        self.wdata_l2_o = Signal()  # output
+        self.waddr_l2_o = Signal()  # output
+        self.wren_l2_o = Signal(N_PORTS)  # output
+
+    def elaborate(self, platform=None):
+        m = Module()
+        return m
+
+
+""" 
+
+
+    // ███████╗██╗ ██████╗ ███╗   ██╗ █████╗ ██╗     ███████╗
+    // ██╔════╝██║██╔════╝ ████╗  ██║██╔══██╗██║     ██╔════╝
+    // ███████╗██║██║  ███╗██╔██╗ ██║███████║██║     ███████╗
+    // ╚════██║██║██║   ██║██║╚██╗██║██╔══██║██║     ╚════██║
+    // ███████║██║╚██████╔╝██║ ╚████║██║  ██║███████╗███████║
+    // ╚══════╝╚═╝ ╚═════╝ ╚═╝  ╚═══╝╚═╝  ╚═╝╚══════╝╚══════╝
+    // signals
+
+  localparam integer ENABLE_L2TLB[N_PORTS-1:0] = `EN_L2TLB_ARRAY;
+
+  localparam integer N_SLICES[N_PORTS-1:0]     = `N_SLICES_ARRAY;
+  localparam         N_SLICES_TOT              = `MY_ARRAY_SUM(N_SLICES,N_PORTS);
+  localparam         N_SLICES_MAX              = `N_SLICES_MAX;
+
+  localparam N_REGS                            = 4*N_SLICES_TOT + 4;
+  localparam AXI_SIZE_WIDTH                    = log2(AXI_DATA_WIDTH/8);
+
+  localparam PORT_ID_WIDTH                     = (N_PORTS < 2) ? 1 : log2(N_PORTS);
+  localparam MISS_META_WIDTH                   = PORT_ID_WIDTH + AXI_USER_WIDTH + AXI_ID_WIDTH;
+
+  logic [N_PORTS-1:0]                      [15:0] p1_burst_size;
+  logic [N_PORTS-1:0]                      [15:0] p2_burst_size;
+
+  logic [N_PORTS-1:0]      [AXI_S_ADDR_WIDTH-1:0] p1_align_addr;
+  logic [N_PORTS-1:0]      [AXI_S_ADDR_WIDTH-1:0] p2_align_addr;
+
+  logic [N_PORTS-1:0]        [AXI_SIZE_WIDTH-1:0] p1_mask;
+  logic [N_PORTS-1:0]        [AXI_SIZE_WIDTH-1:0] p2_mask;
+
+  logic [N_PORTS-1:0]      [AXI_S_ADDR_WIDTH-1:0] p1_max_addr;
+  logic [N_PORTS-1:0]      [AXI_S_ADDR_WIDTH-1:0] p2_max_addr;
+
+  logic [N_PORTS-1:0]                             p1_prefetch;
+  logic [N_PORTS-1:0]                             p2_prefetch;
+
+  logic [N_PORTS-1:0]                             int_rw;
+  logic [N_PORTS-1:0]      [AXI_S_ADDR_WIDTH-1:0] int_addr_min;
+  logic [N_PORTS-1:0]      [AXI_S_ADDR_WIDTH-1:0] int_addr_max;
+  logic [N_PORTS-1:0]          [AXI_ID_WIDTH-1:0] int_id;
+  logic [N_PORTS-1:0]                       [7:0] int_len;
+  logic [N_PORTS-1:0]        [AXI_USER_WIDTH-1:0] int_user;
+
+  logic [N_PORTS-1:0]                             hit;
+  logic [N_PORTS-1:0]                             prot;
+  logic [N_PORTS-1:0]                             prefetch;
+
+  logic [N_PORTS-1:0]                             no_hit;
+  logic [N_PORTS-1:0]                             no_prot;
+
+  logic [N_PORTS-1:0]          [N_SLICES_MAX-1:0] hit_slices;
+  logic [N_PORTS-1:0]          [N_SLICES_MAX-1:0] prot_slices;
+
+  logic [N_PORTS-1:0]      [AXI_M_ADDR_WIDTH-1:0] out_addr;
+  logic [N_PORTS-1:0]      [AXI_M_ADDR_WIDTH-1:0] out_addr_reg;
+
+  logic [N_PORTS-1:0]                             cache_coherent;
+  logic [N_PORTS-1:0]                             cache_coherent_reg;
+
+  logic [N_PORTS-1:0]                             select;
+  reg   [N_PORTS-1:0]                             curr_priority;
+
+  reg   [N_PORTS-1:0]                             multi_hit;
+
+  logic [N_PORTS-1:0]                             miss_valid_mhf;
+  logic [N_PORTS-1:0]      [AXI_S_ADDR_WIDTH-1:0] miss_addr_mhf;
+  logic [N_PORTS-1:0]       [MISS_META_WIDTH-1:0] miss_meta_mhf;
+
+  logic [N_REGS-1:0]                       [63:0] int_cfg_regs;
+  logic [N_PORTS-1:0] [4*N_SLICES_MAX-1:0] [63:0] int_cfg_regs_slices;
+
+  logic                                           L1AllowMultiHit_S;
+
+  genvar z;
+
+  //  █████╗ ███████╗███████╗██╗ ██████╗ ███╗   ██╗███╗   ███╗███████╗███╗   ██╗████████╗███████╗
+  // ██╔══██╗██╔════╝██╔════╝██║██╔════╝ ████╗  ██║████╗ ████║██╔════╝████╗  ██║╚══██╔══╝██╔════╝
+  // ███████║███████╗███████╗██║██║  ███╗██╔██╗ ██║██╔████╔██║█████╗  ██╔██╗ ██║   ██║   ███████╗
+  // ██╔══██║╚════██║╚════██║██║██║   ██║██║╚██╗██║██║╚██╔╝██║██╔══╝  ██║╚██╗██║   ██║   ╚════██║
+  // ██║  ██║███████║███████║██║╚██████╔╝██║ ╚████║██║ ╚═╝ ██║███████╗██║ ╚████║   ██║   ███████║
+  // ╚═╝  ╚═╝╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝  ╚═══╝╚═╝     ╚═╝╚══════╝╚═╝  ╚═══╝   ╚═╝   ╚══════╝
+  // assignments
+
+  always_comb
+    begin : PORT_SELECT
+      var integer idx;
+
+      for (idx=0; idx<N_PORTS; idx++) begin
+
+        // select = 1 -> port1 active
+        // select = 0 -> port2 active
+        select[idx] = (curr_priority[idx] & port1_addr_valid[idx]) | ~port2_addr_valid[idx];
+
+        p1_burst_size[idx] = (port1_len[idx] + 1) << port1_size[idx];
+        p2_burst_size[idx] = (port2_len[idx] + 1) << port2_size[idx];
+
+        // align min addr for max addr computation to allow for smart AXI bursts around the 4k boundary
+        if      (port1_size[idx] == 3'b001)
+          p1_mask[idx] = 3'b110;
+        else if (port1_size[idx] == 3'b010)
+          p1_mask[idx] = 3'b100;
+        else if (port1_size[idx] == 3'b011)
+          p1_mask[idx] = 3'b000;
+        else
+          p1_mask[idx] = 3'b111;
+
+        p1_align_addr[idx][AXI_S_ADDR_WIDTH-1:AXI_SIZE_WIDTH] = port1_addr[idx][AXI_S_ADDR_WIDTH-1:AXI_SIZE_WIDTH];
+        p1_align_addr[idx][AXI_SIZE_WIDTH-1:0]                = port1_addr[idx][AXI_SIZE_WIDTH-1:0] & p1_mask[idx];
+
+        if      (port2_size[idx] == 3'b001)
+          p2_mask[idx] = 3'b110;
+        else if (port2_size[idx] == 3'b010)
+          p2_mask[idx] = 3'b100;
+        else if (port2_size[idx] == 3'b011)
+          p2_mask[idx] = 3'b000;
+        else
+          p2_mask[idx] = 3'b111;
+
+        if (port1_user[idx] == {AXI_USER_WIDTH{1'b1}})
+          p1_prefetch[idx] = 1'b1;
+        else
+          p1_prefetch[idx] = 1'b0;
+
+        if (port2_user[idx] == {AXI_USER_WIDTH{1'b1}})
+          p2_prefetch[idx] = 1'b1;
+        else
+          p2_prefetch[idx] = 1'b0;
+
+        p2_align_addr[idx][AXI_S_ADDR_WIDTH-1:AXI_SIZE_WIDTH] = port2_addr[idx][AXI_S_ADDR_WIDTH-1:AXI_SIZE_WIDTH];
+        p2_align_addr[idx][AXI_SIZE_WIDTH-1:0]                = port2_addr[idx][AXI_SIZE_WIDTH-1:0] & p2_mask[idx];
+
+        p1_max_addr[idx]  = p1_align_addr[idx] + p1_burst_size[idx] - 1;
+        p2_max_addr[idx]  = p2_align_addr[idx] + p2_burst_size[idx] - 1;
+
+        int_addr_min[idx] = select[idx] ? port1_addr[idx]  : port2_addr[idx];
+        int_addr_max[idx] = select[idx] ? p1_max_addr[idx] : p2_max_addr[idx];
+        int_rw[idx]       = select[idx] ? port1_type[idx]  : port2_type[idx];
+        int_id[idx]       = select[idx] ? port1_id[idx]    : port2_id[idx];
+        int_len[idx]      = select[idx] ? port1_len[idx]   : port2_len[idx];
+        int_user[idx]     = select[idx] ? port1_user[idx]  : port2_user[idx];
+        prefetch[idx]     = select[idx] ? p1_prefetch[idx] : p2_prefetch[idx];
+
+        hit [idx]    = | hit_slices [idx];
+        prot[idx]    = | prot_slices[idx];
+
+        no_hit [idx] = ~hit [idx];
+        no_prot[idx] = ~prot[idx];
+
+        port1_out_addr[idx] = out_addr_reg[idx];
+        port2_out_addr[idx] = out_addr_reg[idx];
+
+        port1_cache_coherent[idx] = cache_coherent_reg[idx];
+        port2_cache_coherent[idx] = cache_coherent_reg[idx];
+      end
+    end
+
+  always_comb
+    begin
+      var integer idx_port, idx_slice;
+      var integer reg_num;
+      reg_num=0;
+      for ( idx_port = 0; idx_port < N_PORTS; idx_port++ ) begin
+        for ( idx_slice = 0; idx_slice < 4*N_SLICES[idx_port]; idx_slice++ ) begin
+          int_cfg_regs_slices[idx_port][idx_slice] = int_cfg_regs[4+reg_num];
+          reg_num++;
+        end
+        // int_cfg_regs_slices[idx_port][N_SLICES_MAX:N_SLICES[idx_port]] will be dangling
+        // Fix to zero. Synthesis will remove these signals.
+        // int_cfg_regs_slices[idx_port][4*N_SLICES_MAX-1:4*N_SLICES[idx_port]] = 0;
+      end
+  end
+
+  always @(posedge Clk_CI or negedge Rst_RBI)
+    begin : PORT_PRIORITY
+      var integer idx;
+      if (Rst_RBI == 1'b0)
+        curr_priority = 'h0;
+      else begin
+        for (idx=0; idx<N_PORTS; idx++) begin
+          if (port1_accept[idx] || port1_drop[idx])
+            curr_priority[idx] = 1'b1;
+          else if (port2_accept[idx] || port2_drop[idx])
+            curr_priority[idx] = 1'b0;
+        end
+      end
+    end
+
+  // find port that misses
+  logic [PORT_ID_WIDTH-1:0] PortIdx_D; // index of the first missing port
+  var integer               idx_miss;
+  always_comb begin : MHF_PORT_SELECT
+    PortIdx_D = 'b0;
+    for (idx_miss = 0; idx_miss < N_PORTS; idx_miss++) begin
+      if (miss_valid_mhf[idx_miss] == 1'b1) begin
+        PortIdx_D = idx_miss;
+        break;
+      end
+    end
+  end // always_comb begin
+
+  //  █████╗ ██╗  ██╗██╗    ██████╗  █████╗ ██████╗      ██████╗███████╗ ██████╗
+  // ██╔══██╗╚██╗██╔╝██║    ██╔══██╗██╔══██╗██╔══██╗    ██╔════╝██╔════╝██╔════╝
+  // ███████║ ╚███╔╝ ██║    ██████╔╝███████║██████╔╝    ██║     █████╗  ██║  ███╗
+  // ██╔══██║ ██╔██╗ ██║    ██╔══██╗██╔══██║██╔══██╗    ██║     ██╔══╝  ██║   ██║
+  // ██║  ██║██╔╝ ██╗██║    ██║  ██║██║  ██║██████╔╝    ╚██████╗██║     ╚██████╔╝
+  // ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝    ╚═╝  ╚═╝╚═╝  ╚═╝╚═════╝      ╚═════╝╚═╝      ╚═════╝
+  axi_rab_cfg
+    #(
+      .N_PORTS         ( N_PORTS             ),
+      .N_REGS          ( N_REGS              ),
+      .N_L2_SETS       ( N_L2_SETS           ),
+      .N_L2_SET_ENTRIES( N_L2_SET_ENTRIES    ),
+      .ADDR_WIDTH_PHYS ( AXI_M_ADDR_WIDTH    ),
+      .ADDR_WIDTH_VIRT ( AXI_S_ADDR_WIDTH    ),
+      .N_FLAGS         ( 4                   ),
+      .AXI_DATA_WIDTH  ( AXI_LITE_DATA_WIDTH ),
+      .AXI_ADDR_WIDTH  ( AXI_LITE_ADDR_WIDTH ),
+      .MISS_META_WIDTH ( MISS_META_WIDTH     ),
+      .MH_FIFO_DEPTH   ( MH_FIFO_DEPTH       )
+    )
+    u_axi_rab_cfg
+    (
+      .Clk_CI             ( Clk_CI                    ),
+      .Rst_RBI            ( Rst_RBI                   ),
+      .s_axi_awaddr       ( s_axi_awaddr              ),
+      .s_axi_awvalid      ( s_axi_awvalid             ),
+      .s_axi_wdata        ( s_axi_wdata               ),
+      .s_axi_wstrb        ( s_axi_wstrb               ),
+      .s_axi_wvalid       ( s_axi_wvalid              ),
+      .s_axi_bready       ( s_axi_bready              ),
+      .s_axi_araddr       ( s_axi_araddr              ),
+      .s_axi_arvalid      ( s_axi_arvalid             ),
+      .s_axi_rready       ( s_axi_rready              ),
+      .s_axi_arready      ( s_axi_arready             ),
+      .s_axi_rdata        ( s_axi_rdata               ),
+      .s_axi_rresp        ( s_axi_rresp               ),
+      .s_axi_rvalid       ( s_axi_rvalid              ),
+      .s_axi_wready       ( s_axi_wready              ),
+      .s_axi_bresp        ( s_axi_bresp               ),
+      .s_axi_bvalid       ( s_axi_bvalid              ),
+      .s_axi_awready      ( s_axi_awready             ),
+      .L1Cfg_DO           ( int_cfg_regs              ),
+      .L1AllowMultiHit_SO ( L1AllowMultiHit_S         ),
+      .MissAddr_DI        ( miss_addr_mhf[PortIdx_D]  ),
+      .MissMeta_DI        ( miss_meta_mhf[PortIdx_D]  ),
+      .Miss_SI            ( miss_valid_mhf[PortIdx_D] ),
+      .MhFifoFull_SO      ( int_mhf_full              ),
+      .wdata_l2           ( wdata_l2_o                ),
+      .waddr_l2           ( waddr_l2_o                ),
+      .wren_l2            ( wren_l2_o                 )
+    );
+
+  generate for (z = 0; z < N_PORTS; z++) begin : MHF_TLB_SELECT
+    if (ENABLE_L2TLB[z] == 1) begin // L2 TLB is enabled
+      assign miss_valid_mhf[z] = miss_l2_i[z];
+      assign miss_addr_mhf[z]  = miss_l2_addr_i[z];
+      assign miss_meta_mhf[z]  = {miss_l2_user_i[z], PortIdx_D, miss_l2_id_i[z]};
+    end else begin// L2 TLB is disabled
+      assign miss_valid_mhf[z] = int_miss[z];
+      assign miss_addr_mhf[z]  = int_addr_min[z];
+      assign miss_meta_mhf[z]  = {int_user[z], PortIdx_D, int_id[z]};
+    end
+  end
+  endgenerate
+
+  // ███████╗██╗     ██╗ ██████╗███████╗    ████████╗ ██████╗ ██████╗
+  // ██╔════╝██║     ██║██╔════╝██╔════╝    ╚══██╔══╝██╔═══██╗██╔══██╗
+  // ███████╗██║     ██║██║     █████╗         ██║   ██║   ██║██████╔╝
+  // ╚════██║██║     ██║██║     ██╔══╝         ██║   ██║   ██║██╔═══╝
+  // ███████║███████╗██║╚██████╗███████╗       ██║   ╚██████╔╝██║
+  // ╚══════╝╚══════╝╚═╝ ╚═════╝╚══════╝       ╚═╝    ╚═════╝ ╚═╝
+  generate for (z = 0; z < N_PORTS; z++) begin : SLICE_TOP_GEN
+    slice_top
+      #(
+        .N_SLICES        ( N_SLICES[z]      ),
+        .N_REGS          ( 4*N_SLICES[z]    ),
+        .ADDR_WIDTH_PHYS ( AXI_M_ADDR_WIDTH ),
+        .ADDR_WIDTH_VIRT ( AXI_S_ADDR_WIDTH )
+      )
+      u_slice_top
+      (
+        .int_cfg_regs    ( int_cfg_regs_slices[z][4*N_SLICES[z]-1:0] ),
+        .int_rw          ( int_rw[z]                                 ),
+        .int_addr_min    ( int_addr_min[z]                           ),
+        .int_addr_max    ( int_addr_max[z]                           ),
+        .multi_hit_allow ( L1AllowMultiHit_S                         ),
+        .multi_hit       ( multi_hit[z]                              ),
+        .prot            ( prot_slices[z][N_SLICES[z]-1:0]           ),
+        .hit             ( hit_slices [z][N_SLICES[z]-1:0]           ),
+        .cache_coherent  ( cache_coherent[z]                         ),
+        .out_addr        ( out_addr[z]                               )
+      );
+    // hit_slices [N_SLICES_MAX-1:N_SLICES_MAX-N_SLICES[z]] will be dangling
+    // prot_slices[N_SLICES_MAX-1:N_SLICES_MAX-N_SLICES[z]] will be dangling
+    // Fix to zero. Synthesis will remove these signals.
+    if ( N_SLICES[z] < N_SLICES_MAX ) begin
+      assign hit_slices [z][N_SLICES_MAX-1:N_SLICES[z]] = 0;
+      assign prot_slices[z][N_SLICES_MAX-1:N_SLICES[z]] = 0;
+    end
+  end // for (z = 0; z < N_PORTS; z++)
+  endgenerate
+
+  // ███████╗███████╗███╗   ███╗
+  // ██╔════╝██╔════╝████╗ ████║
+  // █████╗  ███████╗██╔████╔██║
+  // ██╔══╝  ╚════██║██║╚██╔╝██║
+  // ██║     ███████║██║ ╚═╝ ██║
+  // ╚═╝     ╚══════╝╚═╝     ╚═╝
+  //
+  generate for (z = 0; z < N_PORTS; z++) begin : FSM_GEN
+    fsm
+      #(
+        .AXI_M_ADDR_WIDTH ( AXI_M_ADDR_WIDTH ),
+        .AXI_S_ADDR_WIDTH ( AXI_S_ADDR_WIDTH ),
+        .AXI_ID_WIDTH     ( AXI_ID_WIDTH     ),
+        .AXI_USER_WIDTH   ( AXI_USER_WIDTH   )
+      )
+      u_fsm
+      (
+        .Clk_CI             ( Clk_CI                ),
+        .Rst_RBI            ( Rst_RBI               ),
+        .port1_addr_valid_i ( port1_addr_valid[z]   ),
+        .port2_addr_valid_i ( port2_addr_valid[z]   ),
+        .port1_sent_i       ( port1_sent[z]         ),
+        .port2_sent_i       ( port2_sent[z]         ),
+        .select_i           ( select[z]             ),
+        .no_hit_i           ( no_hit[z]             ),
+        .multi_hit_i        ( multi_hit[z]          ),
+        .no_prot_i          ( no_prot[z]            ),
+        .prefetch_i         ( prefetch[z]           ),
+        .out_addr_i         ( out_addr[z]           ),
+        .cache_coherent_i   ( cache_coherent[z]     ),
+        .port1_accept_o     ( port1_accept[z]       ),
+        .port1_drop_o       ( port1_drop[z]         ),
+        .port1_miss_o       ( port1_miss[z]         ),
+        .port2_accept_o     ( port2_accept[z]       ),
+        .port2_drop_o       ( port2_drop[z]         ),
+        .port2_miss_o       ( port2_miss[z]         ),
+        .out_addr_o         ( out_addr_reg[z]       ),
+        .cache_coherent_o   ( cache_coherent_reg[z] ),
+        .miss_o             ( int_miss[z]           ),
+        .multi_o            ( int_multi[z]          ),
+        .prot_o             ( int_prot[z]           ),
+        .prefetch_o         ( int_prefetch[z]       ),
+        .in_addr_i          ( int_addr_min[z]       ),
+        .in_id_i            ( int_id[z]             ),
+        .in_len_i           ( int_len[z]            ),
+        .in_user_i          ( int_user[z]           ),
+        .in_addr_o          ( int_axaddr_o[z]       ),
+        .in_id_o            ( int_axid_o[z]         ),
+        .in_len_o           ( int_axlen_o[z]        ),
+        .in_user_o          ( int_axuser_o[z]       )
+      );
+  end
+  endgenerate
+  
+"""