]>
Commit | Line | Data |
---|---|---|
1 | ////////////////////////////////////////////////////////////////////// | |
2 | //// //// | |
3 | //// Generic Dual-Port Synchronous RAM //// | |
4 | //// //// | |
5 | //// This file is part of memory library available from //// | |
6 | //// http://www.opencores.org/cvsweb.shtml/generic_memories/ //// | |
7 | //// //// | |
8 | //// Description //// | |
9 | //// This block is a wrapper with common dual-port //// | |
10 | //// synchronous memory interface for different //// | |
11 | //// types of ASIC and FPGA RAMs. Beside universal memory //// | |
12 | //// interface it also provides behavioral model of generic //// | |
13 | //// dual-port synchronous RAM. //// | |
14 | //// It also contains a fully synthesizeable model for FPGAs. //// | |
15 | //// It should be used in all OPENCORES designs that want to be //// | |
16 | //// portable accross different target technologies and //// | |
17 | //// independent of target memory. //// | |
18 | //// //// | |
19 | //// Supported ASIC RAMs are: //// | |
20 | //// - Artisan Dual-Port Sync RAM //// | |
21 | //// - Avant! Two-Port Sync RAM (*) //// | |
22 | //// - Virage 2-port Sync RAM //// | |
23 | //// //// | |
24 | //// Supported FPGA RAMs are: //// | |
25 | //// - Generic FPGA (VENDOR_FPGA) //// | |
26 | //// Tested RAMs: Altera, Xilinx //// | |
27 | //// Synthesis tools: LeonardoSpectrum, Synplicity //// | |
28 | //// - Xilinx (VENDOR_XILINX) //// | |
29 | //// - Altera (VENDOR_ALTERA) //// | |
30 | //// //// | |
31 | //// To Do: //// | |
32 | //// - fix Avant! //// | |
33 | //// - add additional RAMs (VS etc) //// | |
34 | //// //// | |
35 | //// Author(s): //// | |
36 | //// - Richard Herveille, richard@asics.ws //// | |
37 | //// - Damjan Lampret, lampret@opencores.org //// | |
38 | //// //// | |
39 | ////////////////////////////////////////////////////////////////////// | |
40 | //// //// | |
41 | //// Copyright (C) 2000 Authors and OPENCORES.ORG //// | |
42 | //// //// | |
43 | //// This source file may be used and distributed without //// | |
44 | //// restriction provided that this copyright statement is not //// | |
45 | //// removed from the file and that any derivative work contains //// | |
46 | //// the original copyright notice and the associated disclaimer. //// | |
47 | //// //// | |
48 | //// This source file is free software; you can redistribute it //// | |
49 | //// and/or modify it under the terms of the GNU Lesser General //// | |
50 | //// Public License as published by the Free Software Foundation; //// | |
51 | //// either version 2.1 of the License, or (at your option) any //// | |
52 | //// later version. //// | |
53 | //// //// | |
54 | //// This source is distributed in the hope that it will be //// | |
55 | //// useful, but WITHOUT ANY WARRANTY; without even the implied //// | |
56 | //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// | |
57 | //// PURPOSE. See the GNU Lesser General Public License for more //// | |
58 | //// details. //// | |
59 | //// //// | |
60 | //// You should have received a copy of the GNU Lesser General //// | |
61 | //// Public License along with this source; if not, download it //// | |
62 | //// from http://www.opencores.org/lgpl.shtml //// | |
63 | //// //// | |
64 | ////////////////////////////////////////////////////////////////////// | |
65 | // | |
66 | // CVS Revision History | |
67 | // | |
68 | // $Log: generic_dpram.v,v $ | |
69 | // Revision 1.3 2007-02-11 22:18:24 michael | |
70 | // component for dram | |
71 | // | |
72 | // Revision 1.2 2007/02/11 22:15:39 sithglan | |
73 | // define xilinix and fpga | |
74 | // | |
75 | // Revision 1.1 2007/02/11 22:05:26 sithglan | |
76 | // += dpram | |
77 | // | |
78 | // Revision 1.4 2002/09/28 08:18:52 rherveille | |
79 | // Changed synthesizeable FPGA memory implementation. | |
80 | // Fixed some issues with Xilinx BlockRAM | |
81 | // | |
82 | // Revision 1.3 2001/11/09 00:34:18 samg | |
83 | // minor changes: unified with all common rams | |
84 | // | |
85 | // Revision 1.2 2001/11/08 19:11:31 samg | |
86 | // added valid checks to behvioral model | |
87 | // | |
88 | // Revision 1.1.1.1 2001/09/14 09:57:10 rherveille | |
89 | // Major cleanup. | |
90 | // Files are now compliant to Altera & Xilinx memories. | |
91 | // Memories are now compatible, i.e. drop-in replacements. | |
92 | // Added synthesizeable generic FPGA description. | |
93 | // Created "generic_memories" cvs entry. | |
94 | // | |
95 | // Revision 1.1.1.2 2001/08/21 13:09:27 damjan | |
96 | // *** empty log message *** | |
97 | // | |
98 | // Revision 1.1 2001/08/20 18:23:20 damjan | |
99 | // Initial revision | |
100 | // | |
101 | // Revision 1.1 2001/08/09 13:39:33 lampret | |
102 | // Major clean-up. | |
103 | // | |
104 | // Revision 1.2 2001/07/30 05:38:02 lampret | |
105 | // Adding empty directories required by HDL coding guidelines | |
106 | // | |
107 | // | |
108 | ||
109 | //`include "timescale.v" | |
110 | ||
111 | `define VENDOR_FPGA | |
112 | `define VENDOR_XILINX | |
113 | //`define VENDOR_ALTERA | |
114 | ||
115 | module generic_dpram( | |
116 | // Generic synchronous dual-port RAM interface | |
117 | rclk, rrst, rce, oe, raddr, do, | |
118 | wclk, wrst, wce, we, waddr, di | |
119 | ); | |
120 | ||
121 | // | |
122 | // Default address and data buses width | |
123 | // | |
124 | parameter aw = 12; // number of bits in address-bus | |
125 | parameter dw = 8; // number of bits in data-bus | |
126 | ||
127 | // | |
128 | // Generic synchronous double-port RAM interface | |
129 | // | |
130 | // read port | |
131 | input rclk; // read clock, rising edge trigger | |
132 | input rrst; // read port reset, active high | |
133 | input rce; // read port chip enable, active high | |
134 | input oe; // output enable, active high | |
135 | input [aw-1:0] raddr; // read address | |
136 | output [dw-1:0] do; // data output | |
137 | ||
138 | // write port | |
139 | input wclk; // write clock, rising edge trigger | |
140 | input wrst; // write port reset, active high | |
141 | input wce; // write port chip enable, active high | |
142 | input we; // write enable, active high | |
143 | input [aw-1:0] waddr; // write address | |
144 | input [dw-1:0] di; // data input | |
145 | ||
146 | // | |
147 | // Module body | |
148 | // | |
149 | ||
150 | `ifdef VENDOR_FPGA | |
151 | // | |
152 | // Instantiation synthesizeable FPGA memory | |
153 | // | |
154 | // This code has been tested using LeonardoSpectrum and Synplicity. | |
155 | // The code correctly instantiates Altera EABs and Xilinx BlockRAMs. | |
156 | // | |
157 | reg [dw-1:0] mem [(1<<aw) -1:0]; // instantiate memory | |
158 | reg [aw-1:0] ra; // register read address | |
159 | ||
160 | // read operation | |
161 | always @(posedge rclk) | |
162 | if (rce) | |
163 | ra <= #1 raddr; | |
164 | ||
165 | assign do = mem[ra]; | |
166 | ||
167 | // write operation | |
168 | always@(posedge wclk) | |
169 | if (we && wce) | |
170 | mem[waddr] <= #1 di; | |
171 | ||
172 | `else | |
173 | ||
174 | `ifdef VENDOR_XILINX | |
175 | // | |
176 | // Instantiation of FPGA memory: | |
177 | // | |
178 | // Virtex/Spartan2 BlockRAMs | |
179 | // | |
180 | xilinx_ram_dp xilinx_ram( | |
181 | // read port | |
182 | .CLKA(rclk), | |
183 | .RSTA(rrst), | |
184 | .ENA(rce), | |
185 | .ADDRA(raddr), | |
186 | .DIA( {dw{1'b0}} ), | |
187 | .WEA(1'b0), | |
188 | .DOA(do), | |
189 | ||
190 | // write port | |
191 | .CLKB(wclk), | |
192 | .RSTB(wrst), | |
193 | .ENB(wce), | |
194 | .ADDRB(waddr), | |
195 | .DIB(di), | |
196 | .WEB(we), | |
197 | .DOB() | |
198 | ); | |
199 | ||
200 | defparam | |
201 | xilinx_ram.dwidth = dw, | |
202 | xilinx_ram.awidth = aw; | |
203 | ||
204 | `else | |
205 | ||
206 | `ifdef VENDOR_ALTERA | |
207 | // | |
208 | // Instantiation of FPGA memory: | |
209 | // | |
210 | // Altera FLEX/APEX EABs | |
211 | // | |
212 | altera_ram_dp altera_ram( | |
213 | // read port | |
214 | .rdclock(rclk), | |
215 | .rdclocken(rce), | |
216 | .rdaddress(raddr), | |
217 | .q(do), | |
218 | ||
219 | // write port | |
220 | .wrclock(wclk), | |
221 | .wrclocken(wce), | |
222 | .wren(we), | |
223 | .wraddress(waddr), | |
224 | .data(di) | |
225 | ); | |
226 | ||
227 | defparam | |
228 | altera_ram.dwidth = dw, | |
229 | altera_ram.awidth = aw; | |
230 | ||
231 | `else | |
232 | ||
233 | `ifdef VENDOR_ARTISAN | |
234 | ||
235 | // | |
236 | // Instantiation of ASIC memory: | |
237 | // | |
238 | // Artisan Synchronous Double-Port RAM (ra2sh) | |
239 | // | |
240 | art_hsdp #(dw, 1<<aw, aw) artisan_sdp( | |
241 | // read port | |
242 | .qa(do), | |
243 | .clka(rclk), | |
244 | .cena(~rce), | |
245 | .wena(1'b1), | |
246 | .aa(raddr), | |
247 | .da( {dw{1'b0}} ), | |
248 | .oena(~oe), | |
249 | ||
250 | // write port | |
251 | .qb(), | |
252 | .clkb(wclk), | |
253 | .cenb(~wce), | |
254 | .wenb(~we), | |
255 | .ab(waddr), | |
256 | .db(di), | |
257 | .oenb(1'b1) | |
258 | ); | |
259 | ||
260 | `else | |
261 | ||
262 | `ifdef VENDOR_AVANT | |
263 | ||
264 | // | |
265 | // Instantiation of ASIC memory: | |
266 | // | |
267 | // Avant! Asynchronous Two-Port RAM | |
268 | // | |
269 | avant_atp avant_atp( | |
270 | .web(~we), | |
271 | .reb(), | |
272 | .oeb(~oe), | |
273 | .rcsb(), | |
274 | .wcsb(), | |
275 | .ra(raddr), | |
276 | .wa(waddr), | |
277 | .di(di), | |
278 | .do(do) | |
279 | ); | |
280 | ||
281 | `else | |
282 | ||
283 | `ifdef VENDOR_VIRAGE | |
284 | ||
285 | // | |
286 | // Instantiation of ASIC memory: | |
287 | // | |
288 | // Virage Synchronous 2-port R/W RAM | |
289 | // | |
290 | virage_stp virage_stp( | |
291 | // read port | |
292 | .CLKA(rclk), | |
293 | .MEA(rce_a), | |
294 | .ADRA(raddr), | |
295 | .DA( {dw{1'b0}} ), | |
296 | .WEA(1'b0), | |
297 | .OEA(oe), | |
298 | .QA(do), | |
299 | ||
300 | // write port | |
301 | .CLKB(wclk), | |
302 | .MEB(wce), | |
303 | .ADRB(waddr), | |
304 | .DB(di), | |
305 | .WEB(we), | |
306 | .OEB(1'b1), | |
307 | .QB() | |
308 | ); | |
309 | ||
310 | `else | |
311 | ||
312 | // | |
313 | // Generic dual-port synchronous RAM model | |
314 | // | |
315 | ||
316 | // | |
317 | // Generic RAM's registers and wires | |
318 | // | |
319 | reg [dw-1:0] mem [(1<<aw)-1:0]; // RAM content | |
320 | reg [dw-1:0] do_reg; // RAM data output register | |
321 | ||
322 | // | |
323 | // Data output drivers | |
324 | // | |
325 | assign do = (oe & rce) ? do_reg : {dw{1'bz}}; | |
326 | ||
327 | // read operation | |
328 | always @(posedge rclk) | |
329 | if (rce) | |
330 | do_reg <= #1 (we && (waddr==raddr)) ? {dw{1'b x}} : mem[raddr]; | |
331 | ||
332 | // write operation | |
333 | always @(posedge wclk) | |
334 | if (wce && we) | |
335 | mem[waddr] <= #1 di; | |
336 | ||
337 | ||
338 | // Task prints range of memory | |
339 | // *** Remember that tasks are non reentrant, don't call this task in parallel for multiple instantiations. | |
340 | task print_ram; | |
341 | input [aw-1:0] start; | |
342 | input [aw-1:0] finish; | |
343 | integer rnum; | |
344 | begin | |
345 | for (rnum=start;rnum<=finish;rnum=rnum+1) | |
346 | $display("Addr %h = %h",rnum,mem[rnum]); | |
347 | end | |
348 | endtask | |
349 | ||
350 | `endif // !VENDOR_VIRAGE | |
351 | `endif // !VENDOR_AVANT | |
352 | `endif // !VENDOR_ARTISAN | |
353 | `endif // !VENDOR_ALTERA | |
354 | `endif // !VENDOR_XILINX | |
355 | `endif // !VENDOR_FPGA | |
356 | ||
357 | endmodule | |
358 | ||
359 | // | |
360 | // Black-box modules | |
361 | // | |
362 | ||
363 | `ifdef VENDOR_ALTERA | |
364 | module altera_ram_dp( | |
365 | data, | |
366 | wraddress, | |
367 | rdaddress, | |
368 | wren, | |
369 | wrclock, | |
370 | wrclocken, | |
371 | rdclock, | |
372 | rdclocken, | |
373 | q) /* synthesis black_box */; | |
374 | ||
375 | parameter awidth = 7; | |
376 | parameter dwidth = 8; | |
377 | ||
378 | input [dwidth -1:0] data; | |
379 | input [awidth -1:0] wraddress; | |
380 | input [awidth -1:0] rdaddress; | |
381 | input wren; | |
382 | input wrclock; | |
383 | input wrclocken; | |
384 | input rdclock; | |
385 | input rdclocken; | |
386 | output [dwidth -1:0] q; | |
387 | ||
388 | // synopsis translate_off | |
389 | // exemplar translate_off | |
390 | ||
391 | syn_dpram_rowr #( | |
392 | "UNUSED", | |
393 | dwidth, | |
394 | awidth, | |
395 | 1 << awidth | |
396 | ) | |
397 | altera_dpram_model ( | |
398 | // read port | |
399 | .RdClock(rdclock), | |
400 | .RdClken(rdclocken), | |
401 | .RdAddress(rdaddress), | |
402 | .RdEn(1'b1), | |
403 | .Q(q), | |
404 | ||
405 | // write port | |
406 | .WrClock(wrclock), | |
407 | .WrClken(wrclocken), | |
408 | .WrAddress(wraddress), | |
409 | .WrEn(wren), | |
410 | .Data(data) | |
411 | ); | |
412 | ||
413 | // exemplar translate_on | |
414 | // synopsis translate_on | |
415 | ||
416 | endmodule | |
417 | `endif // VENDOR_ALTERA | |
418 | ||
419 | `ifdef VENDOR_XILINX | |
420 | module xilinx_ram_dp ( | |
421 | ADDRA, | |
422 | CLKA, | |
423 | ADDRB, | |
424 | CLKB, | |
425 | DIA, | |
426 | WEA, | |
427 | DIB, | |
428 | WEB, | |
429 | ENA, | |
430 | ENB, | |
431 | RSTA, | |
432 | RSTB, | |
433 | DOA, | |
434 | DOB) /* synthesis black_box */ ; | |
435 | ||
436 | parameter awidth = 7; | |
437 | parameter dwidth = 8; | |
438 | ||
439 | // port_a | |
440 | input CLKA; | |
441 | input RSTA; | |
442 | input ENA; | |
443 | input [awidth-1:0] ADDRA; | |
444 | input [dwidth-1:0] DIA; | |
445 | input WEA; | |
446 | output [dwidth-1:0] DOA; | |
447 | ||
448 | // port_b | |
449 | input CLKB; | |
450 | input RSTB; | |
451 | input ENB; | |
452 | input [awidth-1:0] ADDRB; | |
453 | input [dwidth-1:0] DIB; | |
454 | input WEB; | |
455 | output [dwidth-1:0] DOB; | |
456 | ||
457 | // insert simulation model | |
458 | ||
459 | ||
460 | // synopsys translate_off | |
461 | // exemplar translate_off | |
462 | ||
463 | C_MEM_DP_BLOCK_V1_0 #( | |
464 | awidth, | |
465 | awidth, | |
466 | 1, | |
467 | 1, | |
468 | "0", | |
469 | 1 << awidth, | |
470 | 1 << awidth, | |
471 | 1, | |
472 | 1, | |
473 | 1, | |
474 | 1, | |
475 | 1, | |
476 | 1, | |
477 | 1, | |
478 | 1, | |
479 | 1, | |
480 | 1, | |
481 | 1, | |
482 | 1, | |
483 | 1, | |
484 | "", | |
485 | 16, | |
486 | 0, | |
487 | 0, | |
488 | 1, | |
489 | 1, | |
490 | 1, | |
491 | 1, | |
492 | dwidth, | |
493 | dwidth) | |
494 | xilinx_dpram_model ( | |
495 | .ADDRA(ADDRA), | |
496 | .CLKA(CLKA), | |
497 | .ADDRB(ADDRB), | |
498 | .CLKB(CLKB), | |
499 | .DIA(DIA), | |
500 | .WEA(WEA), | |
501 | .DIB(DIB), | |
502 | .WEB(WEB), | |
503 | .ENA(ENA), | |
504 | .ENB(ENB), | |
505 | .RSTA(RSTA), | |
506 | .RSTB(RSTB), | |
507 | .DOA(DOA), | |
508 | .DOB(DOB)); | |
509 | ||
510 | // exemplar translate_on | |
511 | // synopsys translate_on | |
512 | ||
513 | endmodule | |
514 | `endif // VENDOR_XILINX |