URL
https://opencores.org/ocsvn/mpeg2fpga/mpeg2fpga/trunk
Subversion Repositories mpeg2fpga
[/] [mpeg2fpga/] [trunk/] [tools/] [ieee1180/] [ieee1180/] [generic_dpram.v] - Rev 2
Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////// //// //// //// 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.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