+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Generic Dual-Port Synchronous RAM ////
+//// ////
+//// This file is part of memory library available from ////
+//// http://www.opencores.org/cvsweb.shtml/generic_memories/ ////
+//// ////
+//// Description ////
+//// This block is a wrapper with common dual-port ////
+//// synchronous memory interface for different ////
+//// types of ASIC and FPGA RAMs. Beside universal memory ////
+//// interface it also provides behavioral model of generic ////
+//// dual-port synchronous RAM. ////
+//// It also contains a fully synthesizeable model for FPGAs. ////
+//// It should be used in all OPENCORES designs that want to be ////
+//// portable accross different target technologies and ////
+//// independent of target memory. ////
+//// ////
+//// Supported ASIC RAMs are: ////
+//// - Artisan Dual-Port Sync RAM ////
+//// - Avant! Two-Port Sync RAM (*) ////
+//// - Virage 2-port Sync RAM ////
+//// ////
+//// Supported FPGA RAMs are: ////
+//// - Generic FPGA (VENDOR_FPGA) ////
+//// Tested RAMs: Altera, Xilinx ////
+//// Synthesis tools: LeonardoSpectrum, Synplicity ////
+//// - Xilinx (VENDOR_XILINX) ////
+//// - Altera (VENDOR_ALTERA) ////
+//// ////
+//// To Do: ////
+//// - fix Avant! ////
+//// - add additional RAMs (VS etc) ////
+//// ////
+//// Author(s): ////
+//// - Richard Herveille, richard@asics.ws ////
+//// - Damjan Lampret, lampret@opencores.org ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: generic_dpram.v,v $
+// Revision 1.1 2007-02-11 22:05:26 sithglan
+// += dpram
+//
+// Revision 1.4 2002/09/28 08:18:52 rherveille
+// Changed synthesizeable FPGA memory implementation.
+// Fixed some issues with Xilinx BlockRAM
+//
+// Revision 1.3 2001/11/09 00:34:18 samg
+// minor changes: unified with all common rams
+//
+// Revision 1.2 2001/11/08 19:11:31 samg
+// added valid checks to behvioral model
+//
+// Revision 1.1.1.1 2001/09/14 09:57:10 rherveille
+// Major cleanup.
+// Files are now compliant to Altera & Xilinx memories.
+// Memories are now compatible, i.e. drop-in replacements.
+// Added synthesizeable generic FPGA description.
+// Created "generic_memories" cvs entry.
+//
+// Revision 1.1.1.2 2001/08/21 13:09:27 damjan
+// *** empty log message ***
+//
+// Revision 1.1 2001/08/20 18:23:20 damjan
+// Initial revision
+//
+// Revision 1.1 2001/08/09 13:39:33 lampret
+// Major clean-up.
+//
+// Revision 1.2 2001/07/30 05:38:02 lampret
+// Adding empty directories required by HDL coding guidelines
+//
+//
+
+//`include "timescale.v"
+
+//`define VENDOR_FPGA
+//`define VENDOR_XILINX
+//`define VENDOR_ALTERA
+
+module generic_dpram(
+ // Generic synchronous dual-port RAM interface
+ rclk, rrst, rce, oe, raddr, do,
+ wclk, wrst, wce, we, waddr, di
+);
+
+ //
+ // Default address and data buses width
+ //
+ parameter aw = 5; // number of bits in address-bus
+ parameter dw = 16; // number of bits in data-bus
+
+ //
+ // Generic synchronous double-port RAM interface
+ //
+ // read port
+ input rclk; // read clock, rising edge trigger
+ input rrst; // read port reset, active high
+ input rce; // read port chip enable, active high
+ input oe; // output enable, active high
+ input [aw-1:0] raddr; // read address
+ output [dw-1:0] do; // data output
+
+ // write port
+ input wclk; // write clock, rising edge trigger
+ input wrst; // write port reset, active high
+ input wce; // write port chip enable, active high
+ input we; // write enable, active high
+ input [aw-1:0] waddr; // write address
+ input [dw-1:0] di; // data input
+
+ //
+ // Module body
+ //
+
+`ifdef VENDOR_FPGA
+ //
+ // Instantiation synthesizeable FPGA memory
+ //
+ // This code has been tested using LeonardoSpectrum and Synplicity.
+ // The code correctly instantiates Altera EABs and Xilinx BlockRAMs.
+ //
+ reg [dw-1:0] mem [(1<<aw) -1:0]; // instantiate memory
+ reg [aw-1:0] ra; // register read address
+
+ // read operation
+ always @(posedge rclk)
+ if (rce)
+ ra <= #1 raddr;
+
+ assign do = mem[ra];
+
+ // write operation
+ always@(posedge wclk)
+ if (we && wce)
+ mem[waddr] <= #1 di;
+
+`else
+
+`ifdef VENDOR_XILINX
+ //
+ // Instantiation of FPGA memory:
+ //
+ // Virtex/Spartan2 BlockRAMs
+ //
+ xilinx_ram_dp xilinx_ram(
+ // read port
+ .CLKA(rclk),
+ .RSTA(rrst),
+ .ENA(rce),
+ .ADDRA(raddr),
+ .DIA( {dw{1'b0}} ),
+ .WEA(1'b0),
+ .DOA(do),
+
+ // write port
+ .CLKB(wclk),
+ .RSTB(wrst),
+ .ENB(wce),
+ .ADDRB(waddr),
+ .DIB(di),
+ .WEB(we),
+ .DOB()
+ );
+
+ defparam
+ xilinx_ram.dwidth = dw,
+ xilinx_ram.awidth = aw;
+
+`else
+
+`ifdef VENDOR_ALTERA
+ //
+ // Instantiation of FPGA memory:
+ //
+ // Altera FLEX/APEX EABs
+ //
+ altera_ram_dp altera_ram(
+ // read port
+ .rdclock(rclk),
+ .rdclocken(rce),
+ .rdaddress(raddr),
+ .q(do),
+
+ // write port
+ .wrclock(wclk),
+ .wrclocken(wce),
+ .wren(we),
+ .wraddress(waddr),
+ .data(di)
+ );
+
+ defparam
+ altera_ram.dwidth = dw,
+ altera_ram.awidth = aw;
+
+`else
+
+`ifdef VENDOR_ARTISAN
+
+ //
+ // Instantiation of ASIC memory:
+ //
+ // Artisan Synchronous Double-Port RAM (ra2sh)
+ //
+ art_hsdp #(dw, 1<<aw, aw) artisan_sdp(
+ // read port
+ .qa(do),
+ .clka(rclk),
+ .cena(~rce),
+ .wena(1'b1),
+ .aa(raddr),
+ .da( {dw{1'b0}} ),
+ .oena(~oe),
+
+ // write port
+ .qb(),
+ .clkb(wclk),
+ .cenb(~wce),
+ .wenb(~we),
+ .ab(waddr),
+ .db(di),
+ .oenb(1'b1)
+ );
+
+`else
+
+`ifdef VENDOR_AVANT
+
+ //
+ // Instantiation of ASIC memory:
+ //
+ // Avant! Asynchronous Two-Port RAM
+ //
+ avant_atp avant_atp(
+ .web(~we),
+ .reb(),
+ .oeb(~oe),
+ .rcsb(),
+ .wcsb(),
+ .ra(raddr),
+ .wa(waddr),
+ .di(di),
+ .do(do)
+ );
+
+`else
+
+`ifdef VENDOR_VIRAGE
+
+ //
+ // Instantiation of ASIC memory:
+ //
+ // Virage Synchronous 2-port R/W RAM
+ //
+ virage_stp virage_stp(
+ // read port
+ .CLKA(rclk),
+ .MEA(rce_a),
+ .ADRA(raddr),
+ .DA( {dw{1'b0}} ),
+ .WEA(1'b0),
+ .OEA(oe),
+ .QA(do),
+
+ // write port
+ .CLKB(wclk),
+ .MEB(wce),
+ .ADRB(waddr),
+ .DB(di),
+ .WEB(we),
+ .OEB(1'b1),
+ .QB()
+ );
+
+`else
+
+ //
+ // Generic dual-port synchronous RAM model
+ //
+
+ //
+ // Generic RAM's registers and wires
+ //
+ reg [dw-1:0] mem [(1<<aw)-1:0]; // RAM content
+ reg [dw-1:0] do_reg; // RAM data output register
+
+ //
+ // Data output drivers
+ //
+ assign do = (oe & rce) ? do_reg : {dw{1'bz}};
+
+ // read operation
+ always @(posedge rclk)
+ if (rce)
+ do_reg <= #1 (we && (waddr==raddr)) ? {dw{1'b x}} : mem[raddr];
+
+ // write operation
+ always @(posedge wclk)
+ if (wce && we)
+ mem[waddr] <= #1 di;
+
+
+ // Task prints range of memory
+ // *** Remember that tasks are non reentrant, don't call this task in parallel for multiple instantiations.
+ task print_ram;
+ input [aw-1:0] start;
+ input [aw-1:0] finish;
+ integer rnum;
+ begin
+ for (rnum=start;rnum<=finish;rnum=rnum+1)
+ $display("Addr %h = %h",rnum,mem[rnum]);
+ end
+ endtask
+
+`endif // !VENDOR_VIRAGE
+`endif // !VENDOR_AVANT
+`endif // !VENDOR_ARTISAN
+`endif // !VENDOR_ALTERA
+`endif // !VENDOR_XILINX
+`endif // !VENDOR_FPGA
+
+endmodule
+
+//
+// Black-box modules
+//
+
+`ifdef VENDOR_ALTERA
+ module altera_ram_dp(
+ data,
+ wraddress,
+ rdaddress,
+ wren,
+ wrclock,
+ wrclocken,
+ rdclock,
+ rdclocken,
+ q) /* synthesis black_box */;
+
+ parameter awidth = 7;
+ parameter dwidth = 8;
+
+ input [dwidth -1:0] data;
+ input [awidth -1:0] wraddress;
+ input [awidth -1:0] rdaddress;
+ input wren;
+ input wrclock;
+ input wrclocken;
+ input rdclock;
+ input rdclocken;
+ output [dwidth -1:0] q;
+
+ // synopsis translate_off
+ // exemplar translate_off
+
+ syn_dpram_rowr #(
+ "UNUSED",
+ dwidth,
+ awidth,
+ 1 << awidth
+ )
+ altera_dpram_model (
+ // read port
+ .RdClock(rdclock),
+ .RdClken(rdclocken),
+ .RdAddress(rdaddress),
+ .RdEn(1'b1),
+ .Q(q),
+
+ // write port
+ .WrClock(wrclock),
+ .WrClken(wrclocken),
+ .WrAddress(wraddress),
+ .WrEn(wren),
+ .Data(data)
+ );
+
+ // exemplar translate_on
+ // synopsis translate_on
+
+ endmodule
+`endif // VENDOR_ALTERA
+
+`ifdef VENDOR_XILINX
+ module xilinx_ram_dp (
+ ADDRA,
+ CLKA,
+ ADDRB,
+ CLKB,
+ DIA,
+ WEA,
+ DIB,
+ WEB,
+ ENA,
+ ENB,
+ RSTA,
+ RSTB,
+ DOA,
+ DOB) /* synthesis black_box */ ;
+
+ parameter awidth = 7;
+ parameter dwidth = 8;
+
+ // port_a
+ input CLKA;
+ input RSTA;
+ input ENA;
+ input [awidth-1:0] ADDRA;
+ input [dwidth-1:0] DIA;
+ input WEA;
+ output [dwidth-1:0] DOA;
+
+ // port_b
+ input CLKB;
+ input RSTB;
+ input ENB;
+ input [awidth-1:0] ADDRB;
+ input [dwidth-1:0] DIB;
+ input WEB;
+ output [dwidth-1:0] DOB;
+
+ // insert simulation model
+
+
+ // synopsys translate_off
+ // exemplar translate_off
+
+ C_MEM_DP_BLOCK_V1_0 #(
+ awidth,
+ awidth,
+ 1,
+ 1,
+ "0",
+ 1 << awidth,
+ 1 << awidth,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ "",
+ 16,
+ 0,
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ dwidth,
+ dwidth)
+ xilinx_dpram_model (
+ .ADDRA(ADDRA),
+ .CLKA(CLKA),
+ .ADDRB(ADDRB),
+ .CLKB(CLKB),
+ .DIA(DIA),
+ .WEA(WEA),
+ .DIB(DIB),
+ .WEB(WEB),
+ .ENA(ENA),
+ .ENB(ENB),
+ .RSTA(RSTA),
+ .RSTB(RSTB),
+ .DOA(DOA),
+ .DOB(DOB));
+
+ // exemplar translate_on
+ // synopsys translate_on
+
+ endmodule
+`endif // VENDOR_XILINX