--- /dev/null
+# 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
--- /dev/null
+# // 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
+
+"""