1 | // ========== Copyright Header Begin ========================================== |
---|
2 | // |
---|
3 | // OpenSPARC T1 Processor File: bw_rf_16x81.v |
---|
4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. |
---|
5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. |
---|
6 | // |
---|
7 | // The above named program is free software; you can redistribute it and/or |
---|
8 | // modify it under the terms of the GNU General Public |
---|
9 | // License version 2 as published by the Free Software Foundation. |
---|
10 | // |
---|
11 | // The above named program is distributed in the hope that it will be |
---|
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
14 | // General Public License for more details. |
---|
15 | // |
---|
16 | // You should have received a copy of the GNU General Public |
---|
17 | // License along with this work; if not, write to the Free Software |
---|
18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
---|
19 | // |
---|
20 | // ========== Copyright Header End ============================================ |
---|
21 | module bw_rf_16x81( |
---|
22 | rd_clk, // read clock |
---|
23 | wr_clk, // read clock |
---|
24 | csn_rd, // read enable -- active low |
---|
25 | csn_wr, // write enable -- active low |
---|
26 | hold, // hold signal -- unflopped -- hold =1 holds input data |
---|
27 | testmux_sel, // bypass signal -- unflopped -- testmux_sel = 1 bypasses di to do |
---|
28 | scan_en, // Scan enable unflopped |
---|
29 | margin, // Delay for the circuits--- set to 01010101 |
---|
30 | rd_a, // read address |
---|
31 | wr_a, // Write address |
---|
32 | di, // Data input |
---|
33 | si, // scan in |
---|
34 | so, // scan out |
---|
35 | listen_out, // Listening flop-- |
---|
36 | do // Data out |
---|
37 | |
---|
38 | ); |
---|
39 | |
---|
40 | input rd_clk; |
---|
41 | input wr_clk; |
---|
42 | input csn_rd; |
---|
43 | input csn_wr; |
---|
44 | input hold; |
---|
45 | input testmux_sel; |
---|
46 | input scan_en; |
---|
47 | input [4:0] margin; |
---|
48 | input [3:0] rd_a; |
---|
49 | input [3:0] wr_a; |
---|
50 | input [80:0] di; |
---|
51 | input si; |
---|
52 | output so; |
---|
53 | output [80:0] do; |
---|
54 | output [80:0] listen_out; |
---|
55 | |
---|
56 | parameter SYNC_CLOCK_CHK1 = 1; |
---|
57 | parameter SYNC_CLOCK_CHK2 = 1; |
---|
58 | parameter SYNC_CLOCK_CHK3 = 1; |
---|
59 | parameter MARGIN_WARNING = 1; // margin warning is on by default |
---|
60 | |
---|
61 | |
---|
62 | |
---|
63 | |
---|
64 | // Start code |
---|
65 | reg [80:0] memarray[15:0] ; |
---|
66 | reg [80:0] array_out ; |
---|
67 | |
---|
68 | reg [80:0] array_out_latch ; |
---|
69 | |
---|
70 | |
---|
71 | |
---|
72 | reg [3:0] rd_a_ff ; |
---|
73 | wire [3:0] rd_a_ff_so; |
---|
74 | wire [3:0] rd_a_ff_si ; |
---|
75 | |
---|
76 | reg [3:0] wr_a_ff ; |
---|
77 | wire [3:0] wr_a_ff_so; |
---|
78 | wire [3:0] wr_a_ff_si ; |
---|
79 | |
---|
80 | reg [80:0] di_ff ; |
---|
81 | wire [80:0] di_ff_so; |
---|
82 | wire [80:0] di_ff_si; |
---|
83 | |
---|
84 | wire [80:0] listen_out_so; |
---|
85 | wire [80:0] listen_out_si ; |
---|
86 | reg [80:0] listen_out ; |
---|
87 | |
---|
88 | |
---|
89 | reg csn_rd_ff ; |
---|
90 | wire csn_rd_ff_si ; |
---|
91 | wire csn_rd_ff_so ; |
---|
92 | |
---|
93 | reg csn_wr_ff ; |
---|
94 | wire csn_wr_ff_si ; |
---|
95 | wire csn_wr_ff_so ; |
---|
96 | |
---|
97 | reg di_ff_latch_so ; |
---|
98 | /////////////////////////////////////// |
---|
99 | // Scan chain connections // |
---|
100 | /////////////////////////////////////// |
---|
101 | assign wr_a_ff_si[3:0] = {si , wr_a_ff_so[3:1]} ; |
---|
102 | assign csn_wr_ff_si = wr_a_ff_so[0] ; |
---|
103 | assign di_ff_si = {csn_wr_ff_so, di_ff_so[80:1]}; |
---|
104 | assign listen_out_si = {listen_out_so[79:0], di_ff_latch_so} ; |
---|
105 | assign csn_rd_ff_si = listen_out_so[80] ; |
---|
106 | assign rd_a_ff_si[3:0] = {rd_a_ff_so[2:0], csn_rd_ff_so} ; |
---|
107 | assign so = rd_a_ff_so[3] ; |
---|
108 | /////////////////////////////////////// |
---|
109 | // Instantiate a clock headers // |
---|
110 | /////////////////////////////////////// |
---|
111 | |
---|
112 | wire rd_ssclk = rd_clk ; // clk_en & rd_clk ; |
---|
113 | wire rd_local_clk = rd_ssclk | scan_en | hold ; |
---|
114 | wire rd_smclk = rd_ssclk | ~(scan_en | hold) ; |
---|
115 | |
---|
116 | wire wr_ssclk = wr_clk ; // clk_en & wr_clk ; |
---|
117 | wire wr_local_clk = wr_ssclk | scan_en | hold ; |
---|
118 | wire wr_smclk = wr_ssclk | ~(scan_en | hold) ; |
---|
119 | |
---|
120 | |
---|
121 | ///////////////////////////////////////////////////// |
---|
122 | // csn_rd Flop // |
---|
123 | ///////////////////////////////////////////////////// |
---|
124 | |
---|
125 | reg csn_rd_ff_inst_mdata ; |
---|
126 | wire csn_rd_ff_inst_smin ; |
---|
127 | reg csn_rd_ff_scan_out ; |
---|
128 | |
---|
129 | assign csn_rd_ff_inst_smin = hold ? csn_rd_ff_scan_out : csn_rd_ff_si ; |
---|
130 | always @(rd_smclk or rd_local_clk or csn_rd or csn_rd_ff_inst_smin ) begin |
---|
131 | if (!rd_local_clk) begin |
---|
132 | csn_rd_ff_inst_mdata = csn_rd ; |
---|
133 | end |
---|
134 | if (!rd_smclk) begin |
---|
135 | csn_rd_ff_inst_mdata = csn_rd_ff_inst_smin; |
---|
136 | end |
---|
137 | end |
---|
138 | always @(posedge rd_ssclk) begin |
---|
139 | csn_rd_ff_scan_out <= csn_rd_ff_inst_mdata ; |
---|
140 | end |
---|
141 | always @(rd_local_clk or csn_rd_ff_inst_mdata) begin |
---|
142 | if (rd_local_clk ) begin |
---|
143 | csn_rd_ff <= csn_rd_ff_inst_mdata ; |
---|
144 | end |
---|
145 | end |
---|
146 | assign csn_rd_ff_so = csn_rd_ff_scan_out; |
---|
147 | |
---|
148 | ///////////////////////////////////////////////////// |
---|
149 | |
---|
150 | ///////////////////////////////////////////////////// |
---|
151 | // rd_a Flop // |
---|
152 | ///////////////////////////////////////////////////// |
---|
153 | reg [3:0] rd_a_ff_inst_mdata ; |
---|
154 | wire [3:0] rd_a_ff_inst_smin ; |
---|
155 | reg [3:0] rd_a_ff_scan_out ; |
---|
156 | |
---|
157 | assign rd_a_ff_inst_smin[3:0] = hold ? rd_a_ff_scan_out[3:0] : rd_a_ff_si[3:0] ; |
---|
158 | always @(rd_smclk or rd_local_clk or rd_a or rd_a_ff_inst_smin ) begin |
---|
159 | if (!rd_local_clk) begin |
---|
160 | rd_a_ff_inst_mdata = rd_a[3:0] ; |
---|
161 | end |
---|
162 | if (!rd_smclk) begin |
---|
163 | rd_a_ff_inst_mdata = rd_a_ff_inst_smin; |
---|
164 | end |
---|
165 | end |
---|
166 | always @(posedge rd_ssclk) begin |
---|
167 | rd_a_ff_scan_out[3:0] <= rd_a_ff_inst_mdata ; |
---|
168 | end |
---|
169 | always @(rd_local_clk or rd_a_ff_inst_mdata) begin |
---|
170 | if (rd_local_clk) begin |
---|
171 | rd_a_ff[3:0] <= rd_a_ff_inst_mdata ; |
---|
172 | end |
---|
173 | end |
---|
174 | assign rd_a_ff_so[3:0] = rd_a_ff_scan_out[3:0] ; |
---|
175 | ///////////////////////////////////////////////////// |
---|
176 | |
---|
177 | ///////////////////////////////////////////////////// |
---|
178 | // csn_wr Flop // |
---|
179 | ///////////////////////////////////////////////////// |
---|
180 | reg csn_wr_ff_inst_mdata ; |
---|
181 | wire csn_wr_ff_inst_smin ; |
---|
182 | |
---|
183 | assign csn_wr_ff_inst_smin = hold ? csn_wr_ff : csn_wr_ff_si ; |
---|
184 | always @(wr_smclk or wr_local_clk or csn_wr or csn_wr_ff_inst_smin ) begin |
---|
185 | if (!wr_local_clk) begin |
---|
186 | csn_wr_ff_inst_mdata = csn_wr ; |
---|
187 | end |
---|
188 | if (!wr_smclk) begin |
---|
189 | csn_wr_ff_inst_mdata = csn_wr_ff_inst_smin; |
---|
190 | end |
---|
191 | end |
---|
192 | always @(posedge wr_ssclk) begin |
---|
193 | csn_wr_ff <= csn_wr_ff_inst_mdata ; |
---|
194 | end |
---|
195 | assign csn_wr_ff_so = csn_wr_ff; |
---|
196 | ///////////////////////////////////////////////////// |
---|
197 | |
---|
198 | ///////////////////////////////////////////////////// |
---|
199 | // wr_a Flop // |
---|
200 | ///////////////////////////////////////////////////// |
---|
201 | reg [3:0] wr_a_ff_inst_mdata ; |
---|
202 | wire [3:0] wr_a_ff_inst_smin ; |
---|
203 | |
---|
204 | assign wr_a_ff_inst_smin[3:0] = hold ? wr_a_ff[3:0] : wr_a_ff_si[3:0] ; |
---|
205 | always @(wr_smclk or wr_local_clk or wr_a or wr_a_ff_inst_smin ) begin |
---|
206 | if (!wr_local_clk) begin |
---|
207 | wr_a_ff_inst_mdata = wr_a[3:0] ; |
---|
208 | end |
---|
209 | if (!wr_smclk) begin |
---|
210 | wr_a_ff_inst_mdata = wr_a_ff_inst_smin; |
---|
211 | end |
---|
212 | end |
---|
213 | always @(posedge wr_ssclk) begin |
---|
214 | wr_a_ff[3:0] <= wr_a_ff_inst_mdata ; |
---|
215 | end |
---|
216 | assign wr_a_ff_so[3:0] = wr_a_ff[3:0] ; |
---|
217 | ///////////////////////////////////////////////////// |
---|
218 | |
---|
219 | ///////////////////////////////////////////////////// |
---|
220 | // di Flop // |
---|
221 | ///////////////////////////////////////////////////// |
---|
222 | reg [80:0] di_ff_inst_mdata ; |
---|
223 | wire [80:0] di_ff_inst_smin ; |
---|
224 | |
---|
225 | assign di_ff_inst_smin[80:0] = hold ? di_ff[80:0] : di_ff_si[80:0] ; |
---|
226 | always @(wr_smclk or wr_local_clk or di or di_ff_inst_smin ) begin |
---|
227 | if (!wr_local_clk) begin |
---|
228 | di_ff_inst_mdata = di[80:0] ; |
---|
229 | end |
---|
230 | if (!wr_smclk) begin |
---|
231 | di_ff_inst_mdata = di_ff_inst_smin; |
---|
232 | end |
---|
233 | end |
---|
234 | always @(posedge wr_ssclk) begin |
---|
235 | di_ff[80:0] <= di_ff_inst_mdata ; |
---|
236 | end |
---|
237 | assign di_ff_so[80:0] = di_ff[80:0] ; |
---|
238 | ///////////////////////////////////////////////////// |
---|
239 | |
---|
240 | wire wr_enable_l = csn_wr_ff | scan_en ; |
---|
241 | wire rd_enable_l = csn_rd_ff | scan_en ; |
---|
242 | |
---|
243 | // wire wr_clk_qual = wr_ssclk & ~scan_en ; |
---|
244 | always @(wr_ssclk or wr_a_ff or wr_enable_l or di_ff ) begin |
---|
245 | if (!wr_ssclk) begin |
---|
246 | if (!wr_enable_l) begin |
---|
247 | memarray[wr_a_ff] <= di_ff[80:0] ; |
---|
248 | end |
---|
249 | end |
---|
250 | end |
---|
251 | |
---|
252 | // wire rd_clk_qual = (rd_ssclk & ~scan_en) ; |
---|
253 | always @(rd_ssclk or rd_a_ff or rd_enable_l) begin |
---|
254 | if (rd_ssclk) begin |
---|
255 | if (rd_enable_l == 1'b0) begin |
---|
256 | array_out[80:0] <= memarray[rd_a_ff] ; |
---|
257 | end else if (rd_enable_l == 1'b1) begin |
---|
258 | array_out[80:0] <= 81'h1FFFFFFFFFFFFFFFFFFFF; |
---|
259 | end else begin |
---|
260 | array_out[80:0] <= 81'hXXXXXXXXXXXXXXXXXXXXX; |
---|
261 | end |
---|
262 | end |
---|
263 | end |
---|
264 | |
---|
265 | |
---|
266 | // synopsys translate_off |
---|
267 | |
---|
268 | `ifdef INNO_MUXEX |
---|
269 | `else |
---|
270 | always @(csn_rd_ff or csn_wr_ff or rd_a_ff or wr_a_ff) begin |
---|
271 | if ((SYNC_CLOCK_CHK1 == 0) & !csn_rd_ff & !csn_wr_ff & (rd_a_ff == wr_a_ff)) begin |
---|
272 | array_out <= 81'hxxxxxxxxxxxxxxxxxxxxx; |
---|
273 | `ifdef MODELSIM |
---|
274 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers", rd_a_ff, wr_a_ff); |
---|
275 | `else |
---|
276 | $error ("sram_conflict", "conflict between read: %h and write: %h pointers", rd_a_ff, wr_a_ff); |
---|
277 | `endif |
---|
278 | end |
---|
279 | end |
---|
280 | `endif |
---|
281 | |
---|
282 | /////////////////////////////////////////////////////////////// |
---|
283 | // Purely ERROR checking code. // |
---|
284 | /////////////////////////////////////////////////////////////// |
---|
285 | reg [3:0] rd_a_ff_del ; |
---|
286 | reg csn_rd_ff_del ; |
---|
287 | reg rd_clk_del ; |
---|
288 | always @(rd_local_clk) begin |
---|
289 | if (rd_local_clk) rd_clk_del = #300 rd_local_clk; |
---|
290 | else rd_clk_del = #300 rd_local_clk; |
---|
291 | end |
---|
292 | always @(posedge rd_clk_del) begin |
---|
293 | rd_a_ff_del <= rd_a_ff ; |
---|
294 | csn_rd_ff_del <= csn_rd_ff ; |
---|
295 | end |
---|
296 | |
---|
297 | `ifdef INNO_MUXEX |
---|
298 | `else |
---|
299 | always @(csn_rd_ff_del or csn_wr_ff or rd_a_ff_del or wr_a_ff or rd_clk_del or wr_ssclk) begin |
---|
300 | if (SYNC_CLOCK_CHK2 == 0) begin |
---|
301 | if (rd_clk_del & !wr_ssclk & !csn_rd_ff_del & !csn_wr_ff & (rd_a_ff_del == wr_a_ff)) begin |
---|
302 | `ifdef MODELSIM |
---|
303 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff_del, wr_a_ff); |
---|
304 | `else |
---|
305 | $error ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff_del, wr_a_ff); |
---|
306 | `endif |
---|
307 | end |
---|
308 | end |
---|
309 | end |
---|
310 | `endif |
---|
311 | |
---|
312 | reg [3:0] wr_a_ff_del ; |
---|
313 | reg csn_wr_ff_del ; |
---|
314 | reg wr_clk_del ; |
---|
315 | always @(wr_ssclk) begin |
---|
316 | if (wr_ssclk) wr_clk_del = #300 wr_ssclk; |
---|
317 | else wr_clk_del = #300 wr_ssclk; |
---|
318 | end |
---|
319 | always @(posedge wr_clk_del) begin |
---|
320 | wr_a_ff_del <= wr_a_ff ; |
---|
321 | csn_wr_ff_del <= csn_wr_ff ; |
---|
322 | end |
---|
323 | |
---|
324 | `ifdef INNO_MUXEX |
---|
325 | `else |
---|
326 | always @(csn_rd_ff or csn_wr_ff_del or rd_a_ff or wr_a_ff_del or rd_local_clk or wr_clk_del) begin |
---|
327 | if (SYNC_CLOCK_CHK3 == 0) begin |
---|
328 | if (rd_local_clk & !wr_clk_del & !csn_rd_ff & !csn_wr_ff_del & (rd_a_ff == wr_a_ff_del)) begin |
---|
329 | $display ("sram_conflict", "conflict between read: %h and write: %h pointers ", rd_a_ff, wr_a_ff_del); |
---|
330 | end |
---|
331 | end |
---|
332 | end |
---|
333 | `endif |
---|
334 | |
---|
335 | /////////////////////////////////////////////////////////////// |
---|
336 | // end the ERROR checking code. // |
---|
337 | /////////////////////////////////////////////////////////////// |
---|
338 | /////////////////////////////////////// |
---|
339 | |
---|
340 | |
---|
341 | // synopsys translate_on |
---|
342 | |
---|
343 | /////////////////////////////////// |
---|
344 | // Transparent latch with reset |
---|
345 | /////////////////////////////////// |
---|
346 | |
---|
347 | always @(array_out or rd_ssclk) begin |
---|
348 | if (rd_ssclk) begin |
---|
349 | array_out_latch <= array_out ; |
---|
350 | end |
---|
351 | end |
---|
352 | |
---|
353 | always @(di_ff_so[0] or wr_ssclk) begin |
---|
354 | if (!wr_ssclk) begin |
---|
355 | di_ff_latch_so <= di_ff_so[0] ; |
---|
356 | end |
---|
357 | end |
---|
358 | |
---|
359 | |
---|
360 | assign do = testmux_sel ? di_ff : array_out_latch ; |
---|
361 | |
---|
362 | ///////////////////////////////////////////////////// |
---|
363 | // listen_out Flop // |
---|
364 | ///////////////////////////////////////////////////// |
---|
365 | reg [80:0] listen_out_ff_inst_mdata ; |
---|
366 | wire [80:0] listen_out_ff_inst_smin ; |
---|
367 | |
---|
368 | assign listen_out_ff_inst_smin[80:0] = hold ? do[80:0] : listen_out_si[80:0] ; |
---|
369 | always @(rd_smclk or rd_local_clk or do or listen_out_ff_inst_smin ) begin |
---|
370 | if (!rd_local_clk) begin |
---|
371 | listen_out_ff_inst_mdata = do[80:0] ; |
---|
372 | end |
---|
373 | if (!rd_smclk) begin |
---|
374 | listen_out_ff_inst_mdata = listen_out_ff_inst_smin; |
---|
375 | end |
---|
376 | end |
---|
377 | always @(posedge rd_ssclk) begin |
---|
378 | listen_out[80:0] <= listen_out_ff_inst_mdata ; |
---|
379 | end |
---|
380 | assign listen_out_so[80:0] = listen_out[80:0] ; |
---|
381 | |
---|
382 | // synopsys translate_off |
---|
383 | |
---|
384 | `ifdef INNO_MUXEX |
---|
385 | `else |
---|
386 | always @(posedge rd_clk) begin |
---|
387 | if ((MARGIN_WARNING == 0) & margin != 5'b10101) begin |
---|
388 | `ifdef MODELSIM |
---|
389 | $display ("sram_margin", "margin is not set to the default value") ; |
---|
390 | `else |
---|
391 | $error ("sram_margin", "margin is not set to the default value") ; |
---|
392 | `endif |
---|
393 | end |
---|
394 | end |
---|
395 | `endif |
---|
396 | |
---|
397 | // synopsys translate_on |
---|
398 | |
---|
399 | endmodule |
---|