| 1 | ////////////////////////////////////////////////////////////////////// |
| 2 | //// //// |
| 3 | //// Generic Two-Port Synchronous RAM //// |
| 4 | //// //// |
| 5 | //// This file is part of pci bridge project //// |
| 6 | //// http://www.opencores.org/cvsweb.shtml/pci/ //// |
| 7 | //// //// |
| 8 | //// Description //// |
| 9 | //// This block is a wrapper with common two-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 | //// two-port synchronous RAM. //// |
| 14 | //// It should be used in all OPENCORES designs that want to be //// |
| 15 | //// portable accross different target technologies and //// |
| 16 | //// independent of target memory. //// |
| 17 | //// //// |
| 18 | //// Supported ASIC RAMs are: //// |
| 19 | //// - Artisan Double-Port Sync RAM //// |
| 20 | //// - Avant! Two-Port Sync RAM (*) //// |
| 21 | //// - Virage 2-port Sync RAM //// |
| 22 | //// //// |
| 23 | //// Supported FPGA RAMs are: //// |
| 24 | //// - Xilinx Virtex RAMB4_S16_S16 //// |
| 25 | //// //// |
| 26 | //// To Do: //// |
| 27 | //// - fix Avant! //// |
| 28 | //// - xilinx rams need external tri-state logic //// |
| 29 | //// - add additional RAMs (Altera, VS etc) //// |
| 30 | //// //// |
| 31 | //// Author(s): //// |
| 32 | //// - Damjan Lampret, lampret@opencores.org //// |
| 33 | //// - Miha Dolenc, mihad@opencores.org //// |
| 34 | //// //// |
| 35 | ////////////////////////////////////////////////////////////////////// |
| 36 | //// //// |
| 37 | //// Copyright (C) 2000 Authors and OPENCORES.ORG //// |
| 38 | //// //// |
| 39 | //// This source file may be used and distributed without //// |
| 40 | //// restriction provided that this copyright statement is not //// |
| 41 | //// removed from the file and that any derivative work contains //// |
| 42 | //// the original copyright notice and the associated disclaimer. //// |
| 43 | //// //// |
| 44 | //// This source file is free software; you can redistribute it //// |
| 45 | //// and/or modify it under the terms of the GNU Lesser General //// |
| 46 | //// Public License as published by the Free Software Foundation; //// |
| 47 | //// either version 2.1 of the License, or (at your option) any //// |
| 48 | //// later version. //// |
| 49 | //// //// |
| 50 | //// This source is distributed in the hope that it will be //// |
| 51 | //// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
| 52 | //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
| 53 | //// PURPOSE. See the GNU Lesser General Public License for more //// |
| 54 | //// details. //// |
| 55 | //// //// |
| 56 | //// You should have received a copy of the GNU Lesser General //// |
| 57 | //// Public License along with this source; if not, download it //// |
| 58 | //// from http://www.opencores.org/lgpl.shtml //// |
| 59 | //// //// |
| 60 | ////////////////////////////////////////////////////////////////////// |
| 61 | // |
| 62 | // CVS Revision History |
| 63 | // |
| 64 | // $Log: pci_wb_tpram.v,v $ |
| 65 | // Revision 1.1 2007-03-20 17:50:56 sithglan |
| 66 | // add shit |
| 67 | // |
| 68 | // Revision 1.4 2004/08/19 15:27:34 mihad |
| 69 | // Changed minimum pci image size to 256 bytes because |
| 70 | // of some PC system problems with size of IO images. |
| 71 | // |
| 72 | // Revision 1.3 2003/10/17 09:11:52 markom |
| 73 | // mbist signals updated according to newest convention |
| 74 | // |
| 75 | // Revision 1.2 2003/08/14 13:06:03 simons |
| 76 | // synchronizer_flop replaced with pci_synchronizer_flop, artisan ram instance updated. |
| 77 | // |
| 78 | // Revision 1.1 2003/01/27 16:49:31 mihad |
| 79 | // Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed. |
| 80 | // |
| 81 | // Revision 1.7 2002/10/18 03:36:37 tadejm |
| 82 | // Changed wrong signal name mbist_sen into mbist_ctrl_i. |
| 83 | // |
| 84 | // Revision 1.6 2002/10/17 22:49:22 tadejm |
| 85 | // Changed BIST signals for RAMs. |
| 86 | // |
| 87 | // Revision 1.5 2002/10/11 10:09:01 mihad |
| 88 | // Added additional testcase and changed rst name in BIST to trst |
| 89 | // |
| 90 | // Revision 1.4 2002/10/08 17:17:06 mihad |
| 91 | // Added BIST signals for RAMs. |
| 92 | // |
| 93 | // Revision 1.3 2002/09/30 17:22:27 mihad |
| 94 | // Added support for Virtual Silicon two port RAM. Didn't run regression on it yet! |
| 95 | // |
| 96 | // Revision 1.2 2002/08/19 16:51:36 mihad |
| 97 | // Extracted distributed RAM module from wb/pci_tpram.v to its own file, got rid of undef directives |
| 98 | // |
| 99 | // Revision 1.1 2002/02/01 14:43:31 mihad |
| 100 | // *** empty log message *** |
| 101 | // |
| 102 | // |
| 103 | |
| 104 | // synopsys translate_off |
| 105 | `include "timescale.v" |
| 106 | // synopsys translate_on |
| 107 | `include "pci_constants.v" |
| 108 | |
| 109 | module pci_wb_tpram |
| 110 | ( |
| 111 | // Generic synchronous two-port RAM interface |
| 112 | clk_a, |
| 113 | rst_a, |
| 114 | ce_a, |
| 115 | we_a, |
| 116 | oe_a, |
| 117 | addr_a, |
| 118 | di_a, |
| 119 | do_a, |
| 120 | clk_b, |
| 121 | rst_b, |
| 122 | ce_b, |
| 123 | we_b, |
| 124 | oe_b, |
| 125 | addr_b, |
| 126 | di_b, |
| 127 | do_b |
| 128 | `ifdef PCI_BIST |
| 129 | , |
| 130 | // debug chain signals |
| 131 | mbist_si_i, // bist scan serial in |
| 132 | mbist_so_o, // bist scan serial out |
| 133 | mbist_ctrl_i // bist chain shift control |
| 134 | `endif |
| 135 | ); |
| 136 | |
| 137 | // |
| 138 | // Default address and data buses width |
| 139 | // |
| 140 | parameter aw = 8; |
| 141 | parameter dw = 40; |
| 142 | |
| 143 | // |
| 144 | // Generic synchronous two-port RAM interface |
| 145 | // |
| 146 | input clk_a; // Clock |
| 147 | input rst_a; // Reset |
| 148 | input ce_a; // Chip enable input |
| 149 | input we_a; // Write enable input |
| 150 | input oe_a; // Output enable input |
| 151 | input [aw-1:0] addr_a; // address bus inputs |
| 152 | input [dw-1:0] di_a; // input data bus |
| 153 | output [dw-1:0] do_a; // output data bus |
| 154 | input clk_b; // Clock |
| 155 | input rst_b; // Reset |
| 156 | input ce_b; // Chip enable input |
| 157 | input we_b; // Write enable input |
| 158 | input oe_b; // Output enable input |
| 159 | input [aw-1:0] addr_b; // address bus inputs |
| 160 | input [dw-1:0] di_b; // input data bus |
| 161 | output [dw-1:0] do_b; // output data bus |
| 162 | |
| 163 | `ifdef PCI_BIST |
| 164 | // debug chain signals |
| 165 | input mbist_si_i; // bist scan serial in |
| 166 | output mbist_so_o; // bist scan serial out |
| 167 | input [`PCI_MBIST_CTRL_WIDTH - 1:0] mbist_ctrl_i; // bist chain shift control |
| 168 | `endif |
| 169 | |
| 170 | // |
| 171 | // Internal wires and registers |
| 172 | // |
| 173 | |
| 174 | `ifdef WB_VS_STP |
| 175 | `define PCI_WB_RAM_SELECTED |
| 176 | `ifdef PCI_BIST |
| 177 | vs_hdtp_64x40_bist i_vs_hdtp_64x40_bist |
| 178 | `else |
| 179 | vs_hdtp_64x40 i_vs_hdtp_64x40 |
| 180 | `endif |
| 181 | ( |
| 182 | .RCK (clk_b), |
| 183 | .WCK (clk_a), |
| 184 | .RADR (addr_b), |
| 185 | .WADR (addr_a), |
| 186 | .DI (di_a), |
| 187 | .DOUT (do_b), |
| 188 | .REN (1'b0), |
| 189 | .WEN (!we_a) |
| 190 | `ifdef PCI_BIST |
| 191 | , |
| 192 | // debug chain signals |
| 193 | .mbist_si_i (mbist_si_i), |
| 194 | .mbist_so_o (mbist_so_o), |
| 195 | .mbist_ctrl_i (mbist_ctrl_i) |
| 196 | `endif |
| 197 | ); |
| 198 | |
| 199 | assign do_a = 0 ; |
| 200 | `endif |
| 201 | |
| 202 | `ifdef WB_ARTISAN_SDP |
| 203 | `define PCI_WB_RAM_SELECTED |
| 204 | // |
| 205 | // Instantiation of ASIC memory: |
| 206 | // |
| 207 | // Artisan Synchronous Double-Port RAM (ra2sh) |
| 208 | // |
| 209 | `ifdef PCI_BIST |
| 210 | art_hsdp_64x40_bist /*#(dw, 1<<aw, aw) */ artisan_sdp |
| 211 | ( |
| 212 | .QA(do_a), |
| 213 | .CLKA(clk_a), |
| 214 | .CENA(~ce_a), |
| 215 | .WENA(~we_a), |
| 216 | .AA(addr_a), |
| 217 | .DA(di_a), |
| 218 | .OENA(~oe_a), |
| 219 | .QB(do_b), |
| 220 | .CLKB(clk_b), |
| 221 | .CENB(~ce_b), |
| 222 | .WENB(~we_b), |
| 223 | .AB(addr_b), |
| 224 | .DB(di_b), |
| 225 | .OENB(~oe_b), |
| 226 | .mbist_si_i (mbist_si_i), |
| 227 | .mbist_so_o (mbist_so_o), |
| 228 | .mbist_ctrl_i (mbist_ctrl_i) |
| 229 | ); |
| 230 | `else |
| 231 | art_hsdp_64x40 /*#(dw, 1<<aw, aw) */ artisan_sdp |
| 232 | ( |
| 233 | .QA(do_a), |
| 234 | .CLKA(clk_a), |
| 235 | .CENA(~ce_a), |
| 236 | .WENA(~we_a), |
| 237 | .AA(addr_a), |
| 238 | .DA(di_a), |
| 239 | .OENA(~oe_a), |
| 240 | .QB(do_b), |
| 241 | .CLKB(clk_b), |
| 242 | .CENB(~ce_b), |
| 243 | .WENB(~we_b), |
| 244 | .AB(addr_b), |
| 245 | .DB(di_b), |
| 246 | .OENB(~oe_b) |
| 247 | ); |
| 248 | `endif |
| 249 | `endif |
| 250 | |
| 251 | `ifdef AVANT_ATP |
| 252 | `define PCI_WB_RAM_SELECTED |
| 253 | // |
| 254 | // Instantiation of ASIC memory: |
| 255 | // |
| 256 | // Avant! Asynchronous Two-Port RAM |
| 257 | // |
| 258 | avant_atp avant_atp( |
| 259 | .web(~we), |
| 260 | .reb(), |
| 261 | .oeb(~oe), |
| 262 | .rcsb(), |
| 263 | .wcsb(), |
| 264 | .ra(addr), |
| 265 | .wa(addr), |
| 266 | .di(di), |
| 267 | .do(do) |
| 268 | ); |
| 269 | |
| 270 | `endif |
| 271 | |
| 272 | `ifdef VIRAGE_STP |
| 273 | `define PCI_WB_RAM_SELECTED |
| 274 | // |
| 275 | // Instantiation of ASIC memory: |
| 276 | // |
| 277 | // Virage Synchronous 2-port R/W RAM |
| 278 | // |
| 279 | virage_stp virage_stp( |
| 280 | .QA(do_a), |
| 281 | .QB(do_b), |
| 282 | |
| 283 | .ADRA(addr_a), |
| 284 | .DA(di_a), |
| 285 | .WEA(we_a), |
| 286 | .OEA(oe_a), |
| 287 | .MEA(ce_a), |
| 288 | .CLKA(clk_a), |
| 289 | |
| 290 | .ADRB(adr_b), |
| 291 | .DB(di_b), |
| 292 | .WEB(we_b), |
| 293 | .OEB(oe_b), |
| 294 | .MEB(ce_b), |
| 295 | .CLKB(clk_b) |
| 296 | ); |
| 297 | |
| 298 | `endif |
| 299 | |
| 300 | `ifdef WB_XILINX_DIST_RAM |
| 301 | `define PCI_WB_RAM_SELECTED |
| 302 | |
| 303 | reg [(aw-1):0] out_address ; |
| 304 | always@(posedge clk_b or posedge rst_b) |
| 305 | begin |
| 306 | if ( rst_b ) |
| 307 | out_address <= #1 0 ; |
| 308 | else if (ce_b) |
| 309 | out_address <= #1 addr_b ; |
| 310 | end |
| 311 | |
| 312 | pci_ram_16x40d #(aw) wb_distributed_ram |
| 313 | ( |
| 314 | .data_out (do_b), |
| 315 | .we (we_a), |
| 316 | .data_in (di_a), |
| 317 | .read_address (out_address), |
| 318 | .write_address (addr_a), |
| 319 | .wclk (clk_a) |
| 320 | ); |
| 321 | assign do_a = 0 ; |
| 322 | `endif |
| 323 | `ifdef WB_XILINX_RAMB4 |
| 324 | `define PCI_WB_RAM_SELECTED |
| 325 | // |
| 326 | // Instantiation of FPGA memory: |
| 327 | // |
| 328 | // Virtex/Spartan2 |
| 329 | // |
| 330 | |
| 331 | // |
| 332 | // Block 0 |
| 333 | // |
| 334 | |
| 335 | RAMB4_S16_S16 ramb4_s16_s16_0( |
| 336 | .CLKA(clk_a), |
| 337 | .RSTA(rst_a), |
| 338 | .ADDRA(addr_a), |
| 339 | .DIA(di_a[15:0]), |
| 340 | .ENA(ce_a), |
| 341 | .WEA(we_a), |
| 342 | .DOA(do_a[15:0]), |
| 343 | |
| 344 | .CLKB(clk_b), |
| 345 | .RSTB(rst_b), |
| 346 | .ADDRB(addr_b), |
| 347 | .DIB(di_b[15:0]), |
| 348 | .ENB(ce_b), |
| 349 | .WEB(we_b), |
| 350 | .DOB(do_b[15:0]) |
| 351 | ); |
| 352 | |
| 353 | // |
| 354 | // Block 1 |
| 355 | // |
| 356 | |
| 357 | RAMB4_S16_S16 ramb4_s16_s16_1( |
| 358 | .CLKA(clk_a), |
| 359 | .RSTA(rst_a), |
| 360 | .ADDRA(addr_a), |
| 361 | .DIA(di_a[31:16]), |
| 362 | .ENA(ce_a), |
| 363 | .WEA(we_a), |
| 364 | .DOA(do_a[31:16]), |
| 365 | |
| 366 | .CLKB(clk_b), |
| 367 | .RSTB(rst_b), |
| 368 | .ADDRB(addr_b), |
| 369 | .DIB(di_b[31:16]), |
| 370 | .ENB(ce_b), |
| 371 | .WEB(we_b), |
| 372 | .DOB(do_b[31:16]) |
| 373 | ); |
| 374 | |
| 375 | // |
| 376 | // Block 2 |
| 377 | // |
| 378 | // block ram2 wires - non generic width of block rams |
| 379 | wire [15:0] blk2_di_a = {8'h00, di_a[39:32]} ; |
| 380 | wire [15:0] blk2_di_b = {8'h00, di_b[39:32]} ; |
| 381 | |
| 382 | wire [15:0] blk2_do_a ; |
| 383 | wire [15:0] blk2_do_b ; |
| 384 | |
| 385 | assign do_a[39:32] = blk2_do_a[7:0] ; |
| 386 | assign do_b[39:32] = blk2_do_b[7:0] ; |
| 387 | |
| 388 | RAMB4_S16_S16 ramb4_s16_s16_2( |
| 389 | .CLKA(clk_a), |
| 390 | .RSTA(rst_a), |
| 391 | .ADDRA(addr_a), |
| 392 | .DIA(blk2_di_a), |
| 393 | .ENA(ce_a), |
| 394 | .WEA(we_a), |
| 395 | .DOA(blk2_do_a), |
| 396 | |
| 397 | .CLKB(clk_b), |
| 398 | .RSTB(rst_b), |
| 399 | .ADDRB(addr_b), |
| 400 | .DIB(blk2_di_b), |
| 401 | .ENB(ce_b), |
| 402 | .WEB(we_b), |
| 403 | .DOB(blk2_do_b) |
| 404 | ); |
| 405 | |
| 406 | `endif |
| 407 | |
| 408 | `ifdef PCI_WB_RAM_SELECTED |
| 409 | `else |
| 410 | // |
| 411 | // Generic two-port synchronous RAM model |
| 412 | // |
| 413 | |
| 414 | // |
| 415 | // Generic RAM's registers and wires |
| 416 | // |
| 417 | reg [dw-1:0] mem [(1<<aw)-1:0]; // RAM content |
| 418 | reg [dw-1:0] do_reg_b; // RAM data output register |
| 419 | |
| 420 | // |
| 421 | // Data output drivers |
| 422 | // |
| 423 | assign do_a = {dw{1'b0}} ; |
| 424 | assign do_b = do_reg_b ; |
| 425 | |
| 426 | // |
| 427 | // RAM read and write |
| 428 | // |
| 429 | always @(posedge clk_a) |
| 430 | if (ce_a && we_a) |
| 431 | mem[addr_a] <= #1 di_a; |
| 432 | |
| 433 | // |
| 434 | // RAM read and write |
| 435 | // |
| 436 | always @(posedge clk_b) |
| 437 | if (ce_b) |
| 438 | do_reg_b <= #1 mem[addr_b]; |
| 439 | `endif |
| 440 | |
| 441 | // synopsys translate_off |
| 442 | initial |
| 443 | begin |
| 444 | if (dw !== 40) |
| 445 | begin |
| 446 | $display("RAM instantiation error! Expected RAM width %d, actual %h!", 40, dw) ; |
| 447 | $finish ; |
| 448 | end |
| 449 | `ifdef XILINX_RAMB4 |
| 450 | if (aw !== 8) |
| 451 | begin |
| 452 | $display("RAM instantiation error! Expected RAM address width %d, actual %h!", 40, aw) ; |
| 453 | $finish ; |
| 454 | end |
| 455 | `endif |
| 456 | // currenlty only artisan ram of depth 256 is supported - they don't provide generic ram models |
| 457 | `ifdef ARTISAN_SDP |
| 458 | if (aw !== 8) |
| 459 | begin |
| 460 | $display("RAM instantiation error! Expected RAM address width %d, actual %h!", 40, aw) ; |
| 461 | $finish ; |
| 462 | end |
| 463 | `endif |
| 464 | end |
| 465 | // synopsys translate_on |
| 466 | |
| 467 | endmodule |
| 468 | |