--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_ar_sender(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.l1_done_o = Signal() # output
+ self.l1_accept_i = Signal() # input
+ self.l1_drop_i = Signal() # input
+ self.l1_save_i = Signal() # input
+ self.l2_done_o = Signal() # output
+ self.l2_accept_i = Signal() # input
+ self.l2_drop_i = Signal() # input
+ self.l2_sending_o = Signal() # output
+ self.l1_araddr_i = Signal(AXI_ADDR_WIDTH) # input
+ self.l2_araddr_i = Signal(AXI_ADDR_WIDTH) # input
+ self.s_axi4_arid = Signal(AXI_ID_WIDTH) # 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(AXI_ADDR_WIDTH) # 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()
+ m.d.comb += self.l1_save.eq(self.None)
+ m.d.comb += self.l1_done_o.eq(self.None)
+ m.d.comb += self.m_axi4_arvalid.eq(self.None)
+ m.d.comb += self.s_axi4_arready.eq(self.None)
+ m.d.comb += self.m_axi4_aruser.eq(self.None)
+ m.d.comb += self.m_axi4_arcache.eq(self.None)
+ m.d.comb += self.m_axi4_arprot.eq(self.None)
+ m.d.comb += self.m_axi4_arlock.eq(self.None)
+ m.d.comb += self.m_axi4_arburst.eq(self.None)
+ m.d.comb += self.m_axi4_arsize.eq(self.None)
+ m.d.comb += self.m_axi4_arlen.eq(self.None)
+ m.d.comb += self.m_axi4_araddr.eq(self.None)
+ m.d.comb += self.m_axi4_arid.eq(self.None)
+ m.d.comb += self.l2_sending_o.eq(self.None)
+ m.d.comb += self.l2_sent.eq(self.None)
+ m.d.comb += self.l2_done_o.eq(self.None)
+ m.d.comb += self.m_axi4_aruser.eq(self.s_axi4_aruser)
+ m.d.comb += self.m_axi4_arcache.eq(self.s_axi4_arcache)
+ m.d.comb += self.m_axi4_arprot.eq(self.s_axi4_arprot)
+ m.d.comb += self.m_axi4_arlock.eq(self.s_axi4_arlock)
+ m.d.comb += self.m_axi4_arburst.eq(self.s_axi4_arburst)
+ m.d.comb += self.m_axi4_arsize.eq(self.s_axi4_arsize)
+ m.d.comb += self.m_axi4_arlen.eq(self.s_axi4_arlen)
+ m.d.comb += self.m_axi4_araddr.eq(self.l1_araddr_i)
+ m.d.comb += self.m_axi4_arid.eq(self.s_axi4_arid)
+ m.d.comb += self.l2_sending_o.eq(self.1: 'b0)
+ m.d.comb += self.l2_available_q.eq(self.1: 'b0)
+ m.d.comb += self.l2_done_o.eq(self.1: 'b0)
+ return m
+
+# // 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.
+#
+# module axi4_ar_sender
+# #(
+# parameter AXI_ADDR_WIDTH = 40,
+# parameter AXI_ID_WIDTH = 4,
+# parameter AXI_USER_WIDTH = 4,
+# parameter ENABLE_L2TLB = 0
+# )
+# (
+# input logic axi4_aclk,
+# input logic axi4_arstn,
+#
+# output logic l1_done_o,
+# input logic l1_accept_i,
+# input logic l1_drop_i,
+# input logic l1_save_i,
+#
+# output logic l2_done_o,
+# input logic l2_accept_i,
+# input logic l2_drop_i,
+# output logic l2_sending_o,
+#
+# input logic [AXI_ADDR_WIDTH-1:0] l1_araddr_i,
+# input logic [AXI_ADDR_WIDTH-1:0] l2_araddr_i,
+#
+# input logic [AXI_ID_WIDTH-1:0] s_axi4_arid,
+# 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 [AXI_ADDR_WIDTH-1: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
+# );
+#
+# logic l1_save;
+#
+# logic l2_sent;
+# logic l2_available_q;
+#
+# assign l1_save = l1_save_i & l2_available_q;
+#
+# assign l1_done_o = s_axi4_arvalid & s_axi4_arready ;
+#
+# // if 1: accept and forward a transaction translated by L1
+# // 2: drop or save request (if L2 slot not occupied already)
+# assign m_axi4_arvalid = (s_axi4_arvalid & l1_accept_i) |
+# l2_sending_o;
+# assign s_axi4_arready = (m_axi4_arvalid & m_axi4_arready & ~l2_sending_o) |
+# (s_axi4_arvalid & (l1_drop_i | l1_save));
+#
+# generate
+# if (ENABLE_L2TLB == 1) begin
+# logic [AXI_USER_WIDTH-1:0] l2_axi4_aruser ;
+# logic [3:0] l2_axi4_arcache ;
+# logic [3:0] l2_axi4_arregion;
+# logic [3:0] l2_axi4_arqos ;
+# logic [2:0] l2_axi4_arprot ;
+# logic l2_axi4_arlock ;
+# logic [1:0] l2_axi4_arburst ;
+# logic [2:0] l2_axi4_arsize ;
+# logic [7:0] l2_axi4_arlen ;
+# logic [AXI_ID_WIDTH-1:0] l2_axi4_arid ;
+#
+# assign m_axi4_aruser = l2_sending_o ? l2_axi4_aruser : s_axi4_aruser;
+# assign m_axi4_arcache = l2_sending_o ? l2_axi4_arcache : s_axi4_arcache;
+# assign m_axi4_arprot = l2_sending_o ? l2_axi4_arprot : s_axi4_arprot;
+# assign m_axi4_arlock = l2_sending_o ? l2_axi4_arlock : s_axi4_arlock;
+# assign m_axi4_arburst = l2_sending_o ? l2_axi4_arburst : s_axi4_arburst;
+# assign m_axi4_arsize = l2_sending_o ? l2_axi4_arsize : s_axi4_arsize;
+# assign m_axi4_arlen = l2_sending_o ? l2_axi4_arlen : s_axi4_arlen;
+# assign m_axi4_araddr = l2_sending_o ? l2_araddr_i : l1_araddr_i;
+# assign m_axi4_arid = l2_sending_o ? l2_axi4_arid : s_axi4_arid;
+#
+# // Buffer AXI signals in case of L1 miss
+# always @(posedge axi4_aclk or negedge axi4_arstn) begin
+# if (axi4_arstn == 1'b0) begin
+# l2_axi4_aruser <= 'b0;
+# l2_axi4_arcache <= 'b0;
+# l2_axi4_arprot <= 'b0;
+# l2_axi4_arlock <= 1'b0;
+# l2_axi4_arburst <= 'b0;
+# l2_axi4_arsize <= 'b0;
+# l2_axi4_arlen <= 'b0;
+# l2_axi4_arid <= 'b0;
+# end else if (l1_save) begin
+# l2_axi4_aruser <= s_axi4_aruser;
+# l2_axi4_arcache <= s_axi4_arcache;
+# l2_axi4_arprot <= s_axi4_arprot;
+# l2_axi4_arlock <= s_axi4_arlock;
+# l2_axi4_arburst <= s_axi4_arburst;
+# l2_axi4_arsize <= s_axi4_arsize;
+# l2_axi4_arlen <= s_axi4_arlen;
+# l2_axi4_arid <= s_axi4_arid;
+# end
+# end
+#
+# // signal that an l1_save_i can be accepted
+# always @(posedge axi4_aclk or negedge axi4_arstn) begin
+# if (axi4_arstn == 1'b0) begin
+# l2_available_q <= 1'b1;
+# end else if (l2_sent | l2_drop_i) begin
+# l2_available_q <= 1'b1;
+# end else if (l1_save) begin
+# l2_available_q <= 1'b0;
+# end
+# end
+#
+# assign l2_sending_o = l2_accept_i & ~l2_available_q;
+# assign l2_sent = l2_sending_o & m_axi4_arvalid & m_axi4_arready;
+#
+# // if 1: having sent out a transaction translated by L2
+# // 2: drop request (L2 slot is available again)
+# assign l2_done_o = l2_sent | l2_drop_i;
+#
+# end else begin // !`ifdef ENABLE_L2TLB
+# assign m_axi4_aruser = s_axi4_aruser;
+# assign m_axi4_arcache = s_axi4_arcache;
+# assign m_axi4_arprot = s_axi4_arprot;
+# assign m_axi4_arlock = s_axi4_arlock;
+# assign m_axi4_arburst = s_axi4_arburst;
+# assign m_axi4_arsize = s_axi4_arsize;
+# assign m_axi4_arlen = s_axi4_arlen;
+# assign m_axi4_araddr = l1_araddr_i;
+# assign m_axi4_arid = s_axi4_arid;
+#
+# assign l2_sending_o = 1'b0;
+# assign l2_available_q = 1'b0;
+# assign l2_done_o = 1'b0;
+# end // else: !if(ENABLE_L2TLB == 1)
+# endgenerate
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_aw_buffer(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.s_axi4_awid = Signal(AXI_ID_WIDTH) # input
+ self.s_axi4_awaddr = Signal(32) # input
+ self.s_axi4_awvalid = Signal() # input
+ self.s_axi4_awready = Signal() # output
+ self.s_axi4_awlen = Signal(8) # input
+ self.s_axi4_awsize = Signal(3) # input
+ self.s_axi4_awburst = Signal(2) # input
+ self.s_axi4_awlock = Signal() # input
+ self.s_axi4_awprot = Signal(3) # input
+ self.s_axi4_awcache = Signal(4) # input
+ self.s_axi4_awregion = Signal(4) # input
+ self.s_axi4_awqos = Signal(4) # input
+ self.s_axi4_awuser = Signal(AXI_USER_WIDTH) # input
+ self.m_axi4_awid = Signal(AXI_ID_WIDTH) # output
+ self.m_axi4_awaddr = Signal(32) # output
+ self.m_axi4_awvalid = Signal() # output
+ self.m_axi4_awready = Signal() # input
+ self.m_axi4_awlen = Signal(8) # output
+ self.m_axi4_awsize = Signal(3) # output
+ self.m_axi4_awburst = Signal(2) # output
+ self.m_axi4_awlock = Signal() # output
+ self.m_axi4_awprot = Signal(3) # output
+ self.m_axi4_awcache = Signal(4) # output
+ self.m_axi4_awregion = Signal(4) # output
+ self.m_axi4_awqos = Signal(4) # output
+ self.m_axi4_awuser = Signal(AXI_USER_WIDTH) # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.None.eq(self.s_axi4_awcache)
+ m.d.comb += self.None.eq(self.s_axi4_awprot)
+ m.d.comb += self.None.eq(self.s_axi4_awlock)
+ m.d.comb += self.None.eq(self.s_axi4_awburst)
+ m.d.comb += self.None.eq(self.s_axi4_awsize)
+ m.d.comb += self.None.eq(self.s_axi4_awlen)
+ m.d.comb += self.None.eq(self.s_axi4_awaddr)
+ m.d.comb += self.None.eq(self.s_axi4_awregion)
+ m.d.comb += self.None.eq(self.s_axi4_awqos)
+ m.d.comb += self.None.eq(self.s_axi4_awid)
+ m.d.comb += self.None.eq(self.s_axi4_awuser)
+ m.d.comb += self.m_axi4_awcache.eq(self.None)
+ m.d.comb += self.m_axi4_awprot.eq(self.None)
+ m.d.comb += self.m_axi4_awlock.eq(self.None)
+ m.d.comb += self.m_axi4_awburst.eq(self.None)
+ m.d.comb += self.m_axi4_awsize.eq(self.None)
+ m.d.comb += self.m_axi4_awlen.eq(self.None)
+ m.d.comb += self.m_axi4_awaddr.eq(self.None)
+ m.d.comb += self.m_axi4_awregion.eq(self.None)
+ m.d.comb += self.m_axi4_awqos.eq(self.None)
+ m.d.comb += self.m_axi4_awid.eq(self.None)
+ m.d.comb += self.m_axi4_awuser.eq(self.None)
+ return m
+
+# // 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.
+#
+# module axi4_aw_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_awid,
+# input logic [31:0] s_axi4_awaddr,
+# input logic s_axi4_awvalid,
+# output logic s_axi4_awready,
+# input logic [7:0] s_axi4_awlen,
+# input logic [2:0] s_axi4_awsize,
+# input logic [1:0] s_axi4_awburst,
+# input logic s_axi4_awlock,
+# input logic [2:0] s_axi4_awprot,
+# input logic [3:0] s_axi4_awcache,
+# input logic [3:0] s_axi4_awregion,
+# input logic [3:0] s_axi4_awqos,
+# input logic [AXI_USER_WIDTH-1:0] s_axi4_awuser,
+#
+# output logic [AXI_ID_WIDTH-1:0] m_axi4_awid,
+# output logic [31:0] m_axi4_awaddr,
+# output logic m_axi4_awvalid,
+# input logic m_axi4_awready,
+# output logic [7:0] m_axi4_awlen,
+# output logic [2:0] m_axi4_awsize,
+# output logic [1:0] m_axi4_awburst,
+# output logic m_axi4_awlock,
+# output logic [2:0] m_axi4_awprot,
+# output logic [3:0] m_axi4_awcache,
+# output logic [3:0] m_axi4_awregion,
+# output logic [3:0] m_axi4_awqos,
+# output logic [AXI_USER_WIDTH-1:0] m_axi4_awuser
+# );
+#
+# wire [AXI_USER_WIDTH+AXI_ID_WIDTH+60:0] data_in;
+# wire [AXI_USER_WIDTH+AXI_ID_WIDTH+60:0] data_out;
+#
+# assign data_in [3:0] = s_axi4_awcache;
+# assign data_in [6:4] = s_axi4_awprot;
+# assign data_in [7] = s_axi4_awlock;
+# assign data_in [9:8] = s_axi4_awburst;
+# assign data_in [12:10] = s_axi4_awsize;
+# assign data_in [20:13] = s_axi4_awlen;
+# assign data_in [52:21] = s_axi4_awaddr;
+# assign data_in [56:53] = s_axi4_awregion;
+# assign data_in [60:57] = s_axi4_awqos;
+# assign data_in [60+AXI_ID_WIDTH:61] = s_axi4_awid;
+# assign data_in [60+AXI_ID_WIDTH+AXI_USER_WIDTH:61+AXI_ID_WIDTH] = s_axi4_awuser;
+#
+# assign m_axi4_awcache = data_out[3:0];
+# assign m_axi4_awprot = data_out[6:4];
+# assign m_axi4_awlock = data_out[7];
+# assign m_axi4_awburst = data_out[9:8];
+# assign m_axi4_awsize = data_out[12:10];
+# assign m_axi4_awlen = data_out[20:13];
+# assign m_axi4_awaddr = data_out[52:21];
+# assign m_axi4_awregion = data_out[56:53];
+# assign m_axi4_awqos = data_out[60:57];
+# assign m_axi4_awid = data_out[60+AXI_ID_WIDTH:61];
+# assign m_axi4_awuser = data_out[60+AXI_ID_WIDTH+AXI_USER_WIDTH:61+AXI_ID_WIDTH];
+#
+# axi_buffer_rab
+# #(
+# .DATA_WIDTH ( AXI_ID_WIDTH+AXI_USER_WIDTH+61 ),
+# .BUFFER_DEPTH ( 4 )
+# )
+# u_buffer
+# (
+# .clk ( axi4_aclk ),
+# .rstn ( axi4_arstn ),
+# .valid_out ( m_axi4_awvalid ),
+# .data_out ( data_out ),
+# .ready_in ( m_axi4_awready ),
+# .valid_in ( s_axi4_awvalid ),
+# .data_in ( data_in ),
+# .ready_out ( s_axi4_awready )
+# );
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_aw_sender(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.l1_done_o = Signal() # output
+ self.l1_accept_i = Signal() # input
+ self.l1_drop_i = Signal() # input
+ self.l1_save_i = Signal() # input
+ self.l2_done_o = Signal() # output
+ self.l2_accept_i = Signal() # input
+ self.l2_drop_i = Signal() # input
+ self.l2_sending_o = Signal() # output
+ self.l1_awaddr_i = Signal(AXI_ADDR_WIDTH) # input
+ self.l2_awaddr_i = Signal(AXI_ADDR_WIDTH) # input
+ self.s_axi4_awid = Signal(AXI_ID_WIDTH) # input
+ self.s_axi4_awvalid = Signal() # input
+ self.s_axi4_awready = Signal() # output
+ self.s_axi4_awlen = Signal(8) # input
+ self.s_axi4_awsize = Signal(3) # input
+ self.s_axi4_awburst = Signal(2) # input
+ self.s_axi4_awlock = Signal() # input
+ self.s_axi4_awprot = Signal(3) # input
+ self.s_axi4_awcache = Signal(4) # input
+ self.s_axi4_awregion = Signal(4) # input
+ self.s_axi4_awqos = Signal(4) # input
+ self.s_axi4_awuser = Signal(AXI_USER_WIDTH) # input
+ self.m_axi4_awid = Signal(AXI_ID_WIDTH) # output
+ self.m_axi4_awaddr = Signal(AXI_ADDR_WIDTH) # output
+ self.m_axi4_awvalid = Signal() # output
+ self.m_axi4_awready = Signal() # input
+ self.m_axi4_awlen = Signal(8) # output
+ self.m_axi4_awsize = Signal(3) # output
+ self.m_axi4_awburst = Signal(2) # output
+ self.m_axi4_awlock = Signal() # output
+ self.m_axi4_awprot = Signal(3) # output
+ self.m_axi4_awcache = Signal(4) # output
+ self.m_axi4_awregion = Signal(4) # output
+ self.m_axi4_awqos = Signal(4) # output
+ self.m_axi4_awuser = Signal(AXI_USER_WIDTH) # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.l1_save.eq(self.None)
+ m.d.comb += self.l1_done_o.eq(self.None)
+ m.d.comb += self.m_axi4_awvalid.eq(self.None)
+ m.d.comb += self.s_axi4_awready.eq(self.None)
+ m.d.comb += self.m_axi4_awuser.eq(self.None)
+ m.d.comb += self.m_axi4_awcache.eq(self.None)
+ m.d.comb += self.m_axi4_awregion.eq(self.None)
+ m.d.comb += self.m_axi4_awqos.eq(self.None)
+ m.d.comb += self.m_axi4_awprot.eq(self.None)
+ m.d.comb += self.m_axi4_awlock.eq(self.None)
+ m.d.comb += self.m_axi4_awburst.eq(self.None)
+ m.d.comb += self.m_axi4_awsize.eq(self.None)
+ m.d.comb += self.m_axi4_awlen.eq(self.None)
+ m.d.comb += self.m_axi4_awaddr.eq(self.None)
+ m.d.comb += self.m_axi4_awid.eq(self.None)
+ m.d.comb += self.l2_sending_o.eq(self.None)
+ m.d.comb += self.l2_sent.eq(self.None)
+ m.d.comb += self.l2_done_o.eq(self.None)
+ m.d.comb += self.m_axi4_awuser.eq(self.s_axi4_awuser)
+ m.d.comb += self.m_axi4_awcache.eq(self.s_axi4_awcache)
+ m.d.comb += self.m_axi4_awregion.eq(self.s_axi4_awregion)
+ m.d.comb += self.m_axi4_awqos.eq(self.s_axi4_awqos)
+ m.d.comb += self.m_axi4_awprot.eq(self.s_axi4_awprot)
+ m.d.comb += self.m_axi4_awlock.eq(self.s_axi4_awlock)
+ m.d.comb += self.m_axi4_awburst.eq(self.s_axi4_awburst)
+ m.d.comb += self.m_axi4_awsize.eq(self.s_axi4_awsize)
+ m.d.comb += self.m_axi4_awlen.eq(self.s_axi4_awlen)
+ m.d.comb += self.m_axi4_awaddr.eq(self.l1_awaddr_i)
+ m.d.comb += self.m_axi4_awid.eq(self.s_axi4_awid)
+ m.d.comb += self.l2_sending_o.eq(self.1: 'b0)
+ m.d.comb += self.l2_available_q.eq(self.1: 'b0)
+ m.d.comb += self.l2_done_o.eq(self.1: 'b0)
+ return m
+
+# // 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.
+#
+# module axi4_aw_sender
+# #(
+# parameter AXI_ADDR_WIDTH = 40,
+# parameter AXI_ID_WIDTH = 4,
+# parameter AXI_USER_WIDTH = 4,
+# parameter ENABLE_L2TLB = 0
+# )
+# (
+# input logic axi4_aclk,
+# input logic axi4_arstn,
+#
+# output logic l1_done_o,
+# input logic l1_accept_i,
+# input logic l1_drop_i,
+# input logic l1_save_i,
+#
+# output logic l2_done_o,
+# input logic l2_accept_i,
+# input logic l2_drop_i,
+# output logic l2_sending_o,
+#
+# input logic [AXI_ADDR_WIDTH-1:0] l1_awaddr_i,
+# input logic [AXI_ADDR_WIDTH-1:0] l2_awaddr_i,
+#
+# input logic [AXI_ID_WIDTH-1:0] s_axi4_awid,
+# input logic s_axi4_awvalid,
+# output logic s_axi4_awready,
+# input logic [7:0] s_axi4_awlen,
+# input logic [2:0] s_axi4_awsize,
+# input logic [1:0] s_axi4_awburst,
+# input logic s_axi4_awlock,
+# input logic [2:0] s_axi4_awprot,
+# input logic [3:0] s_axi4_awcache,
+# input logic [3:0] s_axi4_awregion,
+# input logic [3:0] s_axi4_awqos,
+# input logic [AXI_USER_WIDTH-1:0] s_axi4_awuser,
+#
+# output logic [AXI_ID_WIDTH-1:0] m_axi4_awid,
+# output logic [AXI_ADDR_WIDTH-1:0] m_axi4_awaddr,
+# output logic m_axi4_awvalid,
+# input logic m_axi4_awready,
+# output logic [7:0] m_axi4_awlen,
+# output logic [2:0] m_axi4_awsize,
+# output logic [1:0] m_axi4_awburst,
+# output logic m_axi4_awlock,
+# output logic [2:0] m_axi4_awprot,
+# output logic [3:0] m_axi4_awcache,
+# output logic [3:0] m_axi4_awregion,
+# output logic [3:0] m_axi4_awqos,
+# output logic [AXI_USER_WIDTH-1:0] m_axi4_awuser
+# );
+#
+# logic l1_save;
+#
+# logic l2_sent;
+# logic l2_available_q;
+#
+# assign l1_save = l1_save_i & l2_available_q;
+#
+# assign l1_done_o = s_axi4_awvalid & s_axi4_awready ;
+#
+# // if 1: accept and forward a transaction translated by L1
+# // 2: drop or save request (if L2 slot not occupied already)
+# assign m_axi4_awvalid = (s_axi4_awvalid & l1_accept_i) |
+# l2_sending_o;
+# assign s_axi4_awready = (m_axi4_awvalid & m_axi4_awready & ~l2_sending_o) |
+# (s_axi4_awvalid & (l1_drop_i | l1_save));
+#
+# generate
+# if (ENABLE_L2TLB == 1) begin
+# logic [AXI_USER_WIDTH-1:0] l2_axi4_awuser ;
+# logic [3:0] l2_axi4_awcache ;
+# logic [3:0] l2_axi4_awregion;
+# logic [3:0] l2_axi4_awqos ;
+# logic [2:0] l2_axi4_awprot ;
+# logic l2_axi4_awlock ;
+# logic [1:0] l2_axi4_awburst ;
+# logic [2:0] l2_axi4_awsize ;
+# logic [7:0] l2_axi4_awlen ;
+# logic [AXI_ID_WIDTH-1:0] l2_axi4_awid ;
+#
+# assign m_axi4_awuser = l2_sending_o ? l2_axi4_awuser : s_axi4_awuser;
+# assign m_axi4_awcache = l2_sending_o ? l2_axi4_awcache : s_axi4_awcache;
+# assign m_axi4_awregion = l2_sending_o ? l2_axi4_awregion : s_axi4_awregion;
+# assign m_axi4_awqos = l2_sending_o ? l2_axi4_awqos : s_axi4_awqos;
+# assign m_axi4_awprot = l2_sending_o ? l2_axi4_awprot : s_axi4_awprot;
+# assign m_axi4_awlock = l2_sending_o ? l2_axi4_awlock : s_axi4_awlock;
+# assign m_axi4_awburst = l2_sending_o ? l2_axi4_awburst : s_axi4_awburst;
+# assign m_axi4_awsize = l2_sending_o ? l2_axi4_awsize : s_axi4_awsize;
+# assign m_axi4_awlen = l2_sending_o ? l2_axi4_awlen : s_axi4_awlen;
+# assign m_axi4_awaddr = l2_sending_o ? l2_awaddr_i : l1_awaddr_i;
+# assign m_axi4_awid = l2_sending_o ? l2_axi4_awid : s_axi4_awid;
+#
+# // buffer AXI signals in case of L1 miss
+# always @(posedge axi4_aclk or negedge axi4_arstn) begin
+# if (axi4_arstn == 1'b0) begin
+# l2_axi4_awuser <= 'b0;
+# l2_axi4_awcache <= 'b0;
+# l2_axi4_awregion <= 'b0;
+# l2_axi4_awqos <= 'b0;
+# l2_axi4_awprot <= 'b0;
+# l2_axi4_awlock <= 1'b0;
+# l2_axi4_awburst <= 'b0;
+# l2_axi4_awsize <= 'b0;
+# l2_axi4_awlen <= 'b0;
+# l2_axi4_awid <= 'b0;
+# end else if (l1_save) begin
+# l2_axi4_awuser <= s_axi4_awuser;
+# l2_axi4_awcache <= s_axi4_awcache;
+# l2_axi4_awregion <= s_axi4_awregion;
+# l2_axi4_awqos <= s_axi4_awqos;
+# l2_axi4_awprot <= s_axi4_awprot;
+# l2_axi4_awlock <= s_axi4_awlock;
+# l2_axi4_awburst <= s_axi4_awburst;
+# l2_axi4_awsize <= s_axi4_awsize;
+# l2_axi4_awlen <= s_axi4_awlen;
+# l2_axi4_awid <= s_axi4_awid;
+# end
+# end
+#
+# // signal that an l1_save_i can be accepted
+# always @(posedge axi4_aclk or negedge axi4_arstn) begin
+# if (axi4_arstn == 1'b0) begin
+# l2_available_q <= 1'b1;
+# end else if (l2_sent | l2_drop_i) begin
+# l2_available_q <= 1'b1;
+# end else if (l1_save) begin
+# l2_available_q <= 1'b0;
+# end
+# end
+#
+# assign l2_sending_o = l2_accept_i & ~l2_available_q;
+# assign l2_sent = l2_sending_o & m_axi4_awvalid & m_axi4_awready;
+#
+# // if 1: having sent out a transaction translated by L2
+# // 2: drop request (L2 slot is available again)
+# assign l2_done_o = l2_sent | l2_drop_i;
+#
+# end else begin // !`ifdef ENABLE_L2TLB
+# assign m_axi4_awuser = s_axi4_awuser;
+# assign m_axi4_awcache = s_axi4_awcache;
+# assign m_axi4_awregion = s_axi4_awregion;
+# assign m_axi4_awqos = s_axi4_awqos;
+# assign m_axi4_awprot = s_axi4_awprot;
+# assign m_axi4_awlock = s_axi4_awlock;
+# assign m_axi4_awburst = s_axi4_awburst;
+# assign m_axi4_awsize = s_axi4_awsize;
+# assign m_axi4_awlen = s_axi4_awlen;
+# assign m_axi4_awaddr = l1_awaddr_i;
+# assign m_axi4_awid = s_axi4_awid;
+#
+# assign l2_sending_o = 1'b0;
+# assign l2_available_q = 1'b0;
+# assign l2_done_o = 1'b0;
+# end // !`ifdef ENABLE_L2TLB
+# endgenerate
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_b_buffer(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.s_axi4_bid = Signal(AXI_ID_WIDTH) # output
+ self.s_axi4_bresp = Signal(2) # output
+ self.s_axi4_bvalid = Signal() # output
+ self.s_axi4_buser = Signal(AXI_USER_WIDTH) # output
+ self.s_axi4_bready = Signal() # input
+ self.m_axi4_bid = Signal(AXI_ID_WIDTH) # input
+ self.m_axi4_bresp = Signal(2) # input
+ self.m_axi4_bvalid = Signal() # input
+ self.m_axi4_buser = Signal(AXI_USER_WIDTH) # input
+ self.m_axi4_bready = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.None.eq(self.m_axi4_bresp)
+ m.d.comb += self.None.eq(self.m_axi4_bid)
+ m.d.comb += self.None.eq(self.m_axi4_buser)
+ m.d.comb += self.s_axi4_buser.eq(self.None)
+ m.d.comb += self.s_axi4_bid.eq(self.None)
+ m.d.comb += self.s_axi4_bresp.eq(self.None)
+ return m
+
+# // 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.
+#
+# module axi4_b_buffer
+# #(
+# parameter AXI_ID_WIDTH = 4,
+# parameter AXI_USER_WIDTH = 4
+# )
+# (
+# input logic axi4_aclk,
+# input logic axi4_arstn,
+#
+# output logic [AXI_ID_WIDTH-1:0] s_axi4_bid,
+# output logic [1:0] s_axi4_bresp,
+# output logic s_axi4_bvalid,
+# output logic [AXI_USER_WIDTH-1:0] s_axi4_buser,
+# input logic s_axi4_bready,
+#
+# input logic [AXI_ID_WIDTH-1:0] m_axi4_bid,
+# input logic [1:0] m_axi4_bresp,
+# input logic m_axi4_bvalid,
+# input logic [AXI_USER_WIDTH-1:0] m_axi4_buser,
+# output logic m_axi4_bready
+# );
+#
+# wire [AXI_ID_WIDTH+AXI_USER_WIDTH+1:0] data_in;
+# wire [AXI_ID_WIDTH+AXI_USER_WIDTH+1:0] data_out;
+#
+# assign data_in [1:0] = m_axi4_bresp;
+# assign data_in [AXI_ID_WIDTH+1:2] = m_axi4_bid;
+# assign data_in[AXI_ID_WIDTH+AXI_USER_WIDTH+1:AXI_ID_WIDTH+2] = m_axi4_buser;
+#
+# assign s_axi4_buser = data_out[AXI_ID_WIDTH+AXI_USER_WIDTH+1:AXI_ID_WIDTH+2];
+# assign s_axi4_bid = data_out[AXI_ID_WIDTH+1:2];
+# assign s_axi4_bresp = data_out[1:0];
+#
+# axi_buffer_rab
+# #(
+# .DATA_WIDTH ( AXI_ID_WIDTH+AXI_USER_WIDTH+2 ),
+# .BUFFER_DEPTH ( 4 )
+# )
+# u_buffer
+# (
+# .clk ( axi4_aclk ),
+# .rstn ( axi4_arstn ),
+# .valid_out( s_axi4_bvalid ),
+# .data_out ( data_out ),
+# .ready_in ( s_axi4_bready ),
+# .valid_in ( m_axi4_bvalid ),
+# .data_in ( data_in ),
+# .ready_out( m_axi4_bready )
+# );
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_b_sender(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.drop_i = Signal() # input
+ self.done_o = Signal() # output
+ self.id_i = Signal(AXI_ID_WIDTH) # input
+ self.prefetch_i = Signal() # input
+ self.hit_i = Signal() # input
+ self.s_axi4_bid = Signal(AXI_ID_WIDTH) # output
+ self.s_axi4_bresp = Signal(2) # output
+ self.s_axi4_bvalid = Signal() # output
+ self.s_axi4_buser = Signal(AXI_USER_WIDTH) # output
+ self.s_axi4_bready = Signal() # input
+ self.m_axi4_bid = Signal(AXI_ID_WIDTH) # input
+ self.m_axi4_bresp = Signal(2) # input
+ self.m_axi4_bvalid = Signal() # input
+ self.m_axi4_buser = Signal(AXI_USER_WIDTH) # input
+ self.m_axi4_bready = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.fifo_push.eq(self.None)
+ m.d.comb += self.done_o.eq(self.fifo_push)
+ m.d.comb += self.fifo_pop.eq(self.None)
+ m.d.comb += self.s_axi4_buser.eq(self.None)
+ m.d.comb += self.s_axi4_bid.eq(self.None)
+ m.d.comb += self.s_axi4_bresp.eq(self.None)
+ m.d.comb += self.s_axi4_bvalid.eq(self.None)
+ m.d.comb += self.m_axi4_bready.eq(self.None)
+ return m
+
+# // 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.
+#
+# module axi4_b_sender
+# #(
+# parameter AXI_ID_WIDTH = 10,
+# parameter AXI_USER_WIDTH = 4
+# )
+# (
+# input logic axi4_aclk,
+# input logic axi4_arstn,
+#
+# input logic drop_i,
+# output logic done_o,
+# input logic [AXI_ID_WIDTH-1:0] id_i,
+# input logic prefetch_i,
+# input logic hit_i,
+#
+# output logic [AXI_ID_WIDTH-1:0] s_axi4_bid,
+# output logic [1:0] s_axi4_bresp,
+# output logic s_axi4_bvalid,
+# output logic [AXI_USER_WIDTH-1:0] s_axi4_buser,
+# input logic s_axi4_bready,
+#
+# input logic [AXI_ID_WIDTH-1:0] m_axi4_bid,
+# input logic [1:0] m_axi4_bresp,
+# input logic m_axi4_bvalid,
+# input logic [AXI_USER_WIDTH-1:0] m_axi4_buser,
+# output logic m_axi4_bready
+# );
+#
+# logic fifo_valid;
+# logic fifo_pop;
+# logic fifo_push;
+# logic fifo_ready;
+# logic [AXI_ID_WIDTH-1:0] id;
+# logic prefetch;
+# logic hit;
+#
+# logic dropping;
+#
+# axi_buffer_rab
+# #(
+# .DATA_WIDTH ( 2+AXI_ID_WIDTH ),
+# .BUFFER_DEPTH ( 4 )
+# )
+# u_fifo
+# (
+# .clk ( axi4_aclk ),
+# .rstn ( axi4_arstn ),
+# // Pop
+# .data_out ( {prefetch, hit, id} ),
+# .valid_out ( fifo_valid ),
+# .ready_in ( fifo_pop ),
+# // Push
+# .valid_in ( fifo_push ),
+# .data_in ( {prefetch_i, hit_i, id_i} ),
+# .ready_out ( fifo_ready )
+# );
+#
+# assign fifo_push = drop_i & fifo_ready;
+# assign done_o = fifo_push;
+#
+# assign fifo_pop = dropping & s_axi4_bready;
+#
+# always @ (posedge axi4_aclk or negedge axi4_arstn) begin
+# if (axi4_arstn == 1'b0) begin
+# dropping <= 1'b0;
+# end else begin
+# if (fifo_valid && ~dropping)
+# dropping <= 1'b1;
+# else if (fifo_pop)
+# dropping <= 1'b0;
+# end
+# end
+#
+# assign s_axi4_buser = dropping ? {AXI_USER_WIDTH{1'b0}} : m_axi4_buser;
+# assign s_axi4_bid = dropping ? id : m_axi4_bid;
+#
+# assign s_axi4_bresp = (dropping & prefetch & hit) ? 2'b00 : // prefetch hit, mutli, prot
+# (dropping & prefetch ) ? 2'b10 : // prefetch miss
+# (dropping & hit) ? 2'b10 : // non-prefetch multi, prot
+# (dropping ) ? 2'b10 : // non-prefetch miss
+# m_axi4_bresp;
+#
+# assign s_axi4_bvalid = dropping | m_axi4_bvalid;
+# assign m_axi4_bready = ~dropping & s_axi4_bready;
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_r_buffer(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.s_axi4_rid = Signal(AXI_ID_WIDTH) # output
+ self.s_axi4_rresp = Signal(2) # output
+ self.s_axi4_rdata = Signal(AXI_DATA_WIDTH) # output
+ self.s_axi4_rlast = Signal() # output
+ self.s_axi4_rvalid = Signal() # output
+ self.s_axi4_ruser = Signal(AXI_USER_WIDTH) # output
+ self.s_axi4_rready = Signal() # input
+ self.m_axi4_rid = Signal(AXI_ID_WIDTH) # input
+ self.m_axi4_rresp = Signal(2) # input
+ self.m_axi4_rdata = Signal(AXI_DATA_WIDTH) # input
+ self.m_axi4_rlast = Signal() # input
+ self.m_axi4_rvalid = Signal() # input
+ self.m_axi4_ruser = Signal(AXI_USER_WIDTH) # input
+ self.m_axi4_rready = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.None.eq(self.m_axi4_rresp)
+ m.d.comb += self.None.eq(self.m_axi4_rlast)
+ m.d.comb += self.None.eq(self.m_axi4_rid)
+ m.d.comb += self.None.eq(self.m_axi4_rdata)
+ m.d.comb += self.None.eq(self.m_axi4_ruser)
+ m.d.comb += self.s_axi4_rresp.eq(self.None)
+ m.d.comb += self.s_axi4_rlast.eq(self.None)
+ m.d.comb += self.s_axi4_rid.eq(self.None)
+ m.d.comb += self.s_axi4_rdata.eq(self.None)
+ m.d.comb += self.s_axi4_ruser.eq(self.None)
+ return m
+
+# // 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.
+#
+# module axi4_r_buffer
+# #(
+# parameter AXI_DATA_WIDTH = 32,
+# parameter AXI_ID_WIDTH = 4,
+# parameter AXI_USER_WIDTH = 4
+# )
+# (
+# input logic axi4_aclk,
+# input logic axi4_arstn,
+#
+# output logic [AXI_ID_WIDTH-1:0] s_axi4_rid,
+# output logic [1:0] s_axi4_rresp,
+# output logic [AXI_DATA_WIDTH-1:0] s_axi4_rdata,
+# output logic s_axi4_rlast,
+# output logic s_axi4_rvalid,
+# output logic [AXI_USER_WIDTH-1:0] s_axi4_ruser,
+# input logic s_axi4_rready,
+#
+# input logic [AXI_ID_WIDTH-1:0] m_axi4_rid,
+# input logic [1:0] m_axi4_rresp,
+# input logic [AXI_DATA_WIDTH-1:0] m_axi4_rdata,
+# input logic m_axi4_rlast,
+# input logic m_axi4_rvalid,
+# input logic [AXI_USER_WIDTH-1:0] m_axi4_ruser,
+# output logic m_axi4_rready
+# );
+#
+# wire [AXI_DATA_WIDTH+AXI_ID_WIDTH+AXI_USER_WIDTH+3-1:0] data_in;
+# wire [AXI_DATA_WIDTH+AXI_ID_WIDTH+AXI_USER_WIDTH+3-1:0] data_out;
+#
+# localparam ID_START = 3;
+# localparam ID_END = AXI_ID_WIDTH-1 + ID_START;
+# localparam DATA_START = ID_END + 1;
+# localparam DATA_END = AXI_DATA_WIDTH-1 + DATA_START;
+# localparam USER_START = DATA_END + 1;
+# localparam USER_END = AXI_USER_WIDTH-1 + USER_START;
+#
+# assign data_in [1:0] = m_axi4_rresp;
+# assign data_in [2] = m_axi4_rlast;
+# assign data_in [ID_END:ID_START] = m_axi4_rid;
+# assign data_in[DATA_END:DATA_START] = m_axi4_rdata;
+# assign data_in[USER_END:USER_START] = m_axi4_ruser;
+#
+# assign s_axi4_rresp = data_out [1:0];
+# assign s_axi4_rlast = data_out [2];
+# assign s_axi4_rid = data_out [ID_END:ID_START];
+# assign s_axi4_rdata = data_out[DATA_END:DATA_START];
+# assign s_axi4_ruser = data_out[USER_END:USER_START];
+#
+# axi_buffer_rab
+# #(
+# .DATA_WIDTH ( AXI_DATA_WIDTH+AXI_ID_WIDTH+AXI_USER_WIDTH+3 ),
+# .BUFFER_DEPTH ( 4 )
+# )
+# u_buffer
+# (
+# .clk ( axi4_aclk ),
+# .rstn ( axi4_arstn ),
+# // Pop
+# .valid_out ( s_axi4_rvalid ),
+# .data_out ( data_out ),
+# .ready_in ( s_axi4_rready ),
+# // Push
+# .valid_in ( m_axi4_rvalid ),
+# .data_in ( data_in ),
+# .ready_out ( m_axi4_rready )
+# );
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_r_sender(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.drop_i = Signal() # input
+ self.drop_len_i = Signal(8) # input
+ self.done_o = Signal() # output
+ self.id_i = Signal(AXI_ID_WIDTH) # input
+ self.prefetch_i = Signal() # input
+ self.hit_i = Signal() # input
+ self.s_axi4_rid = Signal(AXI_ID_WIDTH) # output
+ self.s_axi4_rresp = Signal(2) # output
+ self.s_axi4_rdata = Signal(AXI_DATA_WIDTH) # output
+ self.s_axi4_rlast = Signal() # output
+ self.s_axi4_rvalid = Signal() # output
+ self.s_axi4_ruser = Signal(AXI_USER_WIDTH) # output
+ self.s_axi4_rready = Signal() # input
+ self.m_axi4_rid = Signal(AXI_ID_WIDTH) # input
+ self.m_axi4_rresp = Signal(2) # input
+ self.m_axi4_rdata = Signal(AXI_DATA_WIDTH) # input
+ self.m_axi4_rlast = Signal() # input
+ self.m_axi4_rvalid = Signal() # input
+ self.m_axi4_ruser = Signal(AXI_USER_WIDTH) # input
+ self.m_axi4_rready = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.fifo_push.eq(self.None)
+ m.d.comb += self.done_o.eq(self.fifo_push)
+ m.d.comb += self.s_axi4_rdata.eq(self.m_axi4_rdata)
+ m.d.comb += self.s_axi4_ruser.eq(self.None)
+ m.d.comb += self.s_axi4_rid.eq(self.None)
+ m.d.comb += self.s_axi4_rresp.eq(self.None)
+ m.d.comb += self.s_axi4_rvalid.eq(self.None)
+ m.d.comb += self.m_axi4_rready.eq(self.None)
+ return m
+
+# // 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.
+#
+# //import CfMath::log2;
+#
+# module axi4_r_sender
+# #(
+# parameter AXI_DATA_WIDTH = 32,
+# parameter AXI_ID_WIDTH = 4,
+# parameter AXI_USER_WIDTH = 4
+# )
+# (
+# input logic axi4_aclk,
+# input logic axi4_arstn,
+#
+# input logic drop_i,
+# input logic [7:0] drop_len_i,
+# output logic done_o,
+# input logic [AXI_ID_WIDTH-1:0] id_i,
+# input logic prefetch_i,
+# input logic hit_i,
+#
+# output logic [AXI_ID_WIDTH-1:0] s_axi4_rid,
+# output logic [1:0] s_axi4_rresp,
+# output logic [AXI_DATA_WIDTH-1:0] s_axi4_rdata,
+# output logic s_axi4_rlast,
+# output logic s_axi4_rvalid,
+# output logic [AXI_USER_WIDTH-1:0] s_axi4_ruser,
+# input logic s_axi4_rready,
+#
+# input logic [AXI_ID_WIDTH-1:0] m_axi4_rid,
+# input logic [1:0] m_axi4_rresp,
+# input logic [AXI_DATA_WIDTH-1:0] m_axi4_rdata,
+# input logic m_axi4_rlast,
+# input logic m_axi4_rvalid,
+# input logic [AXI_USER_WIDTH-1:0] m_axi4_ruser,
+# output logic m_axi4_rready
+# );
+#
+# localparam BUFFER_DEPTH = 16;
+#
+# logic fifo_valid;
+# logic fifo_pop;
+# logic fifo_push;
+# logic fifo_ready;
+# logic [AXI_ID_WIDTH-1:0] id;
+# logic [7:0] len;
+# logic prefetch;
+# logic hit;
+#
+# logic dropping;
+#
+# enum logic [1:0] { FORWARDING, DROPPING }
+# state_d, state_q;
+# logic burst_ongoing_d, burst_ongoing_q;
+# logic [7:0] drop_cnt_d, drop_cnt_q;
+#
+# axi_buffer_rab
+# #(
+# .DATA_WIDTH ( 2+AXI_ID_WIDTH+8 ),
+# .BUFFER_DEPTH ( BUFFER_DEPTH )
+# )
+# u_fifo
+# (
+# .clk ( axi4_aclk ),
+# .rstn ( axi4_arstn ),
+# // Pop
+# .data_out ( {prefetch, hit, id, len} ),
+# .valid_out ( fifo_valid ),
+# .ready_in ( fifo_pop ),
+# // Push
+# .valid_in ( fifo_push ),
+# .data_in ( {prefetch_i, hit_i, id_i, drop_len_i} ),
+# .ready_out ( fifo_ready )
+# );
+#
+# assign fifo_push = drop_i & fifo_ready;
+# assign done_o = fifo_push;
+#
+# always_comb begin
+# burst_ongoing_d = burst_ongoing_q;
+# drop_cnt_d = drop_cnt_q;
+# dropping = 1'b0;
+# s_axi4_rlast = 1'b0;
+# fifo_pop = 1'b0;
+# state_d = state_q;
+#
+# case (state_q)
+# FORWARDING: begin
+# s_axi4_rlast = m_axi4_rlast;
+# // Remember whether there is currently a burst ongoing.
+# if (m_axi4_rvalid && m_axi4_rready) begin
+# if (m_axi4_rlast) begin
+# burst_ongoing_d = 1'b0;
+# end else begin
+# burst_ongoing_d = 1'b1;
+# end
+# end
+# // If there is no burst ongoing and the FIFO has a drop request ready, process it.
+# if (!burst_ongoing_d && fifo_valid) begin
+# drop_cnt_d = len;
+# state_d = DROPPING;
+# end
+# end
+#
+# DROPPING: begin
+# dropping = 1'b1;
+# s_axi4_rlast = (drop_cnt_q == '0);
+# // Handshake on slave interface
+# if (s_axi4_rready) begin
+# drop_cnt_d -= 1;
+# if (drop_cnt_q == '0) begin
+# drop_cnt_d = '0;
+# fifo_pop = 1'b1;
+# state_d = FORWARDING;
+# end
+# end
+# end
+#
+# default: begin
+# state_d = FORWARDING;
+# end
+# endcase
+# end
+#
+# assign s_axi4_rdata = m_axi4_rdata;
+#
+# assign s_axi4_ruser = dropping ? {AXI_USER_WIDTH{1'b0}} : m_axi4_ruser;
+# assign s_axi4_rid = dropping ? id : m_axi4_rid;
+#
+# assign s_axi4_rresp = (dropping & prefetch & hit) ? 2'b00 : // prefetch hit, mutli, prot
+# (dropping & prefetch ) ? 2'b10 : // prefetch miss
+# (dropping & hit) ? 2'b10 : // non-prefetch multi, prot
+# (dropping ) ? 2'b10 : // non-prefetch miss
+# m_axi4_rresp;
+#
+# assign s_axi4_rvalid = dropping | m_axi4_rvalid;
+# assign m_axi4_rready = ~dropping & s_axi4_rready;
+#
+# always_ff @(posedge axi4_aclk, negedge axi4_arstn) begin
+# if (axi4_arstn == 1'b0) begin
+# burst_ongoing_q <= 1'b0;
+# drop_cnt_q <= 'b0;
+# state_q <= FORWARDING;
+# end else begin
+# burst_ongoing_q <= burst_ongoing_d;
+# drop_cnt_q <= drop_cnt_d;
+# state_q <= state_d;
+# end
+# end
+#
+# endmodule
+#
+#
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+# // 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.
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_w_buffer(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.l1_done_o = Signal() # output
+ self.l1_accept_i = Signal() # input
+ self.l1_save_i = Signal() # input
+ self.l1_drop_i = Signal() # input
+ self.l1_master_i = Signal() # input
+ self.l1_id_i = Signal(AXI_ID_WIDTH) # input
+ self.l1_len_i = Signal(8) # input
+ self.l1_prefetch_i = Signal() # input
+ self.l1_hit_i = Signal() # input
+ self.l2_done_o = Signal() # output
+ self.l2_accept_i = Signal() # input
+ self.l2_drop_i = Signal() # input
+ self.l2_master_i = Signal() # input
+ self.l2_id_i = Signal(AXI_ID_WIDTH) # input
+ self.l2_len_i = Signal(8) # input
+ self.l2_prefetch_i = Signal() # input
+ self.l2_hit_i = Signal() # input
+ self.master_select_o = Signal() # output
+ self.input_stall_o = Signal() # output
+ self.output_stall_o = Signal() # output
+ self.b_drop_o = Signal() # output
+ self.b_done_i = Signal() # input
+ self.id_o = Signal(AXI_ID_WIDTH) # output
+ self.prefetch_o = Signal() # output
+ self.hit_o = Signal() # output
+ self.s_axi4_wdata = Signal(AXI_DATA_WIDTH) # input
+ self.s_axi4_wvalid = Signal() # input
+ self.s_axi4_wready = Signal() # output
+ self.s_axi4_wstrb = Signal(1+ERROR p_expression_25) # input
+ self.s_axi4_wlast = Signal() # input
+ self.s_axi4_wuser = Signal(AXI_USER_WIDTH) # input
+ self.m_axi4_wdata = Signal(AXI_DATA_WIDTH) # output
+ self.m_axi4_wvalid = Signal() # output
+ self.m_axi4_wready = Signal() # input
+ self.m_axi4_wstrb = Signal(1+ERROR p_expression_25) # output
+ self.m_axi4_wlast = Signal() # output
+ self.m_axi4_wuser = Signal(AXI_USER_WIDTH) # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ return m
+
+
+#
+# //import CfMath::log2;
+#
+# module axi4_w_buffer
+# #(
+# parameter AXI_DATA_WIDTH = 32,
+# parameter AXI_ID_WIDTH = 4,
+# parameter AXI_USER_WIDTH = 4,
+# parameter ENABLE_L2TLB = 0,
+# parameter HUM_BUFFER_DEPTH = 16
+# )
+# (
+# input logic axi4_aclk,
+# input logic axi4_arstn,
+#
+# // L1 & L2 interfaces
+# output logic l1_done_o,
+# input logic l1_accept_i,
+# input logic l1_save_i,
+# input logic l1_drop_i,
+# input logic l1_master_i,
+# input logic [AXI_ID_WIDTH-1:0] l1_id_i,
+# input logic [7:0] l1_len_i,
+# input logic l1_prefetch_i,
+# input logic l1_hit_i,
+#
+# output logic l2_done_o,
+# input logic l2_accept_i,
+# input logic l2_drop_i,
+# input logic l2_master_i,
+# input logic [AXI_ID_WIDTH-1:0] l2_id_i,
+# input logic [7:0] l2_len_i,
+# input logic l2_prefetch_i,
+# input logic l2_hit_i,
+#
+# output logic master_select_o,
+# output logic input_stall_o,
+# output logic output_stall_o,
+#
+# // B sender interface
+# output logic b_drop_o,
+# input logic b_done_i,
+# output logic [AXI_ID_WIDTH-1:0] id_o,
+# output logic prefetch_o,
+# output logic hit_o,
+#
+# // AXI W channel interfaces
+# input logic [AXI_DATA_WIDTH-1:0] s_axi4_wdata,
+# input logic s_axi4_wvalid,
+# output logic s_axi4_wready,
+# input logic [AXI_DATA_WIDTH/8-1:0] s_axi4_wstrb,
+# input logic s_axi4_wlast,
+# input logic [AXI_USER_WIDTH-1:0] s_axi4_wuser,
+#
+# output logic [AXI_DATA_WIDTH-1:0] m_axi4_wdata,
+# output logic m_axi4_wvalid,
+# input logic m_axi4_wready,
+# output logic [AXI_DATA_WIDTH/8-1:0] m_axi4_wstrb,
+# output logic m_axi4_wlast,
+# output logic [AXI_USER_WIDTH-1:0] m_axi4_wuser
+# );
+#
+"""
+
+ localparam BUFFER_WIDTH = AXI_DATA_WIDTH+AXI_USER_WIDTH+AXI_DATA_WIDTH/8+1;
+
+ localparam INPUT_BUFFER_DEPTH = 4;
+ localparam L1_FIFO_DEPTH = 8;
+ localparam L2_FIFO_DEPTH = 4;
+
+ logic [AXI_DATA_WIDTH-1:0] axi4_wdata;
+ logic axi4_wvalid;
+ logic axi4_wready;
+ logic [AXI_DATA_WIDTH/8-1:0] axi4_wstrb;
+ logic axi4_wlast;
+ logic [AXI_USER_WIDTH-1:0] axi4_wuser;
+
+ logic l1_fifo_valid_out;
+ logic l1_fifo_ready_in;
+ logic l1_fifo_valid_in;
+ logic l1_fifo_ready_out;
+
+ logic l1_req;
+ logic l1_accept_cur, l1_save_cur, l1_drop_cur;
+ logic l1_master_cur;
+ logic [AXI_ID_WIDTH-1:0] l1_id_cur;
+ logic [7:0] l1_len_cur;
+ logic l1_hit_cur, l1_prefetch_cur;
+ logic l1_save_in, l1_save_out;
+ logic [log2(L1_FIFO_DEPTH)-1:0] n_l1_save_SP;
+
+ logic l2_fifo_valid_out;
+ logic l2_fifo_ready_in;
+ logic l2_fifo_valid_in;
+ logic l2_fifo_ready_out;
+
+ logic l2_req;
+ logic l2_accept_cur, l2_drop_cur;
+ logic l2_master_cur;
+ logic [AXI_ID_WIDTH-1:0] l2_id_cur;
+ logic [7:0] l2_len_cur;
+ logic l2_hit_cur, l2_prefetch_cur;
+
+ logic fifo_select, fifo_select_SN, fifo_select_SP;
+ logic w_done;
+ logic b_drop_set;
+
+ // HUM buffer signals
+ logic hum_buf_ready_out;
+ logic hum_buf_valid_in;
+ logic hum_buf_ready_in;
+ logic hum_buf_valid_out;
+ logic hum_buf_underfull;
+
+ logic [AXI_DATA_WIDTH-1:0] hum_buf_wdata;
+ logic [AXI_DATA_WIDTH/8-1:0] hum_buf_wstrb;
+ logic hum_buf_wlast;
+ logic [AXI_USER_WIDTH-1:0] hum_buf_wuser;
+
+ logic hum_buf_drop_req_SN, hum_buf_drop_req_SP;
+ logic [7:0] hum_buf_drop_len_SN, hum_buf_drop_len_SP;
+ logic hum_buf_almost_full;
+
+ logic stop_store;
+ logic wlast_in, wlast_out;
+ logic signed [3:0] n_wlast_SN, n_wlast_SP;
+ logic block_forwarding;
+
+ // Search FSM
+ typedef enum logic [3:0] {STORE, BYPASS,
+ WAIT_L1_BYPASS_YES, WAIT_L2_BYPASS_YES,
+ WAIT_L1_BYPASS_NO, WAIT_L2_BYPASS_NO,
+ FLUSH, DISCARD,
+ DISCARD_FINISH}
+ hum_buf_state_t;
+ hum_buf_state_t hum_buf_SP; // Present state
+ hum_buf_state_tbg hum_buf_SN; // Next State
+
+ axi_buffer_rab
+ #(
+ .DATA_WIDTH ( BUFFER_WIDTH ),
+ .BUFFER_DEPTH ( INPUT_BUFFER_DEPTH )
+ )
+ u_input_buf
+ (
+ .clk ( axi4_aclk ),
+ .rstn ( axi4_arstn ),
+ // Push
+ .data_in ( {s_axi4_wuser, s_axi4_wstrb, s_axi4_wdata, s_axi4_wlast} ),
+ .valid_in ( s_axi4_wvalid ),
+ .ready_out ( s_axi4_wready ),
+ // Pop
+ .data_out ( {axi4_wuser, axi4_wstrb, axi4_wdata, axi4_wlast} ),
+ .valid_out ( axi4_wvalid ),
+ .ready_in ( axi4_wready )
+ );
+
+ axi_buffer_rab
+ #(
+ .DATA_WIDTH ( 2+AXI_ID_WIDTH+8+4 ),
+ .BUFFER_DEPTH ( L1_FIFO_DEPTH )
+ )
+ u_l1_fifo
+ (
+ .clk ( axi4_aclk ),
+ .rstn ( axi4_arstn ),
+ // Push
+ .data_in ( {l1_prefetch_i, l1_hit_i, l1_id_i, l1_len_i, l1_master_i, l1_accept_i, l1_save_i, l1_drop_i} ),
+ .valid_in ( l1_fifo_valid_in ),
+ .ready_out ( l1_fifo_ready_out ),
+ // Pop
+ .data_out ( {l1_prefetch_cur, l1_hit_cur, l1_id_cur, l1_len_cur, l1_master_cur, l1_accept_cur, l1_save_cur, l1_drop_cur} ),
+ .valid_out ( l1_fifo_valid_out ),
+ .ready_in ( l1_fifo_ready_in )
+ );
+
+ // Push upon receiving new requests from the TLB.
+ assign l1_req = l1_accept_i | l1_save_i | l1_drop_i;
+ assign l1_fifo_valid_in = l1_req & l1_fifo_ready_out;
+
+ // Signal handshake
+ assign l1_done_o = l1_fifo_valid_in;
+ assign l2_done_o = l2_fifo_valid_in;
+
+ // Stall AW input of L1 TLB
+ assign input_stall_o = ~(l1_fifo_ready_out & l2_fifo_ready_out);
+
+ // Interface b_drop signals + handshake
+ always_comb begin
+ if (fifo_select == 1'b0) begin
+ prefetch_o = l1_prefetch_cur;
+ hit_o = l1_hit_cur;
+ id_o = l1_id_cur;
+
+ l1_fifo_ready_in = w_done | b_done_i;
+ l2_fifo_ready_in = 1'b0;
+ end else begin
+ prefetch_o = l2_prefetch_cur;
+ hit_o = l2_hit_cur;
+ id_o = l2_id_cur;
+
+ l1_fifo_ready_in = 1'b0;
+ l2_fifo_ready_in = w_done | b_done_i;
+ end
+ end
+
+ // Detect when an L1 transaction save request enters or exits the L1 FIFO.
+ assign l1_save_in = l1_fifo_valid_in & l1_save_i;
+ assign l1_save_out = l1_fifo_ready_in & l1_save_cur;
+
+ // Count the number of L1 transaction to save in the L1 FIFO.
+ always_ff @(posedge axi4_aclk or negedge axi4_arstn) begin
+ if (axi4_arstn == 0) begin
+ n_l1_save_SP <= '0;
+ end else if (l1_save_in ^ l1_save_out) begin
+ if (l1_save_in) begin
+ n_l1_save_SP <= n_l1_save_SP + 1'b1;
+ end else if (l1_save_out) begin
+ n_l1_save_SP <= n_l1_save_SP - 1'b1;
+ end
+ end
+ end
+
+ // Stall forwarding of AW L1 hits if:
+ // 1. The HUM buffer does not allow to be bypassed.
+ // 2. There are multiple L1 save requests in the FIFO, i.e., multiple L2 outputs pending.
+ assign output_stall_o = (n_l1_save_SP > 1) || (block_forwarding == 1'b1);
+
+ generate
+ if (ENABLE_L2TLB == 1) begin : HUM_BUFFER
+
+ axi_buffer_rab_bram
+ #(
+ .DATA_WIDTH ( BUFFER_WIDTH ),
+ .BUFFER_DEPTH ( HUM_BUFFER_DEPTH )
+ )
+ u_hum_buf
+ (
+ .clk ( axi4_aclk ),
+ .rstn ( axi4_arstn ),
+ // Push
+ .data_in ( {axi4_wuser, axi4_wstrb, axi4_wdata, axi4_wlast} ),
+ .valid_in ( hum_buf_valid_in ),
+ .ready_out ( hum_buf_ready_out ),
+ // Pop
+ .data_out ( {hum_buf_wuser, hum_buf_wstrb, hum_buf_wdata, hum_buf_wlast} ),
+ .valid_out ( hum_buf_valid_out ),
+ .ready_in ( hum_buf_ready_in ),
+ // Clear
+ .almost_full ( hum_buf_almost_full ),
+ .underfull ( hum_buf_underfull ),
+ .drop_req ( hum_buf_drop_req_SP ),
+ .drop_len ( hum_buf_drop_len_SP )
+ );
+
+ axi_buffer_rab
+ #(
+ .DATA_WIDTH ( 2+AXI_ID_WIDTH+8+3 ),
+ .BUFFER_DEPTH ( L2_FIFO_DEPTH )
+ )
+ u_l2_fifo
+ (
+ .clk ( axi4_aclk ),
+ .rstn ( axi4_arstn ),
+ // Push
+ .data_in ( {l2_prefetch_i, l2_hit_i, l2_id_i, l2_len_i, l2_master_i, l2_accept_i, l2_drop_i} ),
+ .valid_in ( l2_fifo_valid_in ),
+ .ready_out ( l2_fifo_ready_out ),
+ // Pop
+ .data_out ( {l2_prefetch_cur, l2_hit_cur, l2_id_cur, l2_len_cur, l2_master_cur, l2_accept_cur, l2_drop_cur} ),
+ .valid_out ( l2_fifo_valid_out ),
+ .ready_in ( l2_fifo_ready_in )
+ );
+
+ // Push upon receiving new result from TLB.
+ assign l2_req = l2_accept_i | l2_drop_i;
+ assign l2_fifo_valid_in = l2_req & l2_fifo_ready_out;
+
+ assign wlast_in = axi4_wlast & hum_buf_valid_in & hum_buf_ready_out;
+ assign wlast_out = hum_buf_wlast & hum_buf_valid_out & hum_buf_ready_in;
+
+ always_ff @(posedge axi4_aclk or negedge axi4_arstn) begin
+ if (axi4_arstn == 0) begin
+ fifo_select_SP <= 1'b0;
+ hum_buf_drop_len_SP <= 'b0;
+ hum_buf_drop_req_SP <= 1'b0;
+ hum_buf_SP <= STORE;
+ n_wlast_SP <= 'b0;
+ end else begin
+ fifo_select_SP <= fifo_select_SN;
+ hum_buf_drop_len_SP <= hum_buf_drop_len_SN;
+ hum_buf_drop_req_SP <= hum_buf_drop_req_SN;
+ hum_buf_SP <= hum_buf_SN;
+ n_wlast_SP <= n_wlast_SN;
+ end
+ end
+
+ always_comb begin
+ n_wlast_SN = n_wlast_SP;
+ if (hum_buf_drop_req_SP) begin // Happens exactly once per burst to be dropped.
+ n_wlast_SN -= 1;
+ end
+ if (wlast_in) begin
+ n_wlast_SN += 1;
+ end
+ if (wlast_out) begin
+ n_wlast_SN -= 1;
+ end
+ end
+
+ always_comb begin : HUM_BUFFER_FSM
+ hum_buf_SN = hum_buf_SP;
+
+ m_axi4_wlast = 1'b0;
+ m_axi4_wdata = 'b0;
+ m_axi4_wstrb = 'b0;
+ m_axi4_wuser = 'b0;
+
+ m_axi4_wvalid = 1'b0;
+ axi4_wready = 1'b0;
+
+ hum_buf_valid_in = 1'b0;
+ hum_buf_ready_in = 1'b0;
+
+ hum_buf_drop_req_SN = hum_buf_drop_req_SP;
+ hum_buf_drop_len_SN = hum_buf_drop_len_SP;
+ master_select_o = 1'b0;
+
+ w_done = 1'b0; // read from FIFO without handshake with B sender
+ b_drop_o = 1'b0; // send data from FIFO to B sender (with handshake)
+ fifo_select = 1'b0;
+
+ fifo_select_SN = fifo_select_SP;
+ stop_store = 1'b0;
+
+ block_forwarding = 1'b0;
+
+ unique case (hum_buf_SP)
+
+ STORE : begin
+ // Simply store the data in the buffer.
+ hum_buf_valid_in = axi4_wvalid & hum_buf_ready_out;
+ axi4_wready = hum_buf_ready_out;
+
+ // We have got a full burst in the HUM buffer, thus stop storing.
+ if (wlast_in & !hum_buf_underfull | (n_wlast_SP > $signed(0))) begin
+ hum_buf_SN = WAIT_L1_BYPASS_YES;
+
+ // The buffer is full, thus wait for decision.
+ end else if (~hum_buf_ready_out) begin
+ hum_buf_SN = WAIT_L1_BYPASS_NO;
+ end
+
+ // Avoid the forwarding of L1 hits until we know whether we can bypass.
+ if (l1_fifo_valid_out & l1_save_cur) begin
+ block_forwarding = 1'b1;
+ end
+ end
+
+ WAIT_L1_BYPASS_YES : begin
+ // Wait for orders from L1 TLB.
+ if (l1_fifo_valid_out) begin
+
+ // L1 hit - forward data from buffer
+ if (l1_accept_cur) begin
+ m_axi4_wlast = hum_buf_wlast;
+ m_axi4_wdata = hum_buf_wdata;
+ m_axi4_wstrb = hum_buf_wstrb;
+ m_axi4_wuser = hum_buf_wuser;
+
+ m_axi4_wvalid = hum_buf_valid_out;
+ hum_buf_ready_in = m_axi4_wready;
+
+ master_select_o = l1_master_cur;
+
+ // Detect last data beat.
+ if (wlast_out) begin
+ fifo_select = 1'b0;
+ w_done = 1'b1;
+ hum_buf_SN = STORE;
+ end
+
+ // L1 miss - wait for L2
+ end else if (l1_save_cur) begin
+ fifo_select = 1'b0;
+ w_done = 1'b1;
+ hum_buf_SN = WAIT_L2_BYPASS_YES;
+
+ // L1 prefetch, prot, multi - drop data
+ end else if (l1_drop_cur) begin
+ fifo_select_SN = 1'b0; // L1
+ hum_buf_drop_req_SN = 1'b1;
+ hum_buf_drop_len_SN = l1_len_cur;
+ hum_buf_SN = FLUSH;
+ end
+ end
+ end
+
+ WAIT_L2_BYPASS_YES : begin
+ // Wait for orders from L2 TLB.
+ if (l2_fifo_valid_out) begin
+
+ // L2 hit - forward data from buffer
+ if (l2_accept_cur) begin
+ m_axi4_wlast = hum_buf_wlast;
+ m_axi4_wdata = hum_buf_wdata;
+ m_axi4_wstrb = hum_buf_wstrb;
+ m_axi4_wuser = hum_buf_wuser;
+
+ m_axi4_wvalid = hum_buf_valid_out;
+ hum_buf_ready_in = m_axi4_wready;
+
+ master_select_o = l2_master_cur;
+
+ // Detect last data beat.
+ if (wlast_out) begin
+ fifo_select = 1'b1;
+ w_done = 1'b1;
+ hum_buf_SN = STORE;
+ end
+
+ // L2 miss/prefetch hit
+ end else if (l2_drop_cur) begin
+ fifo_select_SN = 1'b1; // L2
+ hum_buf_drop_req_SN = 1'b1;
+ hum_buf_drop_len_SN = l2_len_cur;
+ hum_buf_SN = FLUSH;
+ end
+
+ // While we wait for orders from L2 TLB, we can still drop and accept L1 transactions.
+ end else if (l1_fifo_valid_out) begin
+
+ // L1 hit
+ if (l1_accept_cur) begin
+ hum_buf_SN = BYPASS;
+
+ // L1 prefetch/prot/multi
+ end else if (l1_drop_cur) begin
+ hum_buf_SN = DISCARD;
+ end
+ end
+ end
+
+ FLUSH : begin
+ // Clear HUM buffer flush request.
+ hum_buf_drop_req_SN = 1'b0;
+
+ // perform handshake with B sender
+ fifo_select = fifo_select_SP;
+ b_drop_o = 1'b1;
+ if (b_done_i) begin
+ hum_buf_SN = STORE;
+ end
+ end
+
+ BYPASS : begin
+ // Forward one full transaction from input buffer.
+ m_axi4_wlast = axi4_wlast;
+ m_axi4_wdata = axi4_wdata;
+ m_axi4_wstrb = axi4_wstrb;
+ m_axi4_wuser = axi4_wuser;
+
+ m_axi4_wvalid = axi4_wvalid;
+ axi4_wready = m_axi4_wready;
+
+ master_select_o = l1_master_cur;
+
+ // We have got a full transaction.
+ if (axi4_wlast & axi4_wready & axi4_wvalid) begin
+ fifo_select = 1'b0;
+ w_done = 1'b1;
+ hum_buf_SN = WAIT_L2_BYPASS_YES;
+ end
+ end
+
+ DISCARD : begin
+ // Discard one full transaction from input buffer.
+ axi4_wready = 1'b1;
+
+ // We have got a full transaction.
+ if (axi4_wlast & axi4_wready & axi4_wvalid) begin
+ // Try to perform handshake with B sender.
+ fifo_select = 1'b0;
+ b_drop_o = 1'b1;
+ // We cannot wait here due to axi4_wready.
+ if (b_done_i) begin
+ hum_buf_SN = WAIT_L2_BYPASS_YES;
+ end else begin
+ hum_buf_SN = DISCARD_FINISH;
+ end
+ end
+ end
+
+ DISCARD_FINISH : begin
+ // Perform handshake with B sender.
+ fifo_select = 1'b0;
+ b_drop_o = 1'b1;
+ if (b_done_i) begin
+ hum_buf_SN = WAIT_L2_BYPASS_YES;
+ end
+ end
+
+ WAIT_L1_BYPASS_NO : begin
+ // Do not allow the forwarding of L1 hits.
+ block_forwarding = 1'b1;
+
+ // Wait for orders from L1 TLB.
+ if (l1_fifo_valid_out) begin
+
+ // L1 hit - forward data from/through HUM buffer and refill the buffer
+ if (l1_accept_cur) begin
+ // Forward data from HUM buffer.
+ m_axi4_wlast = hum_buf_wlast;
+ m_axi4_wdata = hum_buf_wdata;
+ m_axi4_wstrb = hum_buf_wstrb;
+ m_axi4_wuser = hum_buf_wuser;
+
+ m_axi4_wvalid = hum_buf_valid_out;
+ hum_buf_ready_in = m_axi4_wready;
+
+ master_select_o = l1_master_cur;
+
+ // Refill the HUM buffer. Stop when buffer full.
+ stop_store = ~hum_buf_ready_out;
+ hum_buf_valid_in = stop_store ? 1'b0 : axi4_wvalid ;
+ axi4_wready = stop_store ? 1'b0 : hum_buf_ready_out;
+
+ // Detect last data beat.
+ if (wlast_out) begin
+ fifo_select = 1'b0;
+ w_done = 1'b1;
+ if (~hum_buf_ready_out | hum_buf_almost_full) begin
+ hum_buf_SN = WAIT_L1_BYPASS_NO;
+ end else begin
+ hum_buf_SN = STORE;
+ end
+ end
+
+ // Allow the forwarding of L1 hits.
+ block_forwarding = 1'b0;
+
+ // L1 miss - wait for L2
+ end else if (l1_save_cur) begin
+ fifo_select = 1'b0;
+ w_done = 1'b1;
+ hum_buf_SN = WAIT_L2_BYPASS_NO;
+
+ // L1 prefetch, prot, multi - drop data
+ end else if (l1_drop_cur) begin
+ fifo_select_SN = 1'b0; // L1
+ hum_buf_drop_req_SN = 1'b1;
+ hum_buf_drop_len_SN = l1_len_cur;
+ hum_buf_SN = FLUSH;
+
+ // Allow the forwarding of L1 hits.
+ block_forwarding = 1'b0;
+ end
+ end
+ end
+
+ WAIT_L2_BYPASS_NO : begin
+ // Do not allow the forwarding of L1 hits.
+ block_forwarding = 1'b1;
+
+ // Wait for orders from L2 TLB.
+ if (l2_fifo_valid_out) begin
+
+ // L2 hit - forward first part from HUM buffer, rest from input buffer
+ if (l2_accept_cur) begin
+ // Forward data from HUM buffer.
+ m_axi4_wlast = hum_buf_wlast;
+ m_axi4_wdata = hum_buf_wdata;
+ m_axi4_wstrb = hum_buf_wstrb;
+ m_axi4_wuser = hum_buf_wuser;
+
+ m_axi4_wvalid = hum_buf_valid_out;
+ hum_buf_ready_in = m_axi4_wready;
+
+ master_select_o = l2_master_cur;
+
+ // Refill the HUM buffer. Stop when buffer full.
+ stop_store = ~hum_buf_ready_out;
+ hum_buf_valid_in = stop_store ? 1'b0 : axi4_wvalid ;
+ axi4_wready = stop_store ? 1'b0 : hum_buf_ready_out;
+
+ // Detect last data beat.
+ if (wlast_out) begin
+ fifo_select = 1'b1;
+ w_done = 1'b1;
+ if (~hum_buf_ready_out | hum_buf_almost_full) begin
+ hum_buf_SN = WAIT_L1_BYPASS_NO;
+ end else begin
+ hum_buf_SN = STORE;
+ end
+ end
+
+ // Allow the forwarding of L1 hits.
+ block_forwarding = 1'b0;
+
+ // L2 miss/prefetch hit - drop data
+ end else if (l2_drop_cur) begin
+ fifo_select_SN = 1'b1; // L2
+ hum_buf_drop_req_SN = 1'b1;
+ hum_buf_drop_len_SN = l2_len_cur;
+ hum_buf_SN = FLUSH;
+
+ // Allow the forwarding of L1 hits.
+ block_forwarding = 1'b0;
+ end
+ end
+ end
+
+
+ default: begin
+ hum_buf_SN = STORE;
+ end
+
+ endcase // hum_buf_SP
+ end // HUM_BUFFER_FSM
+
+ assign b_drop_set = 1'b0;
+
+ end else begin // HUM_BUFFER
+
+ // register to perform the handshake with B sender
+ always_ff @(posedge axi4_aclk or negedge axi4_arstn) begin
+ if (axi4_arstn == 0) begin
+ b_drop_o <= 1'b0;
+ end else if (b_done_i) begin
+ b_drop_o <= 1'b0;
+ end else if (b_drop_set) begin
+ b_drop_o <= 1'b1;;
+ end
+ end
+
+ always_comb begin : OUTPUT_CTRL
+
+ fifo_select = 1'b0;
+ w_done = 1'b0;
+ b_drop_set = 1'b0;
+
+ m_axi4_wlast = 1'b0;
+ m_axi4_wdata = 'b0;
+ m_axi4_wstrb = 'b0;
+ m_axi4_wuser = 'b0;
+
+ m_axi4_wvalid = 1'b0;
+ axi4_wready = 1'b0;
+
+ if (l1_fifo_valid_out) begin
+ // forward data
+ if (l1_accept_cur) begin
+ m_axi4_wlast = axi4_wlast;
+ m_axi4_wdata = axi4_wdata;
+ m_axi4_wstrb = axi4_wstrb;
+ m_axi4_wuser = axi4_wuser;
+
+ m_axi4_wvalid = axi4_wvalid;
+ axi4_wready = m_axi4_wready;
+
+ // Simply pop from FIFO upon last data beat.
+ w_done = axi4_wlast & axi4_wvalid & axi4_wready;
+
+ // discard entire burst
+ end else if (b_drop_o == 1'b0) begin
+ axi4_wready = 1'b1;
+
+ // Simply pop from FIFO upon last data beat. Perform handshake with B sender.
+ if (axi4_wlast & axi4_wvalid & axi4_wready)
+ b_drop_set = 1'b1;
+ end
+ end
+
+ end // OUTPUT_CTRL
+
+ assign master_select_o = l1_master_cur;
+ assign l2_fifo_ready_out = 1'b1;
+ assign block_forwarding = 1'b0;
+
+ // unused signals
+ assign hum_buf_ready_out = 1'b0;
+ assign hum_buf_valid_in = 1'b0;
+ assign hum_buf_ready_in = 1'b0;
+ assign hum_buf_valid_out = 1'b0;
+ assign hum_buf_wdata = 'b0;
+ assign hum_buf_wstrb = 'b0;
+ assign hum_buf_wlast = 1'b0;
+ assign hum_buf_wuser = 'b0;
+ assign hum_buf_drop_len_SN = 'b0;
+ assign hum_buf_drop_req_SN = 1'b0;
+ assign hum_buf_almost_full = 1'b0;
+
+ assign l2_fifo_valid_in = 1'b0;
+ assign l2_fifo_valid_out = 1'b0;
+ assign l2_prefetch_cur = 1'b0;
+ assign l2_hit_cur = 1'b0;
+ assign l2_id_cur = 'b0;
+ assign l2_len_cur = 'b0;
+ assign l2_master_cur = 1'b0;
+ assign l2_accept_cur = 1'b0;
+ assign l2_drop_cur = 1'b0;
+
+ assign l2_req = 1'b0;
+
+ assign fifo_select_SN = 1'b0;
+ assign fifo_select_SP = 1'b0;
+
+ assign stop_store = 1'b0;
+ assign n_wlast_SP = 'b0;
+ assign wlast_in = 1'b0;
+ assign wlast_out = 1'b0;
+
+ end // HUM_BUFFER
+
+ endgenerate
+"""
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi4_w_sender(Elaboratable):
+
+ def __init__(self):
+ self.axi4_aclk = Signal() # input
+ self.axi4_arstn = Signal() # input
+ self.s_axi4_wdata = Signal() # input
+ self.s_axi4_wvalid = Signal() # input
+ self.s_axi4_wready = Signal() # output
+ self.s_axi4_wstrb = Signal() # input
+ self.s_axi4_wlast = Signal() # input
+ self.s_axi4_wuser = Signal() # input
+ self.m_axi4_wdata = Signal() # output
+ self.m_axi4_wvalid = Signal() # output
+ self.m_axi4_wready = Signal() # input
+ self.m_axi4_wstrb = Signal() # output
+ self.m_axi4_wlast = Signal() # output
+ self.m_axi4_wuser = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.m_axi4_wdata.eq(self.s_axi4_wdata)
+ m.d.comb += self.m_axi4_wstrb.eq(self.s_axi4_wstrb)
+ m.d.comb += self.m_axi4_wlast.eq(self.s_axi4_wlast)
+ m.d.comb += self.m_axi4_wuser.eq(self.s_axi4_wuser)
+ m.d.comb += self.m_axi4_wvalid.eq(self.s_axi4_wvalid)
+ m.d.comb += self.s_axi4_wready.eq(self.m_axi4_wready)
+ return m
+
+# // 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.
+#
+# module axi4_w_sender
+# #(
+# parameter AXI_DATA_WIDTH = 32,
+# parameter AXI_USER_WIDTH = 2
+# )
+# (
+# input axi4_aclk,
+# input axi4_arstn,
+#
+# input [AXI_DATA_WIDTH-1:0] s_axi4_wdata,
+# input s_axi4_wvalid,
+# output s_axi4_wready,
+# input [AXI_DATA_WIDTH/8-1:0] s_axi4_wstrb,
+# input s_axi4_wlast,
+# input [AXI_USER_WIDTH-1:0] s_axi4_wuser,
+#
+# output [AXI_DATA_WIDTH-1:0] m_axi4_wdata,
+# output m_axi4_wvalid,
+# input m_axi4_wready,
+# output [AXI_DATA_WIDTH/8-1:0] m_axi4_wstrb,
+# output m_axi4_wlast,
+# output [AXI_USER_WIDTH-1:0] m_axi4_wuser
+# );
+#
+# assign m_axi4_wdata = s_axi4_wdata;
+# assign m_axi4_wstrb = s_axi4_wstrb;
+# assign m_axi4_wlast = s_axi4_wlast;
+# assign m_axi4_wuser = s_axi4_wuser;
+#
+# assign m_axi4_wvalid = s_axi4_wvalid;
+# assign s_axi4_wready = m_axi4_wready;
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi_buffer_rab(Elaboratable):
+
+ def __init__(self):
+ self.clk = Signal() # input
+ self.rstn = Signal() # input
+ self.data_out = Signal(DATA_WIDTH) # output
+ self.valid_out = Signal() # output
+ self.ready_in = Signal() # input
+ self.valid_in = Signal() # input
+ self.data_in = Signal(DATA_WIDTH) # input
+ self.ready_out = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.full.eq(self.None)
+ m.d.comb += self.data_out.eq(self.None)
+ m.d.comb += self.valid_out.eq(self.None)
+ m.d.comb += self.ready_out.eq(self.None)
+ return m
+
+# // 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.
+#
+# //import CfMath::log2;
+#
+# module axi_buffer_rab
+# //#(
+# // parameter DATA_WIDTH,
+# // parameter BUFFER_DEPTH
+# //)
+# (
+# input logic clk,
+# input logic rstn,
+#
+# // Downstream port
+# output logic [DATA_WIDTH-1:0] data_out,
+# output logic valid_out,
+# input logic ready_in,
+#
+# // Upstream port
+# input logic valid_in,
+# input logic [DATA_WIDTH-1:0] data_in,
+# output logic ready_out
+# );
+#
+# localparam integer LOG_BUFFER_DEPTH = log2(BUFFER_DEPTH);
+#
+# // Internal data structures
+# reg [LOG_BUFFER_DEPTH - 1 : 0] pointer_in; // location to which we last wrote
+# reg [LOG_BUFFER_DEPTH - 1 : 0] pointer_out; // location from which we last sent
+# reg [LOG_BUFFER_DEPTH : 0] elements; // number of elements in the buffer
+# reg [DATA_WIDTH - 1 : 0] buffer [BUFFER_DEPTH - 1 : 0];
+#
+# wire full;
+#
+# integer loop1;
+#
+# assign full = (elements == BUFFER_DEPTH);
+#
+# always @(posedge clk or negedge rstn)
+# begin: elements_sequential
+# if (rstn == 1'b0)
+# elements <= 0;
+# else
+# begin
+# // ------------------
+# // Are we filling up?
+# // ------------------
+# // One out, none in
+# if (ready_in && valid_out && (!valid_in || full))
+# elements <= elements - 1;
+# // None out, one in
+# else if ((!valid_out || !ready_in) && valid_in && !full)
+# elements <= elements + 1;
+# // Else, either one out and one in, or none out and none in - stays unchanged
+# end
+# end
+#
+# always @(posedge clk or negedge rstn)
+# begin: buffers_sequential
+# if (rstn == 1'b0)
+# begin
+# for (loop1 = 0 ; loop1 < BUFFER_DEPTH ; loop1 = loop1 + 1)
+# buffer[loop1] <= 0;
+# end
+# else
+# begin
+# // Update the memory
+# if (valid_in && !full)
+# buffer[pointer_in] <= data_in;
+# end
+# end
+#
+# always @(posedge clk or negedge rstn)
+# begin: sequential
+# if (rstn == 1'b0)
+# begin
+# pointer_out <= 0;
+# pointer_in <= 0;
+# end
+# else
+# begin
+# // ------------------------------------
+# // Check what to do with the input side
+# // ------------------------------------
+# // We have some input, increase by 1 the input pointer
+# if (valid_in && !full)
+# begin
+# if (pointer_in == $unsigned(BUFFER_DEPTH - 1))
+# pointer_in <= 0;
+# else
+# pointer_in <= pointer_in + 1;
+# end
+# // Else we don't have any input, the input pointer stays the same
+#
+# // -------------------------------------
+# // Check what to do with the output side
+# // -------------------------------------
+# // We had pushed one flit out, we can try to go for the next one
+# if (ready_in && valid_out)
+# begin
+# if (pointer_out == $unsigned(BUFFER_DEPTH - 1))
+# pointer_out <= 0;
+# else
+# pointer_out <= pointer_out + 1;
+# end
+# // Else stay on the same output location
+# end
+# end
+#
+# // Update output ports
+# assign data_out = buffer[pointer_out];
+# assign valid_out = (elements != 0);
+#
+# assign ready_out = ~full;
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi_buffer_rab_bram(Elaboratable):
+
+ def __init__(self):
+ self.clk = Signal() # input
+ self.rstn = Signal() # input
+ self.data_out = Signal(DATA_WIDTH) # output
+ self.valid_out = Signal() # output
+ self.ready_in = Signal() # input
+ self.valid_in = Signal() # input
+ self.data_in = Signal(DATA_WIDTH) # input
+ self.ready_out = Signal() # output
+ self.almost_full = Signal() # output
+ self.underfull = Signal() # output
+ self.drop_req = Signal() # input
+ self.drop_len = Signal(8) # input
+
+ def elaborate(self, platform=None):
+ m = Module()
+ return m
+
+
+# // 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.
+#
+# ////import CfMath::log2;
+#
+# module axi_buffer_rab_bram
+# //#(
+# // parameter DATA_WIDTH,
+# // parameter BUFFER_DEPTH
+# // )
+# (
+# input logic clk,
+# input logic rstn,
+#
+# // Downstream port
+# output logic [DATA_WIDTH-1:0] data_out,
+# output logic valid_out,
+# input logic ready_in,
+#
+# // Upstream port
+# input logic valid_in,
+# input logic [DATA_WIDTH-1:0] data_in,
+# output logic ready_out,
+#
+# // Status and drop control
+# output logic almost_full,
+# output logic underfull,
+# input logic drop_req,
+# // Number of items to drop. As for AXI lengths, counting starts at zero, i.e., `drop_len == 0`
+# // and `drop_req` means drop one item.
+# input logic [7:0] drop_len
+# );
+#
+""" #docstring_begin
+ // The BRAM needs to be in "write-first" mode for first-word fall-through FIFO behavior.
+ // To still push and pop simultaneously if the buffer is full, we internally increase the
+ // buffer depth by 1.
+ localparam ACT_BUFFER_DEPTH = BUFFER_DEPTH+1;
+ localparam ACT_LOG_BUFFER_DEPTH = log2(ACT_BUFFER_DEPTH+1);
+
+ /**
+ * Internal data structures
+ */
+ // Location to which we last wrote
+ logic [ACT_LOG_BUFFER_DEPTH-1:0] ptr_in_d, ptr_in_q;
+ // Location from which we last sent
+ logic [ACT_LOG_BUFFER_DEPTH-1:0] ptr_out_d, ptr_out_q;
+ // Required for fall-through behavior on the first word
+ logic [ACT_LOG_BUFFER_DEPTH-1:0] ptr_out_bram;
+ // Number of elements in the buffer. Can be negative if elements that have been dropped have not
+ // yet been written.
+ logic signed [ACT_LOG_BUFFER_DEPTH:0] n_elems_d, n_elems_q;
+
+ logic [DATA_WIDTH-1:0] data_out_bram, data_out_q;
+ logic valid_out_q;
+
+ logic full;
+
+ assign almost_full = (n_elems_q == BUFFER_DEPTH-1);
+ assign full = (n_elems_q == BUFFER_DEPTH);
+
+ always_ff @(posedge clk, negedge rstn) begin
+ if (~rstn) begin
+ n_elems_q <= '0;
+ ptr_in_q <= '0;
+ ptr_out_q <= '0;
+ end else begin
+ n_elems_q <= n_elems_d;
+ ptr_in_q <= ptr_in_d;
+ ptr_out_q <= ptr_out_d;
+ end
+ end
+
+ // Update the number of elements.
+ always_comb begin
+ n_elems_d = n_elems_q;
+ if (drop_req) begin
+ n_elems_d -= (drop_len + 1);
+ end
+ if (valid_in && ready_out) begin
+ n_elems_d += 1;
+ end
+ if (valid_out && ready_in) begin
+ n_elems_d -= 1;
+ end
+ end
+
+ // Update the output pointer.
+ always_comb begin
+ ptr_out_d = ptr_out_q;
+ if (drop_req) begin
+ if ((ptr_out_q + drop_len + 1) > (ACT_BUFFER_DEPTH - 1)) begin
+ ptr_out_d = drop_len + 1 - (ACT_BUFFER_DEPTH - ptr_out_q);
+ end else begin
+ ptr_out_d += (drop_len + 1);
+ end
+ end
+ if (valid_out && ready_in) begin
+ if (ptr_out_d == (ACT_BUFFER_DEPTH - 1)) begin
+ ptr_out_d = '0;
+ end else begin
+ ptr_out_d += 1;
+ end
+ end
+ end
+
+ // The BRAM has a read latency of one cycle, so apply the new address one cycle earlier for
+ // first-word fall-through FIFO behavior.
+ //assign ptr_out_bram = (ptr_out_q == (ACT_BUFFER_DEPTH-1)) ? '0 : (ptr_out_q + 1);
+ assign ptr_out_bram = ptr_out_d;
+
+ // Update the input pointer.
+ always_comb begin
+ ptr_in_d = ptr_in_q;
+ if (valid_in && ready_out) begin
+ if (ptr_in_d == (ACT_BUFFER_DEPTH - 1)) begin
+ ptr_in_d = '0;
+ end else begin
+ ptr_in_d += 1;
+ end
+ end
+ end
+
+ // Update output ports.
+ assign valid_out = (n_elems_q > $signed(0));
+ assign underfull = (n_elems_q < $signed(0));
+ assign ready_out = ~full;
+
+ ram_tp_write_first #(
+ .ADDR_WIDTH ( ACT_LOG_BUFFER_DEPTH ),
+ .DATA_WIDTH ( DATA_WIDTH )
+ )
+ ram_tp_write_first_0
+ (
+ .clk ( clk ),
+ .we ( valid_in & ~full ),
+ .addr0 ( ptr_in_q ),
+ .addr1 ( ptr_out_bram ),
+ .d_i ( data_in ),
+ .d0_o ( ),
+ .d1_o ( data_out_bram )
+ );
+
+ // When reading from/writing two the same address on both ports ("Write-Read Collision"),
+ // the data on the read port is invalid (during the write cycle). In this implementation,
+ // this can happen only when the buffer is empty. Thus, we forward the data from an
+ // register in this case.
+ always @(posedge clk) begin
+ if (rstn == 1'b0) begin
+ data_out_q <= 'b0;
+ end else if ( (ptr_out_bram == ptr_in_q) && (valid_in && !full) ) begin
+ data_out_q <= data_in;
+ end
+ end
+
+ always @(posedge clk) begin
+ if (rstn == 1'b0) begin
+ valid_out_q <= 'b0;
+ end else begin
+ valid_out_q <= valid_out;
+ end
+ end
+
+ // Drive output data
+ always_comb begin
+ if (valid_out && !valid_out_q) begin // We have just written to an empty FIFO
+ data_out = data_out_q;
+ end else begin
+ data_out = data_out_bram;
+ end
+ end
+
+"""
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi_rab_cfg(Elaboratable):
+
+ def __init__(self):
+ self.Clk_CI = Signal() # input
+ self.Rst_RBI = Signal() # input
+ self.s_axi_awaddr = Signal(AXI_ADDR_WIDTH) # input
+ self.s_axi_awvalid = Signal() # input
+ self.s_axi_awready = Signal() # output
+ self.s_axi_wdata = Signal() # input
+ self.s_axi_wstrb = Signal(1+ERROR p_expression_25) # input
+ self.s_axi_wvalid = Signal() # input
+ self.s_axi_wready = Signal() # output
+ self.s_axi_bresp = Signal(2) # output
+ self.s_axi_bvalid = Signal() # output
+ self.s_axi_bready = Signal() # input
+ self.s_axi_araddr = Signal(AXI_ADDR_WIDTH) # input
+ self.s_axi_arvalid = Signal() # input
+ self.s_axi_arready = Signal() # output
+ self.s_axi_rdata = Signal(AXI_DATA_WIDTH) # output
+ self.s_axi_rresp = Signal(2) # output
+ self.s_axi_rvalid = Signal() # output
+ self.s_axi_rready = Signal() # input
+ self.L1Cfg_DO = Signal() # output
+ self.L1AllowMultiHit_SO = Signal() # output
+ self.MissAddr_DI = Signal(ADDR_WIDTH_VIRT) # input
+ self.MissMeta_DI = Signal(MISS_META_WIDTH) # input
+ self.Miss_SI = Signal() # input
+ self.MhFifoFull_SO = Signal() # output
+ self.wdata_l2 = Signal() # output
+ self.waddr_l2 = Signal() # output
+ self.wren_l2 = Signal(N_PORTS) # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ return m
+
+
+# // 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.
+#
+# // --=========================================================================--
+# //
+# // █████╗ ██╗ ██╗██╗ ██████╗ █████╗ ██████╗ ██████╗███████╗ ██████╗
+# // ██╔══██╗╚██╗██╔╝██║ ██╔══██╗██╔══██╗██╔══██╗ ██╔════╝██╔════╝██╔════╝
+# // ███████║ ╚███╔╝ ██║ ██████╔╝███████║██████╔╝ ██║ █████╗ ██║ ███╗
+# // ██╔══██║ ██╔██╗ ██║ ██╔══██╗██╔══██║██╔══██╗ ██║ ██╔══╝ ██║ ██║
+# // ██║ ██║██╔╝ ██╗██║ ██║ ██║██║ ██║██████╔╝ ╚██████╗██║ ╚██████╔╝
+# // ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚═════╝╚═╝ ╚═════╝
+# //
+# //
+# // Author: Pirmin Vogel - vogelpi@iis.ee.ethz.ch
+# //
+# // Purpose : AXI4-Lite configuration and miss handling interface for RAB
+# //
+# // --=========================================================================--
+#
+# //import CfMath::log2;
+#
+# module axi_rab_cfg
+# #(
+# parameter N_PORTS = 3,
+# parameter N_REGS = 196,
+# parameter N_L2_SETS = 32,
+# parameter N_L2_SET_ENTRIES= 32,
+# parameter ADDR_WIDTH_PHYS = 40,
+# parameter ADDR_WIDTH_VIRT = 32,
+# parameter N_FLAGS = 4,
+# parameter AXI_DATA_WIDTH = 64,
+# parameter AXI_ADDR_WIDTH = 32,
+# parameter MISS_META_WIDTH = 10, // <= FIFO_WIDTH
+# parameter MH_FIFO_DEPTH = 16
+# )
+# (
+# input logic Clk_CI,
+# input logic Rst_RBI,
+#
+# // AXI Lite interface
+# input logic [AXI_ADDR_WIDTH-1:0] s_axi_awaddr,
+# input logic s_axi_awvalid,
+# output logic s_axi_awready,
+# input logic [AXI_DATA_WIDTH/8-1:0][7:0] s_axi_wdata,
+# input logic [AXI_DATA_WIDTH/8-1:0] s_axi_wstrb,
+# input logic s_axi_wvalid,
+# output logic s_axi_wready,
+# output logic [1:0] s_axi_bresp,
+# output logic s_axi_bvalid,
+# input logic s_axi_bready,
+# input logic [AXI_ADDR_WIDTH-1:0] s_axi_araddr,
+# input logic s_axi_arvalid,
+# output logic s_axi_arready,
+# output logic [AXI_DATA_WIDTH-1:0] s_axi_rdata,
+# output logic [1:0] s_axi_rresp,
+# output logic s_axi_rvalid,
+# input logic s_axi_rready,
+#
+# // Slice configuration
+# output logic [N_REGS-1:0][63:0] L1Cfg_DO,
+# output logic L1AllowMultiHit_SO,
+#
+# // Miss handling
+# input logic [ADDR_WIDTH_VIRT-1:0] MissAddr_DI,
+# input logic [MISS_META_WIDTH-1:0] MissMeta_DI,
+# input logic Miss_SI,
+# output logic MhFifoFull_SO,
+#
+# // L2 TLB
+# output logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] wdata_l2,
+# output logic [N_PORTS-1:0] [AXI_ADDR_WIDTH-1:0] waddr_l2,
+# output logic [N_PORTS-1:0] wren_l2
+# );
+#
+""" #docstring_begin
+
+ localparam ADDR_LSB = log2(64/8); // 64 even if the AXI Lite interface is 32,
+ // because RAB slices are 64 bit wide.
+ localparam ADDR_MSB = log2(N_REGS)+ADDR_LSB-1;
+
+ localparam L2SINGLE_AMAP_SIZE = 16'h4000; // Maximum 2048 TLB entries in L2
+
+ localparam integer N_L2_ENTRIES = N_L2_SETS * N_L2_SET_ENTRIES;
+
+ localparam logic [AXI_ADDR_WIDTH-1:0] L2_VA_MAX_ADDR = (N_L2_ENTRIES-1) << 2;
+
+ logic [AXI_DATA_WIDTH/8-1:0][7:0] L1Cfg_DP[N_REGS]; // [Byte][Bit]
+ genvar j;
+
+ // █████╗ ██╗ ██╗██╗██╗ ██╗ ██╗ ██╗████████╗███████╗
+ // ██╔══██╗╚██╗██╔╝██║██║ ██║ ██║ ██║╚══██╔══╝██╔════╝
+ // ███████║ ╚███╔╝ ██║███████║█████╗██║ ██║ ██║ █████╗
+ // ██╔══██║ ██╔██╗ ██║╚════██║╚════╝██║ ██║ ██║ ██╔══╝
+ // ██║ ██║██╔╝ ██╗██║ ██║ ███████╗██║ ██║ ███████╗
+ // ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚══════╝
+ //
+ logic [AXI_ADDR_WIDTH-1:0] awaddr_reg;
+ logic awaddr_done_rise;
+ logic awaddr_done_reg;
+ logic awaddr_done_reg_dly;
+
+ logic [AXI_DATA_WIDTH/8-1:0][7:0] wdata_reg;
+ logic [AXI_DATA_WIDTH/8-1:0] wstrb_reg;
+ logic wdata_done_rise;
+ logic wdata_done_reg;
+ logic wdata_done_reg_dly;
+
+ logic wresp_done_reg;
+ logic wresp_running_reg;
+
+ logic [AXI_ADDR_WIDTH-1:0] araddr_reg;
+ logic araddr_done_reg;
+
+ logic [AXI_DATA_WIDTH-1:0] rdata_reg;
+ logic rresp_done_reg;
+ logic rresp_running_reg;
+
+ logic awready;
+ logic wready;
+ logic bvalid;
+
+ logic arready;
+ logic rvalid;
+
+ logic wren;
+ logic wren_l1;
+
+ assign wren = ( wdata_done_rise & awaddr_done_reg ) | ( awaddr_done_rise & wdata_done_reg );
+ assign wdata_done_rise = wdata_done_reg & ~wdata_done_reg_dly;
+ assign awaddr_done_rise = awaddr_done_reg & ~awaddr_done_reg_dly;
+
+ // reg_dly
+ always @(posedge Clk_CI or negedge Rst_RBI)
+ begin
+ if (!Rst_RBI)
+ begin
+ wdata_done_reg_dly <= 1'b0;
+ awaddr_done_reg_dly <= 1'b0;
+ end
+ else
+ begin
+ wdata_done_reg_dly <= wdata_done_reg;
+ awaddr_done_reg_dly <= awaddr_done_reg;
+ end
+ end
+
+ // AW Channel
+ always @(posedge Clk_CI or negedge Rst_RBI)
+ begin
+ if (!Rst_RBI)
+ begin
+ awaddr_done_reg <= 1'b0;
+ awaddr_reg <= '0;
+ awready <= 1'b1;
+ end
+ else
+ begin
+ if (awready && s_axi_awvalid)
+ begin
+ awready <= 1'b0;
+ awaddr_done_reg <= 1'b1;
+ awaddr_reg <= s_axi_awaddr;
+ end
+ else if (awaddr_done_reg && wresp_done_reg)
+ begin
+ awready <= 1'b1;
+ awaddr_done_reg <= 1'b0;
+ end
+ end
+ end
+
+ // W Channel
+ always @(posedge Clk_CI or negedge Rst_RBI)
+ begin
+ if (!Rst_RBI)
+ begin
+ wdata_done_reg <= 1'b0;
+ wready <= 1'b1;
+ wdata_reg <= '0;
+ wstrb_reg <= '0;
+ end
+ else
+ begin
+ if (wready && s_axi_wvalid)
+ begin
+ wready <= 1'b0;
+ wdata_done_reg <= 1'b1;
+ wdata_reg <= s_axi_wdata;
+ wstrb_reg <= s_axi_wstrb;
+ end
+ else if (wdata_done_reg && wresp_done_reg)
+ begin
+ wready <= 1'b1;
+ wdata_done_reg <= 1'b0;
+ end
+ end
+ end
+
+ // B Channel
+ always @(posedge Clk_CI or negedge Rst_RBI)
+ begin
+ if (!Rst_RBI)
+ begin
+ bvalid <= 1'b0;
+ wresp_done_reg <= 1'b0;
+ wresp_running_reg <= 1'b0;
+ end
+ else
+ begin
+ if (awaddr_done_reg && wdata_done_reg && !wresp_done_reg)
+ begin
+ if (!wresp_running_reg)
+ begin
+ bvalid <= 1'b1;
+ wresp_running_reg <= 1'b1;
+ end
+ else if (s_axi_bready)
+ begin
+ bvalid <= 1'b0;
+ wresp_done_reg <= 1'b1;
+ wresp_running_reg <= 1'b0;
+ end
+ end
+ else
+ begin
+ bvalid <= 1'b0;
+ wresp_done_reg <= 1'b0;
+ wresp_running_reg <= 1'b0;
+ end
+ end
+ end
+
+ // AR Channel
+ always @(posedge Clk_CI or negedge Rst_RBI)
+ begin
+ if (!Rst_RBI)
+ begin
+ araddr_done_reg <= 1'b0;
+ arready <= 1'b1;
+ araddr_reg <= '0;
+ end
+ else
+ begin
+ if (arready && s_axi_arvalid)
+ begin
+ arready <= 1'b0;
+ araddr_done_reg <= 1'b1;
+ araddr_reg <= s_axi_araddr;
+ end
+ else if (araddr_done_reg && rresp_done_reg)
+ begin
+ arready <= 1'b1;
+ araddr_done_reg <= 1'b0;
+ end
+ end
+ end
+
+ // R Channel
+ always @(posedge Clk_CI or negedge Rst_RBI)
+ begin
+ if (!Rst_RBI)
+ begin
+ rresp_done_reg <= 1'b0;
+ rvalid <= 1'b0;
+ rresp_running_reg <= 1'b0;
+ end
+ else
+ begin
+ if (araddr_done_reg && !rresp_done_reg)
+ begin
+ if (!rresp_running_reg)
+ begin
+ rvalid <= 1'b1;
+ rresp_running_reg <= 1'b1;
+ end
+ else if (s_axi_rready)
+ begin
+ rvalid <= 1'b0;
+ rresp_done_reg <= 1'b1;
+ rresp_running_reg <= 1'b0;
+ end
+ end
+ else
+ begin
+ rvalid <= 1'b0;
+ rresp_done_reg <= 1'b0;
+ rresp_running_reg <= 1'b0;
+ end
+ end
+ end
+
+ // ██╗ ██╗ ██████╗███████╗ ██████╗ ██████╗ ███████╗ ██████╗
+ // ██║ ███║ ██╔════╝██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝
+ // ██║ ╚██║ ██║ █████╗ ██║ ███╗ ██████╔╝█████╗ ██║ ███╗
+ // ██║ ██║ ██║ ██╔══╝ ██║ ██║ ██╔══██╗██╔══╝ ██║ ██║
+ // ███████╗██║ ╚██████╗██║ ╚██████╔╝ ██║ ██║███████╗╚██████╔╝
+ // ╚══════╝╚═╝ ╚═════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝
+ //
+ assign wren_l1 = wren && (awaddr_reg < L2SINGLE_AMAP_SIZE);
+
+ always @( posedge Clk_CI or negedge Rst_RBI )
+ begin
+ var integer idx_reg, idx_byte;
+ if ( Rst_RBI == 1'b0 )
+ begin
+ for ( idx_reg = 0; idx_reg < N_REGS; idx_reg++ )
+ L1Cfg_DP[idx_reg] <= '0;
+ end
+ else if ( wren_l1 )
+ begin
+ if ( awaddr_reg[ADDR_LSB+1] == 1'b0 ) begin // VIRT_ADDR
+ for ( idx_byte = 0; idx_byte < AXI_DATA_WIDTH/8; idx_byte++ ) begin
+ if ( (idx_byte < ADDR_WIDTH_VIRT/8) ) begin
+ if ( wstrb_reg[idx_byte] ) begin
+ L1Cfg_DP[awaddr_reg[ADDR_MSB:ADDR_LSB]][idx_byte] <= wdata_reg[idx_byte];
+ end
+ end
+ else begin // Let synthesizer optimize away unused registers.
+ L1Cfg_DP[awaddr_reg[ADDR_MSB:ADDR_LSB]][idx_byte] <= '0;
+ end
+ end
+ end
+ else if ( awaddr_reg[ADDR_LSB+1:ADDR_LSB] == 2'b10 ) begin // PHYS_ADDR
+ for ( idx_byte = 0; idx_byte < AXI_DATA_WIDTH/8; idx_byte++ ) begin
+ if ( (idx_byte < ADDR_WIDTH_PHYS/8) ) begin
+ if ( wstrb_reg[idx_byte] ) begin
+ L1Cfg_DP[awaddr_reg[ADDR_MSB:ADDR_LSB]][idx_byte] <= wdata_reg[idx_byte];
+ end
+ end
+ else begin // Let synthesizer optimize away unused registers.
+ L1Cfg_DP[awaddr_reg[ADDR_MSB:ADDR_LSB]][idx_byte] <= '0;
+ end
+ end
+ end
+ else begin // ( awaddr_reg[ADDR_LSB+1:ADDR_LSB] == 2'b11 ) // FLAGS
+ for ( idx_byte = 0; idx_byte < AXI_DATA_WIDTH/8; idx_byte++ ) begin
+ if ( (idx_byte < 1) ) begin
+ if ( wstrb_reg[idx_byte] ) begin
+ L1Cfg_DP[awaddr_reg[ADDR_MSB:ADDR_LSB]][idx_byte] <= wdata_reg[idx_byte] & { {{8-N_FLAGS}{1'b0}}, {{N_FLAGS}{1'b1}} };
+ end
+ end
+ else begin // Let synthesizer optimize away unused registers.
+ L1Cfg_DP[awaddr_reg[ADDR_MSB:ADDR_LSB]][idx_byte] <= '0;
+ end
+ end
+ end
+ end
+ end // always @ ( posedge Clk_CI or negedge Rst_RBI )
+
+ generate
+ // Mask unused bits -> Synthesizer should optimize away unused registers
+ for( j=0; j<N_REGS; j++ ) begin
+ if ( j[1] == 1'b0 ) // VIRT_ADDR
+ assign L1Cfg_DO[j] = { {{64-ADDR_WIDTH_VIRT}{1'b0}},{ADDR_WIDTH_VIRT{1'b1}} } & L1Cfg_DP[j];
+ else if ( j[1:0] == 2'b10 ) // PHYS_ADDR
+ assign L1Cfg_DO[j] = { {{64-ADDR_WIDTH_PHYS}{1'b0}},{ADDR_WIDTH_PHYS{1'b1}} } & L1Cfg_DP[j];
+ else // if ( j[1:0] == 2'b11 ) // FLAGS
+ assign L1Cfg_DO[j] = { {{64-N_FLAGS}{1'b0}},{N_FLAGS{1'b1}} } & L1Cfg_DP[j];
+ end
+ endgenerate
+
+ always_comb
+ begin
+ if ( araddr_reg[ADDR_LSB-1] == 1'b1 ) // read upper 32 bit, for debugging over 32-bit interface
+ rdata_reg = { {32'h00000000},{L1Cfg_DO[araddr_reg[ADDR_MSB:ADDR_LSB]][63:32]} };
+ else
+ rdata_reg = L1Cfg_DO[araddr_reg[ADDR_MSB:ADDR_LSB]];
+ end
+
+ assign s_axi_awready = awready;
+ assign s_axi_wready = wready;
+
+ assign s_axi_bresp = 2'b00;
+ assign s_axi_bvalid = bvalid;
+
+ assign s_axi_arready = arready;
+ assign s_axi_rresp = 2'b00;
+ assign s_axi_rvalid = rvalid;
+
+ // ██╗ ██████╗ ██████╗███████╗ ██████╗
+ // ██║ ╚════██╗ ██╔════╝██╔════╝██╔════╝
+ // ██║ █████╔╝ ██║ █████╗ ██║ ███╗
+ // ██║ ██╔═══╝ ██║ ██╔══╝ ██║ ██║
+ // ███████╗███████╗ ╚██████╗██║ ╚██████╔╝
+ // ╚══════╝╚══════╝ ╚═════╝╚═╝ ╚═════╝
+ //
+ logic [N_PORTS-1:0] l2_addr_is_in_va_rams;
+ logic [N_PORTS-1:0] upper_word_is_written;
+ logic [N_PORTS-1:0] lower_word_is_written;
+ generate
+ for( j=0; j< N_PORTS; j++)
+ begin
+ if (AXI_DATA_WIDTH == 64) begin
+ assign l2_addr_is_in_va_rams[j] = (awaddr_reg >= (j+1)*L2SINGLE_AMAP_SIZE) && (awaddr_reg[log2(L2SINGLE_AMAP_SIZE)-1:0] <= L2_VA_MAX_ADDR);
+ assign upper_word_is_written[j] = (wstrb_reg[7:4] != 4'b0000);
+ assign lower_word_is_written[j] = (wstrb_reg[3:0] != 4'b0000);
+ end else begin
+ assign l2_addr_is_in_va_rams[j] = 1'b0;
+ assign upper_word_is_written[j] = 1'b0;
+ assign lower_word_is_written[j] = 1'b0;
+ end
+
+ always @( posedge Clk_CI or negedge Rst_RBI ) begin
+ var integer idx_byte, off_byte;
+ if ( Rst_RBI == 1'b0 )
+ begin
+ wren_l2[j] <= 1'b0;
+ wdata_l2[j] <= '0;
+ end
+ else if (wren)
+ begin
+ if ( (awaddr_reg >= (j+1)*L2SINGLE_AMAP_SIZE) && (awaddr_reg < (j+2)*L2SINGLE_AMAP_SIZE) && (|wstrb_reg) )
+ wren_l2[j] <= 1'b1;
+ if (AXI_DATA_WIDTH == 32) begin
+ for ( idx_byte = 0; idx_byte < AXI_DATA_WIDTH/8; idx_byte++ )
+ wdata_l2[j][idx_byte*8 +: 8] <= wdata_reg[idx_byte] & {8{wstrb_reg[idx_byte]}};
+ end
+ else if (AXI_DATA_WIDTH == 64) begin
+ if (lower_word_is_written[j] == 1'b1)
+ off_byte = 0;
+ else
+ off_byte = 4;
+ // always put the payload in the lower word and set upper word to 0
+ for ( idx_byte = 0; idx_byte < AXI_DATA_WIDTH/8/2; idx_byte++ )
+ wdata_l2[j][idx_byte*8 +: 8] <= wdata_reg[idx_byte+off_byte] & {8{wstrb_reg[idx_byte+off_byte]}};
+ wdata_l2[j][AXI_DATA_WIDTH-1:AXI_DATA_WIDTH/2] <= 'b0;
+ end
+ // pragma translate_off
+ else
+ $fatal(1, "Unsupported AXI_DATA_WIDTH!");
+ // pragma translate_on
+ end
+ else
+ wren_l2[j] <= '0;
+ end // always @ ( posedge Clk_CI or negedge Rst_RBI )
+
+ // Properly align the 32-bit word address when writing from 64-bit interface:
+ // Depending on the system, the incoming address is (non-)aligned to the 64-bit
+ // word when writing the upper 32-bit word.
+ always_comb begin
+ waddr_l2[j] = (awaddr_reg -(j+1)*L2SINGLE_AMAP_SIZE)/4;
+ if (wren_l2[j]) begin
+ if (AXI_DATA_WIDTH == 64) begin
+ if (upper_word_is_written[j] == 1'b1) begin
+ // address must be non-aligned
+ waddr_l2[j][0] = 1'b1;
+ end
+ end
+ // pragma translate_off
+ else if (AXI_DATA_WIDTH != 32) begin
+ $fatal(1, "Unsupported AXI_DATA_WIDTH!");
+ end
+ // pragma translate_on
+ end
+ end
+
+ // Assert that only one 32-bit word is ever written at a time to VA RAMs on 64-bit data
+ // systems.
+ // pragma translate_off
+ always_ff @ (posedge Clk_CI) begin
+ if (AXI_DATA_WIDTH == 64) begin
+ if (l2_addr_is_in_va_rams[j]) begin
+ if (upper_word_is_written[j]) begin
+ assert (!lower_word_is_written[j])
+ else $error("Unsupported write across two 32-bit words to VA RAMs!");
+ end
+ else if (lower_word_is_written[j]) begin
+ assert (!upper_word_is_written[j])
+ else $error("Unsupported write across two 32-bit words to VA RAMs!");
+ end
+ end
+ end
+ end
+ // pragma translate_on
+
+ end // for (j=0; j< N_PORTS; j++)
+ endgenerate
+
+ // ███╗ ███╗██╗ ██╗ ███████╗██╗███████╗ ██████╗ ███████╗
+ // ████╗ ████║██║ ██║ ██╔════╝██║██╔════╝██╔═══██╗██╔════╝
+ // ██╔████╔██║███████║ █████╗ ██║█████╗ ██║ ██║███████╗
+ // ██║╚██╔╝██║██╔══██║ ██╔══╝ ██║██╔══╝ ██║ ██║╚════██║
+ // ██║ ╚═╝ ██║██║ ██║ ██║ ██║██║ ╚██████╔╝███████║
+ // ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═════╝ ╚══════╝
+ //
+ logic [ADDR_WIDTH_VIRT-1:0] AddrFifoDin_D;
+ logic AddrFifoWen_S;
+ logic AddrFifoRen_S;
+ logic [ADDR_WIDTH_VIRT-1:0] AddrFifoDout_D;
+ logic AddrFifoFull_S;
+ logic AddrFifoEmpty_S;
+ logic AddrFifoEmpty_SB;
+ logic AddrFifoFull_SB;
+
+ logic [MISS_META_WIDTH-1:0] MetaFifoDin_D;
+ logic MetaFifoWen_S;
+ logic MetaFifoRen_S;
+ logic [MISS_META_WIDTH-1:0] MetaFifoDout_D;
+ logic MetaFifoFull_S;
+ logic MetaFifoEmpty_S;
+ logic MetaFifoEmpty_SB;
+ logic MetaFifoFull_SB;
+
+ logic FifosDisabled_S;
+ logic ConfRegWen_S;
+ logic [1:0] ConfReg_DN;
+ logic [1:0] ConfReg_DP;
+
+ logic [AXI_DATA_WIDTH-1:0] wdata_reg_vec;
+
+ assign FifosDisabled_S = ConfReg_DP[0];
+ assign L1AllowMultiHit_SO = ConfReg_DP[1];
+
+ assign AddrFifoEmpty_S = ~AddrFifoEmpty_SB;
+ assign MetaFifoEmpty_S = ~MetaFifoEmpty_SB;
+
+ assign AddrFifoFull_S = ~AddrFifoFull_SB;
+ assign MetaFifoFull_S = ~MetaFifoFull_SB;
+
+ assign MhFifoFull_SO = (AddrFifoWen_S & AddrFifoFull_S) | (MetaFifoWen_S & MetaFifoFull_S);
+
+ generate
+ for ( j=0; j<AXI_DATA_WIDTH/8; j++ )
+ assign wdata_reg_vec[(j+1)*8-1:j*8] = wdata_reg[j];
+ endgenerate
+
+ // write address FIFO
+ always_comb
+ begin
+ AddrFifoWen_S = 1'b0;
+ AddrFifoDin_D = 'b0;
+ if ( (Miss_SI == 1'b1) && (FifosDisabled_S == 1'b0) ) // register a new miss
+ begin
+ AddrFifoWen_S = 1'b1;
+ AddrFifoDin_D = MissAddr_DI;
+ end
+ else if ( (wren_l1 == 1'b1) && (awaddr_reg[ADDR_MSB:0] == 'b0) && (FifosDisabled_S == 1'b0)) // write request from AXI interface
+ begin
+ AddrFifoWen_S = 1'b1;
+ AddrFifoDin_D = wdata_reg_vec[ADDR_WIDTH_VIRT-1:0];
+ end
+ end
+
+ // write meta FIFO
+ always_comb
+ begin
+ MetaFifoWen_S = 1'b0;
+ MetaFifoDin_D = 'b0;
+ if ( (Miss_SI == 1'b1) && (FifosDisabled_S == 1'b0) ) // register a new miss
+ begin
+ MetaFifoWen_S = 1'b1;
+ MetaFifoDin_D[MISS_META_WIDTH-1:0] = MissMeta_DI;
+ end
+ else if ( (wren_l1 == 1'b1) && (awaddr_reg[ADDR_MSB:0] == 4'h8) && (FifosDisabled_S == 1'b0) ) // write request from AXI interface
+ begin
+ MetaFifoWen_S = 1'b1;
+ MetaFifoDin_D = wdata_reg_vec[MISS_META_WIDTH-1:0];
+ end
+ end
+
+ // write configuration register
+ always_comb
+ begin
+ ConfRegWen_S = 1'b0;
+ ConfReg_DN = 1'b0;
+ if ( (wren_l1 == 1'b1) && (awaddr_reg[ADDR_MSB:0] == 8'h10) ) // write request from AXI interface
+ begin
+ ConfRegWen_S = 1'b1;
+ ConfReg_DN = wdata_reg_vec[$high(ConfReg_DN):0];
+ end
+ end
+
+ // AXI read data
+ always_comb
+ begin
+ s_axi_rdata = rdata_reg; // read L1 config
+ AddrFifoRen_S = 1'b0;
+ MetaFifoRen_S = 1'b0;
+ if ( rvalid == 1'b1 )
+ begin
+ // read address FIFO
+ if ( araddr_reg[ADDR_MSB:0] == 'b0 )
+ begin
+ s_axi_rdata = {AXI_DATA_WIDTH{1'b0}};
+ s_axi_rdata[ADDR_WIDTH_VIRT-1:0] = AddrFifoDout_D;
+ if ( AddrFifoEmpty_S == 1'b0 )
+ AddrFifoRen_S = 1'b1;
+ end
+ // read meta FIFO
+ else if ( araddr_reg[ADDR_MSB:0] == 4'h8 )
+ begin
+ s_axi_rdata = {AXI_DATA_WIDTH{1'b0}};
+ s_axi_rdata[31] = MetaFifoEmpty_S;
+ s_axi_rdata[MISS_META_WIDTH-1:0] = MetaFifoDout_D;
+ if ( MetaFifoEmpty_S == 1'b0 )
+ MetaFifoRen_S = 1'b1;
+ end
+ // read configuration register
+ else if ( araddr_reg[ADDR_MSB:0] == 8'h10 )
+ begin
+ s_axi_rdata = {AXI_DATA_WIDTH{1'b0}};
+ s_axi_rdata[$high(ConfReg_DP):0] = ConfReg_DP;
+ end
+ end // if ( rvalid == 1'b1 )
+ end // always_comb begin
+
+ // configuration register
+ always_ff @(posedge Clk_CI or negedge Rst_RBI) begin
+ if (Rst_RBI == 1'b0)
+ begin
+ ConfReg_DP <= 'b0;
+ end
+ else if (ConfRegWen_S == 1'b1)
+ begin
+ ConfReg_DP <= ConfReg_DN;
+ end
+ end
+
+ generic_fifo
+ #(
+ .DATA_WIDTH ( ADDR_WIDTH_VIRT ),
+ .DATA_DEPTH ( MH_FIFO_DEPTH )
+ )
+ fifo_addr_i
+ (
+ .clk ( Clk_CI ),
+ .rst_n ( Rst_RBI ),
+ .data_i ( AddrFifoDin_D ),
+ .valid_i ( AddrFifoWen_S & AddrFifoFull_SB ),
+ .grant_o ( AddrFifoFull_SB ),
+ .data_o ( AddrFifoDout_D ),
+ .valid_o ( AddrFifoEmpty_SB ),
+ .grant_i ( AddrFifoRen_S ),
+ .test_mode_i ( 1'b0 )
+ );
+
+ generic_fifo
+ #(
+ .DATA_WIDTH ( MISS_META_WIDTH ),
+ .DATA_DEPTH ( MH_FIFO_DEPTH )
+ )
+ fifo_meta_i
+ (
+ .clk ( Clk_CI ),
+ .rst_n ( Rst_RBI ),
+ .data_i ( MetaFifoDin_D ),
+ .valid_i ( MetaFifoWen_S & MetaFifoFull_SB ),
+ .grant_o ( MetaFifoFull_SB ),
+ .data_o ( MetaFifoDout_D ),
+ .valid_o ( MetaFifoEmpty_SB ),
+ .grant_i ( MetaFifoRen_S ),
+ .test_mode_i ( 1'b0 )
+ );
+"""
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class axi_rab_top(Elaboratable):
+
+ def __init__(self):
+ self.Clk_CI = Signal() # input
+ self.NonGatedClk_CI = Signal() # input
+ self.Rst_RBI = Signal() # input
+ self.s_axi4_awid = Signal() # input
+ self.s_axi4_awaddr = Signal() # input
+ self.s_axi4_awvalid = Signal(N_PORTS) # input
+ self.s_axi4_awready = Signal(N_PORTS) # output
+ self.s_axi4_awlen = Signal() # input
+ self.s_axi4_awsize = Signal() # input
+ self.s_axi4_awburst = Signal() # input
+ self.s_axi4_awlock = Signal(N_PORTS) # input
+ self.s_axi4_awprot = Signal() # input
+ self.s_axi4_awcache = Signal() # input
+ self.s_axi4_awregion = Signal() # input
+ self.s_axi4_awqos = Signal() # input
+ self.s_axi4_awuser = Signal() # input
+ self.s_axi4_wdata = Signal() # input
+ self.s_axi4_wvalid = Signal(N_PORTS) # input
+ self.s_axi4_wready = Signal(N_PORTS) # output
+ self.s_axi4_wstrb = Signal() # input
+ self.s_axi4_wlast = Signal(N_PORTS) # input
+ self.s_axi4_wuser = Signal() # input
+ self.s_axi4_bid = Signal() # output
+ self.s_axi4_bresp = Signal() # output
+ self.s_axi4_bvalid = Signal(N_PORTS) # output
+ self.s_axi4_buser = Signal() # output
+ self.s_axi4_bready = Signal(N_PORTS) # input
+ self.s_axi4_arid = Signal() # input
+ self.s_axi4_araddr = Signal() # input
+ self.s_axi4_arvalid = Signal(N_PORTS) # input
+ self.s_axi4_arready = Signal(N_PORTS) # output
+ self.s_axi4_arlen = Signal() # input
+ self.s_axi4_arsize = Signal() # input
+ self.s_axi4_arburst = Signal() # input
+ self.s_axi4_arlock = Signal(N_PORTS) # input
+ self.s_axi4_arprot = Signal() # input
+ self.s_axi4_arcache = Signal() # input
+ self.s_axi4_aruser = Signal() # input
+ self.s_axi4_rid = Signal() # output
+ self.s_axi4_rdata = Signal() # output
+ self.s_axi4_rresp = Signal() # output
+ self.s_axi4_rvalid = Signal(N_PORTS) # output
+ self.s_axi4_rready = Signal(N_PORTS) # input
+ self.s_axi4_rlast = Signal(N_PORTS) # output
+ self.s_axi4_ruser = Signal() # output
+ self.m0_axi4_awid = Signal() # output
+ self.m0_axi4_awaddr = Signal() # output
+ self.m0_axi4_awvalid = Signal(N_PORTS) # output
+ self.m0_axi4_awready = Signal(N_PORTS) # input
+ self.m0_axi4_awlen = Signal() # output
+ self.m0_axi4_awsize = Signal() # output
+ self.m0_axi4_awburst = Signal() # output
+ self.m0_axi4_awlock = Signal(N_PORTS) # output
+ self.m0_axi4_awprot = Signal() # output
+ self.m0_axi4_awcache = Signal() # output
+ self.m0_axi4_awregion = Signal() # output
+ self.m0_axi4_awqos = Signal() # output
+ self.m0_axi4_awuser = Signal() # output
+ self.m0_axi4_wdata = Signal() # output
+ self.m0_axi4_wvalid = Signal(N_PORTS) # output
+ self.m0_axi4_wready = Signal(N_PORTS) # input
+ self.m0_axi4_wstrb = Signal() # output
+ self.m0_axi4_wlast = Signal(N_PORTS) # output
+ self.m0_axi4_wuser = Signal() # output
+ self.m0_axi4_bid = Signal() # input
+ self.m0_axi4_bresp = Signal() # input
+ self.m0_axi4_bvalid = Signal(N_PORTS) # input
+ self.m0_axi4_buser = Signal() # input
+ self.m0_axi4_bready = Signal(N_PORTS) # output
+ self.m0_axi4_arid = Signal() # output
+ self.m0_axi4_araddr = Signal() # output
+ self.m0_axi4_arvalid = Signal(N_PORTS) # output
+ self.m0_axi4_arready = Signal(N_PORTS) # input
+ self.m0_axi4_arlen = Signal() # output
+ self.m0_axi4_arsize = Signal() # output
+ self.m0_axi4_arburst = Signal() # output
+ self.m0_axi4_arlock = Signal(N_PORTS) # output
+ self.m0_axi4_arprot = Signal() # output
+ self.m0_axi4_arcache = Signal() # output
+ self.m0_axi4_aruser = Signal() # output
+ self.m0_axi4_rid = Signal() # input
+ self.m0_axi4_rdata = Signal() # input
+ self.m0_axi4_rresp = Signal() # input
+ self.m0_axi4_rvalid = Signal(N_PORTS) # input
+ self.m0_axi4_rready = Signal(N_PORTS) # output
+ self.m0_axi4_rlast = Signal(N_PORTS) # input
+ self.m0_axi4_ruser = Signal() # input
+ self.m1_axi4_awid = Signal() # output
+ self.m1_axi4_awaddr = Signal() # output
+ self.m1_axi4_awvalid = Signal(N_PORTS) # output
+ self.m1_axi4_awready = Signal(N_PORTS) # input
+ self.m1_axi4_awlen = Signal() # output
+ self.m1_axi4_awsize = Signal() # output
+ self.m1_axi4_awburst = Signal() # output
+ self.m1_axi4_awlock = Signal(N_PORTS) # output
+ self.m1_axi4_awprot = Signal() # output
+ self.m1_axi4_awcache = Signal() # output
+ self.m1_axi4_awregion = Signal() # output
+ self.m1_axi4_awqos = Signal() # output
+ self.m1_axi4_awuser = Signal() # output
+ self.m1_axi4_wdata = Signal() # output
+ self.m1_axi4_wvalid = Signal(N_PORTS) # output
+ self.m1_axi4_wready = Signal(N_PORTS) # input
+ self.m1_axi4_wstrb = Signal() # output
+ self.m1_axi4_wlast = Signal(N_PORTS) # output
+ self.m1_axi4_wuser = Signal() # output
+ self.m1_axi4_bid = Signal() # input
+ self.m1_axi4_bresp = Signal() # input
+ self.m1_axi4_bvalid = Signal(N_PORTS) # input
+ self.m1_axi4_buser = Signal() # input
+ self.m1_axi4_bready = Signal(N_PORTS) # output
+ self.m1_axi4_arid = Signal() # output
+ self.m1_axi4_araddr = Signal() # output
+ self.m1_axi4_arvalid = Signal(N_PORTS) # output
+ self.m1_axi4_arready = Signal(N_PORTS) # input
+ self.m1_axi4_arlen = Signal() # output
+ self.m1_axi4_arsize = Signal() # output
+ self.m1_axi4_arburst = Signal() # output
+ self.m1_axi4_arlock = Signal(N_PORTS) # output
+ self.m1_axi4_arprot = Signal() # output
+ self.m1_axi4_arcache = Signal() # output
+ self.m1_axi4_aruser = Signal() # output
+ self.m1_axi4_rid = Signal() # input
+ self.m1_axi4_rdata = Signal() # input
+ self.m1_axi4_rresp = Signal() # input
+ self.m1_axi4_rvalid = Signal(N_PORTS) # input
+ self.m1_axi4_rready = Signal(N_PORTS) # output
+ self.m1_axi4_rlast = Signal(N_PORTS) # input
+ self.m1_axi4_ruser = Signal() # input
+ self.s_axi4lite_awaddr = Signal(AXI_LITE_ADDR_WIDTH) # input
+ self.s_axi4lite_awvalid = Signal() # input
+ self.s_axi4lite_awready = Signal() # output
+ self.s_axi4lite_wdata = Signal(AXI_LITE_DATA_WIDTH) # input
+ self.s_axi4lite_wvalid = Signal() # input
+ self.s_axi4lite_wready = Signal() # output
+ self.s_axi4lite_wstrb = Signal(1+ERROR p_expression_25) # input
+ self.s_axi4lite_bresp = Signal(2) # output
+ self.s_axi4lite_bvalid = Signal() # output
+ self.s_axi4lite_bready = Signal() # input
+ self.s_axi4lite_araddr = Signal(AXI_LITE_ADDR_WIDTH) # input
+ self.s_axi4lite_arvalid = Signal() # input
+ self.s_axi4lite_arready = Signal() # output
+ self.s_axi4lite_rdata = Signal(AXI_LITE_DATA_WIDTH) # output
+ self.s_axi4lite_rresp = Signal(2) # output
+ self.s_axi4lite_rvalid = Signal() # output
+ self.s_axi4lite_rready = Signal() # input
+ self.int_miss = Signal(N_PORTS) # output
+ self.int_multi = Signal(N_PORTS) # output
+ self.int_prot = Signal(N_PORTS) # output
+ self.int_mhf_full = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ return m
+
+
+# // 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.
+#
+# // --=========================================================================--
+# //
+# // █████╗ ██╗ ██╗██╗ ██████╗ █████╗ ██████╗ ████████╗ ██████╗ ██████╗
+# // ██╔══██╗╚██╗██╔╝██║ ██╔══██╗██╔══██╗██╔══██╗ ╚══██╔══╝██╔═══██╗██╔══██╗
+# // ███████║ ╚███╔╝ ██║ ██████╔╝███████║██████╔╝ ██║ ██║ ██║██████╔╝
+# // ██╔══██║ ██╔██╗ ██║ ██╔══██╗██╔══██║██╔══██╗ ██║ ██║ ██║██╔═══╝
+# // ██║ ██║██╔╝ ██╗██║ ██║ ██║██║ ██║██████╔╝ ██║ ╚██████╔╝██║
+# // ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═════╝ ╚═╝
+# //
+# // --=========================================================================--
+# /*
+# * axi_rab_top
+# *
+# * The remapping address block (RAB) performs address translation for AXI
+# * transactions arriving at the input port and forwards them to different
+# * downstream AXI ports.
+# *
+# * The five axi channels are each buffered on the input side using a FIFO,
+# * described in axi4_XX_buffer. The RAB lookup result is merged into the
+# * AXI transaction via the axi4_XX_sender instances, which manages upstream
+# * error signaling for failed lookups.
+# *
+# * Address translation is performed based on data stored in up to two
+# * translation lookaside buffers (TLBs), which are private per RAB port (each
+# * of which having two AXI master ports and one AXI slave port). These TLBs
+# * are managed in software through the AXI-Lite interface.
+# *
+# * If ACP is enabled, the `cache_coherent` flag in the TLBs is used to
+# * multiplex between the two ports. If ACP is disabled, only the first master
+# * port is used. In this case, the `cache_coherent` flag is used to set the
+# * AxCACHE signals of the AXI bus accordingly.
+# *
+# * Authors:
+# * Antonio Pullini <pullinia@iis.ee.ethz.ch>
+# * Conrad Burchert <bconrad@ethz.ch>
+# * Maheshwara Sharma <msharma@student.ethz.ch>
+# * Andreas Kurth <akurth@iis.ee.ethz.ch>
+# * Johannes Weinbuch <jweinbuch@student.ethz.ch>
+# * Pirmin Vogel <vogelpi@iis.ee.ethz.ch>
+# */
+#
+# //`include "pulp_soc_defines.sv"
+#
+# ////import CfMath::log2;
+#
+# module axi_rab_top
+#
+# // Parameters {{{
+# #(
+# parameter N_PORTS = 2,
+# 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 = 10,
+# parameter AXI_USER_WIDTH = 6,
+# parameter MH_FIFO_DEPTH = 16
+# )
+# // }}}
+#
+# // Ports {{{
+# (
+#
+# input logic Clk_CI, // This clock may be gated.
+# input logic NonGatedClk_CI,
+# input logic Rst_RBI,
+#
+# // For every slave port there are two master ports. The master
+# // port to use can be set using the master_select flag of the protection
+# // bits of a slice
+#
+# // AXI4 Slave {{{
+# input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] s_axi4_awid,
+# input logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] s_axi4_awaddr,
+# input logic [N_PORTS-1:0] s_axi4_awvalid,
+# output logic [N_PORTS-1:0] s_axi4_awready,
+# input logic [N_PORTS-1:0] [7:0] s_axi4_awlen,
+# input logic [N_PORTS-1:0] [2:0] s_axi4_awsize,
+# input logic [N_PORTS-1:0] [1:0] s_axi4_awburst,
+# input logic [N_PORTS-1:0] s_axi4_awlock,
+# input logic [N_PORTS-1:0] [2:0] s_axi4_awprot,
+# input logic [N_PORTS-1:0] [3:0] s_axi4_awcache,
+# input logic [N_PORTS-1:0] [3:0] s_axi4_awregion,
+# input logic [N_PORTS-1:0] [3:0] s_axi4_awqos,
+# input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] s_axi4_awuser,
+#
+# input logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] s_axi4_wdata,
+# input logic [N_PORTS-1:0] s_axi4_wvalid,
+# output logic [N_PORTS-1:0] s_axi4_wready,
+# input logic [N_PORTS-1:0] [AXI_DATA_WIDTH/8-1:0] s_axi4_wstrb,
+# input logic [N_PORTS-1:0] s_axi4_wlast,
+# input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] s_axi4_wuser,
+#
+# output logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] s_axi4_bid,
+# output logic [N_PORTS-1:0] [1:0] s_axi4_bresp,
+# output logic [N_PORTS-1:0] s_axi4_bvalid,
+# output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] s_axi4_buser,
+# input logic [N_PORTS-1:0] s_axi4_bready,
+#
+# input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] s_axi4_arid,
+# input logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] s_axi4_araddr,
+# input logic [N_PORTS-1:0] s_axi4_arvalid,
+# output logic [N_PORTS-1:0] s_axi4_arready,
+# input logic [N_PORTS-1:0] [7:0] s_axi4_arlen,
+# input logic [N_PORTS-1:0] [2:0] s_axi4_arsize,
+# input logic [N_PORTS-1:0] [1:0] s_axi4_arburst,
+# input logic [N_PORTS-1:0] s_axi4_arlock,
+# input logic [N_PORTS-1:0] [2:0] s_axi4_arprot,
+# input logic [N_PORTS-1:0] [3:0] s_axi4_arcache,
+# input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] s_axi4_aruser,
+#
+# output logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] s_axi4_rid,
+# output logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] s_axi4_rdata,
+# output logic [N_PORTS-1:0] [1:0] s_axi4_rresp,
+# output logic [N_PORTS-1:0] s_axi4_rvalid,
+# input logic [N_PORTS-1:0] s_axi4_rready,
+# output logic [N_PORTS-1:0] s_axi4_rlast,
+# output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] s_axi4_ruser,
+# // }}}
+#
+# // AXI4 Master 0 {{{
+# output logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] m0_axi4_awid,
+# output logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] m0_axi4_awaddr,
+# output logic [N_PORTS-1:0] m0_axi4_awvalid,
+# input logic [N_PORTS-1:0] m0_axi4_awready,
+# output logic [N_PORTS-1:0] [7:0] m0_axi4_awlen,
+# output logic [N_PORTS-1:0] [2:0] m0_axi4_awsize,
+# output logic [N_PORTS-1:0] [1:0] m0_axi4_awburst,
+# output logic [N_PORTS-1:0] m0_axi4_awlock,
+# output logic [N_PORTS-1:0] [2:0] m0_axi4_awprot,
+# output logic [N_PORTS-1:0] [3:0] m0_axi4_awcache,
+# output logic [N_PORTS-1:0] [3:0] m0_axi4_awregion,
+# output logic [N_PORTS-1:0] [3:0] m0_axi4_awqos,
+# output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m0_axi4_awuser,
+#
+# output logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] m0_axi4_wdata,
+# output logic [N_PORTS-1:0] m0_axi4_wvalid,
+# input logic [N_PORTS-1:0] m0_axi4_wready,
+# output logic [N_PORTS-1:0] [AXI_DATA_WIDTH/8-1:0] m0_axi4_wstrb,
+# output logic [N_PORTS-1:0] m0_axi4_wlast,
+# output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m0_axi4_wuser,
+#
+# input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] m0_axi4_bid,
+# input logic [N_PORTS-1:0] [1:0] m0_axi4_bresp,
+# input logic [N_PORTS-1:0] m0_axi4_bvalid,
+# input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m0_axi4_buser,
+# output logic [N_PORTS-1:0] m0_axi4_bready,
+#
+# output logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] m0_axi4_arid,
+# output logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] m0_axi4_araddr,
+# output logic [N_PORTS-1:0] m0_axi4_arvalid,
+# input logic [N_PORTS-1:0] m0_axi4_arready,
+# output logic [N_PORTS-1:0] [7:0] m0_axi4_arlen,
+# output logic [N_PORTS-1:0] [2:0] m0_axi4_arsize,
+# output logic [N_PORTS-1:0] [1:0] m0_axi4_arburst,
+# output logic [N_PORTS-1:0] m0_axi4_arlock,
+# output logic [N_PORTS-1:0] [2:0] m0_axi4_arprot,
+# output logic [N_PORTS-1:0] [3:0] m0_axi4_arcache,
+# output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m0_axi4_aruser,
+#
+# input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] m0_axi4_rid,
+# input logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] m0_axi4_rdata,
+# input logic [N_PORTS-1:0] [1:0] m0_axi4_rresp,
+# input logic [N_PORTS-1:0] m0_axi4_rvalid,
+# output logic [N_PORTS-1:0] m0_axi4_rready,
+# input logic [N_PORTS-1:0] m0_axi4_rlast,
+# input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m0_axi4_ruser,
+# // }}}
+#
+# // AXI4 Master 1 {{{
+# output logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] m1_axi4_awid,
+# output logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] m1_axi4_awaddr,
+# output logic [N_PORTS-1:0] m1_axi4_awvalid,
+# input logic [N_PORTS-1:0] m1_axi4_awready,
+# output logic [N_PORTS-1:0] [7:0] m1_axi4_awlen,
+# output logic [N_PORTS-1:0] [2:0] m1_axi4_awsize,
+# output logic [N_PORTS-1:0] [1:0] m1_axi4_awburst,
+# output logic [N_PORTS-1:0] m1_axi4_awlock,
+# output logic [N_PORTS-1:0] [2:0] m1_axi4_awprot,
+# output logic [N_PORTS-1:0] [3:0] m1_axi4_awcache,
+# output logic [N_PORTS-1:0] [3:0] m1_axi4_awregion,
+# output logic [N_PORTS-1:0] [3:0] m1_axi4_awqos,
+# output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m1_axi4_awuser,
+#
+# output logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] m1_axi4_wdata,
+# output logic [N_PORTS-1:0] m1_axi4_wvalid,
+# input logic [N_PORTS-1:0] m1_axi4_wready,
+# output logic [N_PORTS-1:0] [AXI_DATA_WIDTH/8-1:0] m1_axi4_wstrb,
+# output logic [N_PORTS-1:0] m1_axi4_wlast,
+# output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m1_axi4_wuser,
+#
+# input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] m1_axi4_bid,
+# input logic [N_PORTS-1:0] [1:0] m1_axi4_bresp,
+# input logic [N_PORTS-1:0] m1_axi4_bvalid,
+# input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m1_axi4_buser,
+# output logic [N_PORTS-1:0] m1_axi4_bready,
+#
+# output logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] m1_axi4_arid,
+# output logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] m1_axi4_araddr,
+# output logic [N_PORTS-1:0] m1_axi4_arvalid,
+# input logic [N_PORTS-1:0] m1_axi4_arready,
+# output logic [N_PORTS-1:0] [7:0] m1_axi4_arlen,
+# output logic [N_PORTS-1:0] [2:0] m1_axi4_arsize,
+# output logic [N_PORTS-1:0] [1:0] m1_axi4_arburst,
+# output logic [N_PORTS-1:0] m1_axi4_arlock,
+# output logic [N_PORTS-1:0] [2:0] m1_axi4_arprot,
+# output logic [N_PORTS-1:0] [3:0] m1_axi4_arcache,
+# output logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m1_axi4_aruser,
+#
+# input logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] m1_axi4_rid,
+# input logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] m1_axi4_rdata,
+# input logic [N_PORTS-1:0] [1:0] m1_axi4_rresp,
+# input logic [N_PORTS-1:0] m1_axi4_rvalid,
+# output logic [N_PORTS-1:0] m1_axi4_rready,
+# input logic [N_PORTS-1:0] m1_axi4_rlast,
+# input logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] m1_axi4_ruser,
+# // }}}
+#
+# // AXI 4 Lite Slave (Configuration Interface) {{{
+# // AXI4-Lite port to setup the rab slices
+# // use this to program the configuration registers
+# input logic [AXI_LITE_ADDR_WIDTH-1:0] s_axi4lite_awaddr,
+# input logic s_axi4lite_awvalid,
+# output logic s_axi4lite_awready,
+#
+# input logic [AXI_LITE_DATA_WIDTH-1:0] s_axi4lite_wdata,
+# input logic s_axi4lite_wvalid,
+# output logic s_axi4lite_wready,
+# input logic [AXI_LITE_DATA_WIDTH/8-1:0] s_axi4lite_wstrb,
+#
+# output logic [1:0] s_axi4lite_bresp,
+# output logic s_axi4lite_bvalid,
+# input logic s_axi4lite_bready,
+#
+# input logic [AXI_LITE_ADDR_WIDTH-1:0] s_axi4lite_araddr,
+# input logic s_axi4lite_arvalid,
+# output logic s_axi4lite_arready,
+#
+# output logic [AXI_LITE_DATA_WIDTH-1:0] s_axi4lite_rdata,
+# output logic [1:0] s_axi4lite_rresp,
+# output logic s_axi4lite_rvalid,
+# input logic s_axi4lite_rready,
+# // }}}
+#
+# // BRAMs {{{
+# //`ifdef RAB_AX_LOG_EN
+# // BramPort.Slave ArBram_PS,
+# // BramPort.Slave AwBram_PS,
+# //`endif
+# // }}}
+#
+# // Logger Control {{{
+# //`ifdef RAB_AX_LOG_EN
+# // input logic LogEn_SI,
+# // input logic ArLogClr_SI,
+# // input logic AwLogClr_SI,
+# // output logic ArLogRdy_SO,
+# // output logic AwLogRdy_SO,
+# //`endif
+# // }}}
+#
+# // Interrupt Outputs {{{
+# // Interrupt lines to handle misses, collisions of slices/multiple hits,
+# // protection faults and overflow of the miss handling fifo
+# //`ifdef RAB_AX_LOG_EN
+# // output logic int_ar_log_full,
+# // output logic int_aw_log_full,
+# //`endif
+# output logic [N_PORTS-1:0] int_miss,
+# output logic [N_PORTS-1:0] int_multi,
+# output logic [N_PORTS-1:0] int_prot,
+# output logic int_mhf_full
+# // }}}
+#
+# );
+#
+"""#docstring_begin
+
+ // }}}
+
+ // Signals {{{
+ // ███████╗██╗ ██████╗ ███╗ ██╗ █████╗ ██╗ ███████╗
+ // ██╔════╝██║██╔════╝ ████╗ ██║██╔══██╗██║ ██╔════╝
+ // ███████╗██║██║ ███╗██╔██╗ ██║███████║██║ ███████╗
+ // ╚════██║██║██║ ██║██║╚██╗██║██╔══██║██║ ╚════██║
+ // ███████║██║╚██████╔╝██║ ╚████║██║ ██║███████╗███████║
+ // ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝╚══════╝
+ //
+
+ // Internal AXI4 lines, these connect buffers on the slave side to the rab core and
+ // multiplexers which switch between the two master outputs
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_awid;
+ logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] int_awaddr;
+ logic [N_PORTS-1:0] int_awvalid;
+ logic [N_PORTS-1:0] int_awready;
+ logic [N_PORTS-1:0] [7:0] int_awlen;
+ logic [N_PORTS-1:0] [2:0] int_awsize;
+ logic [N_PORTS-1:0] [1:0] int_awburst;
+ logic [N_PORTS-1:0] int_awlock;
+ logic [N_PORTS-1:0] [2:0] int_awprot;
+ logic [N_PORTS-1:0] [3:0] int_awcache;
+ logic [N_PORTS-1:0] [3:0] int_awregion;
+ logic [N_PORTS-1:0] [3:0] int_awqos;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_awuser;
+
+ logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] int_wdata;
+ logic [N_PORTS-1:0] int_wvalid;
+ logic [N_PORTS-1:0] int_wready;
+ logic [N_PORTS-1:0] [AXI_DATA_WIDTH/8-1:0] int_wstrb;
+ logic [N_PORTS-1:0] int_wlast;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_wuser;
+
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_bid;
+ logic [N_PORTS-1:0] [1:0] int_bresp;
+ logic [N_PORTS-1:0] int_bvalid;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_buser;
+ logic [N_PORTS-1:0] int_bready;
+
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_arid;
+ logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] int_araddr;
+ logic [N_PORTS-1:0] int_arvalid;
+ logic [N_PORTS-1:0] int_arready;
+ logic [N_PORTS-1:0] [7:0] int_arlen;
+ logic [N_PORTS-1:0] [2:0] int_arsize;
+ logic [N_PORTS-1:0] [1:0] int_arburst;
+ logic [N_PORTS-1:0] int_arlock;
+ logic [N_PORTS-1:0] [2:0] int_arprot;
+ logic [N_PORTS-1:0] [3:0] int_arcache;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_aruser;
+
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_rid;
+ logic [N_PORTS-1:0] [1:0] int_rresp;
+ logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] int_rdata;
+ logic [N_PORTS-1:0] int_rlast;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_ruser;
+ logic [N_PORTS-1:0] int_rvalid;
+ logic [N_PORTS-1:0] int_rready;
+
+ // rab_core outputs
+ logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] int_wtrans_addr;
+ logic [N_PORTS-1:0] int_wtrans_accept;
+ logic [N_PORTS-1:0] int_wtrans_drop;
+ logic [N_PORTS-1:0] int_wtrans_miss;
+ logic [N_PORTS-1:0] int_wtrans_sent;
+ logic [N_PORTS-1:0] int_wtrans_cache_coherent;
+ logic [N_PORTS-1:0] int_wmaster_select;
+
+ logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] int_rtrans_addr;
+ logic [N_PORTS-1:0] int_rtrans_accept;
+ logic [N_PORTS-1:0] int_rtrans_drop;
+ logic [N_PORTS-1:0] int_rtrans_miss;
+ logic [N_PORTS-1:0] int_rtrans_sent;
+ logic [N_PORTS-1:0] int_rtrans_cache_coherent;
+ logic [N_PORTS-1:0] int_rmaster_select;
+
+ logic [N_PORTS-1:0] w_master_select;
+
+ // Internal master0 AXI4 lines. These connect the first master port to the
+ // multiplexers
+ // For channels read address, write address and write data the other lines
+ // are ignored if valid is not set, therefore we only need to multiplex those
+ logic [N_PORTS-1:0] int_m0_awvalid;
+ logic [N_PORTS-1:0] int_m0_awready;
+
+ logic [N_PORTS-1:0] int_m0_wvalid;
+ logic [N_PORTS-1:0] int_m0_wready;
+
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_m0_bid;
+ logic [N_PORTS-1:0] [1:0] int_m0_bresp;
+ logic [N_PORTS-1:0] int_m0_bvalid;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_m0_buser;
+ logic [N_PORTS-1:0] int_m0_bready;
+
+ logic [N_PORTS-1:0] int_m0_arvalid;
+ logic [N_PORTS-1:0] int_m0_arready;
+
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_m0_rid;
+ logic [N_PORTS-1:0] [1:0] int_m0_rresp;
+ logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] int_m0_rdata;
+ logic [N_PORTS-1:0] int_m0_rlast;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_m0_ruser;
+ logic [N_PORTS-1:0] int_m0_rready;
+ logic [N_PORTS-1:0] int_m0_rvalid;
+
+ logic [N_PORTS-1:0] l1_m0_ar_accept;
+ logic [N_PORTS-1:0] l1_m0_ar_drop;
+ logic [N_PORTS-1:0] l1_m0_ar_save;
+ logic [N_PORTS-1:0] l1_m0_ar_done;
+ logic [N_PORTS-1:0] l2_m0_ar_accept;
+ logic [N_PORTS-1:0] l2_m0_ar_drop;
+ logic [N_PORTS-1:0] l2_m0_ar_done;
+ logic [N_PORTS-1:0] l2_m0_ar_sending;
+
+ logic [N_PORTS-1:0] l1_m0_aw_accept;
+ logic [N_PORTS-1:0] l1_m0_aw_drop;
+ logic [N_PORTS-1:0] l1_m0_aw_save;
+ logic [N_PORTS-1:0] l1_m0_aw_done;
+ logic [N_PORTS-1:0] l2_m0_aw_accept;
+ logic [N_PORTS-1:0] l2_m0_aw_drop;
+ logic [N_PORTS-1:0] l2_m0_aw_done;
+ logic [N_PORTS-1:0] l2_m0_aw_sending;
+
+ // Internal master1 AXI4 lines. These connect the second master port to the
+ // multiplexers
+ // For channels read address, write address and write data the other lines
+ // are ignored if valid is not set, therefore we only need to multiplex those
+ logic [N_PORTS-1:0] int_m1_awvalid;
+ logic [N_PORTS-1:0] int_m1_awready;
+
+ logic [N_PORTS-1:0] int_m1_wvalid;
+ logic [N_PORTS-1:0] int_m1_wready;
+
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_m1_bid;
+ logic [N_PORTS-1:0] [1:0] int_m1_bresp;
+ logic [N_PORTS-1:0] int_m1_bvalid;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_m1_buser;
+ logic [N_PORTS-1:0] int_m1_bready;
+
+ logic [N_PORTS-1:0] int_m1_arvalid;
+ logic [N_PORTS-1:0] int_m1_arready;
+
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] int_m1_rid;
+ logic [N_PORTS-1:0] [1:0] int_m1_rresp;
+ logic [N_PORTS-1:0] [AXI_DATA_WIDTH-1:0] int_m1_rdata;
+ logic [N_PORTS-1:0] int_m1_rlast;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] int_m1_ruser;
+ logic [N_PORTS-1:0] int_m1_rvalid;
+ logic [N_PORTS-1:0] int_m1_rready;
+
+ logic [N_PORTS-1:0] l1_m1_ar_accept;
+ logic [N_PORTS-1:0] l1_m1_ar_drop;
+ logic [N_PORTS-1:0] l1_m1_ar_save;
+ logic [N_PORTS-1:0] l1_m1_ar_done;
+ logic [N_PORTS-1:0] l2_m1_ar_accept;
+ logic [N_PORTS-1:0] l2_m1_ar_drop;
+ logic [N_PORTS-1:0] l2_m1_ar_done;
+
+ logic [N_PORTS-1:0] l1_m1_aw_accept;
+ logic [N_PORTS-1:0] l1_m1_aw_drop;
+ logic [N_PORTS-1:0] l1_m1_aw_save;
+ logic [N_PORTS-1:0] l1_m1_aw_done;
+ logic [N_PORTS-1:0] l2_m1_aw_accept;
+ logic [N_PORTS-1:0] l2_m1_aw_drop;
+ logic [N_PORTS-1:0] l2_m1_aw_done;
+
+ // L1 outputs
+ logic [N_PORTS-1:0] rab_miss; // L1 RAB miss
+ logic [N_PORTS-1:0] rab_prot;
+ logic [N_PORTS-1:0] rab_multi;
+ logic [N_PORTS-1:0] rab_prefetch;
+
+ //
+ // Signals used to support L2 TLB
+ //
+ // L2 RAM configuration signals
+ logic [N_PORTS-1:0] [AXI_LITE_DATA_WIDTH-1:0] L2CfgWData_D;
+ logic [N_PORTS-1:0] [AXI_LITE_ADDR_WIDTH-1:0] L2CfgWAddr_D;
+ logic [N_PORTS-1:0] L2CfgWE_S;
+
+ // L1 output and drop Buffer
+ logic [N_PORTS-1:0] L1OutRwType_D, L1DropRwType_DP;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] L1OutUser_D, L1DropUser_DP;
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] L1OutId_D, L1DropId_DP;
+ logic [N_PORTS-1:0] [7:0] L1OutLen_D, L1DropLen_DP;
+ logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] L1OutAddr_D, L1DropAddr_DP;
+ logic [N_PORTS-1:0] L1OutProt_D, L1DropProt_DP;
+ logic [N_PORTS-1:0] L1OutMulti_D, L1DropMulti_DP;
+ logic [N_PORTS-1:0] L1DropEn_S;
+ logic [N_PORTS-1:0] L1DropPrefetch_S;
+
+ logic [N_PORTS-1:0] L1DropValid_SN, L1DropValid_SP;
+
+ // L2 input Buffer
+ logic [N_PORTS-1:0] L2InRwType_DP;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] L2InUser_DP;
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] L2InId_DP;
+ logic [N_PORTS-1:0] [7:0] L2InLen_DP;
+ logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] L2InAddr_DP;
+ logic [N_PORTS-1:0] L2InEn_S;
+
+ // L2 output Buffer
+ logic [N_PORTS-1:0] L2OutRwType_DP;
+ logic [N_PORTS-1:0] [AXI_USER_WIDTH-1:0] L2OutUser_DP;
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] L2OutId_DP;
+ logic [N_PORTS-1:0] [7:0] L2OutLen_DP;
+ logic [N_PORTS-1:0] [AXI_S_ADDR_WIDTH-1:0] L2OutInAddr_DP;
+
+ logic [N_PORTS-1:0] L2OutHit_SN, L2OutHit_SP;
+ logic [N_PORTS-1:0] L2OutMiss_SN, L2OutMiss_SP;
+ logic [N_PORTS-1:0] L2OutProt_SN, L2OutProt_SP;
+ logic [N_PORTS-1:0] L2OutMulti_SN, L2OutMulti_SP;
+ logic [N_PORTS-1:0] L2OutCC_SN, L2OutCC_SP;
+ logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] L2OutAddr_DN, L2OutAddr_DP;
+
+ logic [N_PORTS-1:0] L2OutValid_SN, L2OutValid_SP;
+ logic [N_PORTS-1:0] L2OutPrefetch_S;
+ logic [N_PORTS-1:0] L2OutReady_S;
+ logic [N_PORTS-1:0] L2OutEn_S;
+
+ // L2 outputs
+ logic [N_PORTS-1:0] L2Busy_S;
+ logic [N_PORTS-1:0] L2OutValid_S;
+
+ logic [N_PORTS-1:0] L2Miss_S;
+
+ // Signals for interfacing the AXI modules
+ logic [N_PORTS-1:0] l1_ar_accept;
+ logic [N_PORTS-1:0] l1_aw_accept;
+ logic [N_PORTS-1:0] l1_w_accept;
+ logic [N_PORTS-1:0] l1_xw_accept;
+
+ logic [N_PORTS-1:0] l1_ar_drop;
+ logic [N_PORTS-1:0] l1_aw_drop;
+ logic [N_PORTS-1:0] l1_w_drop;
+ logic [N_PORTS-1:0] l1_xw_drop;
+
+ logic [N_PORTS-1:0] l1_ar_save;
+ logic [N_PORTS-1:0] l1_aw_save;
+ logic [N_PORTS-1:0] l1_w_save;
+ logic [N_PORTS-1:0] l1_xw_save;
+
+ logic [N_PORTS-1:0] l1_ar_done;
+ logic [N_PORTS-1:0] l1_r_done;
+ logic [N_PORTS-1:0] l1_r_drop;
+ logic [N_PORTS-1:0] lx_r_drop;
+ logic [N_PORTS-1:0] lx_r_done;
+
+ logic [N_PORTS-1:0] l1_aw_done;
+ logic [N_PORTS-1:0] l1_w_done;
+ logic [N_PORTS-1:0] l1_xw_done;
+ logic [N_PORTS-1:0] l1_aw_done_SP;
+ logic [N_PORTS-1:0] l1_w_done_SP;
+
+ logic [N_PORTS-1:0] l2_ar_accept;
+ logic [N_PORTS-1:0] l2_aw_accept;
+ logic [N_PORTS-1:0] l2_w_accept;
+ logic [N_PORTS-1:0] l2_xw_accept;
+
+ logic [N_PORTS-1:0] l2_ar_drop;
+ logic [N_PORTS-1:0] l2_r_drop;
+ logic [N_PORTS-1:0] l2_xr_drop;
+ logic [N_PORTS-1:0] l2_aw_drop;
+ logic [N_PORTS-1:0] l2_w_drop;
+ logic [N_PORTS-1:0] l2_xw_drop;
+
+ logic [N_PORTS-1:0] l2_aw_done;
+ logic [N_PORTS-1:0] l2_w_done;
+ logic [N_PORTS-1:0] l2_xw_done;
+ logic [N_PORTS-1:0] l2_aw_done_SP;
+ logic [N_PORTS-1:0] l2_w_done_SP;
+
+ logic [N_PORTS-1:0] l2_ar_done;
+ logic [N_PORTS-1:0] l2_r_done;
+ logic [N_PORTS-1:0] l2_xr_done;
+ logic [N_PORTS-1:0] l2_ar_done_SP;
+ logic [N_PORTS-1:0] l2_r_done_SP;
+
+ logic [N_PORTS-1:0] l1_mx_aw_done;
+ logic [N_PORTS-1:0] l1_mx_ar_done;
+ logic [N_PORTS-1:0] l1_m0_aw_done_SP;
+ logic [N_PORTS-1:0] l1_m0_ar_done_SP;
+ logic [N_PORTS-1:0] l1_m1_aw_done_SP;
+ logic [N_PORTS-1:0] l1_m1_ar_done_SP;
+
+ logic [N_PORTS-1:0] l2_mx_aw_done;
+ logic [N_PORTS-1:0] l2_mx_ar_done;
+ logic [N_PORTS-1:0] l2_m0_aw_done_SP;
+ logic [N_PORTS-1:0] l2_m0_ar_done_SP;
+ logic [N_PORTS-1:0] l2_m1_aw_done_SP;
+ logic [N_PORTS-1:0] l2_m1_ar_done_SP;
+
+ logic [N_PORTS-1:0] [AXI_ID_WIDTH-1:0] l1_id_drop, lx_id_drop, b_id_drop;
+ logic [N_PORTS-1:0] [7:0] l1_len_drop, lx_len_drop;
+ logic [N_PORTS-1:0] l1_prefetch_drop, lx_prefetch_drop, b_prefetch_drop;
+ logic [N_PORTS-1:0] l1_hit_drop, lx_hit_drop, b_hit_drop;
+
+ logic [N_PORTS-1:0] b_drop;
+ logic [N_PORTS-1:0] b_done;
+
+ logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] l2_aw_addr;
+ logic [N_PORTS-1:0] [AXI_M_ADDR_WIDTH-1:0] l2_ar_addr;
+
+ logic [N_PORTS-1:0] l2_cache_coherent;
+ logic [N_PORTS-1:0] l2_master_select;
+
+ logic [N_PORTS-1:0] aw_in_stall;
+ logic [N_PORTS-1:0] aw_out_stall;
+
+ genvar i;
+
+ // RRESP FSM
+ typedef enum logic {IDLE, BUSY} r_resp_mux_ctrl_state_t;
+ r_resp_mux_ctrl_state_t [N_PORTS-1:0] RRespMuxCtrl_SN, RRespMuxCtrl_SP;
+ logic [N_PORTS-1:0] RRespSel_SN, RRespSel_SP;
+ logic [N_PORTS-1:0] RRespBurst_S;
+ logic [N_PORTS-1:0] RRespSelIm_S;
+
+ // }}}
+
+ // Local parameters {{{
+
+ // Enable L2 for select ports
+ localparam integer ENABLE_L2TLB[N_PORTS-1:0] = `EN_L2TLB_ARRAY;
+
+ // L2TLB parameters
+ localparam integer HUM_BUFFER_DEPTH = (N_L2_SET_ENTRIES/2/`RAB_L2_N_PAR_VA_RAMS)+13;
+
+ // }}}
+
+ // Derive `master_select` from cache coherency flag. {{{
+ `ifdef EN_ACP
+ assign int_wmaster_select = int_wtrans_cache_coherent;
+ assign int_rmaster_select = int_rtrans_cache_coherent;
+ assign l2_master_select = l2_cache_coherent;
+ `else
+ assign int_wmaster_select = '0;
+ assign int_rmaster_select = '0;
+ assign l2_master_select = '0;
+ `endif
+ // }}}
+
+ // Buf and Send {{{
+ // ██████╗ ██╗ ██╗███████╗ ██╗ ███████╗███████╗███╗ ██╗██████╗
+ // ██╔══██╗██║ ██║██╔════╝ ██║ ██╔════╝██╔════╝████╗ ██║██╔══██╗
+ // ██████╔╝██║ ██║█████╗ ████████╗ ███████╗█████╗ ██╔██╗ ██║██║ ██║
+ // ██╔══██╗██║ ██║██╔══╝ ██╔═██╔═╝ ╚════██║██╔══╝ ██║╚██╗██║██║ ██║
+ // ██████╔╝╚██████╔╝██║ ██████║ ███████║███████╗██║ ╚████║██████╔╝
+ // ╚═════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═══╝╚═════╝
+ //
+ logic[N_PORTS-1:0] m0_write_is_burst, m0_read_is_burst;
+ logic[N_PORTS-1:0] m1_write_is_burst, m1_read_is_burst;
+
+ generate for (i = 0; i < N_PORTS; i++) begin : BUF_AND_SEND
+
+ // Write Address channel (aw) {{{
+ /*
+ * write address channel (aw)
+ *
+ * ██╗ ██╗██████╗ ██╗████████╗███████╗ █████╗ ██████╗ ██████╗ ██████╗
+ * ██║ ██║██╔══██╗██║╚══██╔══╝██╔════╝ ██╔══██╗██╔══██╗██╔══██╗██╔══██╗
+ * ██║ █╗ ██║██████╔╝██║ ██║ █████╗ ███████║██║ ██║██║ ██║██████╔╝
+ * ██║███╗██║██╔══██╗██║ ██║ ██╔══╝ ██╔══██║██║ ██║██║ ██║██╔══██╗
+ * ╚███╔███╔╝██║ ██║██║ ██║ ███████╗ ██║ ██║██████╔╝██████╔╝██║ ██║
+ * ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝
+ *
+ */
+
+ axi4_aw_buffer
+ #(
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_aw_buffer
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .s_axi4_awid ( s_axi4_awid[i] ),
+ .s_axi4_awaddr ( s_axi4_awaddr[i] ),
+ .s_axi4_awvalid ( s_axi4_awvalid[i] ),
+ .s_axi4_awready ( s_axi4_awready[i] ),
+ .s_axi4_awlen ( s_axi4_awlen[i] ),
+ .s_axi4_awsize ( s_axi4_awsize[i] ),
+ .s_axi4_awburst ( s_axi4_awburst[i] ),
+ .s_axi4_awlock ( s_axi4_awlock[i] ),
+ .s_axi4_awprot ( s_axi4_awprot[i] ),
+ .s_axi4_awcache ( s_axi4_awcache[i] ),
+ .s_axi4_awregion ( s_axi4_awregion[i] ),
+ .s_axi4_awqos ( s_axi4_awqos[i] ),
+ .s_axi4_awuser ( s_axi4_awuser[i] ),
+ .m_axi4_awid ( int_awid[i] ),
+ .m_axi4_awaddr ( int_awaddr[i] ),
+ .m_axi4_awvalid ( int_awvalid[i] ),
+ .m_axi4_awready ( int_awready[i] ),
+ .m_axi4_awlen ( int_awlen[i] ),
+ .m_axi4_awsize ( int_awsize[i] ),
+ .m_axi4_awburst ( int_awburst[i] ),
+ .m_axi4_awlock ( int_awlock[i] ),
+ .m_axi4_awprot ( int_awprot[i] ),
+ .m_axi4_awcache ( int_awcache[i] ),
+ .m_axi4_awregion ( int_awregion[i] ),
+ .m_axi4_awqos ( int_awqos[i] ),
+ .m_axi4_awuser ( int_awuser[i] )
+ );
+
+ axi4_aw_sender
+ #(
+ .AXI_ADDR_WIDTH ( AXI_M_ADDR_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH ),
+ .ENABLE_L2TLB ( ENABLE_L2TLB[i] )
+ )
+ u_aw_sender_m0
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .l1_done_o ( l1_m0_aw_done[i] ),
+ .l1_accept_i ( l1_m0_aw_accept[i] ),
+ .l1_drop_i ( l1_m0_aw_drop[i] ),
+ .l1_save_i ( l1_m0_aw_save[i] ),
+ .l2_done_o ( l2_m0_aw_done[i] ),
+ .l2_accept_i ( l2_m0_aw_accept[i] ),
+ .l2_drop_i ( l2_m0_aw_drop[i] ),
+ .l2_sending_o ( l2_m0_aw_sending[i] ),
+ .l1_awaddr_i ( int_wtrans_addr[i] ),
+ .l2_awaddr_i ( l2_aw_addr[i] ),
+ .s_axi4_awid ( int_awid[i] ),
+ .s_axi4_awvalid ( int_m0_awvalid[i] ),
+ .s_axi4_awready ( int_m0_awready[i] ),
+ .s_axi4_awlen ( int_awlen[i] ),
+ .s_axi4_awsize ( int_awsize[i] ),
+ .s_axi4_awburst ( int_awburst[i] ),
+ .s_axi4_awlock ( int_awlock[i] ),
+ .s_axi4_awprot ( int_awprot[i] ),
+ .s_axi4_awcache ( int_awcache[i] ),
+ .s_axi4_awregion ( int_awregion[i] ),
+ .s_axi4_awqos ( int_awqos[i] ),
+ .s_axi4_awuser ( int_awuser[i] ),
+ .m_axi4_awid ( m0_axi4_awid[i] ),
+ .m_axi4_awaddr ( m0_axi4_awaddr[i] ),
+ .m_axi4_awvalid ( m0_axi4_awvalid[i] ),
+ .m_axi4_awready ( m0_axi4_awready[i] ),
+ .m_axi4_awlen ( m0_axi4_awlen[i] ),
+ .m_axi4_awsize ( m0_axi4_awsize[i] ),
+ .m_axi4_awburst ( m0_axi4_awburst[i] ),
+ .m_axi4_awlock ( m0_axi4_awlock[i] ),
+ .m_axi4_awprot ( m0_axi4_awprot[i] ),
+ .m_axi4_awcache ( ),
+ .m_axi4_awregion ( m0_axi4_awregion[i] ),
+ .m_axi4_awqos ( m0_axi4_awqos[i] ),
+ .m_axi4_awuser ( m0_axi4_awuser[i] )
+ );
+
+ // The AXCACHE signals are set according to burstiness and cache coherence or statically
+ // when not connected to ACP on Zynq (implemented below).
+ assign m0_write_is_burst[i] = (m0_axi4_awlen[i] != {8{1'b0}}) && (m0_axi4_awburst[i] != 2'b00);
+ `ifndef EN_ACP
+ always_comb begin
+ if ( (l2_m0_aw_sending[i] & l2_cache_coherent[i]) | int_wtrans_cache_coherent[i]) begin
+ if (m0_write_is_burst[i]) begin
+ m0_axi4_awcache[i] = 4'b0111;
+ end else begin
+ m0_axi4_awcache[i] = 4'b1111;
+ end
+ end else begin
+ m0_axi4_awcache[i] = 4'b0011;
+ end
+ end
+ `else
+ assign m0_axi4_awcache[i] = 4'b0011;
+ `endif
+
+ axi4_aw_sender
+ #(
+ .AXI_ADDR_WIDTH ( AXI_M_ADDR_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH ),
+ .ENABLE_L2TLB ( ENABLE_L2TLB[i] )
+ )
+ u_aw_sender_m1
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .l1_accept_i ( l1_m1_aw_accept[i] ),
+ .l1_drop_i ( l1_m1_aw_drop[i] ),
+ .l1_save_i ( l1_m1_aw_save[i] ),
+ .l1_done_o ( l1_m1_aw_done[i] ),
+ .l2_accept_i ( l2_m1_aw_accept[i] ),
+ .l2_drop_i ( l2_m1_aw_drop[i] ),
+ .l2_done_o ( l2_m1_aw_done[i] ),
+ .l2_sending_o ( ), // just helps to set axcache
+ .l1_awaddr_i ( int_wtrans_addr[i] ),
+ .l2_awaddr_i ( l2_aw_addr[i] ),
+ .s_axi4_awid ( int_awid[i] ),
+ .s_axi4_awvalid ( int_m1_awvalid[i] ),
+ .s_axi4_awready ( int_m1_awready[i] ),
+ .s_axi4_awlen ( int_awlen[i] ),
+ .s_axi4_awsize ( int_awsize[i] ),
+ .s_axi4_awburst ( int_awburst[i] ),
+ .s_axi4_awlock ( int_awlock[i] ),
+ .s_axi4_awprot ( int_awprot[i] ),
+ .s_axi4_awcache ( int_awcache[i] ),
+ .s_axi4_awregion ( int_awregion[i] ),
+ .s_axi4_awqos ( int_awqos[i] ),
+ .s_axi4_awuser ( int_awuser[i] ),
+ .m_axi4_awid ( m1_axi4_awid[i] ),
+ .m_axi4_awaddr ( m1_axi4_awaddr[i] ),
+ .m_axi4_awvalid ( m1_axi4_awvalid[i] ),
+ .m_axi4_awready ( m1_axi4_awready[i] ),
+ .m_axi4_awlen ( m1_axi4_awlen[i] ),
+ .m_axi4_awsize ( m1_axi4_awsize[i] ),
+ .m_axi4_awburst ( m1_axi4_awburst[i] ),
+ .m_axi4_awlock ( m1_axi4_awlock[i] ),
+ .m_axi4_awprot ( m1_axi4_awprot[i] ),
+ .m_axi4_awcache ( ),
+ .m_axi4_awregion ( m1_axi4_awregion[i] ),
+ .m_axi4_awqos ( m1_axi4_awqos[i] ),
+ .m_axi4_awuser ( m1_axi4_awuser[i] )
+ );
+
+ // The AXCACHE signals are set according to burstiness and cache coherence or statically
+ // when not connected to ACP on Zynq (implemented below).
+ assign m1_write_is_burst[i] = (m1_axi4_awlen[i] != {8{1'b0}}) && (m1_axi4_awburst[i] != 2'b00);
+ `ifdef EN_ACP
+ always_comb begin
+ if (m1_write_is_burst[i]) begin
+ m1_axi4_awcache[i] = 4'b1011;
+ end else begin
+ m1_axi4_awcache[i] = 4'b1111;
+ end
+ end
+ `else
+ assign m1_axi4_awcache[i] = 4'b0011;
+ `endif
+
+ // }}}
+
+ // Write Data channel (w) {{{
+ /*
+ * write data channel (w)
+ *
+ * ██╗ ██╗██████╗ ██╗████████╗███████╗ ██████╗ █████╗ ████████╗ █████╗
+ * ██║ ██║██╔══██╗██║╚══██╔══╝██╔════╝ ██╔══██╗██╔══██╗╚══██╔══╝██╔══██╗
+ * ██║ █╗ ██║██████╔╝██║ ██║ █████╗ ██║ ██║███████║ ██║ ███████║
+ * ██║███╗██║██╔══██╗██║ ██║ ██╔══╝ ██║ ██║██╔══██║ ██║ ██╔══██║
+ * ╚███╔███╔╝██║ ██║██║ ██║ ███████╗ ██████╔╝██║ ██║ ██║ ██║ ██║
+ * ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
+ *
+ */
+ axi4_w_buffer
+ #(
+ .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH ),
+ .ENABLE_L2TLB ( ENABLE_L2TLB[i] ),
+ .HUM_BUFFER_DEPTH ( HUM_BUFFER_DEPTH )
+ )
+ u_w_buffer
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+
+ // L1 interface
+ .l1_done_o ( l1_w_done[i] ),
+ .l1_accept_i ( l1_w_accept[i] ),
+ .l1_save_i ( l1_w_save[i] ),
+ .l1_drop_i ( l1_w_drop[i] ),
+ .l1_master_i ( int_wmaster_select[i] ),
+ .l1_id_i ( l1_id_drop[i] ),
+ .l1_len_i ( l1_len_drop[i] ),
+ .l1_prefetch_i ( l1_prefetch_drop[i] ),
+ .l1_hit_i ( l1_hit_drop[i] ),
+
+ // L2 interface
+ .l2_done_o ( l2_w_done[i] ),
+ .l2_accept_i ( l2_w_accept[i] ),
+ .l2_drop_i ( l2_w_drop[i] ),
+ .l2_master_i ( l2_master_select[i] ),
+ .l2_id_i ( lx_id_drop[i] ),
+ .l2_len_i ( lx_len_drop[i] ),
+ .l2_prefetch_i ( lx_prefetch_drop[i] ),
+ .l2_hit_i ( lx_hit_drop[i] ),
+
+ // Top-level control outputs
+ .master_select_o ( w_master_select[i] ),
+ .input_stall_o ( aw_in_stall[i] ), // stall L1 AW input if request buffers full
+ .output_stall_o ( aw_out_stall[i] ), // stall L1 AW hit forwarding if bypass not possible
+
+ // B sender interface
+ .b_drop_o ( b_drop[i] ),
+ .b_done_i ( b_done[i] ),
+ .id_o ( b_id_drop[i] ),
+ .prefetch_o ( b_prefetch_drop[i] ),
+ .hit_o ( b_hit_drop[i] ),
+
+ // AXI W channel interfaces
+ .s_axi4_wdata ( s_axi4_wdata[i] ),
+ .s_axi4_wvalid ( s_axi4_wvalid[i] ),
+ .s_axi4_wready ( s_axi4_wready[i] ),
+ .s_axi4_wstrb ( s_axi4_wstrb[i] ),
+ .s_axi4_wlast ( s_axi4_wlast[i] ),
+ .s_axi4_wuser ( s_axi4_wuser[i] ),
+ .m_axi4_wdata ( int_wdata[i] ),
+ .m_axi4_wvalid ( int_wvalid[i] ),
+ .m_axi4_wready ( int_wready[i] ),
+ .m_axi4_wstrb ( int_wstrb[i] ),
+ .m_axi4_wlast ( int_wlast[i] ),
+ .m_axi4_wuser ( int_wuser[i] )
+ );
+
+ axi4_w_sender
+ #(
+ .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_w_sender_m0
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .s_axi4_wdata ( int_wdata[i] ),
+ .s_axi4_wvalid ( int_m0_wvalid[i] ),
+ .s_axi4_wready ( int_m0_wready[i] ),
+ .s_axi4_wstrb ( int_wstrb[i] ),
+ .s_axi4_wlast ( int_wlast[i] ),
+ .s_axi4_wuser ( int_wuser[i] ),
+ .m_axi4_wdata ( m0_axi4_wdata[i] ),
+ .m_axi4_wvalid ( m0_axi4_wvalid[i] ),
+ .m_axi4_wready ( m0_axi4_wready[i] ),
+ .m_axi4_wstrb ( m0_axi4_wstrb[i] ),
+ .m_axi4_wlast ( m0_axi4_wlast[i] ),
+ .m_axi4_wuser ( m0_axi4_wuser[i] )
+ );
+
+ axi4_w_sender
+ #(
+ .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+
+ )
+ u_w_sender_m1
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .s_axi4_wdata ( int_wdata[i] ),
+ .s_axi4_wvalid ( int_m1_wvalid[i] ),
+ .s_axi4_wready ( int_m1_wready[i] ),
+ .s_axi4_wstrb ( int_wstrb[i] ),
+ .s_axi4_wlast ( int_wlast[i] ),
+ .s_axi4_wuser ( int_wuser[i] ),
+ .m_axi4_wdata ( m1_axi4_wdata[i] ),
+ .m_axi4_wvalid ( m1_axi4_wvalid[i] ),
+ .m_axi4_wready ( m1_axi4_wready[i] ),
+ .m_axi4_wstrb ( m1_axi4_wstrb[i] ),
+ .m_axi4_wlast ( m1_axi4_wlast[i] ),
+ .m_axi4_wuser ( m1_axi4_wuser[i] )
+ );
+
+ /*
+ * Multiplexer to switch between the two output master ports on the write data (w) channel
+ */
+ always_comb begin
+ /* Only one output can be selected at any time */
+ if (w_master_select[i] == 1'b0) begin
+ int_m0_wvalid[i] = int_wvalid[i];
+ int_m1_wvalid[i] = 1'b0;
+ int_wready[i] = int_m0_wready[i];
+ end else begin
+ int_m0_wvalid[i] = 1'b0;
+ int_m1_wvalid[i] = int_wvalid[i];
+ int_wready[i] = int_m1_wready[i];
+ end
+ end
+
+ // }}}
+
+ // Write Response channel (b) {{{
+ /*
+ * write response channel (b)
+ *
+ * ██╗ ██╗██████╗ ██╗████████╗███████╗ ██████╗ ███████╗███████╗██████╗
+ * ██║ ██║██╔══██╗██║╚══██╔══╝██╔════╝ ██╔══██╗██╔════╝██╔════╝██╔══██╗
+ * ██║ █╗ ██║██████╔╝██║ ██║ █████╗ ██████╔╝█████╗ ███████╗██████╔╝
+ * ██║███╗██║██╔══██╗██║ ██║ ██╔══╝ ██╔══██╗██╔══╝ ╚════██║██╔═══╝
+ * ╚███╔███╔╝██║ ██║██║ ██║ ███████╗ ██║ ██║███████╗███████║██║
+ * ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝
+ *
+ */
+ axi4_b_buffer
+ #(
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_b_buffer_m0
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .s_axi4_bid ( int_m0_bid[i] ),
+ .s_axi4_bresp ( int_m0_bresp[i] ),
+ .s_axi4_bvalid ( int_m0_bvalid[i] ),
+ .s_axi4_buser ( int_m0_buser[i] ),
+ .s_axi4_bready ( int_m0_bready[i] ),
+ .m_axi4_bid ( m0_axi4_bid[i] ),
+ .m_axi4_bresp ( m0_axi4_bresp[i] ),
+ .m_axi4_bvalid ( m0_axi4_bvalid[i] ),
+ .m_axi4_buser ( m0_axi4_buser[i] ),
+ .m_axi4_bready ( m0_axi4_bready[i] )
+ );
+
+ axi4_b_buffer
+ #(
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_b_buffer_m1
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .s_axi4_bid ( int_m1_bid[i] ),
+ .s_axi4_bresp ( int_m1_bresp[i] ),
+ .s_axi4_bvalid ( int_m1_bvalid[i] ),
+ .s_axi4_buser ( int_m1_buser[i] ),
+ .s_axi4_bready ( int_m1_bready[i] ),
+ .m_axi4_bid ( m1_axi4_bid[i] ),
+ .m_axi4_bresp ( m1_axi4_bresp[i] ),
+ .m_axi4_bvalid ( m1_axi4_bvalid[i] ),
+ .m_axi4_buser ( m1_axi4_buser[i] ),
+ .m_axi4_bready ( m1_axi4_bready[i] )
+ );
+
+ axi4_b_sender
+ #(
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_b_sender
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .drop_i ( b_drop[i] ),
+ .done_o ( b_done[i] ),
+ .id_i ( b_id_drop[i] ),
+ .prefetch_i ( b_prefetch_drop[i] ),
+ .hit_i ( b_hit_drop[i] ),
+ .s_axi4_bid ( s_axi4_bid[i] ),
+ .s_axi4_bresp ( s_axi4_bresp[i] ),
+ .s_axi4_bvalid ( s_axi4_bvalid[i] ),
+ .s_axi4_buser ( s_axi4_buser[i] ),
+ .s_axi4_bready ( s_axi4_bready[i] ),
+ .m_axi4_bid ( int_bid[i] ),
+ .m_axi4_bresp ( int_bresp[i] ),
+ .m_axi4_bvalid ( int_bvalid[i] ),
+ .m_axi4_buser ( int_buser[i] ),
+ .m_axi4_bready ( int_bready[i] )
+ );
+
+ /*
+ * Multiplexer to switch between the two output master ports on the write response (b) channel
+ */
+ always_comb begin
+ /* Output 1 always gets priority, so if it has something to send connect
+ it and let output 0 wait using rready = 0 */
+ if (int_m1_bvalid[i] == 1'b1) begin
+ int_m0_bready[i] = 1'b0;
+ int_m1_bready[i] = int_bready[i];
+
+ int_bid[i] = int_m1_bid[i];
+ int_bresp[i] = int_m1_bresp[i];
+ int_buser[i] = int_m1_buser[i];
+ int_bvalid[i] = int_m1_bvalid[i];
+ end else begin
+ int_m0_bready[i] = int_bready[i];
+ int_m1_bready[i] = 1'b0;
+
+ int_bid[i] = int_m0_bid[i];
+ int_bresp[i] = int_m0_bresp[i];
+ int_buser[i] = int_m0_buser[i];
+ int_bvalid[i] = int_m0_bvalid[i];
+ end
+ end
+
+ // }}}
+
+ // Read Address channel (ar) {{{
+ /*
+ * read address channel (ar)
+ *
+ * ██████╗ ███████╗ █████╗ ██████╗ █████╗ ██████╗ ██████╗ ██████╗
+ * ██╔══██╗██╔════╝██╔══██╗██╔══██╗ ██╔══██╗██╔══██╗██╔══██╗██╔══██╗
+ * ██████╔╝█████╗ ███████║██║ ██║ ███████║██║ ██║██║ ██║██████╔╝
+ * ██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██╔══██║██║ ██║██║ ██║██╔══██╗
+ * ██║ ██║███████╗██║ ██║██████╔╝ ██║ ██║██████╔╝██████╔╝██║ ██║
+ * ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝
+ *
+ */
+ axi4_ar_buffer
+ #(
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_ar_buffer
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .s_axi4_arid ( s_axi4_arid[i] ),
+ .s_axi4_araddr ( s_axi4_araddr[i] ),
+ .s_axi4_arvalid ( s_axi4_arvalid[i] ),
+ .s_axi4_arready ( s_axi4_arready[i] ),
+ .s_axi4_arlen ( s_axi4_arlen[i] ),
+ .s_axi4_arsize ( s_axi4_arsize[i] ),
+ .s_axi4_arburst ( s_axi4_arburst[i] ),
+ .s_axi4_arlock ( s_axi4_arlock[i] ),
+ .s_axi4_arprot ( s_axi4_arprot[i] ),
+ .s_axi4_arcache ( s_axi4_arcache[i] ),
+ .s_axi4_aruser ( s_axi4_aruser[i] ),
+ .m_axi4_arid ( int_arid[i] ),
+ .m_axi4_araddr ( int_araddr[i] ),
+ .m_axi4_arvalid ( int_arvalid[i] ),
+ .m_axi4_arready ( int_arready[i] ),
+ .m_axi4_arlen ( int_arlen[i] ),
+ .m_axi4_arsize ( int_arsize[i] ),
+ .m_axi4_arburst ( int_arburst[i] ),
+ .m_axi4_arlock ( int_arlock[i] ),
+ .m_axi4_arprot ( int_arprot[i] ),
+ .m_axi4_arcache ( int_arcache[i] ),
+ .m_axi4_aruser ( int_aruser[i] )
+ );
+
+ axi4_ar_sender
+ #(
+ .AXI_ADDR_WIDTH ( AXI_M_ADDR_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH ),
+ .ENABLE_L2TLB ( ENABLE_L2TLB[i] )
+ )
+ u_ar_sender_m0
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .l1_done_o ( l1_m0_ar_done[i] ),
+ .l1_accept_i ( l1_m0_ar_accept[i] ),
+ .l1_drop_i ( l1_m0_ar_drop[i] ),
+ .l1_save_i ( l1_m0_ar_save[i] ),
+ .l2_done_o ( l2_m0_ar_done[i] ),
+ .l2_accept_i ( l2_m0_ar_accept[i] ),
+ .l2_drop_i ( l2_m0_ar_drop[i] ),
+ .l2_sending_o ( l2_m0_ar_sending[i] ),
+ .l1_araddr_i ( int_rtrans_addr[i] ),
+ .l2_araddr_i ( l2_ar_addr[i] ),
+ .s_axi4_arid ( int_arid[i] ),
+ .s_axi4_arvalid ( int_m0_arvalid[i] ),
+ .s_axi4_arready ( int_m0_arready[i] ),
+ .s_axi4_arlen ( int_arlen[i] ),
+ .s_axi4_arsize ( int_arsize[i] ),
+ .s_axi4_arburst ( int_arburst[i] ),
+ .s_axi4_arlock ( int_arlock[i] ),
+ .s_axi4_arprot ( int_arprot[i] ),
+ .s_axi4_arcache ( int_arcache[i] ),
+ .s_axi4_aruser ( int_aruser[i] ),
+ .m_axi4_arid ( m0_axi4_arid[i] ),
+ .m_axi4_araddr ( m0_axi4_araddr[i] ),
+ .m_axi4_arvalid ( m0_axi4_arvalid[i] ),
+ .m_axi4_arready ( m0_axi4_arready[i] ),
+ .m_axi4_arlen ( m0_axi4_arlen[i] ),
+ .m_axi4_arsize ( m0_axi4_arsize[i] ),
+ .m_axi4_arburst ( m0_axi4_arburst[i] ),
+ .m_axi4_arlock ( m0_axi4_arlock[i] ),
+ .m_axi4_arprot ( m0_axi4_arprot[i] ),
+ .m_axi4_arcache ( ),
+ .m_axi4_aruser ( m0_axi4_aruser[i] )
+ );
+
+ // The AXCACHE signals are set according to burstiness and cache coherence or statically
+ // when not connected to ACP on Zynq (implemented below).
+ assign m0_read_is_burst[i] = (m0_axi4_arlen[i] != {8{1'b0}}) && (m0_axi4_arburst[i] != 2'b00);
+ `ifndef EN_ACP
+ always_comb begin
+ if ( (l2_m0_ar_sending[i] & l2_cache_coherent[i]) | int_rtrans_cache_coherent[i]) begin
+ if (m0_read_is_burst[i]) begin
+ m0_axi4_arcache[i] = 4'b1011;
+ end else begin
+ m0_axi4_arcache[i] = 4'b1111;
+ end
+ end else begin
+ m0_axi4_arcache[i] = 4'b0011;
+ end
+ end
+ `else
+ assign m0_axi4_arcache[i] = 4'b0011;
+ `endif
+
+ axi4_ar_sender
+ #(
+ .AXI_ADDR_WIDTH ( AXI_M_ADDR_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH ),
+ .ENABLE_L2TLB ( ENABLE_L2TLB[i] )
+ )
+ u_ar_sender_m1
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .l1_done_o ( l1_m1_ar_done[i] ),
+ .l1_accept_i ( l1_m1_ar_accept[i] ),
+ .l1_drop_i ( l1_m1_ar_drop[i] ),
+ .l1_save_i ( l1_m1_ar_save[i] ),
+ .l2_done_o ( l2_m1_ar_done[i] ),
+ .l2_accept_i ( l2_m1_ar_accept[i] ),
+ .l2_drop_i ( l2_m1_ar_drop[i] ),
+ .l2_sending_o ( ), // just helps to set axcache
+ .l1_araddr_i ( int_rtrans_addr[i] ),
+ .l2_araddr_i ( l2_ar_addr[i] ),
+ .s_axi4_arid ( int_arid[i] ),
+ .s_axi4_arvalid ( int_m1_arvalid[i] ),
+ .s_axi4_arready ( int_m1_arready[i] ),
+ .s_axi4_arlen ( int_arlen[i] ),
+ .s_axi4_arsize ( int_arsize[i] ),
+ .s_axi4_arburst ( int_arburst[i] ),
+ .s_axi4_arlock ( int_arlock[i] ),
+ .s_axi4_arprot ( int_arprot[i] ),
+ .s_axi4_arcache ( int_arcache[i] ),
+ .s_axi4_aruser ( int_aruser[i] ),
+ .m_axi4_arid ( m1_axi4_arid[i] ),
+ .m_axi4_araddr ( m1_axi4_araddr[i] ),
+ .m_axi4_arvalid ( m1_axi4_arvalid[i] ),
+ .m_axi4_arready ( m1_axi4_arready[i] ),
+ .m_axi4_arlen ( m1_axi4_arlen[i] ),
+ .m_axi4_arsize ( m1_axi4_arsize[i] ),
+ .m_axi4_arburst ( m1_axi4_arburst[i] ),
+ .m_axi4_arlock ( m1_axi4_arlock[i] ),
+ .m_axi4_arprot ( m1_axi4_arprot[i] ),
+ .m_axi4_arcache ( ),
+ .m_axi4_aruser ( m1_axi4_aruser[i] )
+ );
+
+ // The AXCACHE signals are set according to burstiness and cache coherence or statically
+ // when not connected to ACP on Zynq (implemented below).
+ assign m1_read_is_burst[i] = (m1_axi4_arlen[i] != {8{1'b0}}) && (m1_axi4_arburst[i] != 2'b00);
+ `ifdef EN_ACP
+ always_comb begin
+ if (m1_read_is_burst[i]) begin
+ m1_axi4_arcache[i] = 4'b1011;
+ end else begin
+ m1_axi4_arcache[i] = 4'b1111;
+ end
+ end
+ `else
+ assign m1_axi4_arcache[i] = 4'b0011;
+ `endif
+
+ // }}}
+
+ // Read Response channel (r) {{{
+ /*
+ * read response channel (r)
+ *
+ * ██████╗ ███████╗ █████╗ ██████╗ ██████╗ ███████╗███████╗██████╗
+ * ██╔══██╗██╔════╝██╔══██╗██╔══██╗ ██╔══██╗██╔════╝██╔════╝██╔══██╗
+ * ██████╔╝█████╗ ███████║██║ ██║ ██████╔╝█████╗ ███████╗██████╔╝
+ * ██╔══██╗██╔══╝ ██╔══██║██║ ██║ ██╔══██╗██╔══╝ ╚════██║██╔═══╝
+ * ██║ ██║███████╗██║ ██║██████╔╝ ██║ ██║███████╗███████║██║
+ * ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝
+ *
+ */
+ axi4_r_buffer
+ #(
+ .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_r_buffer_m0
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .s_axi4_rid ( int_m0_rid[i] ),
+ .s_axi4_rresp ( int_m0_rresp[i] ),
+ .s_axi4_rdata ( int_m0_rdata[i] ),
+ .s_axi4_rlast ( int_m0_rlast[i] ),
+ .s_axi4_rvalid ( int_m0_rvalid[i] ),
+ .s_axi4_ruser ( int_m0_ruser[i] ),
+ .s_axi4_rready ( int_m0_rready[i] ),
+ .m_axi4_rid ( m0_axi4_rid[i] ),
+ .m_axi4_rresp ( m0_axi4_rresp[i] ),
+ .m_axi4_rdata ( m0_axi4_rdata[i] ),
+ .m_axi4_rlast ( m0_axi4_rlast[i] ),
+ .m_axi4_rvalid ( m0_axi4_rvalid[i] ),
+ .m_axi4_ruser ( m0_axi4_ruser[i] ),
+ .m_axi4_rready ( m0_axi4_rready[i] )
+ );
+
+ axi4_r_buffer
+ #(
+ .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_r_buffer_m1
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .s_axi4_rid ( int_m1_rid[i] ),
+ .s_axi4_rresp ( int_m1_rresp[i] ),
+ .s_axi4_rdata ( int_m1_rdata[i] ),
+ .s_axi4_rlast ( int_m1_rlast[i] ),
+ .s_axi4_rvalid ( int_m1_rvalid[i] ),
+ .s_axi4_ruser ( int_m1_ruser[i] ),
+ .s_axi4_rready ( int_m1_rready[i] ),
+ .m_axi4_rid ( m1_axi4_rid[i] ),
+ .m_axi4_rresp ( m1_axi4_rresp[i] ),
+ .m_axi4_rdata ( m1_axi4_rdata[i] ),
+ .m_axi4_rlast ( m1_axi4_rlast[i] ),
+ .m_axi4_rvalid ( m1_axi4_rvalid[i] ),
+ .m_axi4_ruser ( m1_axi4_ruser[i] ),
+ .m_axi4_rready ( m1_axi4_rready[i] )
+ );
+
+ axi4_r_sender
+ #(
+ .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH )
+ )
+ u_r_sender
+ (
+ .axi4_aclk ( Clk_CI ),
+ .axi4_arstn ( Rst_RBI ),
+ .drop_i ( lx_r_drop[i] ),
+ .drop_len_i ( lx_len_drop[i] ),
+ .done_o ( lx_r_done[i] ),
+ .id_i ( lx_id_drop[i] ),
+ .prefetch_i ( lx_prefetch_drop[i] ),
+ .hit_i ( lx_hit_drop[i] ),
+ .s_axi4_rid ( s_axi4_rid[i] ),
+ .s_axi4_rresp ( s_axi4_rresp[i] ),
+ .s_axi4_rdata ( s_axi4_rdata[i] ),
+ .s_axi4_rlast ( s_axi4_rlast[i] ),
+ .s_axi4_rvalid ( s_axi4_rvalid[i] ),
+ .s_axi4_ruser ( s_axi4_ruser[i] ),
+ .s_axi4_rready ( s_axi4_rready[i] ),
+ .m_axi4_rid ( int_rid[i] ),
+ .m_axi4_rresp ( int_rresp[i] ),
+ .m_axi4_rdata ( int_rdata[i] ),
+ .m_axi4_rlast ( int_rlast[i] ),
+ .m_axi4_rvalid ( int_rvalid[i] ),
+ .m_axi4_ruser ( int_ruser[i] ),
+ .m_axi4_rready ( int_rready[i] )
+ );
+
+ /*
+ * Multiplexer to switch between the two output master ports on the read response(r) channel
+ *
+ * Do not perform read burst interleaving as the DMA does not support it. This means we can only
+ * switch between the two masters upon sending rlast or when idle.
+ *
+ * However, if the downstream already performs burst interleaving, this cannot be undone here.
+ * Also, the downstream may interleave a burst reponse with a single-beat transaction. In this
+ * case, the FSM below falls out of the burst mode. To avoid it performing burst interleaving
+ * after such an event, it gives priority to the master which received the last burst in case
+ * both have a have a burst ready (rvalid).
+ *
+ * Order of priority:
+ * 1. Ongoing burst transaction
+ * 2. Single-beat transaction on Master 1.
+ * 3. Single-beat transaction on Master 0.
+ * 4. Burst transaction on master that received the last burst.
+ */
+ // Select signal
+ always_ff @(posedge Clk_CI) begin
+ if (Rst_RBI == 0) begin
+ RRespSel_SP[i] <= 1'b0;
+ end else begin
+ RRespSel_SP[i] <= RRespSel_SN[i];
+ end
+ end
+
+ // FSM
+ always_comb begin : RRespMuxFsm
+ RRespMuxCtrl_SN[i] = RRespMuxCtrl_SP[i];
+ RRespSel_SN[i] = RRespSel_SP[i];
+
+ RRespBurst_S[i] = 1'b0;
+ RRespSelIm_S[i] = 1'b0;
+
+ unique case (RRespMuxCtrl_SP[i])
+
+ IDLE: begin
+ // immediately forward single-beat transactions
+ if (int_m1_rvalid[i] && int_m1_rlast[i])
+ RRespSelIm_S[i] = 1'b1;
+ else if (int_m0_rvalid[i] && int_m0_rlast[i])
+ RRespSelIm_S[i] = 1'b0;
+
+ // bursts - they also start immediately
+ else if (int_m1_rvalid[i] || int_m0_rvalid[i]) begin
+ RRespMuxCtrl_SN[i] = BUSY;
+
+ // in case both are ready, continue with the master that had the last burst
+ if (int_m1_rvalid[i] && int_m0_rvalid[i]) begin
+ RRespSel_SN[i] = RRespSel_SP[i];
+ RRespSelIm_S[i] = RRespSel_SP[i];
+ end else if (int_m1_rvalid[i]) begin
+ RRespSel_SN[i] = 1'b1;
+ RRespSelIm_S[i] = 1'b1;
+ end else begin
+ RRespSel_SN[i] = 1'b0;
+ RRespSelIm_S[i] = 1'b0;
+ end
+ end
+ end
+
+ BUSY: begin
+ RRespBurst_S[i] = 1'b1;
+ // detect last handshake of currently ongoing transfer
+ if (int_rvalid[i] && int_rready[i] && int_rlast[i])
+ RRespMuxCtrl_SN[i] = IDLE;
+ end
+
+ default: begin
+ RRespMuxCtrl_SN[i] = IDLE;
+ end
+
+ endcase
+ end
+
+ // FSM state
+ always_ff @(posedge Clk_CI) begin
+ if (Rst_RBI == 0) begin
+ RRespMuxCtrl_SP[i] <= IDLE;
+ end else begin
+ RRespMuxCtrl_SP[i] <= RRespMuxCtrl_SN[i];
+ end
+ end
+
+ // Actual multiplexer
+ always_comb begin
+ if ( (RRespBurst_S[i] && RRespSel_SP[i]) || (!RRespBurst_S[i] && RRespSelIm_S[i]) ) begin
+ int_m0_rready[i] = 1'b0;
+ int_m1_rready[i] = int_rready[i];
+
+ int_rid[i] = int_m1_rid[i];
+ int_rresp[i] = int_m1_rresp[i];
+ int_rdata[i] = int_m1_rdata[i];
+ int_rlast[i] = int_m1_rlast[i];
+ int_ruser[i] = int_m1_ruser[i];
+ int_rvalid[i] = int_m1_rvalid[i];
+ end else begin
+ int_m0_rready[i] = int_rready[i];
+ int_m1_rready[i] = 1'b0;
+
+ int_rid[i] = int_m0_rid[i];
+ int_rresp[i] = int_m0_rresp[i];
+ int_rdata[i] = int_m0_rdata[i];
+ int_rlast[i] = int_m0_rlast[i];
+ int_ruser[i] = int_m0_ruser[i];
+ int_rvalid[i] = int_m0_rvalid[i];
+ end
+ end
+
+ end // BUF & SEND
+
+ // }}}
+
+ endgenerate // BUF & SEND }}}
+
+ // Log {{{
+
+`ifdef RAB_AX_LOG_EN
+ AxiBramLogger
+ #(
+ .AXI_ID_BITW ( AXI_ID_WIDTH ),
+ .AXI_ADDR_BITW ( AXI_S_ADDR_WIDTH ),
+ .NUM_LOG_ENTRIES ( `RAB_AX_LOG_ENTRIES )
+ )
+ u_aw_logger
+ (
+ .Clk_CI ( NonGatedClk_CI ),
+ .TimestampClk_CI ( Clk_CI ),
+ .Rst_RBI ( Rst_RBI ),
+ .AxiValid_SI ( s_axi4_awvalid[1] ),
+ .AxiReady_SI ( s_axi4_awready[1] ),
+ .AxiId_DI ( s_axi4_awid[1] ),
+ .AxiAddr_DI ( s_axi4_awaddr[1] ),
+ .AxiLen_DI ( s_axi4_awlen[1] ),
+ .Clear_SI ( AwLogClr_SI ),
+ .LogEn_SI ( LogEn_SI ),
+ .Full_SO ( int_aw_log_full ),
+ .Ready_SO ( AwLogRdy_SO ),
+ .Bram_PS ( AwBram_PS )
+ );
+
+ AxiBramLogger
+ #(
+ .AXI_ID_BITW ( AXI_ID_WIDTH ),
+ .AXI_ADDR_BITW ( AXI_S_ADDR_WIDTH ),
+ .NUM_LOG_ENTRIES ( `RAB_AX_LOG_ENTRIES )
+ )
+ u_ar_logger
+ (
+ .Clk_CI ( NonGatedClk_CI ),
+ .TimestampClk_CI ( Clk_CI ),
+ .Rst_RBI ( Rst_RBI ),
+ .AxiValid_SI ( s_axi4_arvalid[1] ),
+ .AxiReady_SI ( s_axi4_arready[1] ),
+ .AxiId_DI ( s_axi4_arid[1] ),
+ .AxiAddr_DI ( s_axi4_araddr[1] ),
+ .AxiLen_DI ( s_axi4_arlen[1] ),
+ .Clear_SI ( ArLogClr_SI ),
+ .LogEn_SI ( LogEn_SI ),
+ .Full_SO ( int_ar_log_full ),
+ .Ready_SO ( ArLogRdy_SO ),
+ .Bram_PS ( ArBram_PS )
+ );
+`endif
+
+ // }}}
+
+ // RAB Core {{{
+ // ██████╗ █████╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗
+ // ██╔══██╗██╔══██╗██╔══██╗ ██╔════╝██╔═══██╗██╔══██╗██╔════╝
+ // ██████╔╝███████║██████╔╝ ██║ ██║ ██║██████╔╝█████╗
+ // ██╔══██╗██╔══██║██╔══██╗ ██║ ██║ ██║██╔══██╗██╔══╝
+ // ██║ ██║██║ ██║██████╔╝ ╚██████╗╚██████╔╝██║ ██║███████╗
+ // ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
+ //
+ /*
+ * rab_core
+ *
+ * The rab core translates addresses. It has two ports, which can be used
+ * independently, however they will compete for time internally, as lookups
+ * are serialized.
+ *
+ * type is the read(0) or write(1) used to check the protection flags. If they
+ * don't match an interrupt is created on the int_prot line.
+ */
+
+ rab_core
+ #(
+ .N_PORTS ( N_PORTS ),
+ .N_L2_SETS ( N_L2_SETS ),
+ .N_L2_SET_ENTRIES ( N_L2_SET_ENTRIES ),
+ .AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
+ .AXI_S_ADDR_WIDTH ( AXI_S_ADDR_WIDTH ),
+ .AXI_M_ADDR_WIDTH ( AXI_M_ADDR_WIDTH ),
+ .AXI_LITE_DATA_WIDTH ( AXI_LITE_DATA_WIDTH ),
+ .AXI_LITE_ADDR_WIDTH ( AXI_LITE_ADDR_WIDTH ),
+ .AXI_ID_WIDTH ( AXI_ID_WIDTH ),
+ .AXI_USER_WIDTH ( AXI_USER_WIDTH ),
+ .MH_FIFO_DEPTH ( MH_FIFO_DEPTH )
+ )
+ u_rab_core
+ (
+ .Clk_CI ( Clk_CI ),
+ .Rst_RBI ( Rst_RBI ),
+
+ // Config IF
+ .s_axi_awaddr ( s_axi4lite_awaddr ),
+ .s_axi_awvalid ( s_axi4lite_awvalid ),
+ .s_axi_awready ( s_axi4lite_awready ),
+ .s_axi_wdata ( s_axi4lite_wdata ),
+ .s_axi_wstrb ( s_axi4lite_wstrb ),
+ .s_axi_wvalid ( s_axi4lite_wvalid ),
+ .s_axi_wready ( s_axi4lite_wready ),
+ .s_axi_bresp ( s_axi4lite_bresp ),
+ .s_axi_bvalid ( s_axi4lite_bvalid ),
+ .s_axi_bready ( s_axi4lite_bready ),
+ .s_axi_araddr ( s_axi4lite_araddr ),
+ .s_axi_arvalid ( s_axi4lite_arvalid ),
+ .s_axi_arready ( s_axi4lite_arready ),
+ .s_axi_rready ( s_axi4lite_rready ),
+ .s_axi_rdata ( s_axi4lite_rdata ),
+ .s_axi_rresp ( s_axi4lite_rresp ),
+ .s_axi_rvalid ( s_axi4lite_rvalid ),
+
+ // L1 miss info outputs -> L2 TLB arbitration
+ .int_miss ( rab_miss ),
+ .int_multi ( rab_multi ),
+ .int_prot ( rab_prot ),
+ .int_prefetch ( rab_prefetch ),
+ .int_mhf_full ( int_mhf_full ),
+
+ // L1 transaction info outputs -> L2 TLB arbitration
+ .int_axaddr_o ( L1OutAddr_D ),
+ .int_axid_o ( L1OutId_D ),
+ .int_axlen_o ( L1OutLen_D ),
+ .int_axuser_o ( L1OutUser_D ),
+
+ // Write Req IF
+ .port1_addr ( int_awaddr ),
+ .port1_id ( int_awid ),
+ .port1_len ( int_awlen ),
+ .port1_size ( int_awsize ),
+ .port1_addr_valid ( int_awvalid & ~aw_in_stall ), // avoid the FSM accepting new AW requests
+ .port1_type ( {N_PORTS{1'b1}} ),
+ .port1_user ( int_awuser ),
+ .port1_sent ( int_wtrans_sent ), // signal done to L1 FSM
+ .port1_out_addr ( int_wtrans_addr ),
+ .port1_cache_coherent ( int_wtrans_cache_coherent ),
+ .port1_accept ( int_wtrans_accept ),
+ .port1_drop ( int_wtrans_drop ),
+ .port1_miss ( int_wtrans_miss ),
+
+ // Read Req IF
+ .port2_addr ( int_araddr ),
+ .port2_id ( int_arid ),
+ .port2_len ( int_arlen ),
+ .port2_size ( int_arsize ),
+ .port2_addr_valid ( int_arvalid ),
+ .port2_type ( {N_PORTS{1'b0}} ),
+ .port2_user ( int_aruser ),
+ .port2_sent ( int_rtrans_sent ), // signal done to L1 FSM
+ .port2_out_addr ( int_rtrans_addr ),
+ .port2_cache_coherent ( int_rtrans_cache_coherent ),
+ .port2_accept ( int_rtrans_accept ),
+ .port2_drop ( int_rtrans_drop ),
+ .port2_miss ( int_rtrans_miss ),
+
+ // L2 miss info inputs -> axi_rab_cfg
+ .miss_l2_i ( L2Miss_S ),
+ .miss_l2_addr_i ( L2OutInAddr_DP ),
+ .miss_l2_id_i ( L2OutId_DP ),
+ .miss_l2_user_i ( L2OutUser_DP ),
+
+ // L2 config outputs
+ .wdata_l2_o ( L2CfgWData_D ),
+ .waddr_l2_o ( L2CfgWAddr_D ),
+ .wren_l2_o ( L2CfgWE_S )
+ );
+
+ // }}}
+
+ // AX SPLITS {{{
+ // █████╗ ██╗ ██╗ ███████╗██████╗ ██╗ ██╗████████╗
+ // ██╔══██╗╚██╗██╔╝ ██╔════╝██╔══██╗██║ ██║╚══██╔══╝
+ // ███████║ ╚███╔╝ ███████╗██████╔╝██║ ██║ ██║
+ // ██╔══██║ ██╔██╗ ╚════██║██╔═══╝ ██║ ██║ ██║
+ // ██║ ██║██╔╝ ██╗ ███████║██║ ███████╗██║ ██║
+ // ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚══════╝╚═╝ ╚═╝
+ //
+ /**
+ * Multiplex the two output master ports of the Read Address and Write Address (AR/AW) channels.
+ *
+ * Use the `int_xmaster_select` signal to route the signals to either Master 0 (to memory) or
+ * Master 1 (to ACP). In case of an L1 miss: Route the signals to both masters. They shall be
+ * saved until the L2 outputs are available.
+ */
+ generate for (i = 0; i < N_PORTS; i++) begin : AX_SPLIT
+
+ /*
+ * When accepting L1 transactions, we must just do so on the selected master. Drop requests must
+ * be performed on any one of the two masters. Save requests must be performed by both masters.
+ */
+ always_comb begin : AW_L1_SPLIT
+
+ // TLB handshake
+ l1_m0_aw_accept[i] = 1'b0;
+ l1_m1_aw_accept[i] = 1'b0;
+ l1_m0_aw_drop[i] = 1'b0;
+ l1_m1_aw_drop[i] = 1'b0;
+ l1_m0_aw_save[i] = 1'b0;
+ l1_m1_aw_save[i] = 1'b0;
+
+ l1_mx_aw_done[i] = 1'b0;
+
+ // AXI sender input handshake
+ int_m0_awvalid[i] = 1'b0;
+ int_m1_awvalid[i] = 1'b0;
+ int_awready[i] = 1'b0;
+
+ // accept on selected master only
+ if (l1_aw_accept[i]) begin
+ if (int_wmaster_select[i]) begin
+ l1_m1_aw_accept[i] = 1'b1;
+ l1_mx_aw_done[i] = l1_m1_aw_done[i];
+
+ int_m1_awvalid[i] = int_awvalid[i];
+ int_awready[i] = int_m1_awready[i];
+
+ end else begin
+ l1_m0_aw_accept[i] = 1'b1;
+ l1_mx_aw_done[i] = l1_m0_aw_done[i];
+
+ int_m0_awvalid[i] = int_awvalid[i];
+ int_awready[i] = int_m0_awready[i];
+ end
+
+ // drop on Master 0 only
+ end else if (l1_aw_drop[i]) begin
+ l1_m0_aw_drop[i] = 1'b1;
+ l1_mx_aw_done[i] = l1_m0_aw_done[i];
+
+ int_m0_awvalid[i] = int_awvalid[i];
+ int_awready[i] = l1_m0_aw_done[i];
+
+ // save on both masters
+ end else if (l1_aw_save[i]) begin
+ // split save
+ l1_m0_aw_save[i] = ~l1_m0_aw_done_SP[i];
+ l1_m1_aw_save[i] = ~l1_m1_aw_done_SP[i];
+
+ // combine done
+ l1_mx_aw_done[i] = l1_m0_aw_done_SP[i] & l1_m1_aw_done_SP[i];
+
+ int_m0_awvalid[i] = int_awvalid[i];
+ int_m1_awvalid[i] = int_awvalid[i];
+ int_awready[i] = l1_mx_aw_done[i];
+ end
+ end
+
+ // signal back to handshake splitter
+ assign l1_aw_done[i] = l1_mx_aw_done[i];
+
+ always_ff @(posedge Clk_CI) begin : L1_MX_AW_DONE_REG
+ if (Rst_RBI == 0) begin
+ l1_m0_aw_done_SP[i] <= 1'b0;
+ l1_m1_aw_done_SP[i] <= 1'b0;
+ end else if (l1_mx_aw_done[i]) begin
+ l1_m0_aw_done_SP[i] <= 1'b0;
+ l1_m1_aw_done_SP[i] <= 1'b0;
+ end else begin
+ l1_m0_aw_done_SP[i] <= l1_m0_aw_done_SP[i] | l1_m0_aw_done[i];
+ l1_m1_aw_done_SP[i] <= l1_m1_aw_done_SP[i] | l1_m1_aw_done[i];
+ end
+ end
+
+ /*
+ * When accepting L2 transactions, we must drop the corresponding transaction from the other
+ * master to make it available again for save requests from L1_DROP_SAVE.
+ */
+ always_comb begin : AW_L2_SPLIT
+
+ l2_m0_aw_accept[i] = 1'b0;
+ l2_m1_aw_accept[i] = 1'b0;
+ l2_m0_aw_drop[i] = 1'b0;
+ l2_m1_aw_drop[i] = 1'b0;
+
+ // de-assert request signals individually upon handshakes
+ if (l2_aw_accept[i]) begin
+ if (l2_master_select[i]) begin
+ l2_m1_aw_accept[i] = ~l2_m1_aw_done_SP[i];
+ l2_m0_aw_drop[i] = ~l2_m0_aw_done_SP[i];
+
+ end else begin
+ l2_m0_aw_accept[i] = ~l2_m0_aw_done_SP[i];
+ l2_m1_aw_drop[i] = ~l2_m1_aw_done_SP[i];
+
+ end
+ end else begin
+ l2_m0_aw_drop[i] = ~l2_m0_aw_done_SP[i] ? l2_aw_drop[i] : 1'b0;
+ l2_m1_aw_drop[i] = ~l2_m1_aw_done_SP[i] ? l2_aw_drop[i] : 1'b0;
+
+ end
+
+ // combine done
+ l2_mx_aw_done[i] = l2_m0_aw_done_SP[i] & l2_m1_aw_done_SP[i];
+
+ l2_aw_done[i] = l2_mx_aw_done[i];
+ end
+
+ always_ff @(posedge Clk_CI) begin : L2_MX_AW_DONE_REG
+ if (Rst_RBI == 0) begin
+ l2_m0_aw_done_SP[i] <= 1'b0;
+ l2_m1_aw_done_SP[i] <= 1'b0;
+ end else if (l2_mx_aw_done[i]) begin
+ l2_m0_aw_done_SP[i] <= 1'b0;
+ l2_m1_aw_done_SP[i] <= 1'b0;
+ end else begin
+ l2_m0_aw_done_SP[i] <= l2_m0_aw_done_SP[i] | l2_m0_aw_done[i];
+ l2_m1_aw_done_SP[i] <= l2_m1_aw_done_SP[i] | l2_m1_aw_done[i];
+ end
+ end
+
+ /*
+ * When accepting L1 transactions, we must just do so on the selected master. Drop requests must
+ * be performed on any one of the two masters. Save requests must be performed by both masters.
+ */
+ always_comb begin : AR_L1_SPLIT
+
+ // TLB handshake
+ l1_m0_ar_accept[i] = 1'b0;
+ l1_m1_ar_accept[i] = 1'b0;
+ l1_m0_ar_drop[i] = 1'b0;
+ l1_m1_ar_drop[i] = 1'b0;
+ l1_m0_ar_save[i] = 1'b0;
+ l1_m1_ar_save[i] = 1'b0;
+
+ l1_mx_ar_done[i] = 1'b0;
+
+ // AXI sender input handshake
+ int_m0_arvalid[i] = 1'b0;
+ int_m1_arvalid[i] = 1'b0;
+ int_arready[i] = 1'b0;
+
+ // accept on selected master only
+ if (l1_ar_accept[i]) begin
+ if (int_rmaster_select[i]) begin
+ l1_m1_ar_accept[i] = 1'b1;
+ l1_mx_ar_done[i] = l1_m1_ar_done[i];
+
+ int_m1_arvalid[i] = int_arvalid[i];
+ int_arready[i] = int_m1_arready[i];
+
+ end else begin
+ l1_m0_ar_accept[i] = 1'b1;
+ l1_mx_ar_done[i] = l1_m0_ar_done[i];
+
+ int_m0_arvalid[i] = int_arvalid[i];
+ int_arready[i] = int_m0_arready[i];
+ end
+
+ // drop on Master 0 only
+ end else if (l1_ar_drop[i]) begin
+ l1_m0_ar_drop[i] = 1'b1;
+ l1_mx_ar_done[i] = l1_m0_ar_done[i];
+
+ int_m0_arvalid[i] = int_arvalid[i];
+ int_arready[i] = l1_m0_ar_done[i];
+
+ // save on both masters
+ end else if (l1_ar_save[i]) begin
+ // split save
+ l1_m0_ar_save[i] = ~l1_m0_ar_done_SP[i];
+ l1_m1_ar_save[i] = ~l1_m1_ar_done_SP[i];
+
+ // combine done
+ l1_mx_ar_done[i] = l1_m0_ar_done_SP[i] & l1_m1_ar_done_SP[i];
+
+ int_m0_arvalid[i] = int_arvalid[i];
+ int_m1_arvalid[i] = int_arvalid[i];
+ int_arready[i] = l1_mx_ar_done[i];
+ end
+ end
+
+ // signal back to handshake splitter
+ assign l1_ar_done[i] = l1_mx_ar_done[i];
+
+ always_ff @(posedge Clk_CI) begin : L1_MX_AR_DONE_REG
+ if (Rst_RBI == 0) begin
+ l1_m0_ar_done_SP[i] <= 1'b0;
+ l1_m1_ar_done_SP[i] <= 1'b0;
+ end else if (l1_mx_ar_done[i]) begin
+ l1_m0_ar_done_SP[i] <= 1'b0;
+ l1_m1_ar_done_SP[i] <= 1'b0;
+ end else begin
+ l1_m0_ar_done_SP[i] <= l1_m0_ar_done_SP[i] | l1_m0_ar_done[i];
+ l1_m1_ar_done_SP[i] <= l1_m1_ar_done_SP[i] | l1_m1_ar_done[i];
+ end
+ end
+
+ /*
+ * When accepting L2 transactions, we must drop the corresponding transaction from the other
+ * master to make it available again for save requests from L1_DROP_SAVE.
+ */
+ always_comb begin : AR_L2_SPLIT
+
+ l2_m0_ar_accept[i] = 1'b0;
+ l2_m1_ar_accept[i] = 1'b0;
+ l2_m0_ar_drop[i] = 1'b0;
+ l2_m1_ar_drop[i] = 1'b0;
+
+ // de-assert request signals individually upon handshakes
+ if (l2_ar_accept[i]) begin
+ if (l2_master_select[i]) begin
+ l2_m1_ar_accept[i] = ~l2_m1_ar_done_SP[i];
+ l2_m0_ar_drop[i] = ~l2_m0_ar_done_SP[i];
+
+ end else begin
+ l2_m0_ar_accept[i] = ~l2_m0_ar_done_SP[i];
+ l2_m1_ar_drop[i] = ~l2_m1_ar_done_SP[i];
+
+ end
+ end else if (l2_ar_drop[i]) begin
+ l2_m0_ar_drop[i] = ~l2_m0_ar_done_SP[i] ? l2_ar_drop[i] : 1'b0;
+ l2_m1_ar_drop[i] = ~l2_m1_ar_done_SP[i] ? l2_ar_drop[i] : 1'b0;
+
+ end
+
+ // combine done
+ l2_mx_ar_done[i] = l2_m0_ar_done_SP[i] & l2_m1_ar_done_SP[i];
+
+ l2_ar_done[i] = l2_mx_ar_done[i];
+ end
+
+ always_ff @(posedge Clk_CI) begin : L2_MX_AR_DONE_REG
+ if (Rst_RBI == 0) begin
+ l2_m0_ar_done_SP[i] <= 1'b0;
+ l2_m1_ar_done_SP[i] <= 1'b0;
+ end else if (l2_mx_ar_done[i]) begin
+ l2_m0_ar_done_SP[i] <= 1'b0;
+ l2_m1_ar_done_SP[i] <= 1'b0;
+ end else begin
+ l2_m0_ar_done_SP[i] <= l2_m0_ar_done_SP[i] | l2_m0_ar_done[i];
+ l2_m1_ar_done_SP[i] <= l2_m1_ar_done_SP[i] | l2_m1_ar_done[i];
+ end
+ end
+
+ end // AX_SPLIT
+ endgenerate // AX_SPLIT
+
+ // }}}
+
+ // HANDSHAKE SPLITS {{{
+ // ██╗ ██╗███████╗ ███████╗██████╗ ██╗ ██╗████████╗
+ // ██║ ██║██╔════╝ ██╔════╝██╔══██╗██║ ██║╚══██╔══╝
+ // ███████║███████╗ ███████╗██████╔╝██║ ██║ ██║
+ // ██╔══██║╚════██║ ╚════██║██╔═══╝ ██║ ██║ ██║
+ // ██║ ██║███████║ ███████║██║ ███████╗██║ ██║
+ // ╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚══════╝╚═╝ ╚═╝
+ //
+ /*
+ * We need to perform combined handshakes with multiple AXI modules
+ * upon transactions drops, accepts, saves etc. from two TLBs.
+ */
+ generate for (i = 0; i < N_PORTS; i++) begin : HANDSHAKE_SPLIT
+
+ assign l1_xw_accept[i] = int_wtrans_accept[i] & ~aw_out_stall[i];
+ assign int_wtrans_sent[i] = l1_xw_done[i];
+
+ assign l1_ar_accept[i] = int_rtrans_accept[i];
+ assign int_rtrans_sent[i] = l1_ar_done[i];
+
+ /*
+ * L1 AW sender + W buffer handshake split
+ */
+ // forward
+ assign l1_aw_accept[i] = l1_xw_accept[i] & ~l1_aw_done_SP[i];
+ assign l1_w_accept[i] = l1_xw_accept[i] & ~l1_w_done_SP[i];
+
+ assign l1_aw_save[i] = l1_xw_save[i] & ~l1_aw_done_SP[i];
+ assign l1_w_save[i] = l1_xw_save[i] & ~l1_w_done_SP[i];
+
+ assign l1_aw_drop[i] = l1_xw_drop[i] & ~l1_aw_done_SP[i];
+ assign l1_w_drop[i] = l1_xw_drop[i] & ~l1_w_done_SP[i];
+
+ // backward
+ assign l1_xw_done[i] = l1_aw_done_SP[i] & l1_w_done_SP[i];
+
+ always_ff @(posedge Clk_CI) begin : L1_XW_HS_SPLIT
+ if (Rst_RBI == 0) begin
+ l1_aw_done_SP[i] <= 1'b0;
+ l1_w_done_SP[i] <= 1'b0;
+ end else if (l1_xw_done[i]) begin
+ l1_aw_done_SP[i] <= 1'b0;
+ l1_w_done_SP[i] <= 1'b0;
+ end else begin
+ l1_aw_done_SP[i] <= l1_aw_done_SP[i] | l1_aw_done[i];
+ l1_w_done_SP[i] <= l1_w_done_SP[i] | l1_w_done[i];
+ end
+ end
+
+ if (ENABLE_L2TLB[i] == 1) begin : L2_HS_SPLIT
+
+ /*
+ * L1 AR sender + R sender handshake split
+ *
+ * AR and R do not need to be strictly in sync. We thus use separate handshakes.
+ * But the handshake signals for the R sender are multiplexed with the those for
+ * the L2. However, L2_ACCEPT_DROP_SAVE has always higher priority.
+ */
+ assign lx_r_drop[i] = l2_r_drop[i] | l1_r_drop[i];
+ assign l1_r_done[i] = l2_r_drop[i] ? 1'b0 : lx_r_done[i];
+ assign l2_r_done[i] = l2_r_drop[i] ? lx_r_done[i] : 1'b0;
+
+ /*
+ * L2 AW sender + W buffer handshake split
+ */
+ // forward
+ assign l2_aw_accept[i] = l2_xw_accept[i] & ~l2_aw_done_SP[i];
+ assign l2_w_accept[i] = l2_xw_accept[i] & ~l2_w_done_SP[i];
+
+ assign l2_aw_drop[i] = l2_xw_drop[i] & ~l2_aw_done_SP[i];
+ assign l2_w_drop[i] = l2_xw_drop[i] & ~l2_w_done_SP[i];
+
+ // backward
+ assign l2_xw_done[i] = l2_aw_done_SP[i] & l2_w_done_SP[i];
+
+ always_ff @(posedge Clk_CI) begin : L2_XW_HS_SPLIT
+ if (Rst_RBI == 0) begin
+ l2_aw_done_SP[i] <= 1'b0;
+ l2_w_done_SP[i] <= 1'b0;
+ end else if (l2_xw_done[i]) begin
+ l2_aw_done_SP[i] <= 1'b0;
+ l2_w_done_SP[i] <= 1'b0;
+ end else begin
+ l2_aw_done_SP[i] <= l2_aw_done_SP[i] | l2_aw_done[i];
+ l2_w_done_SP[i] <= l2_w_done_SP[i] | l2_w_done[i];
+ end
+ end
+
+ /*
+ * L2 AR + R sender handshake split
+ */
+ // forward
+ assign l2_ar_drop[i] = l2_xr_drop[i] & ~l2_ar_done_SP[i];
+ assign l2_r_drop[i] = l2_xr_drop[i] & ~l2_r_done_SP[i];
+
+ // backward - make sure to always clear L2_XR_HS_SPLIT
+ always_comb begin
+ if (l2_xr_drop[i]) begin
+ l2_xr_done[i] = l2_ar_done_SP[i] & l2_r_done_SP[i];
+ end else begin
+ l2_xr_done[i] = l2_ar_done_SP[i];
+ end
+ end
+
+ always_ff @(posedge Clk_CI) begin : L2_XR_HS_SPLIT
+ if (Rst_RBI == 0) begin
+ l2_ar_done_SP[i] <= 1'b0;
+ l2_r_done_SP[i] <= 1'b0;
+ end else if (l2_xr_done[i]) begin
+ l2_ar_done_SP[i] <= 1'b0;
+ l2_r_done_SP[i] <= 1'b0;
+ end else begin
+ l2_ar_done_SP[i] <= l2_ar_done_SP[i] | l2_ar_done[i];
+ l2_r_done_SP[i] <= l2_r_done_SP[i] | l2_r_done[i];
+ end
+ end
+
+ end else begin // if (ENABLE_L2TLB[i] == 1)
+
+ assign lx_r_drop[i] = l1_r_drop[i];
+ assign l1_r_done[i] = lx_r_done[i];
+
+ assign l2_aw_accept[i] = 1'b0;
+ assign l2_w_accept[i] = 1'b0;
+ assign l2_aw_drop[i] = 1'b0;
+ assign l2_w_drop[i] = 1'b0;
+ assign l2_xw_done[i] = 1'b0;
+ assign l2_aw_done_SP[i] = 1'b0;
+ assign l2_w_done_SP[i] = 1'b0;
+
+ assign l2_ar_accept[i] = 1'b0;
+ assign l2_ar_drop[i] = 1'b0;
+ assign l2_r_drop[i] = 1'b0;
+ assign l2_xr_done[i] = 1'b0;
+ assign l2_r_done[i] = 1'b0;
+ assign l2_ar_done_SP[i] = 1'b0;
+ assign l2_r_done_SP[i] = 1'b0;
+
+ end // if (ENABLE_L2TLB[i] == 1)
+
+ end // HANDSHAKE_SPLIT
+ endgenerate // HANDSHAKE_SPLIT
+
+ // }}}
+
+ // L2 TLB {{{
+ // ██╗ ██████╗ ████████╗██╗ ██████╗
+ // ██║ ╚════██╗ ╚══██╔══╝██║ ██╔══██╗
+ // ██║ █████╔╝ ██║ ██║ ██████╔╝
+ // ██║ ██╔═══╝ ██║ ██║ ██╔══██╗
+ // ███████╗███████╗ ██║ ███████╗██████╔╝
+ // ╚══════╝╚══════╝ ╚═╝ ╚══════╝╚═════╝
+ //
+ /*
+ * l2_tlb
+ *
+ * The L2 TLB translates addresses upon misses in the L1 TLB (rab_core).
+ *
+ * It supports one ongoing translation at a time. If an L1 miss occurs while the L2 is busy,
+ * the L1 is stalled untill the L2 is available again.
+ *
+ */
+ generate for (i = 0; i < N_PORTS; i++) begin : L2_TLB
+ if (ENABLE_L2TLB[i] == 1) begin : L2_TLB
+
+ /*
+ * L1 output selector
+ */
+ assign L1OutRwType_D[i] = int_wtrans_drop[i] ? 1'b1 : 1'b0;
+ assign L1OutProt_D[i] = rab_prot[i];
+ assign L1OutMulti_D[i] = rab_multi[i];
+
+ /*
+ * L1 output control + L1_DROP_BUF, L2_IN_BUF management
+ *
+ * Forward the L1 drop request to AR/AW sender modules if
+ * 1. the transactions needs to be dropped (L1 multi, prot, prefetch), or
+ * 2. if a lookup in the L2 TLB is required (L1 miss) and the input buffer is not full.
+ *
+ * The AR/AW senders do not support more than 1 oustanding L1 miss. The push back towards
+ * the upstream is realized by not accepting the save request (saving the L1 transaction)
+ * in the senders as long as the L2 TLB is busy or has valid output. This ultimately
+ * blocks the L1 TLB.
+ *
+ * Together with the AW drop/save, we also perform the W drop/save as AW and W need to
+ * absolutely remain in order. In contrast, the R drop is performed
+ */
+ always_comb begin : L1_DROP_SAVE
+
+ l1_ar_drop[i] = 1'b0;
+ l1_ar_save[i] = 1'b0;
+ l1_xw_drop[i] = 1'b0;
+ l1_xw_save[i] = 1'b0;
+
+ l1_id_drop[i] = L1OutId_D[i];
+ l1_len_drop[i] = L1OutLen_D[i];
+ l1_prefetch_drop[i] = rab_prefetch[i];
+ l1_hit_drop[i] = 1'b1; // there are no drops for L1 misses
+
+ L1DropEn_S[i] = 1'b0;
+ L2InEn_S[i] = 1'b0;
+
+ if ( rab_prot[i] | rab_multi[i] | rab_prefetch[i] ) begin
+ // 1. Drop
+ l1_ar_drop[i] = int_rtrans_drop[i] & ~L1DropValid_SP[i];
+ l1_xw_drop[i] = int_wtrans_drop[i] & ~L1DropValid_SP[i];
+
+ // Store to L1_DROP_BUF upon handshake
+ L1DropEn_S[i] = (l1_ar_drop[i] & l1_ar_done[i]) |
+ (l1_xw_drop[i] & l1_xw_done[i]);
+
+ end else if ( rab_miss[i] ) begin
+ // 2. Save - Make sure L2 is really available.
+ l1_ar_save[i] = int_rtrans_drop[i] & ~L2Busy_S[i];
+ l1_xw_save[i] = int_wtrans_drop[i] & ~L2Busy_S[i];
+
+ // Store to L2_IN_BUF upon handshake - triggers the L2 TLB
+ L2InEn_S[i] = (l1_ar_save[i] & l1_ar_done[i]) |
+ (l1_xw_save[i] & l1_xw_done[i]);
+ end
+ end
+
+ /*
+ * L2 output control + L2_OUT_BUF management + R/B sender control + W buffer control
+ *
+ * Perform L1 R transaction drops unless the L2 output buffer holds valid data. The AXI specs
+ * require the B response to be sent only after consuming/discarding the corresponding data
+ * in the W channel. Thus, we only send L2 drop request to the W buffer here. The drop
+ * request to the B sender is then sent by the W buffer autonomously.
+ *
+ * L1 AW/W drop requests are managed by L1_DROP_SAVE.
+ */
+ always_comb begin : L2_ACCEPT_DROP_SAVE
+
+ l2_ar_addr[i] = 'b0;
+ l2_aw_addr[i] = 'b0;
+ l2_ar_accept[i] = 1'b0;
+ l2_xr_drop[i] = 1'b0;
+ l2_xw_accept[i] = 1'b0;
+ l2_xw_drop[i] = 1'b0;
+
+ l1_r_drop[i] = 1'b0;
+
+ lx_id_drop[i] = 'b0;
+ lx_len_drop[i] = 'b0;
+ lx_prefetch_drop[i] = 1'b0;
+ lx_hit_drop[i] = 1'b0;
+
+ L1DropValid_SN[i] = L1DropValid_SP[i] | L1DropEn_S[i];
+ L2OutValid_SN[i] = L2OutValid_SP[i];
+ L2OutReady_S[i] = 1'b0;
+ L2OutEn_S[i] = 1'b0;
+
+ L2Miss_S[i] = 1'b0;
+ int_multi[i] = 1'b0;
+ int_prot[i] = 1'b0;
+
+ if (L2OutValid_SP[i] == 1'b0) begin
+
+ // Drop L1 from R senders
+ if (L1DropValid_SP[i] == 1'b1) begin
+
+ // Only perform the R sender drop here.
+ if (~L1DropRwType_DP[i]) begin
+
+ l1_r_drop[i] = 1'b1;
+ lx_id_drop[i] = L1DropId_DP[i];
+ lx_len_drop[i] = L1DropLen_DP[i];
+ lx_prefetch_drop[i] = L1DropPrefetch_S[i];
+ lx_hit_drop[i] = 1'b1; // there are no drops for L1 misses
+
+ // Invalidate L1_DROP_BUF upon handshake
+ if ( l1_r_drop[i] & l1_r_done[i] ) begin
+
+ L1DropValid_SN[i] = 1'b0;
+ int_prot[i] = L1DropProt_DP[i];
+ int_multi[i] = L1DropMulti_DP[i];
+ end
+
+ end else begin
+ // Invalidate L1_DROP_BUF
+ L1DropValid_SN[i] = 1'b0;
+ int_prot[i] = L1DropProt_DP[i];
+ int_multi[i] = L1DropMulti_DP[i];
+ end
+ end
+
+ end else begin // L2_OUT_BUF has valid data
+
+ if ( L2OutHit_SP[i] & ~(L2OutPrefetch_S[i] | L2OutProt_SP[i] | L2OutMulti_SP[i]) ) begin
+
+ l2_ar_addr[i] = L2OutAddr_DP[i];
+ l2_aw_addr[i] = L2OutAddr_DP[i];
+
+ l2_ar_accept[i] = L2OutRwType_DP[i] ? 1'b0 : 1'b1;
+ l2_xw_accept[i] = L2OutRwType_DP[i] ? 1'b1 : 1'b0;
+
+ // Invalidate L2_OUT_BUF upon handshake
+ L2OutValid_SN[i] = ~( (l2_ar_accept[i] & l2_ar_done[i]) |
+ (l2_xw_accept[i] & l2_xw_done[i]) );
+ end else begin
+
+ lx_id_drop[i] = L2OutId_DP[i];
+ lx_len_drop[i] = L2OutLen_DP[i];
+ lx_prefetch_drop[i] = L2OutPrefetch_S[i];
+ lx_hit_drop[i] = L2OutHit_SP[i];
+
+ // The l2_xr_drop will also perform the handshake with the R sender
+ l2_xr_drop[i] = L2OutRwType_DP[i] ? 1'b0 : 1'b1;
+ l2_xw_drop[i] = L2OutRwType_DP[i] ? 1'b1 : 1'b0;
+
+ // Invalidate L1_DROP_BUF upon handshake
+ if ( (l2_xr_drop[i] & l2_xr_done[i]) | (l2_xw_drop[i] & l2_xw_done[i]) ) begin
+
+ L2OutValid_SN[i] = 1'b0;
+ L2Miss_S[i] = ~L2OutHit_SP[i];
+ int_prot[i] = L2OutProt_SP[i];
+ int_multi[i] = L2OutMulti_SP[i];
+ end
+ end
+ end
+
+ // Only accept new L2 output after ongoing drops have finished.
+ if ( (l2_xr_drop[i] == l2_xr_done[i]) &
+ (l2_xw_drop[i] == l2_xw_done[i]) &
+ (l1_r_drop[i] == l1_r_done[i] ) ) begin
+ // Store to L2_OUT_BUF upon handshake with L2 TLB module
+ if ( (L2OutValid_SP[i] == 1'b0) && (L2OutValid_S[i] == 1'b1) ) begin
+ L2OutValid_SN[i] = 1'b1;
+ L2OutReady_S[i] = 1'b1;
+ L2OutEn_S[i] = 1'b1;
+ end
+ end
+ end
+
+ /*
+ * L1 drop buffer
+ *
+ * Used in case of multi, prot and prefetch hits in the L1 TLB.
+ */
+ always_ff @(posedge Clk_CI) begin : L1_DROP_BUF
+ if (Rst_RBI == 0) begin
+ L1DropProt_DP[i] <= 1'b0;
+ L1DropMulti_DP[i] <= 1'b0;
+ L1DropRwType_DP[i] <= 1'b0;
+ L1DropUser_DP[i] <= 'b0;
+ L1DropId_DP[i] <= 'b0;
+ L1DropLen_DP[i] <= 'b0;
+ L1DropAddr_DP[i] <= 'b0;
+ end else if (L1DropEn_S[i] == 1'b1) begin
+ L1DropProt_DP[i] <= L1OutProt_D[i] ;
+ L1DropMulti_DP[i] <= L1OutMulti_D[i] ;
+ L1DropRwType_DP[i] <= L1OutRwType_D[i];
+ L1DropUser_DP[i] <= L1OutUser_D[i] ;
+ L1DropId_DP[i] <= L1OutId_D[i] ;
+ L1DropLen_DP[i] <= L1OutLen_D[i] ;
+ L1DropAddr_DP[i] <= L1OutAddr_D[i] ;
+ end
+ end // always_ff @ (posedge Clk_CI)
+
+ /*
+ * L2 input buffer
+ *
+ * Make sure there are no combinational paths between L1 TLB/inputs and L2 TLB.
+ */
+ always_ff @(posedge Clk_CI) begin : L2_IN_BUF
+ if (Rst_RBI == 0) begin
+ L2InRwType_DP[i] <= 1'b0;
+ L2InUser_DP[i] <= 'b0;
+ L2InId_DP[i] <= 'b0;
+ L2InLen_DP[i] <= 'b0;
+ L2InAddr_DP[i] <= 'b0;
+ end else if (L2InEn_S[i] == 1'b1) begin
+ L2InRwType_DP[i] <= L1OutRwType_D[i];
+ L2InUser_DP[i] <= L1OutUser_D[i] ;
+ L2InId_DP[i] <= L1OutId_D[i] ;
+ L2InLen_DP[i] <= L1OutLen_D[i] ;
+ L2InAddr_DP[i] <= L1OutAddr_D[i] ;
+ end
+ end // always_ff @ (posedge Clk_CI)
+
+ l2_tlb
+ #(
+ .AXI_S_ADDR_WIDTH ( AXI_S_ADDR_WIDTH ),
+ .AXI_M_ADDR_WIDTH ( AXI_M_ADDR_WIDTH ),
+ .AXI_LITE_DATA_WIDTH ( AXI_LITE_DATA_WIDTH ),
+ .AXI_LITE_ADDR_WIDTH ( AXI_LITE_ADDR_WIDTH ),
+ .N_SETS ( `RAB_L2_N_SETS ),
+ .N_OFFSETS ( `RAB_L2_N_SET_ENTRIES/2/`RAB_L2_N_PAR_VA_RAMS ),
+ .N_PAR_VA_RAMS ( `RAB_L2_N_PAR_VA_RAMS ),
+ .HIT_OFFSET_STORE_WIDTH ( log2(`RAB_L2_N_SET_ENTRIES/2/`RAB_L2_N_PAR_VA_RAMS) )
+ )
+ u_l2_tlb
+ (
+ .clk_i ( Clk_CI ),
+ .rst_ni ( Rst_RBI ),
+
+ // Config inputs
+ .we_i ( L2CfgWE_S[i] ),
+ .waddr_i ( L2CfgWAddr_D[i] ),
+ .wdata_i ( L2CfgWData_D[i] ),
+
+ // Request input
+ .start_i ( L2InEn_S[i] ),
+ .busy_o ( L2Busy_S[i] ),
+ .rw_type_i ( L2InRwType_DP[i] ),
+ .in_addr_i ( L2InAddr_DP[i] ),
+
+ // Response output
+ .out_ready_i ( L2OutReady_S[i] ),
+ .out_valid_o ( L2OutValid_S[i] ),
+ .hit_o ( L2OutHit_SN[i] ),
+ .miss_o ( L2OutMiss_SN[i] ),
+ .prot_o ( L2OutProt_SN[i] ),
+ .multi_o ( L2OutMulti_SN[i] ),
+ .cache_coherent_o ( L2OutCC_SN[i] ),
+ .out_addr_o ( L2OutAddr_DN[i] )
+ );
+
+ /*
+ * L2 output buffer
+ *
+ * Make sure there are no combinational paths between L1 TLB/inputs and L2 TLB.
+ */
+ always_ff @(posedge Clk_CI) begin : L2_OUT_BUF
+ if (Rst_RBI == 0) begin
+ L2OutRwType_DP[i] <= 1'b0;
+ L2OutUser_DP[i] <= 'b0;
+ L2OutLen_DP[i] <= 'b0;
+ L2OutId_DP[i] <= 'b0;
+ L2OutInAddr_DP[i] <= 'b0;
+
+ L2OutHit_SP[i] <= 1'b0;
+ L2OutMiss_SP[i] <= 1'b0;
+ L2OutProt_SP[i] <= 1'b0;
+ L2OutMulti_SP[i] <= 1'b0;
+ L2OutCC_SP[i] <= 1'b0;
+ L2OutAddr_DP[i] <= 'b0;
+ end else if (L2OutEn_S[i] == 1'b1) begin
+ L2OutRwType_DP[i] <= L2InRwType_DP[i];
+ L2OutUser_DP[i] <= L2InUser_DP[i] ;
+ L2OutLen_DP[i] <= L2InLen_DP[i] ;
+ L2OutId_DP[i] <= L2InId_DP[i] ;
+ L2OutInAddr_DP[i] <= L2InAddr_DP[i] ;
+
+ L2OutHit_SP[i] <= L2OutHit_SN[i] ;
+ L2OutMiss_SP[i] <= L2OutMiss_SN[i] ;
+ L2OutProt_SP[i] <= L2OutProt_SN[i] ;
+ L2OutMulti_SP[i] <= L2OutMulti_SN[i];
+ L2OutCC_SP[i] <= L2OutCC_SN[i] ;
+ L2OutAddr_DP[i] <= L2OutAddr_DN[i] ;
+ end
+ end // always_ff @ (posedge Clk_CI)
+
+ always_ff @(posedge Clk_CI) begin : BUF_VALID
+ if (Rst_RBI == 0) begin
+ L1DropValid_SP[i] = 1'b0;
+ L2OutValid_SP[i] = 1'b0;
+ end else begin
+ L1DropValid_SP[i] = L1DropValid_SN[i];
+ L2OutValid_SP[i] = L2OutValid_SN[i];
+ end
+ end
+
+ always_comb begin : BUF_TO_PREFETCH
+ // L1 Drop Buf
+ if (L1DropUser_DP[i] == {AXI_USER_WIDTH{1'b1}})
+ L1DropPrefetch_S[i] = 1'b1;
+ else
+ L1DropPrefetch_S[i] = 1'b0;
+
+ // L2 Out Buf
+ if (L2OutUser_DP[i] == {AXI_USER_WIDTH{1'b1}})
+ L2OutPrefetch_S[i] = 1'b1;
+ else
+ L2OutPrefetch_S[i] = 1'b0;
+ end
+
+ assign l2_cache_coherent[i] = L2OutCC_SP[i];
+ assign int_miss[i] = L2Miss_S[i];
+
+ end else begin : L2_TLB_STUB // if (ENABLE_L2TLB[i] == 1)
+
+ assign l1_ar_drop[i] = int_rtrans_drop[i];
+ assign l1_r_drop[i] = int_rtrans_drop[i];
+ assign l1_xw_drop[i] = int_wtrans_drop[i];
+
+ assign l1_ar_save[i] = 1'b0;
+ assign l1_xw_save[i] = 1'b0;
+ assign l2_xw_accept[i] = 1'b0;
+ assign l2_xr_drop[i] = 1'b0;
+ assign l2_xw_drop[i] = 1'b0;
+
+ assign l2_ar_addr[i] = 'b0;
+ assign l2_aw_addr[i] = 'b0;
+
+ assign l1_id_drop[i] = int_wtrans_drop[i] ? int_awid[i] :
+ int_rtrans_drop[i] ? int_arid[i] :
+ '0;
+ assign l1_len_drop[i] = int_wtrans_drop[i] ? int_awlen[i] :
+ int_rtrans_drop[i] ? int_arlen[i] :
+ '0;
+ assign l1_prefetch_drop[i] = rab_prefetch[i];
+ assign l1_hit_drop[i] = ~rab_miss[i];
+
+ assign lx_id_drop[i] = int_wtrans_drop[i] ? int_awid[i] :
+ int_rtrans_drop[i] ? int_arid[i] :
+ '0;
+ assign lx_len_drop[i] = int_wtrans_drop[i] ? int_awlen[i] :
+ int_rtrans_drop[i] ? int_arlen[i] :
+ '0;
+ assign lx_prefetch_drop[i] = rab_prefetch[i];
+ assign lx_hit_drop[i] = ~rab_miss[i];
+
+ assign l2_cache_coherent[i] = 1'b0;
+
+ assign int_miss[i] = rab_miss[i];
+ assign int_prot[i] = rab_prot[i];
+ assign int_multi[i] = rab_multi[i];
+
+ // unused signals
+ assign L2Miss_S[i] = 1'b0;
+
+ assign L1OutRwType_D[i] = 1'b0;
+ assign L1OutProt_D[i] = 1'b0;
+ assign L1OutMulti_D[i] = 1'b0;
+
+ assign L1DropRwType_DP[i] = 1'b0;
+ assign L1DropUser_DP[i] = 'b0;
+ assign L1DropId_DP[i] = 'b0;
+ assign L1DropLen_DP[i] = 'b0;
+ assign L1DropAddr_DP[i] = 'b0;
+ assign L1DropProt_DP[i] = 1'b0;
+ assign L1DropMulti_DP[i] = 1'b0;
+
+ assign L1DropEn_S[i] = 1'b0;
+ assign L1DropPrefetch_S[i] = 1'b0;
+ assign L1DropValid_SN[i] = 1'b0;
+ assign L1DropValid_SP[i] = 1'b0;
+
+ assign L2InRwType_DP[i] = 1'b0;
+ assign L2InUser_DP[i] = 'b0;
+ assign L2InId_DP[i] = 'b0;
+ assign L2InLen_DP[i] = 'b0;
+ assign L2InAddr_DP[i] = 'b0;
+
+ assign L2InEn_S[i] = 1'b0;
+
+ assign L2OutHit_SN[i] = 1'b0;
+ assign L2OutMiss_SN[i] = 1'b0;
+ assign L2OutProt_SN[i] = 1'b0;
+ assign L2OutMulti_SN[i] = 1'b0;
+ assign L2OutCC_SN[i] = 1'b0;
+ assign L2OutAddr_DN[i] = 'b0;
+
+ assign L2OutRwType_DP[i] = 1'b0;
+ assign L2OutUser_DP[i] = 'b0;
+ assign L2OutId_DP[i] = 'b0;
+ assign L2OutLen_DP[i] = 'b0;
+ assign L2OutInAddr_DP[i] = 'b0;
+ assign L2OutHit_SP[i] = 1'b0;
+ assign L2OutMiss_SP[i] = 1'b0;
+ assign L2OutProt_SP[i] = 1'b0;
+ assign L2OutMulti_SP[i] = 1'b0;
+ assign L2OutCC_SP[i] = 1'b0;
+ assign L2OutAddr_DP[i] = 'b0;
+
+ assign L2OutEn_S[i] = 1'b0;
+ assign L2OutPrefetch_S[i] = 1'b0;
+ assign L2Busy_S[i] = 1'b0;
+ assign L2OutValid_S[i] = 1'b0;
+ assign L2OutValid_SN[i] = 1'b0;
+ assign L2OutValid_SP[i] = 1'b0;
+ assign L2OutReady_S[i] = 1'b0;
+
+ end // !`ifdef ENABLE_L2TLB
+ end // for (i = 0; i < N_PORTS; i++)
+ endgenerate
+
+// }}}
+"""
+# endmodule
+#
+#
+# // vim: ts=2 sw=2 sts=2 et nosmartindent autoindent foldmethod=marker
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class check_ram(Elaboratable):
+
+ def __init__(self):
+ self.clk_i = Signal() # input
+ self.rst_ni = Signal() # input
+ self.in_addr = Signal(ADDR_WIDTH) # input
+ self.rw_type = Signal() # input
+ self.ram_we = Signal() # input
+ self.port0_addr = Signal(1+ERROR p_expression_25) # input
+ self.port1_addr = Signal(1+ERROR p_expression_25) # input
+ self.ram_wdata = Signal(RAM_DATA_WIDTH) # input
+ self.output_sent = Signal() # input
+ self.output_valid = Signal() # input
+ self.offset_addr_d = Signal(OFFSET_WIDTH) # input
+ self.hit_addr = Signal(1+ERROR p_expression_25) # output
+ self.master = Signal() # output
+ self.hit = Signal() # output
+ self.multi_hit = Signal() # output
+ self.prot = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ return m
+
+
+# // 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.
+#
+# //import CfMath::log2;
+#
+# //`define MULTI_HIT_FULL_SET
+#
+# module check_ram
+# //#(
+# // parameter ADDR_WIDTH = 32,
+# // parameter RAM_DATA_WIDTH = 32,
+# // parameter PAGE_SIZE = 4096, // 4kB
+# // parameter SET_WIDTH = 5,
+# // parameter OFFSET_WIDTH = 4
+# // )
+# (
+# input logic clk_i,
+# input logic rst_ni,
+# input logic [ADDR_WIDTH-1:0] in_addr,
+# input logic rw_type, // 1 => write, 0=> read
+# input logic ram_we,
+# input logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] port0_addr,
+# input logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] port1_addr,
+# input logic [RAM_DATA_WIDTH-1:0] ram_wdata,
+# input logic output_sent,
+# input logic output_valid,
+# input logic [OFFSET_WIDTH-1:0] offset_addr_d,
+# output logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] hit_addr,
+# output logic master,
+# output logic hit,
+# output logic multi_hit,
+# output logic prot
+# );
+#
+""" #docstring_begin
+
+ localparam IGNORE_LSB = log2(PAGE_SIZE); // 12
+
+ logic [RAM_DATA_WIDTH-1:0] port0_data_o, port1_data_o; // RAM read data outputs
+ logic port0_hit, port1_hit; // Ram output matches in_addr
+
+ logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] port0_addr_saved, port1_addr_saved;
+
+ // Hit FSM Signals
+ typedef enum logic {SEARCH, HIT} hit_state_t;
+ hit_state_t hit_SP; // Hit FSM state
+ hit_state_t hit_SN; // Hit FSM next state
+
+ // Multi Hit FSM signals
+`ifdef MULTI_HIT_FULL_SET
+ typedef enum logic[1:0] {NO_HITS, ONE_HIT, MULTI_HIT} multi_state_t;
+ multi_state_t multi_SP; // Multi Hit FSM state
+ multi_state_t multi_SN; // Multi Hit FSM next state
+
+ logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] hit_addr_saved;
+ logic master_saved;
+`endif
+
+ //// --------------- Block RAM (Dual Port) -------------- ////
+
+ // The outputs of the BRAMs are only valid if in the previous cycle:
+ // 1. the inputs were valid, and
+ // 2. the BRAM was not written to.
+ // Otherwise, the outputs must be ignored which is controlled by the output_valid signal.
+ // This signal is driven by the uppler level L2 TLB module.
+ ram_tp_no_change #(
+ .ADDR_WIDTH( SET_WIDTH+OFFSET_WIDTH+1 ),
+ .DATA_WIDTH( RAM_DATA_WIDTH )
+ )
+ ram_tp_no_change_0
+ (
+ .clk ( clk_i ),
+ .we ( ram_we ),
+ .addr0 ( port0_addr ),
+ .addr1 ( port1_addr ),
+ .d_i ( ram_wdata ),
+ .d0_o ( port0_data_o ),
+ .d1_o ( port1_data_o )
+ );
+
+ //// Check Ram Outputs
+ assign port0_hit = (port0_data_o[0] == 1'b1) && (in_addr[ADDR_WIDTH-1: IGNORE_LSB] == port0_data_o[RAM_DATA_WIDTH-1:4]);
+ assign port1_hit = (port1_data_o[0] == 1'b1) && (in_addr[ADDR_WIDTH-1: IGNORE_LSB] == port1_data_o[RAM_DATA_WIDTH-1:4]);
+ //// ----------------------------------------------------- /////
+
+ //// ------------------- Check if Hit ------------------------ ////
+ // FSM
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ hit_SP <= SEARCH;
+ end else begin
+ hit_SP <= hit_SN;
+ end
+ end
+
+ always_ff @(posedge clk_i, negedge rst_ni) begin
+ if (!rst_ni) begin
+ port0_addr_saved <= '0;
+ port1_addr_saved <= '0;
+ end else begin
+ port0_addr_saved <= port0_addr;
+ port1_addr_saved <= port1_addr;
+ end
+ end
+
+ always_comb begin
+ hit_SN = hit_SP;
+ hit = 1'b0;
+ hit_addr = 0;
+ master = 1'b0;
+ unique case(hit_SP)
+ SEARCH :
+ if (output_valid)
+ if (port0_hit || port1_hit) begin
+ hit_SN = HIT;
+ hit = 1'b1;
+ hit_addr = port0_hit ? {port0_addr_saved[SET_WIDTH+OFFSET_WIDTH:OFFSET_WIDTH], offset_addr_d} :
+ port1_hit ? {port1_addr_saved[SET_WIDTH+OFFSET_WIDTH:OFFSET_WIDTH], offset_addr_d} :
+ 0;
+ master = port0_hit ? port0_data_o[3] :
+ port1_hit ? port1_data_o[3] :
+ 1'b0;
+ end
+
+ HIT : begin
+`ifdef MULTI_HIT_FULL_SET // Since the search continues after the first hit, it needs to be saved to be accessed later.
+ hit = 1'b1;
+ hit_addr = hit_addr_saved;
+ master = master_saved;
+`endif
+ if (output_sent)
+ hit_SN = SEARCH;
+ end
+
+ default : begin
+ hit_SN = SEARCH;
+ end
+ endcase // case (hit_SP)
+ end // always_comb begin
+
+ //// ------------------------------------------- ////
+
+ assign prot = output_valid && port0_hit ? ((~port0_data_o[2] && rw_type) || (~port0_data_o[1] && ~rw_type)) :
+ output_valid && port1_hit ? ((~port1_data_o[2] && rw_type) || (~port1_data_o[1] && ~rw_type)) :
+ 1'b0;
+
+ //// ------------------- Multi ------------------- ////
+`ifdef MULTI_HIT_FULL_SET
+
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ hit_addr_saved <= 0;
+ master_saved <= 1'b0;
+ end else if (output_valid) begin
+ hit_addr_saved <= hit_addr;
+ master_saved <= master;
+ end
+ end
+
+ // FSM
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ multi_SP <= NO_HITS;
+ end else begin
+ multi_SP <= multi_SN;
+ end
+ end
+
+ always_comb begin
+ multi_SN = multi_SP;
+ multi_hit = 1'b0;
+ unique case(multi_SP)
+ NO_HITS :
+ if(output_valid && (port0_hit && port1_hit)) begin
+ multi_SN = MULTI_HIT;
+ multi_hit = 1'b1;
+ end else if(output_valid && (port0_hit || port1_hit))
+ multi_SN = ONE_HIT;
+
+ ONE_HIT :
+ if(output_valid && (port0_hit || port1_hit)) begin
+ multi_SN = MULTI_HIT;
+ multi_hit = 1'b1;
+ end else if (output_sent)
+ multi_SN = NO_HITS;
+
+ MULTI_HIT : begin
+ multi_hit = 1'b1;
+ if (output_sent)
+ multi_SN = NO_HITS;
+ end
+
+ endcase // case (multi_SP)
+ end // always_comb begin
+
+`else // !`ifdef MULTI_HIT_FULL_SET
+ assign multi_hit = output_valid && port0_hit && port1_hit;
+`endif // !`ifdef MULTI_HIT_FULL_SET
+ //// ------------------------------------------- ////
+"""
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class fsm(Elaboratable):
+
+ def __init__(self):
+ self.Clk_CI = Signal() # input
+ self.Rst_RBI = Signal() # input
+ self.port1_addr_valid_i = Signal() # input
+ self.port2_addr_valid_i = Signal() # input
+ self.port1_sent_i = Signal() # input
+ self.port2_sent_i = Signal() # input
+ self.select_i = Signal() # input
+ self.no_hit_i = Signal() # input
+ self.multi_hit_i = Signal() # input
+ self.no_prot_i = Signal() # input
+ self.prefetch_i = Signal() # input
+ self.out_addr_i = Signal(AXI_M_ADDR_WIDTH) # input
+ self.cache_coherent_i = Signal() # input
+ self.port1_accept_o = Signal() # output
+ self.port1_drop_o = Signal() # output
+ self.port1_miss_o = Signal() # output
+ self.port2_accept_o = Signal() # output
+ self.port2_drop_o = Signal() # output
+ self.port2_miss_o = Signal() # output
+ self.out_addr_o = Signal(AXI_M_ADDR_WIDTH) # output
+ self.cache_coherent_o = Signal() # output
+ self.miss_o = Signal() # output
+ self.multi_o = Signal() # output
+ self.prot_o = Signal() # output
+ self.prefetch_o = Signal() # output
+ self.in_addr_i = Signal(AXI_S_ADDR_WIDTH) # input
+ self.in_id_i = Signal(AXI_ID_WIDTH) # input
+ self.in_len_i = Signal(8) # input
+ self.in_user_i = Signal(AXI_USER_WIDTH) # input
+ self.in_addr_o = Signal(AXI_S_ADDR_WIDTH) # output
+ self.in_id_o = Signal(AXI_ID_WIDTH) # output
+ self.in_len_o = Signal(8) # output
+ self.in_user_o = Signal(AXI_USER_WIDTH) # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ return m
+
+
+# // 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.
+#
+# //`timescale 1ns / 1ps
+#
+# module fsm
+# #(
+# parameter AXI_M_ADDR_WIDTH = 40,
+# parameter AXI_S_ADDR_WIDTH = 32,
+# parameter AXI_ID_WIDTH = 8,
+# parameter AXI_USER_WIDTH = 6
+# )
+# (
+# input logic Clk_CI,
+# input logic Rst_RBI,
+#
+# input logic port1_addr_valid_i,
+# input logic port2_addr_valid_i,
+# input logic port1_sent_i,
+# input logic port2_sent_i,
+# input logic select_i,
+# input logic no_hit_i,
+# input logic multi_hit_i,
+# input logic no_prot_i,
+# input logic prefetch_i,
+# input logic [AXI_M_ADDR_WIDTH-1:0] out_addr_i,
+# input logic cache_coherent_i,
+# output logic port1_accept_o,
+# output logic port1_drop_o,
+# output logic port1_miss_o,
+# output logic port2_accept_o,
+# output logic port2_drop_o,
+# output logic port2_miss_o,
+# output logic [AXI_M_ADDR_WIDTH-1:0] out_addr_o,
+# output logic cache_coherent_o,
+# output logic miss_o,
+# output logic multi_o,
+# output logic prot_o,
+# output logic prefetch_o,
+# input logic [AXI_S_ADDR_WIDTH-1:0] in_addr_i,
+# input logic [AXI_ID_WIDTH-1:0] in_id_i,
+# input logic [7:0] in_len_i,
+# input logic [AXI_USER_WIDTH-1:0] in_user_i,
+# output logic [AXI_S_ADDR_WIDTH-1:0] in_addr_o,
+# output logic [AXI_ID_WIDTH-1:0] in_id_o,
+# output logic [7:0] in_len_o,
+# output logic [AXI_USER_WIDTH-1:0] in_user_o
+# );
+#
+""" #docstring_begin
+
+ //-------------Internal Signals----------------------
+
+ typedef enum logic {IDLE, WAIT} state_t;
+ logic state_SP; // Present state
+ logic state_SN; // Next State
+
+ logic port1_accept_SN;
+ logic port1_drop_SN;
+ logic port1_miss_SN;
+ logic port2_accept_SN;
+ logic port2_drop_SN;
+ logic port2_miss_SN;
+ logic miss_SN;
+ logic multi_SN;
+ logic prot_SN;
+ logic prefetch_SN;
+ logic cache_coherent_SN;
+ logic [AXI_M_ADDR_WIDTH-1:0] out_addr_DN;
+
+ logic out_reg_en_S;
+
+ //----------FSM comb------------------------------
+
+ always_comb begin: FSM_COMBO
+ state_SN = state_SP;
+
+ port1_accept_SN = 1'b0;
+ port1_drop_SN = 1'b0;
+ port1_miss_SN = 1'b0;
+ port2_accept_SN = 1'b0;
+ port2_drop_SN = 1'b0;
+ port2_miss_SN = 1'b0;
+ miss_SN = 1'b0;
+ multi_SN = 1'b0;
+ prot_SN = 1'b0;
+ prefetch_SN = 1'b0;
+ cache_coherent_SN = 1'b0;
+ out_addr_DN = '0;
+
+ out_reg_en_S = 1'b0; // by default hold register output
+
+ unique case(state_SP)
+ IDLE :
+ if ( (port1_addr_valid_i & select_i) | (port2_addr_valid_i & ~select_i) ) begin
+ out_reg_en_S = 1'b1;
+ state_SN = WAIT;
+
+ // Select inputs for output registers
+ if (port1_addr_valid_i & select_i) begin
+ port1_accept_SN = ~(no_hit_i | multi_hit_i | ~no_prot_i | prefetch_i);
+ port1_drop_SN = (no_hit_i | multi_hit_i | ~no_prot_i | prefetch_i);
+ port1_miss_SN = no_hit_i;
+ port2_accept_SN = 1'b0;
+ port2_drop_SN = 1'b0;
+ port2_miss_SN = 1'b0;
+ end else if (port2_addr_valid_i & ~select_i) begin
+ port1_accept_SN = 1'b0;
+ port1_drop_SN = 1'b0;
+ port1_miss_SN = 1'b0;
+ port2_accept_SN = ~(no_hit_i | multi_hit_i | ~no_prot_i | prefetch_i);
+ port2_drop_SN = (no_hit_i | multi_hit_i | ~no_prot_i | prefetch_i);
+ port2_miss_SN = no_hit_i;
+ end
+
+ miss_SN = port1_miss_SN | port2_miss_SN;
+ multi_SN = multi_hit_i;
+ prot_SN = ~no_prot_i;
+ prefetch_SN = ~no_hit_i & prefetch_i;
+
+ cache_coherent_SN = cache_coherent_i;
+ out_addr_DN = out_addr_i;
+ end
+
+ WAIT :
+ if ( port1_sent_i | port2_sent_i ) begin
+ out_reg_en_S = 1'b1; // "clear" the register
+ state_SN = IDLE;
+ end
+
+ default : begin
+ state_SN = IDLE;
+ end
+ endcase
+ end
+
+ //----------FSM seq-------------------------------
+
+ always_ff @(posedge Clk_CI, negedge Rst_RBI) begin: FSM_SEQ
+ if (Rst_RBI == 1'b0)
+ state_SP <= IDLE;
+ else
+ state_SP <= state_SN;
+ end
+
+ //----------Output seq--------------------------
+
+ always_ff @(posedge Clk_CI, negedge Rst_RBI) begin: OUTPUT_SEQ
+ if (Rst_RBI == 1'b0) begin
+ port1_accept_o = 1'b0;
+ port1_drop_o = 1'b0;
+ port1_miss_o = 1'b0;
+ port2_accept_o = 1'b0;
+ port2_drop_o = 1'b0;
+ port2_miss_o = 1'b0;
+ miss_o = 1'b0;
+ multi_o = 1'b0;
+ prot_o = 1'b0;
+ prefetch_o = 1'b0;
+ cache_coherent_o = 1'b0;
+ out_addr_o = '0;
+ in_addr_o = '0;
+ in_id_o = '0;
+ in_len_o = '0;
+ in_user_o = '0;
+ end else if (out_reg_en_S == 1'b1) begin
+ port1_accept_o = port1_accept_SN;
+ port1_drop_o = port1_drop_SN;
+ port1_miss_o = port1_miss_SN;
+ port2_accept_o = port2_accept_SN;
+ port2_drop_o = port2_drop_SN;
+ port2_miss_o = port2_miss_SN;
+ miss_o = miss_SN;
+ multi_o = multi_SN;
+ prot_o = prot_SN;
+ prefetch_o = prefetch_SN;
+ cache_coherent_o = cache_coherent_SN;
+ out_addr_o = out_addr_DN;
+ in_addr_o = in_addr_i;
+ in_id_o = in_id_i;
+ in_len_o = in_len_i;
+ in_user_o = in_user_i;
+ end
+ end // block: OUTPUT_SEQ
+"""
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class l2_tlb(Elaboratable):
+
+ def __init__(self):
+ self.clk_i = Signal() # input
+ self.rst_ni = Signal() # input
+ self.we_i = Signal() # input
+ self.waddr_i = Signal(AXI_LITE_ADDR_WIDTH) # input
+ self.wdata_i = Signal(AXI_LITE_DATA_WIDTH) # input
+ self.start_i = Signal() # input
+ self.busy_o = Signal() # output
+ self.in_addr_i = Signal(AXI_S_ADDR_WIDTH) # input
+ self.rw_type_i = Signal() # input
+ self.out_ready_i = Signal() # input
+ self.out_valid_o = Signal() # output
+ self.hit_o = Signal() # output
+ self.miss_o = Signal() # output
+ self.prot_o = Signal() # output
+ self.multi_o = Signal() # output
+ self.cache_coherent_o = Signal() # output
+ self.out_addr_o = Signal(AXI_M_ADDR_WIDTH) # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ return m
+
+
+# // 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.
+#
+# //`include "pulp_soc_defines.sv"
+#
+# ////import CfMath::log2;
+#
+# //`define MULTI_HIT_FULL_SET // Enable full multi hit detection. Always the entire set is searched.
+# //`define MULTI_HIT_CUR_CYCLE // Enable partial multi hit detection. Only multi hits in the same search cycle are detected.
+#
+# //`ifdef MULTI_HIT_FULL_SET
+# // `ifndef MULTI_HIT_CUR_CYCLE
+# // `define MULTI_HIT_CUR_CYCLE
+# // `endif
+# //`endif
+#
+# module l2_tlb
+# //#(
+# // 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 N_SETS = 32,
+# // parameter N_OFFSETS = 4, //per port. There are 2 ports.
+# // parameter PAGE_SIZE = 4096, // 4kB
+# // parameter N_PAR_VA_RAMS = 4,
+# // parameter HIT_OFFSET_STORE_WIDTH = 2 // Num of bits of VA RAM offset stored. This should not be greater than OFFSET_WIDTH
+# // )
+# (
+# input logic clk_i,
+# input logic rst_ni,
+#
+# input logic we_i,
+# input logic [AXI_LITE_ADDR_WIDTH-1:0] waddr_i,
+# input logic [AXI_LITE_DATA_WIDTH-1:0] wdata_i,
+#
+# input logic start_i,
+# output logic busy_o,
+# input logic [AXI_S_ADDR_WIDTH-1:0] in_addr_i,
+# input logic rw_type_i, //1 => write, 0=> read
+#
+# input logic out_ready_i,
+# output logic out_valid_o,
+# output logic hit_o,
+# output logic miss_o,
+# output logic prot_o,
+# output logic multi_o,
+# output logic cache_coherent_o,
+# output logic [AXI_M_ADDR_WIDTH-1:0] out_addr_o
+# );
+#
+""" #docstring_begin
+
+ localparam VA_RAM_DEPTH = N_SETS * N_OFFSETS * 2;
+ localparam PA_RAM_DEPTH = VA_RAM_DEPTH * N_PAR_VA_RAMS;
+ localparam VA_RAM_ADDR_WIDTH = log2(VA_RAM_DEPTH);
+ localparam PA_RAM_ADDR_WIDTH = log2(PA_RAM_DEPTH);
+ localparam SET_WIDTH = log2(N_SETS);
+ localparam OFFSET_WIDTH = log2(N_OFFSETS);
+ localparam LL_WIDTH = log2(N_PAR_VA_RAMS);
+ localparam IGNORE_LSB = log2(PAGE_SIZE);
+
+ localparam VA_RAM_DATA_WIDTH = AXI_S_ADDR_WIDTH - IGNORE_LSB + 4;
+ localparam PA_RAM_DATA_WIDTH = AXI_M_ADDR_WIDTH - IGNORE_LSB;
+
+ logic [N_PAR_VA_RAMS-1:0] hit, prot, multi_hit, cache_coherent;
+ logic [N_PAR_VA_RAMS-1:0] ram_we;
+ logic last_search, last_search_next;
+ logic first_search, first_search_next;
+ logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] ram_waddr;
+ logic [N_PAR_VA_RAMS-1:0][SET_WIDTH+OFFSET_WIDTH+1-1:0] hit_addr;
+ logic pa_ram_we;
+ logic [PA_RAM_ADDR_WIDTH-1:0] pa_port0_raddr, pa_port0_waddr; // PA RAM read, Write addr;
+ logic [PA_RAM_ADDR_WIDTH-1:0] pa_port0_raddr_reg_SN, pa_port0_raddr_reg_SP; // registered addresses, needed for WAIT_ON_WRITE;
+ logic [PA_RAM_ADDR_WIDTH-1:0] pa_port0_addr; // PA RAM addr
+ logic [PA_RAM_DATA_WIDTH-1:0] pa_port0_data, pa_data, pa_port0_data_reg; // PA RAM data
+ logic pa_ram_store_data_SN, pa_ram_store_data_SP;
+ logic hit_top, prot_top, multi_hit_top, first_hit_top;
+ logic output_sent;
+ int hit_block_num;
+
+ logic searching, search_done;
+ logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] port0_addr, port0_raddr; // VA RAM port0 addr
+ logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] port1_addr; // VA RAM port1 addr
+ logic [OFFSET_WIDTH-1:0] offset_addr, offset_addr_d;
+ logic [OFFSET_WIDTH-1:0] offset_start_addr, offset_end_addr;
+ logic [SET_WIDTH-1:0] set_num;
+
+ logic va_output_valid;
+ logic searching_q;
+
+ genvar z;
+
+ // Search FSM
+ typedef enum logic [1:0] {IDLE, SEARCH, DONE} search_state_t;
+ search_state_t search_SP; // Present state
+ search_state_t search_SN; // Next State
+
+ // Output FSM
+ typedef enum logic [1:0] {OUT_IDLE, SEND_OUTPUT, WAIT_ON_WRITE} out_state_t;
+ out_state_t out_SP; // Present state
+ out_state_t out_SN; // Next State
+
+ logic miss_next;
+ logic hit_next;
+ logic prot_next;
+ logic multi_next;
+ logic cache_coherent_next;
+
+ // Generate the VA Block rams and their surrounding logic
+ generate
+ for (z = 0; z < N_PAR_VA_RAMS; z++) begin : VA_RAMS
+ check_ram
+ #(
+ .ADDR_WIDTH ( AXI_S_ADDR_WIDTH ),
+ .RAM_DATA_WIDTH ( VA_RAM_DATA_WIDTH ),
+ .PAGE_SIZE ( PAGE_SIZE ),
+ .SET_WIDTH ( SET_WIDTH ),
+ .OFFSET_WIDTH ( OFFSET_WIDTH )
+ )
+ u_check_ram
+ (
+ .clk_i ( clk_i ),
+ .rst_ni ( rst_ni ),
+ .in_addr ( in_addr_i ),
+ .rw_type ( rw_type_i ),
+ .ram_we ( ram_we[z] ),
+ .port0_addr ( port0_addr ),
+ .port1_addr ( port1_addr ),
+ .ram_wdata ( wdata_i[VA_RAM_DATA_WIDTH-1:0] ),
+ .output_sent ( output_sent ),
+ .output_valid ( va_output_valid ),
+ .offset_addr_d ( offset_addr_d ),
+ .hit_addr ( hit_addr[z] ),
+ .master ( cache_coherent[z] ),
+ .hit ( hit[z] ),
+ .multi_hit ( multi_hit[z] ),
+ .prot ( prot[z] )
+ );
+ end // for (z = 0; z < N_PORTS; z++)
+ endgenerate
+
+ ////////////////// ---------------- Control and Address --------------- ////////////////////////
+ // FSM
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ search_SP <= IDLE;
+ end else begin
+ search_SP <= search_SN;
+ end
+ end
+
+ always_comb begin : SEARCH_FSM
+ search_SN = search_SP;
+ busy_o = 1'b0;
+ searching = 1'b0;
+ search_done = 1'b0;
+ last_search_next = 1'b0;
+ first_search_next = first_search;
+
+ unique case (search_SP)
+ IDLE : begin
+ if (start_i) begin
+ search_SN = SEARCH;
+ first_search_next = 1'b1;
+ end
+ end
+
+ SEARCH : begin
+ busy_o = 1'b1;
+
+ // detect last search cycle
+ if ( (first_search == 1'b0) && (offset_addr == offset_end_addr) )
+ last_search_next = 1'b1;
+
+ // pause search during VA RAM reconfigration
+ if (|ram_we) begin
+ searching = 1'b0;
+ end else begin
+ searching = 1'b1;
+ first_search_next = 1'b0;
+ end
+
+ if (va_output_valid) begin
+ // stop search
+`ifdef MULTI_HIT_FULL_SET
+ if (last_search | prot_top | multi_hit_top) begin
+`else
+ if (last_search | prot_top | multi_hit_top | hit_top ) begin
+`endif
+ search_SN = DONE;
+ search_done = 1'b1;
+ end
+ end
+ end
+
+ DONE : begin
+ busy_o = 1'b1;
+ if (out_valid_o & out_ready_i)
+ search_SN = IDLE;
+ end
+
+ default : begin
+ search_SN = IDLE;
+ end
+ endcase // case (prot_SP)
+ end // always_comb begin
+
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ last_search <= 1'b0;
+ first_search <= 1'b0;
+ end else begin
+ last_search <= last_search_next;
+ first_search <= first_search_next;
+ end
+ end
+
+ /*
+ * VA RAM address generation
+ *
+ * The input address and set number, and thus the offset start address, are available in the
+ * cycle after the start signal. The buffered offset_addr becomes available one cycle later.
+ * During the first search cycle, we therefore directly use offset_addr_start for the lookup.
+ */
+ assign set_num = in_addr_i[SET_WIDTH+IGNORE_LSB -1 : IGNORE_LSB];
+
+ assign port0_raddr[OFFSET_WIDTH] = 1'b0;
+ assign port1_addr [OFFSET_WIDTH] = 1'b1;
+
+ assign port0_raddr[OFFSET_WIDTH-1:0] = first_search ? offset_start_addr : offset_addr;
+ assign port1_addr [OFFSET_WIDTH-1:0] = first_search ? offset_start_addr : offset_addr;
+
+ assign port0_raddr[SET_WIDTH+OFFSET_WIDTH : OFFSET_WIDTH+1] = set_num;
+ assign port1_addr [SET_WIDTH+OFFSET_WIDTH : OFFSET_WIDTH+1] = set_num;
+
+ assign port0_addr = ram_we ? ram_waddr : port0_raddr;
+
+ // The outputs of the BRAMs are only valid if in the previous cycle:
+ // 1. the inputs were valid, and
+ // 2. the BRAMs were not written to.
+ // Otherwise, the outputs must be ignored.
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ searching_q <= 1'b0;
+ end else begin
+ searching_q <= searching;
+ end
+ end
+ assign va_output_valid = searching_q;
+
+ // Address offset for looking up the VA RAMs
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ offset_addr <= 0;
+ end else if (first_search) begin
+ offset_addr <= offset_start_addr + 1'b1;
+ end else if (searching) begin
+ offset_addr <= offset_addr + 1'b1;
+ end
+ end
+
+ // Delayed address offest for looking up the PA RAM upon a hit in the VA RAMs
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ offset_addr_d <= 0;
+ end else if (first_search) begin
+ offset_addr_d <= offset_start_addr;
+ end else if (searching) begin
+ offset_addr_d <= offset_addr_d + 1'b1;
+ end
+ end
+
+ // Store the offset addr for hit to reduce latency for next search.
+ generate
+ if (HIT_OFFSET_STORE_WIDTH > 0) begin : OFFSET_STORE
+`ifndef MULTI_HIT_FULL_SET
+ logic [N_SETS-1:0][HIT_OFFSET_STORE_WIDTH-1:0] hit_offset_addr; // Contains offset addr for previous hit for every SET.
+ logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] hit_addr_reg;
+
+ assign offset_start_addr = { hit_offset_addr[set_num] , {{OFFSET_WIDTH-HIT_OFFSET_STORE_WIDTH}{1'b0}} };
+ assign offset_end_addr = hit_offset_addr[set_num]-1'b1;
+
+ // Register the hit addr
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ hit_addr_reg <= 0;
+ end else if (hit_top) begin
+ hit_addr_reg <= hit_addr[hit_block_num];
+ end
+ end
+
+ // Store hit addr for each set. The next search in the same set will start from the saved addr.
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ hit_offset_addr <= 0;
+ end else if (hit_o) begin
+ hit_offset_addr[set_num][HIT_OFFSET_STORE_WIDTH-1:0] <= hit_addr_reg[OFFSET_WIDTH-1 : (OFFSET_WIDTH - HIT_OFFSET_STORE_WIDTH)];
+ end
+ end
+`else // No need to store offset if full multi hit detection is enabled because the entire SET is searched.
+ assign offset_start_addr = 0;
+ assign offset_end_addr = {OFFSET_WIDTH{1'b1}};
+`endif
+ end else begin // if (HIT_OFFSET_STORE_WIDTH > 0)
+ assign offset_start_addr = 0;
+ assign offset_end_addr = {OFFSET_WIDTH{1'b1}};
+ end
+ endgenerate
+
+ assign prot_top = |prot;
+
+ //////////////////////////////////////////////////////////////////////////////////////
+ // check for hit, multi hit
+ // In case of a multi hit, the hit_block_num indicates the lowest VA RAM with a hit.
+ // In case of a multi hit in the same VA RAM, Port 0 is given priority.
+ always_comb begin : HIT_CHECK
+ hit_top = |hit;
+ hit_block_num = 0;
+ first_hit_top = 1'b0;
+ multi_hit_top = 1'b0;
+ for (int i=N_PAR_VA_RAMS-1; i>=0; i--) begin
+ if (hit[i] == 1'b1) begin
+`ifdef MULTI_HIT_CUR_CYCLE
+ if (multi_hit[i] | first_hit_top ) begin
+ multi_hit_top = 1'b1;
+ end
+`endif
+ first_hit_top = 1'b1;
+ hit_block_num = i;
+ end
+ end // for (int i=0; i<N_PAR_VA_RAMS; i++)
+ end // always_comb begin
+
+ ///////////////////// ------------- Outputs ------------ //////////////////////////////////
+ //// FSM
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ out_SP <= OUT_IDLE;
+ pa_ram_store_data_SP <= 1'b0;
+ pa_port0_raddr_reg_SP <= 'b0;
+ end else begin
+ out_SP <= out_SN;
+ pa_ram_store_data_SP <= pa_ram_store_data_SN;
+ pa_port0_raddr_reg_SP <= pa_port0_raddr_reg_SN;
+ end
+ end
+
+ always_comb begin : OUTPUT_FSM
+ out_SN = out_SP;
+
+ miss_next = miss_o;
+ prot_next = prot_o;
+ multi_next = multi_o;
+ hit_next = hit_o;
+ cache_coherent_next = cache_coherent_o;
+ pa_port0_raddr_reg_SN = pa_port0_raddr_reg_SP;
+
+ pa_port0_raddr = 'b0;
+ pa_ram_store_data_SN = 1'b0;
+
+ out_valid_o = 1'b0;
+ output_sent = 1'b0;
+
+ unique case (out_SP)
+ OUT_IDLE : begin
+ hit_next = 1'b0;
+ miss_next = 1'b0;
+ prot_next = 1'b0;
+ multi_next = 1'b0;
+ cache_coherent_next = 1'b0;
+
+ // abort transaction
+ if ((search_done & ~hit_top) | prot_top | multi_hit_top) begin
+ out_SN = SEND_OUTPUT;
+
+ if (search_done & ~hit_top) begin
+ miss_next = 1'b1;
+ end
+ if (prot_top) begin
+ prot_next = 1'b1;
+ hit_next = 1'b1;
+ end
+ if (multi_hit_top) begin
+ multi_next = 1'b1;
+ hit_next = 1'b1;
+ end
+
+ // read PA RAM
+ end else if (search_done & hit_top) begin
+ hit_next = 1'b1;
+ cache_coherent_next = cache_coherent[hit_block_num];
+ pa_port0_raddr = (N_PAR_VA_RAMS * hit_addr[hit_block_num]) + hit_block_num;
+ pa_port0_raddr_reg_SN = pa_port0_raddr;
+
+ // read PA RAM now
+ if (~pa_ram_we) begin
+ out_SN = SEND_OUTPUT;
+ pa_ram_store_data_SN = 1'b1;
+
+ // read PA RAM after PA RAM reconfiguration
+ end else begin // pa_ram_we
+ out_SN = WAIT_ON_WRITE;
+
+ end
+ end
+ end
+
+ WAIT_ON_WRITE : begin
+ if ( ~pa_ram_we ) begin
+ out_SN = SEND_OUTPUT;
+ pa_port0_raddr = pa_port0_raddr_reg_SP;
+ pa_ram_store_data_SN = 1'b1;
+ end
+ end
+
+ SEND_OUTPUT : begin
+ out_valid_o = 1'b1;
+ if (out_ready_i) begin
+ out_SN = OUT_IDLE;
+ output_sent = 1'b1;
+ end
+ end
+
+ default : begin
+ out_SN = OUT_IDLE;
+ end
+
+ endcase // case (out_SP)
+ end // always_comb begin
+
+ //// Output signals
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ miss_o <= 1'b0;
+ prot_o <= 1'b0;
+ multi_o <= 1'b0;
+ hit_o <= 1'b0;
+ cache_coherent_o <= 1'b0;
+ end else begin
+ miss_o <= miss_next;
+ prot_o <= prot_next;
+ multi_o <= multi_next;
+ hit_o <= hit_next;
+ cache_coherent_o <= cache_coherent_next;
+ end
+ end
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ ///////////////////// --------------- Physical Address -------------- ////////////////////////////
+
+ /// PA Block RAM
+ ram_tp_no_change #(
+ .ADDR_WIDTH( PA_RAM_ADDR_WIDTH ),
+ .DATA_WIDTH( PA_RAM_DATA_WIDTH )
+ )
+ pa_ram
+ (
+ .clk ( clk_i ),
+ .we ( pa_ram_we ),
+ .addr0 ( pa_port0_addr ),
+ .addr1 ( '0 ),
+ .d_i ( wdata_i[PA_RAM_DATA_WIDTH-1:0] ),
+ .d0_o ( pa_port0_data ),
+ .d1_o ( )
+ );
+
+ assign out_addr_o[IGNORE_LSB-1:0] = in_addr_i[IGNORE_LSB-1:0];
+ assign out_addr_o[AXI_M_ADDR_WIDTH-1:IGNORE_LSB] = pa_data;
+
+ always_ff @(posedge clk_i) begin
+ if (rst_ni == 0) begin
+ pa_port0_data_reg <= 0;
+ end else if (pa_ram_store_data_SP) begin
+ pa_port0_data_reg <= pa_port0_data;
+ end
+ end
+
+ assign pa_data = pa_ram_store_data_SP ? pa_port0_data : pa_port0_data_reg;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+///// Write enable for all block rams
+generate if (LL_WIDTH != 0) begin
+ always_comb begin
+ var reg[LL_WIDTH:0] para;
+ var int para_int;
+ for (para = 0; para < N_PAR_VA_RAMS; para=para+1'b1) begin
+ para_int = int'(para);
+ ram_we[para_int] = we_i && (waddr_i[LL_WIDTH+VA_RAM_ADDR_WIDTH] == 1'b0) && (waddr_i[LL_WIDTH-1:0] == para);
+ end
+ end
+end else begin
+ assign ram_we[0] = we_i && (waddr_i[LL_WIDTH+VA_RAM_ADDR_WIDTH] == 1'b0);
+end
+
+endgenerate
+
+// Addresses are word, not byte addresses
+assign pa_ram_we = we_i && (waddr_i[LL_WIDTH+VA_RAM_ADDR_WIDTH] == 1'b1); //waddr_i[LL_WIDTH+VA_RAM_ADDR_WIDTH] will be 0 for all VA writes and 1 for all PA writes
+assign ram_waddr = waddr_i[LL_WIDTH+VA_RAM_ADDR_WIDTH-1:LL_WIDTH];
+assign pa_port0_waddr = waddr_i[PA_RAM_ADDR_WIDTH-1:0];
+assign pa_port0_addr = pa_ram_we ? pa_port0_waddr : pa_port0_raddr;
+
+"""
+# endmodule
+#
+# // vim: ts=3 sw=3 sts=3 et nosmartindent autoindent foldmethod=marker tw=100
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class rab_slice(Elaboratable):
+
+ def __init__(self):
+ self.cfg_min = Signal(ADDR_WIDTH_VIRT) # input
+ self.cfg_max = Signal(ADDR_WIDTH_VIRT) # input
+ self.cfg_offset = Signal(ADDR_WIDTH_PHYS) # input
+ self.cfg_wen = Signal() # input
+ self.cfg_ren = Signal() # input
+ self.cfg_en = Signal() # input
+ self.in_trans_type = Signal() # input
+ self.in_addr_min = Signal(ADDR_WIDTH_VIRT) # input
+ self.in_addr_max = Signal(ADDR_WIDTH_VIRT) # input
+ self.out_hit = Signal() # output
+ self.out_prot = Signal() # output
+ self.out_addr = Signal(ADDR_WIDTH_PHYS) # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.min_above_min.eq(self.None)
+ m.d.comb += self.min_below_max.eq(self.None)
+ m.d.comb += self.max_below_max.eq(self.None)
+ m.d.comb += self.out_hit.eq(self.None)
+ m.d.comb += self.out_prot.eq(self.None)
+ m.d.comb += self.out_addr.eq(self.None)
+ return m
+
+# // 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.
+#
+# module rab_slice
+# #(
+# parameter ADDR_WIDTH_PHYS = 40,
+# parameter ADDR_WIDTH_VIRT = 32
+# )
+# (
+# input logic [ADDR_WIDTH_VIRT-1:0] cfg_min,
+# input logic [ADDR_WIDTH_VIRT-1:0] cfg_max,
+# input logic [ADDR_WIDTH_PHYS-1:0] cfg_offset,
+# input logic cfg_wen,
+# input logic cfg_ren,
+# input logic cfg_en,
+# input logic in_trans_type,
+# input logic [ADDR_WIDTH_VIRT-1:0] in_addr_min,
+# input logic [ADDR_WIDTH_VIRT-1:0] in_addr_max,
+# output logic out_hit,
+# output logic out_prot,
+# output logic [ADDR_WIDTH_PHYS-1:0] out_addr
+# );
+#
+# wire min_above_min;
+# wire min_below_max;
+# wire max_below_max;
+#
+# assign min_above_min = (in_addr_min >= cfg_min) ? 1'b1 : 1'b0;
+# assign min_below_max = (in_addr_min <= cfg_max) ? 1'b1 : 1'b0;
+# assign max_below_max = (in_addr_max <= cfg_max) ? 1'b1 : 1'b0;
+#
+# assign out_hit = cfg_en & min_above_min & min_below_max & max_below_max;
+# assign out_prot = out_hit & ((in_trans_type & ~cfg_wen) | (~in_trans_type & ~cfg_ren));
+# assign out_addr = in_addr_min - cfg_min + cfg_offset;
+#
+# endmodule
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class ram_tp_no_change(Elaboratable):
+
+ def __init__(self):
+ self.clk = Signal() # input
+ self.we = Signal() # input
+ self.addr0 = Signal() # input
+ self.addr1 = Signal() # input
+ self.d_i = Signal() # input
+ self.d0_o = Signal() # output
+ self.d1_o = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.d0_o.eq(self.d0)
+ m.d.comb += self.d1_o.eq(self.d1)
+ return m
+
+# // 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.
+#
+# /*
+# * ram_tp_no_change
+# *
+# * This code implements a parameterizable two-port memory. Port 0 can read and
+# * write while Port 1 can read only. The Xilinx tools will infer a BRAM with
+# * Port 0 in "no change" mode, i.e., during a write, it retains the last read
+# * value on the output. Port 1 (read-only) is in "write first" mode. Still, it
+# * outputs the old data during the write cycle. Note: Port 1 outputs invalid
+# * data in the cycle after the write when reading the same address.
+# *
+# * For more information, see Xilinx PG058 Block Memory Generator Product Guide.
+# */
+#
+# module ram_tp_no_change
+# #(
+# parameter ADDR_WIDTH = 10,
+# parameter DATA_WIDTH = 36
+# )
+# (
+# input clk,
+# input we,
+# input [ADDR_WIDTH-1:0] addr0,
+# input [ADDR_WIDTH-1:0] addr1,
+# input [DATA_WIDTH-1:0] d_i,
+# output [DATA_WIDTH-1:0] d0_o,
+# output [DATA_WIDTH-1:0] d1_o
+# );
+#
+# localparam DEPTH = 2**ADDR_WIDTH;
+#
+# (* ram_style = "block" *) reg [DATA_WIDTH-1:0] ram[DEPTH];
+# reg [DATA_WIDTH-1:0] d0;
+# reg [DATA_WIDTH-1:0] d1;
+#
+# always_ff @(posedge clk) begin
+# if(we == 1'b1) begin
+# ram[addr0] <= d_i;
+# end else begin
+# d0 <= ram[addr0];
+# end
+# d1 <= ram[addr1];
+# end
+#
+# assign d0_o = d0;
+# assign d1_o = d1;
+#
+#endmodule // ram_tp_no_change
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class ram_tp_write_first(Elaboratable):
+
+ def __init__(self):
+ self.clk = Signal() # input
+ self.we = Signal() # input
+ self.addr0 = Signal() # input
+ self.addr1 = Signal() # input
+ self.d_i = Signal() # input
+ self.d0_o = Signal() # output
+ self.d1_o = Signal() # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ m.d.comb += self.d0_o.eq(self.None)
+ m.d.comb += self.d1_o.eq(self.None)
+ return m
+
+# // 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.
+#
+# /*
+# * ram_tp_write_first
+# *
+# * This code implements a parameterizable two-port memory. Port 0 can read and
+# * write while Port 1 can read only. Xilinx Vivado will infer a BRAM in
+# * "write first" mode, i.e., upon a read and write to the same address, the
+# * new value is read. Note: Port 1 outputs invalid data in the cycle after
+# * the write when reading the same address.
+# *
+# * For more information, see Xilinx PG058 Block Memory Generator Product Guide.
+# */
+#
+# module ram_tp_write_first
+# #(
+# parameter ADDR_WIDTH = 10,
+# parameter DATA_WIDTH = 36
+# )
+# (
+# input clk,
+# input we,
+# input [ADDR_WIDTH-1:0] addr0,
+# input [ADDR_WIDTH-1:0] addr1,
+# input [DATA_WIDTH-1:0] d_i,
+# output [DATA_WIDTH-1:0] d0_o,
+# output [DATA_WIDTH-1:0] d1_o
+# );
+#
+# localparam DEPTH = 2**ADDR_WIDTH;
+#
+# (* ram_style = "block" *) reg [DATA_WIDTH-1:0] ram[DEPTH];
+# reg [ADDR_WIDTH-1:0] raddr0;
+# reg [ADDR_WIDTH-1:0] raddr1;
+#
+# always_ff @(posedge clk) begin
+# if(we == 1'b1) begin
+# ram[addr0] <= d_i;
+# end
+# raddr0 <= addr0;
+# raddr1 <= addr1;
+# end
+#
+# assign d0_o = ram[raddr0];
+# assign d1_o = ram[raddr1];
+#
+#endmodule // ram
+#
+#
--- /dev/null
+# this file has been generated by sv2nmigen
+
+from nmigen import Signal, Module, Const, Cat, Elaboratable
+
+
+class slice_top(Elaboratable):
+
+ def __init__(self):
+ self.int_cfg_regs = Signal() # input
+ self.int_rw = Signal() # input
+ self.int_addr_min = Signal(ADDR_WIDTH_VIRT) # input
+ self.int_addr_max = Signal(ADDR_WIDTH_VIRT) # input
+ self.multi_hit_allow = Signal() # input
+ self.multi_hit = Signal() # output
+ self.prot = Signal(N_SLICES) # output
+ self.hit = Signal(N_SLICES) # output
+ self.cache_coherent = Signal() # output
+ self.out_addr = Signal(ADDR_WIDTH_PHYS) # output
+
+ def elaborate(self, platform=None):
+ m = Module()
+ return m
+
+
+# // 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.
+#
+# module slice_top
+# //#(
+# // parameter N_SLICES = 16,
+# // parameter N_REGS = 4*N_SLICES,
+# // parameter ADDR_WIDTH_PHYS = 40,
+# // parameter ADDR_WIDTH_VIRT = 32
+# // )
+# (
+# input logic [N_REGS-1:0] [63:0] int_cfg_regs,
+# input logic int_rw,
+# input logic [ADDR_WIDTH_VIRT-1:0] int_addr_min,
+# input logic [ADDR_WIDTH_VIRT-1:0] int_addr_max,
+# input logic multi_hit_allow,
+# output logic multi_hit,
+# output logic [N_SLICES-1:0] prot,
+# output logic [N_SLICES-1:0] hit,
+# output logic cache_coherent,
+# output logic [ADDR_WIDTH_PHYS-1:0] out_addr
+# );
+#
+""" #docstring_begin
+
+ logic first_hit;
+
+ genvar i;
+ integer j;
+
+ logic [ADDR_WIDTH_PHYS*N_SLICES-1:0] slice_out_addr;
+
+ generate
+ for ( i=0; i<N_SLICES; i++ )
+ begin
+ rab_slice
+ #(
+ .ADDR_WIDTH_PHYS ( ADDR_WIDTH_PHYS ),
+ .ADDR_WIDTH_VIRT ( ADDR_WIDTH_VIRT )
+ )
+ u_slice
+ (
+ .cfg_min ( int_cfg_regs[4*i] [ADDR_WIDTH_VIRT-1:0] ),
+ .cfg_max ( int_cfg_regs[4*i+1][ADDR_WIDTH_VIRT-1:0] ),
+ .cfg_offset ( int_cfg_regs[4*i+2][ADDR_WIDTH_PHYS-1:0] ),
+ .cfg_wen ( int_cfg_regs[4*i+3][2] ),
+ .cfg_ren ( int_cfg_regs[4*i+3][1] ),
+ .cfg_en ( int_cfg_regs[4*i+3][0] ),
+ .in_trans_type ( int_rw ),
+ .in_addr_min ( int_addr_min ),
+ .in_addr_max ( int_addr_max ),
+ .out_addr ( slice_out_addr[ADDR_WIDTH_PHYS*i+ADDR_WIDTH_PHYS-1:ADDR_WIDTH_PHYS*i] ),
+ .out_prot ( prot[i] ),
+ .out_hit ( hit[i] )
+ );
+ end
+ endgenerate
+
+ // In case of a multi hit, the lowest slice with a hit is selected.
+ always_comb begin : HIT_CHECK
+ first_hit = 0;
+ multi_hit = 0;
+ out_addr = '0;
+ cache_coherent = 0;
+ for (j = 0; j < N_SLICES; j++) begin
+ if (hit[j] == 1'b1) begin
+ if (first_hit == 1'b1) begin
+ if (multi_hit_allow == 1'b0) begin
+ multi_hit = 1'b1;
+ end
+ end else begin
+ first_hit = 1'b1;
+ out_addr = slice_out_addr[ADDR_WIDTH_PHYS*j +: ADDR_WIDTH_PHYS];
+ cache_coherent = int_cfg_regs[4*j+3][3];
+ end
+ end
+ end
+ end
+"""
+# endmodule
+#
+# // vim: ts=2 sw=2 sts=2 et nosmartindent autoindent foldmethod=marker
+#
+#