31bf32ea1e72339cf968c40afc179e8e8c870e0b
1 # this file has been generated by sv2nmigen
3 from nmigen
import Signal
, Module
, Const
, Cat
, Elaboratable
6 class check_ram(Elaboratable
):
9 self
.clk_i
= Signal() # input
10 self
.rst_ni
= Signal() # input
11 self
.in_addr
= Signal(ADDR_WIDTH
) # input
12 self
.rw_type
= Signal() # input
13 self
.ram_we
= Signal() # input
14 self
.port0_addr
= Signal(1+ERROR p_expression_25
) # input
15 self
.port1_addr
= Signal(1+ERROR p_expression_25
) # input
16 self
.ram_wdata
= Signal(RAM_DATA_WIDTH
) # input
17 self
.output_sent
= Signal() # input
18 self
.output_valid
= Signal() # input
19 self
.offset_addr_d
= Signal(OFFSET_WIDTH
) # input
20 self
.hit_addr
= Signal(1+ERROR p_expression_25
) # output
21 self
.master
= Signal() # output
22 self
.hit
= Signal() # output
23 self
.multi_hit
= Signal() # output
24 self
.prot
= Signal() # output
26 def elaborate(self
, platform
=None):
31 # // Copyright 2018 ETH Zurich and University of Bologna.
32 # // Copyright and related rights are licensed under the Solderpad Hardware
33 # // License, Version 0.51 (the "License"); you may not use this file except in
34 # // compliance with the License. You may obtain a copy of the License at
35 # // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
36 # // or agreed to in writing, software, hardware and materials distributed under
37 # // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
38 # // CONDITIONS OF ANY KIND, either express or implied. See the License for the
39 # // specific language governing permissions and limitations under the License.
41 # //import CfMath::log2;
43 # //`define MULTI_HIT_FULL_SET
47 # // parameter ADDR_WIDTH = 32,
48 # // parameter RAM_DATA_WIDTH = 32,
49 # // parameter PAGE_SIZE = 4096, // 4kB
50 # // parameter SET_WIDTH = 5,
51 # // parameter OFFSET_WIDTH = 4
56 # input logic [ADDR_WIDTH-1:0] in_addr,
57 # input logic rw_type, // 1 => write, 0=> read
59 # input logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] port0_addr,
60 # input logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] port1_addr,
61 # input logic [RAM_DATA_WIDTH-1:0] ram_wdata,
62 # input logic output_sent,
63 # input logic output_valid,
64 # input logic [OFFSET_WIDTH-1:0] offset_addr_d,
65 # output logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] hit_addr,
66 # output logic master,
68 # output logic multi_hit,
74 localparam IGNORE_LSB = log2(PAGE_SIZE); // 12
76 logic [RAM_DATA_WIDTH-1:0] port0_data_o, port1_data_o; // RAM read data outputs
77 logic port0_hit, port1_hit; // Ram output matches in_addr
79 logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] port0_addr_saved, port1_addr_saved;
82 typedef enum logic {SEARCH, HIT} hit_state_t;
83 hit_state_t hit_SP; // Hit FSM state
84 hit_state_t hit_SN; // Hit FSM next state
86 // Multi Hit FSM signals
87 `ifdef MULTI_HIT_FULL_SET
88 typedef enum logic[1:0] {NO_HITS, ONE_HIT, MULTI_HIT} multi_state_t;
89 multi_state_t multi_SP; // Multi Hit FSM state
90 multi_state_t multi_SN; // Multi Hit FSM next state
92 logic [SET_WIDTH+OFFSET_WIDTH+1-1:0] hit_addr_saved;
96 //// --------------- Block RAM (Dual Port) -------------- ////
98 // The outputs of the BRAMs are only valid if in the previous cycle:
99 // 1. the inputs were valid, and
100 // 2. the BRAM was not written to.
101 // Otherwise, the outputs must be ignored which is controlled by the output_valid signal.
102 // This signal is driven by the uppler level L2 TLB module.
104 .ADDR_WIDTH( SET_WIDTH+OFFSET_WIDTH+1 ),
105 .DATA_WIDTH( RAM_DATA_WIDTH )
111 .addr0 ( port0_addr ),
112 .addr1 ( port1_addr ),
114 .d0_o ( port0_data_o ),
115 .d1_o ( port1_data_o )
118 //// Check Ram Outputs
119 assign port0_hit = (port0_data_o[0] == 1'b1) && (in_addr[ADDR_WIDTH-1: IGNORE_LSB] == port0_data_o[RAM_DATA_WIDTH-1:4]);
120 assign port1_hit = (port1_data_o[0] == 1'b1) && (in_addr[ADDR_WIDTH-1: IGNORE_LSB] == port1_data_o[RAM_DATA_WIDTH-1:4]);
121 //// ----------------------------------------------------- /////
123 //// ------------------- Check if Hit ------------------------ ////
125 always_ff @(posedge clk_i) begin
126 if (rst_ni == 0) begin
133 always_ff @(posedge clk_i, negedge rst_ni) begin
135 port0_addr_saved <= '0;
136 port1_addr_saved <= '0;
138 port0_addr_saved <= port0_addr;
139 port1_addr_saved <= port1_addr;
151 if (port0_hit || port1_hit) begin
154 hit_addr = port0_hit ? {port0_addr_saved[SET_WIDTH+OFFSET_WIDTH:OFFSET_WIDTH], offset_addr_d} :
155 port1_hit ? {port1_addr_saved[SET_WIDTH+OFFSET_WIDTH:OFFSET_WIDTH], offset_addr_d} :
157 master = port0_hit ? port0_data_o[3] :
158 port1_hit ? port1_data_o[3] :
163 `ifdef MULTI_HIT_FULL_SET // Since the search continues after the first hit, it needs to be saved to be accessed later.
165 hit_addr = hit_addr_saved;
166 master = master_saved;
175 endcase // case (hit_SP)
176 end // always_comb begin
178 //// ------------------------------------------- ////
180 assign prot = output_valid && port0_hit ? ((~port0_data_o[2] && rw_type) || (~port0_data_o[1] && ~rw_type)) :
181 output_valid && port1_hit ? ((~port1_data_o[2] && rw_type) || (~port1_data_o[1] && ~rw_type)) :
184 //// ------------------- Multi ------------------- ////
185 `ifdef MULTI_HIT_FULL_SET
187 always_ff @(posedge clk_i) begin
188 if (rst_ni == 0) begin
190 master_saved <= 1'b0;
191 end else if (output_valid) begin
192 hit_addr_saved <= hit_addr;
193 master_saved <= master;
198 always_ff @(posedge clk_i) begin
199 if (rst_ni == 0) begin
202 multi_SP <= multi_SN;
209 unique case(multi_SP)
211 if(output_valid && (port0_hit && port1_hit)) begin
212 multi_SN = MULTI_HIT;
214 end else if(output_valid && (port0_hit || port1_hit))
218 if(output_valid && (port0_hit || port1_hit)) begin
219 multi_SN = MULTI_HIT;
221 end else if (output_sent)
230 endcase // case (multi_SP)
231 end // always_comb begin
233 `else // !`ifdef MULTI_HIT_FULL_SET
234 assign multi_hit = output_valid && port0_hit && port1_hit;
235 `endif // !`ifdef MULTI_HIT_FULL_SET
236 //// ------------------------------------------- ////