diff options
Diffstat (limited to 'fpga/usrp2/models')
25 files changed, 13917 insertions, 0 deletions
diff --git a/fpga/usrp2/models/BUFG.v b/fpga/usrp2/models/BUFG.v new file mode 100644 index 000000000..a935c6285 --- /dev/null +++ b/fpga/usrp2/models/BUFG.v @@ -0,0 +1,33 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/BUFG.v,v 1.5 2005/03/14 22:32:51 yanx Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2004 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 8.1i (I.13) +// \ \ Description : Xilinx Functional Simulation Library Component +// / / Global Clock Buffer +// /___/ /\ Filename : BUFG.v +// \ \ / \ Timestamp : Thu Mar 25 16:42:14 PST 2004 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// End Revision + +`timescale 100 ps / 10 ps + + +module BUFG (O, I); + + output O; + + input I; + + buf B1 (O, I); + + +endmodule + diff --git a/fpga/usrp2/models/CY7C1356C/cy1356.inp b/fpga/usrp2/models/CY7C1356C/cy1356.inp new file mode 100644 index 000000000..a55ffac39 --- /dev/null +++ b/fpga/usrp2/models/CY7C1356C/cy1356.inp @@ -0,0 +1,140 @@ +/*Address inputs only 0=LOW + "Data is in HEX, four bytes (LSB,MSB)" 1=HIGH + ZZZZZZZZZZZZZZZZ=Tri-state G-WRITE = Global Write + XXXXXXXXXXXXXXXX= Don't care B-WRITE = Byte Write + YYYY=unknown BG-WRITE = BURST GLOBAL WRITE + BB-WRITE = BURST BYTE WRITE + +*/ +// CE3# BW2# ADV/LD# +// CEN# CE2 WE# +// Add IN OUT CE1# BW1# +0000000000000000_XXXXXXXXXXXXXXXX_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000000001_XXXXXXXXXXXXXXXX_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000000010_0000000000000000_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000000011_0000000000000001_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000000100_0000000000000010_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000000101_0000000000000011_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000000110_0000000000000100_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000000111_0000000000000101_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001000_0000000000000110_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001001_0000000000000111_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001010_0000000000001000_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001011_0000000000001001_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001100_0000000000001010_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001101_0000000000001011_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001110_0000000000001100_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001111_0000000000001101_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000000000_0000000000001110_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000000001_0000000000001111_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000000010_xxxxxxxxxxxxxxxx_0000000000000000_0_0_1_0_1_X_X_0 +0000000000000011_xxxxxxxxxxxxxxxx_0000000000000001_0_0_1_0_1_X_X_0 +0000000000000100_xxxxxxxxxxxxxxxx_0000000000000010_0_0_1_0_1_X_X_0 +0000000000000101_xxxxxxxxxxxxxxxx_0000000000000011_0_0_1_0_1_X_X_0 +0000000000000110_xxxxxxxxxxxxxxxx_0000000000000100_0_0_1_0_1_X_X_0 +0000000000000111_xxxxxxxxxxxxxxxx_0000000000000101_0_0_1_0_1_X_X_0 +0000000000001000_xxxxxxxxxxxxxxxx_0000000000000110_0_0_1_0_1_X_X_0 +0000000000001001_xxxxxxxxxxxxxxxx_0000000000000111_0_0_1_0_1_X_X_0 +0000000000001010_xxxxxxxxxxxxxxxx_0000000000001000_0_0_1_0_1_X_X_0 +0000000000001011_xxxxxxxxxxxxxxxx_0000000000001001_0_0_1_0_1_X_X_0 +0000000000001100_xxxxxxxxxxxxxxxx_0000000000001010_0_0_1_0_1_X_X_0 +0000000000001101_xxxxxxxxxxxxxxxx_0000000000001011_0_0_1_0_1_X_X_0 +0000000000001110_xxxxxxxxxxxxxxxx_0000000000001100_0_0_1_0_1_X_X_0 +0000000000001111_xxxxxxxxxxxxxxxx_0000000000001101_0_0_1_0_1_X_X_0 +0000000000000000_xxxxxxxxxxxxxxxx_0000000000001110_0_0_1_0_0_0_0_0 +0000000000001111_xxxxxxxxxxxxxxxx_0000000000001111_0_0_1_0_1_X_X_0 +0000000000000000_0001000100010001_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_1_0_0 +0000000000000000_xxxxxxxxxxxxxxxx_0000000000001111_0_0_1_0_1_X_X_0 +0000000000001100_XXXX1010XXXX1010_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_0_0 +0000000000001011_xxxxxxxxxxxxxxxx_0001101000011010_0_0_1_0_1_X_X_0 +0000000000000111_0010001000100010_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_1_0 +0000000000000111_xxxxxxxxxxxxxxxx_0000000000001011_0_0_1_0_1_X_X_0 +0000000000001000_001100110011XXXX_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000001001_xxxxxxxxxxxxxxxx_0011001100110111_0_0_1_0_0_0_0_0 +0000000000001001_xxxxxxxxxxxxxxxx_0000000000001000_0_0_1_0_0_0_1_0 +0000000000001001_0100010001000100_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_1_1_0 +0000000000001010_XXXX01010101XXXX_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_1_1_0 +0000000000000000_xxxxxxxxxxxxxxxx_0100010101010100_0_0_1_0_0_0_0_0 +0000000000000001_xxxxxxxxxxxxxxxx_0000000000001010_0_0_1_0_0_0_0_0 +0000000000001001_0110011001100110_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000000000_0111011101110111_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000000101_xxxxxxxxxxxxxxxx_0100010101010100_0_0_1_0_0_0_1_0 +0000000000000100_xxxxxxxxxxxxxxxx_0110011001100110_0_0_1_0_0_1_0_0 +0000000000000001_1000XXXX1000XXXX_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000000010_XXXX1001XXXX1001_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000001100_xxxxxxxxxxxxxxxx_0111011101110111_0_0_1_0_0_1_1_0 +0000000000001101_xxxxxxxxxxxxxxxx_0000000000000010_0_0_1_0_0_0_0_0 +0000000000001010_00010001XXXXXXXX_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000001011_0000111100001111_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +0000000000001100_xxxxxxxxxxxxxxxx_0000000000001010_0_0_1_0_1_X_X_0 +0000000000000011_xxxxxxxxxxxxxxxx_0000000000001011_0_0_1_0_0_0_0_0 +0000000000000100_xxxxxxxxxxxxxxxx_0001000100100010_0_0_1_0_0_0_1_0 +0000000000000101_0011001100110011_xxxxxxxxxxxxxxxx_0_0_1_0_0_0_0_0 +0000000000000011_010001000100XXXX_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000100_0101010101010101_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000101_xxxxxxxxxxxxxxxx_0011001100110011_0_0_1_0_1_X_X_0 +0000000000000110_xxxxxxxxxxxxxxxx_0100010001001001_0_0_1_0_0_0_0_0 +0000000000000111_xxxxxxxxxxxxxxxx_0101010101010101_0_0_1_0_0_0_0_0 +0000000000001000_0110011001100110_xxxxxxxxxxxxxxxx_0_0_1_0_0_0_0_0 +0000000000000110_0111011101110111_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000111_1000100010001000_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000001000_xxxxxxxxxxxxxxxx_0110011001100110_0_0_1_0_1_X_X_0 +0000000000000110_xxxxxxxxxxxxxxxx_0111011101110111_0_0_1_0_0_0_1_0 +0000000000000111_xxxxxxxxxxxxxxxx_1000100010001000_0_0_1_0_0_1_0_0 +0000000000001000_0001XXXX0001XXXX_xxxxxxxxxxxxxxxx_0_0_1_0_0_0_1_0 +0000000000000110_XXXX0001XXXX0001_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000111_0001XXXX0001XXXX_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000001000_xxxxxxxxxxxxxxxx_0001011000010110_0_0_1_0_1_X_X_0 +0000000000001001_xxxxxxxxxxxxxxxx_0111000101110001_0_0_1_0_0_1_1_0 +0000000000001010_xxxxxxxxxxxxxxxx_0001100000011000_0_0_1_0_0_0_0_0 +0000000000001011_00100010XXXXXXXX_xxxxxxxxxxxxxxxx_0_0_1_0_0_1_1_0 +0000000000000001_XXXXXXXX00110011_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000010_01000100XXXXXXXX_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000011_xxxxxxxxxxxxxxxx_0111011101110111_0_0_1_0_1_X_X_0 +0000000000000100_xxxxxxxxxxxxxxxx_0000000000000010_0_0_1_0_1_X_X_0 +0000000000000001_xxxxxxxxxxxxxxxx_0011001100110011_0_0_1_0_0_0_0_0 +0000000000000010_xxxxxxxxxxxxxxxx_0100010001001001_0_0_1_0_0_0_0_0 +0000000000000011_0001000100010001_xxxxxxxxxxxxxxxx_0_0_1_0_0_0_0_0 +0000000000000100_0010001000100010_xxxxxxxxxxxxxxxx_0_0_1_0_0_0_0_0 +0000000000000001_0011001100110011_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000010_0100010001000100_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000011_xxxxxxxxxxxxxxxx_0001000100010001_0_0_1_0_1_X_X_0 +0000000000000100_xxxxxxxxxxxxxxxx_0010001000100010_0_0_1_0_1_X_X_0 +0000000000000101_xxxxxxxxxxxxxxxx_0011001100110011_0_0_1_0_0_0_0_0 +0000000000000110_xxxxxxxxxxxxxxxx_0100010001000100_0_X_X_X_X_0_0_1 +0000000000000111_0101010101010101_xxxxxxxxxxxxxxxx_0_X_X_X_X_1_1_1 +0000000000001000_0110011001100110_xxxxxxxxxxxxxxxx_0_X_X_X_X_0_0_1 +0000000000000101_01110111XXXXXXXX_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +XXXXXXXXXXXXXXXX_XXXXXXXX10001000_xxxxxxxxxxxxxxxx_0_X_X_X_X_X_X_1 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0101010101010101_0_X_X_X_X_X_X_1 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0110011001100110_0_X_X_X_X_X_X_1 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0111011101110001_0_1_X_X_X_X_X_0 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0100010010001000_1_X_X_X_X_X_X_X +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0100010010001000_0_X_0_X_X_X_X_0 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_ZZZZZZZZZZZZZZZZ_0_X_X_1_X_X_X_0 +0000000000000101_xxxxxxxxxxxxxxxx_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_ZZZZZZZZZZZZZZZZ_1_X_X_X_X_X_X_X +0000000000001000_xxxxxxxxxxxxxxxx_ZZZZZZZZZZZZZZZZ_0_0_1_0_0_0_1_0 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0101010101010101_1_X_X_X_X_X_X_X +0000000000000111_xxxxxxxxxxxxxxxx_0101010101010101_0_0_1_0_1_X_X_0 +xxxxxxxxxxxxxxxx_XXXXXXXXXXXXXXXX_ZZZZZZZZZZZZZZZZ_1_X_X_X_X_X_X_X +0000000000001000_0000XXXX0000XXXX_ZZZZZZZZZZZZZZZZ_0_0_1_0_1_X_X_0 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0111011101110001_1_X_X_X_X_X_X_X +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0111011101110001_1_X_X_X_X_X_X_X +0000000000000000_xxxxxxxxxxxxxxxx_0111011101110001_0_0_1_0_1_X_X_0 +0000000000000001_xxxxxxxxxxxxxxxx_0000100000001000_0_0_1_0_1_X_X_0 +0000000000000001_xxxxxxxxxxxxxxxx_0110011001100110_0_0_1_0_0_1_1_0 +0000000000000001_xxxxxxxxxxxxxxxx_0001000100010001_0_0_1_0_0_1_1_0 +0000000000000001_0001XXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0_0_1_0_0_0_1_0 +0000000000000001_XXXX0010XXXXXXXX_xxxxxxxxxxxxxxxx_0_0_1_0_0_1_0_0 +0000000000000001_XXXXXXXX0011XXXX_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +0000000000000000_XXXXXXXXXXXX0100_xxxxxxxxxxxxxxxx_0_0_1_0_1_X_X_0 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0001001000110100_0_X_X_X_X_X_X_1 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0110011001100110_0_X_X_X_X_X_X_1 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0001001000110100_0_X_X_X_X_X_X_1 +XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxx_0010001000100010_0_1_X_X_X_X_X_0 +xxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxx_0011001100110011_0_1_x_x_x_x_x_x +xxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxx_ZZZZZZZZZZZZZZZZ_0_1_x_x_x_x_x_x +//Lines =126 + + diff --git a/fpga/usrp2/models/CY7C1356C/cy1356.v b/fpga/usrp2/models/CY7C1356C/cy1356.v new file mode 100644 index 000000000..ab7ace610 --- /dev/null +++ b/fpga/usrp2/models/CY7C1356C/cy1356.v @@ -0,0 +1,502 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +`define sb200
+//************************************************************************
+//************************************************************************
+//** This model is the property of Cypress Semiconductor Corp and is **
+//** protected by the US copyright laws, any unauthorized copying and **
+//** distribution is prohibited. Cypress reserves the right to change **
+//** any of the functional specifications without any prior notice. **
+//** Cypress is not liable for any damages which may result from the **
+//** use of this functional model. **
+//** **
+//** File Name : CY7C1356 **
+//** **
+//** Revision : 1.0 - 08/03/2004 **
+//** **
+//** The timings are to be selected by the user depending upon the **
+//** frequency of operation from the datasheet. **
+//** **
+//** Model : CY7C1356C - NoBL Pipelined SRAM **
+//** Queries : MPD Applications **
+//** Website: www.cypress.com/support **
+//************************************************************************
+//************************************************************************
+
+`timescale 1ns / 10ps
+
+// NOTE : Any setup/hold errors will force input signal to x state
+// or if results indeterminant (write addr) core is reset x
+
+// define fixed values
+
+`define wordsize (18 -1) //
+`define no_words (1048576 -1) // 1M x 18 RAM
+
+module cy1356 ( d, clk, a, bws, we_b, adv_lb, ce1b, ce2, ce3b, oeb, cenb, mode);
+
+inout [`wordsize:0] d;
+input clk, // clock input (R)
+ we_b, // byte write enable(L)
+ adv_lb, // burst(H)/load(L) address
+ ce1b, // chip enable(L)
+ ce2, // chip enable(H)
+ ce3b, // chip enable(L)
+ oeb, // async output enable(L)(read)
+ cenb, // clock enable(L)
+ mode; // interleave(H)/linear(L) burst
+input [1:0] bws; // byte write select(L)
+input [18:0] a; // address bus
+
+// *** NOTE DEVICE OPERATES #0.01 AFTER CLOCK ***
+// *** THEREFORE DELAYS HAVE TO TAKE THIS INTO ACCOUNT ***
+
+
+//**********************************************************************
+// Timings for 225MHz
+//**********************************************************************
+`ifdef sb225
+ `define teohz #2.8
+ `define teolz #0
+ `define tchz #2.8
+ `define tclz #1.25
+
+ `define tco #2.8
+ `define tdoh #1.25
+ `define tas 1.4
+ `define tah 0.4
+`endif
+//***********************************************************************
+// Timings for 200MHz
+//**********************************************************************
+`ifdef sb200
+ `define teohz #3.2
+ `define teolz #0
+ `define tchz #3.2
+ `define tclz #1.5
+
+ `define tco #3.2
+ `define tdoh #1.5
+
+ `define tas 1.5
+ `define tah 0.5
+`endif
+//***********************************************************************
+
+//**********************************************************************
+// This model is configured for 166 MHz Operation (CY7C1356-166).
+//**********************************************************************
+`ifdef sb166
+ `define teohz #3.5
+ `define teolz #0
+ `define tchz #3.5
+ `define tclz #1.5
+
+ `define tco #3.5
+ `define tdoh #1.5
+
+ `define tas 1.5
+ `define tah 0.5
+`endif
+
+reg notifier; // error support reg's
+reg noti1_0;
+reg noti1_1;
+reg noti1_2;
+reg noti1_3;
+reg noti1_4;
+reg noti1_5;
+reg noti1_6;
+reg noti2;
+
+
+wire chipen; // combined chip enable (high for an active chip)
+
+reg chipen_d; // _d = delayed
+reg chipen_o; // _o = operational = delayed sig or _d sig
+
+wire writestate; // holds 1 if any of writebus is low
+reg writestate_d;
+reg writestate_o;
+
+wire loadcyc; // holds 1 for load cycles (setup and hold checks)
+wire writecyc; // holds 1 for write cycles (setup and hold checks)
+wire [1:0] bws; // holds the bws values
+
+wire [1:0] writebusb; // holds the "internal" bws bus based on we_b
+reg [1:0] writebusb_d;
+reg [1:0] writebusb_o;
+
+wire [2:0] operation; // holds chipen, adv_ld and writestate
+reg [2:0] operation_d;
+reg [2:0] operation_o;
+
+wire [18:0] a; // address input bus
+reg [18:0] a_d;
+reg [18:0] a_o;
+
+reg [`wordsize:0] do; // data output reg
+reg [`wordsize:0] di; // data input bus
+reg [`wordsize:0] dd; // data delayed bus
+
+wire tristate; // tristate output (on a bytewise basis) when asserted
+reg cetri; // register set by chip disable which sets the tristate
+reg oetri; // register set by oe which sets the tristate
+reg enable; // register to make the ram enabled when equal to 1
+reg [18:0] addreg; // register to hold the input address
+reg [`wordsize:0] pipereg; // register for the output data
+
+reg [`wordsize:0] mem [0:`no_words]; // RAM array
+
+reg [`wordsize:0] writeword; // temporary holding register for the write data
+reg burstinit; // register to hold a[0] for burst type
+reg [18:0] i; // temporary register used to write to all mem locs.
+reg writetri; // tristate
+reg lw, bw; // pipelined write functions
+reg we_bl;
+
+
+wire [`wordsize:0] d = !tristate ? do[`wordsize:0] : 18'bz ; // data bus
+
+assign chipen = (adv_lb == 1 ) ? chipen_d :
+ ~ce1b & ce2 & ~ce3b ;
+
+assign writestate = ~& writebusb;
+
+assign operation = {chipen, adv_lb, writestate};
+
+assign writebusb[1:0] = ( we_b ==0 & adv_lb ==0) ? bws[1:0]:
+ ( we_b ==1 & adv_lb ==0) ? 2'b11 :
+ ( we_bl ==0 & adv_lb ==1) ? bws[1:0]:
+ ( we_bl ==1 & adv_lb ==1) ? 2'b11 :
+ 2'bxx ;
+
+assign loadcyc = chipen & !cenb;
+
+assign writecyc = writestate_d & enable & ~cenb & chipen; // check
+
+assign tristate = cetri | writetri | oetri;
+
+pullup (mode);
+
+// formers for notices/errors etc
+//
+//$display("NOTICE : xxx :");
+//$display("WARNING : xxx :");
+//$display("ERROR *** : xxx :");
+
+
+// initialize the output to be tri-state, ram to be disabled
+
+initial
+ begin
+// signals
+
+ writetri = 0;
+ cetri = 1;
+ enable = 0;
+ lw = 0;
+ bw = 0;
+
+// error signals
+
+ notifier = 0;
+ noti1_0 = 0;
+ noti1_1 = 0;
+ noti1_2 = 0;
+ noti1_3 = 0;
+ noti1_4 = 0;
+ noti1_5 = 0;
+ noti1_6 = 0;
+ noti2 = 0;
+
+end
+
+
+
+// asynchronous OE
+
+always @(oeb)
+begin
+ if (oeb == 1)
+ oetri <= `teohz 1;
+ else
+ oetri <= `teolz 0;
+end
+
+// *** SETUP / HOLD VIOLATIONS ***
+
+always @(noti2)
+begin
+$display("NOTICE : 020 : Data bus corruption");
+ force d =18'bx;
+ #1;
+ release d;
+end
+
+always @(noti1_0)
+begin
+$display("NOTICE : 010 : Byte write corruption");
+ force bws = 2'bx;
+ #1;
+ release bws;
+end
+
+always @(noti1_1)
+begin
+$display("NOTICE : 011 : Byte enable corruption");
+ force we_b = 1'bx;
+ #1;
+ release we_b;
+end
+
+always @(noti1_2)
+begin
+$display("NOTICE : 012 : CE1B corruption");
+ force ce1b =1'bx;
+ #1;
+ release ce1b;
+end
+
+always @(noti1_3)
+begin
+$display("NOTICE : 013 : CE2 corruption");
+ force ce2 =1'bx;
+ #1;
+ release ce2;
+end
+
+always @(noti1_4)
+begin
+$display("NOTICE : 014 : CE3B corruption");
+ force ce3b =1'bx;
+ #1;
+ release ce3b;
+end
+
+always @(noti1_5)
+begin
+$display("NOTICE : 015 : CENB corruption");
+ force cenb =1'bx;
+ #1;
+ release cenb;
+end
+
+always @(noti1_6)
+begin
+$display("NOTICE : 016 : ADV_LB corruption");
+ force adv_lb = 1'bx;
+ #1;
+ release adv_lb;
+end
+
+// synchronous functions from clk edge
+
+always @(posedge clk)
+if (!cenb)
+begin
+#0.01;
+ // latch conditions on adv_lb
+
+ if (adv_lb)
+ we_bl <= we_bl;
+ else
+ we_bl <= we_b;
+
+ chipen_d <= chipen;
+
+
+ chipen_o <= chipen;
+ writestate_o <= writestate;
+ writestate_d <= writestate_o;
+ writebusb_o <= writebusb;
+ writebusb_d <= writebusb_o;
+ operation_o <= operation;
+ a_o <= a;
+ a_d <= a_o;
+ di = d;
+
+ // execute previously pipelined fns
+
+ if (lw) begin
+ loadwrite;
+ lw =0;
+ end
+
+ if (bw) begin
+ burstwrite;
+ bw =0;
+ end
+
+ // decode input/piplined state
+
+ casex (operation_o)
+ 3'b0?? : turnoff;
+ 3'b101 : setlw;
+ 3'b111 : setbw;
+ 3'b100 : loadread;
+ 3'b110 : burstread;
+ default : unknown; // output unknown values and display an error message
+ endcase
+
+ do <= `tco pipereg;
+
+end
+
+// *** task section ***
+
+task read;
+begin
+ if (enable) cetri <= `tclz 0;
+ writetri <= `tchz 0;
+ do <= `tdoh 18'hx;
+ pipereg = mem[addreg];
+end
+endtask
+
+task write;
+begin
+ if (enable) cetri <= `tclz 0;
+ writeword = mem[addreg]; // set up a word to hold the data for the current location
+ /* overwrite the current word for the bytes being written to */
+ if (!writebusb_d[1]) writeword[17:9] = di[17:9];
+ if (!writebusb_d[0]) writeword[8:0] = di[8:0];
+ writeword = writeword & writeword; //convert z to x states
+ mem[addreg] = writeword; // store the new word into the memory location
+ //writetri <= `tchz 1; // tristate the outputs
+end
+endtask
+
+task setlw;
+begin
+ lw =1;
+ writetri <= `tchz 1; // tristate the outputs
+end
+endtask
+
+task setbw;
+begin
+ bw =1;
+ writetri <= `tchz 1; // tristate the outputs
+end
+endtask
+
+task loadread;
+begin
+ burstinit = a_o[0];
+ addreg = a_o;
+ enable = 1;
+ read;
+end
+endtask
+
+task loadwrite;
+begin
+ burstinit = a_d[0];
+ addreg = a_d;
+ enable = 1;
+ write;
+end
+endtask
+
+task burstread;
+begin
+ burst;
+ read;
+end
+endtask
+
+task burstwrite;
+begin
+ burst;
+ write;
+end
+endtask
+
+task unknown;
+begin
+ do = 18'bx;
+ // $display ("Unknown function: Operation = %b\n", operation);
+end
+endtask
+
+task turnoff;
+begin
+ enable = 0;
+ cetri <= `tchz 1;
+ pipereg = 18'h0;
+end
+endtask
+
+task burst;
+begin
+ if (burstinit == 0 || mode == 0)
+ begin
+ case (addreg[1:0])
+ 2'b00: addreg[1:0] = 2'b01;
+ 2'b01: addreg[1:0] = 2'b10;
+ 2'b10: addreg[1:0] = 2'b11;
+ 2'b11: addreg[1:0] = 2'b00;
+ default: addreg[1:0] = 2'bxx;
+ endcase
+ end
+ else
+ begin
+ case (addreg[1:0])
+ 2'b00: addreg[1:0] = 2'b11;
+ 2'b01: addreg[1:0] = 2'b00;
+ 2'b10: addreg[1:0] = 2'b01;
+ 2'b11: addreg[1:0] = 2'b10;
+ default: addreg[1:0] = 2'bxx;
+ endcase
+ end
+end
+endtask
+
+// IO checks
+
+specify
+// specify the setup and hold checks
+
+// notifier will wipe memory as result is indeterminent
+
+$setuphold(posedge clk &&& loadcyc, a, `tas, `tah, notifier);
+
+// noti1 should make ip = 'bx;
+
+$setuphold(posedge clk, bws, `tas, `tah, noti1_0);
+
+$setuphold(posedge clk, we_b, `tas, `tah, noti1_1);
+$setuphold(posedge clk, ce1b, `tas, `tah, noti1_2);
+$setuphold(posedge clk, ce2, `tas, `tah, noti1_3);
+$setuphold(posedge clk, ce3b, `tas, `tah, noti1_4);
+
+// noti2 should make d = 18'hxxxxx;
+
+$setuphold(posedge clk &&& writecyc, d, `tas, `tah, noti2);
+
+// add extra tests here.
+
+$setuphold(posedge clk, cenb, `tas, `tah, noti1_5);
+$setuphold(posedge clk, adv_lb, `tas, `tah, noti1_6);
+
+endspecify
+
+endmodule
+
+
diff --git a/fpga/usrp2/models/CY7C1356C/readme.txt b/fpga/usrp2/models/CY7C1356C/readme.txt new file mode 100644 index 000000000..3578c80dc --- /dev/null +++ b/fpga/usrp2/models/CY7C1356C/readme.txt @@ -0,0 +1,33 @@ +***************************
+Cypress Semiconductor
+MPD Applications
+Verilog model for NoBL SRAM CY7C1356
+Created: August 04, 2004
+Rev: 1.0
+***************************
+
+This is the verilog model for the CY7C1356 along with the testbench and test vectors.
+
+Contact support@cypress.com if you have any questions.
+
+This directory has 4 files. including this readme.
+
+1)cy7c1356c.v -> Verilog model for CY7C1356c
+
+2)cy1356.inp -> Test Vector File used for testing the verilog model
+
+3)testbench.v -> Test bench used for testing the verilog model
+
+
+COMPILING METHOD :
+------------------
+
+ verilog +define+<speed_bin> <Main File> <Test bench File>
+
+ Ex:
+ verilog +define+sb133 CY7C1356c.v testbench.v
+
+VERIFIED WITH:
+--------------
+
+VERILOG-XL 2.2
\ No newline at end of file diff --git a/fpga/usrp2/models/CY7C1356C/testbench.v b/fpga/usrp2/models/CY7C1356C/testbench.v new file mode 100644 index 000000000..01e0cbe00 --- /dev/null +++ b/fpga/usrp2/models/CY7C1356C/testbench.v @@ -0,0 +1,206 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +`timescale 1ns / 10ps
+
+
+//
+// CY7C1356
+// Simulatiom of Verilog model
+//
+//
+
+//
+// test bench for US vector input
+//
+//
+
+// define speed 166MHz
+
+`define tx10 #6
+`define tx08 #4.8
+`define tx05 #3
+`define tx04 #2.4
+`define tx02 #1.2
+
+/*
+`define tx10 #4.0 // period
+`define tx08 #3.2 //0.8 period
+`define tx05 #2.0 //0.5 period 250MHZ
+`define tx04 #1.6 //0.4 period
+`define tx02 #0.8 //0.2 period
+
+`define tx10 #4.4 // period
+`define tx08 #3.52 //0.8 period
+`define tx05 #2.2 //0.5 period 225MHZ
+`define tx04 #1.76 //0.4 period
+`define tx02 #0.88 //0.2 period
+
+`define tx10 #5 // period
+`define tx08 #4 //0.8 period
+`define tx05 #2.5 //0.5 period 200MHZ
+`define tx04 #2.0 //0.4 period
+`define tx02 #1.0 //0.2 period
+*/
+
+
+module rw_test;
+
+`define num_vectors 126
+`define impi {a[15:0],io[15:0],tsti[15:0],cenb,ce1b,ce2,ce3b,bweb,bwb,adv_lb}
+
+
+reg [57:1] lsim_vectors [1:`num_vectors];
+
+
+reg clk;
+reg adv_lb;
+reg ce1b; //cs1b
+reg ce2; //cs2
+reg ce3b; //cs3b
+reg [1:0] bwb;
+reg bweb;
+reg oeb;
+reg ftb;
+reg mode; //lbob
+reg cenb; //zz
+reg tp42; //sclk
+reg tp39; //se
+reg tp38; //tm
+reg [19:0] a;
+reg [17:0] io;
+reg [17:0] tsti;
+reg vddq;
+reg vssqr;
+reg iosel;
+
+
+wire [17:0] d = iosel ? io[17:0] : 18'bz;
+
+reg noti3;
+reg strb,j;
+integer vector,i;
+
+
+
+cy1356 testram ( d, clk, a, bwb, bweb, adv_lb, ce1b, ce2, ce3b, oeb, cenb, mode);
+
+initial
+begin
+ $dumpfile("dumpfile.dump");
+ $dumpvars(0,rw_test);
+end
+
+initial
+begin
+io = 18'bz;
+ftb = 1;
+oeb = 0;
+a[19:16] = 4'h0;
+mode = 0;
+strb = 0;
+tp38 = 0;
+tp39 = 0;
+tp42 = 0;
+`tx02;
+forever `tx05 strb = ~strb;
+end
+
+initial
+begin
+clk = 0;
+forever `tx05 clk =~clk;
+end
+
+initial
+ begin
+
+ $readmemb("cy1356.inp", lsim_vectors); //load input vector file
+
+ `impi = lsim_vectors[1]; //apply 1st test vector
+
+ for (vector = 2; vector <= `num_vectors; vector = vector + 1)
+ @(posedge strb)
+ begin
+
+ `impi = lsim_vectors[vector];
+
+
+
+ io[16:13] = io[07:04];
+ io[12:09] = io[07:04];
+ io[07:04] = io[03:00];
+ io[03:00] = io[03:00];
+
+ io[17] = io[16] ^^ io[15] ^^ io[14] ^^ io[13] ^^ io[11] ^^ io[11] ^^ io[10] ^^ io[9];
+ io[8] = io[7] ^^ io[6] ^^ io[5] ^^ io[4] ^^ io[3] ^^ io[2] ^^ io[1] ^^ io[0];
+
+ tsti[16:13] = tsti[07:04];
+ tsti[12:09] = tsti[07:04];
+ tsti[07:04] = tsti[03:00];
+ tsti[03:00] = tsti[03:00];
+
+ tsti[17] = tsti[16] ^^ tsti[15] ^^ tsti[14] ^^ tsti[13] ^^ tsti[11] ^^ tsti[11] ^^ tsti[10] ^^ tsti[9];
+ tsti[8] = tsti[7] ^^ tsti[6] ^^ tsti[5] ^^ tsti[4] ^^ tsti[3] ^^ tsti[2] ^^ tsti[1] ^^ tsti[0];
+
+ if (io === 18'hxxxxx)
+ iosel = `tx05 0;
+ else
+ iosel = `tx05 1;
+
+ end
+ #15 $finish; // This prevents simulation beyond end of test patterns
+ end
+
+always@(posedge clk)
+begin
+
+ if (io !== 18'hxxxxx) //input cycle
+ begin
+ $display("NOTICE : 001 : line = %d OK",vector -1);
+ end
+ else //do the test
+ begin
+ if (d == tsti)
+ begin
+ $display("NOTICE : 002 : line = %d OK",vector -1);
+ end
+ else
+ begin
+ j =0;
+ for (i =0;i< 18; i=i+1)
+ begin
+ if(tsti[i] !== 1'bx)
+ begin
+ if (d[i] !== tsti[i]) j = 1;
+ end
+ else
+ j = 0;
+ end
+ if (j)
+ $display("ERROR *** : 003 : line = %d data = %b test = %b",vector -1,d,tsti);
+ else
+ $display("NOTICE : 003 : line = %d OK",vector -1);
+ end
+ end
+end
+
+endmodule
+
+
+
+
diff --git a/fpga/usrp2/models/FIFO_GENERATOR_V4_3.v b/fpga/usrp2/models/FIFO_GENERATOR_V4_3.v new file mode 100644 index 000000000..bcb9af8a7 --- /dev/null +++ b/fpga/usrp2/models/FIFO_GENERATOR_V4_3.v @@ -0,0 +1,3494 @@ +/* + * $RDCfile: $ $Revision: 1.1.2.15 $ $Date: 2007/07/25 15:58:33 $ + ******************************************************************************* + * + * FIFO Generator v3.3 - Verilog Behavioral Model + * + ******************************************************************************* + * + * Copyright(C) 2006 by Xilinx, Inc. All rights reserved. + * This text/file contains proprietary, confidential + * information of Xilinx, Inc., is distributed under + * license from Xilinx, Inc., and may be used, copied + * and/or disclosed only pursuant to the terms of a valid + * license agreement with Xilinx, Inc. Xilinx hereby + * grants you a license to use this text/file solely for + * design, simulation, implementation and creation of + * design files limited to Xilinx devices or technologies. + * Use with non-Xilinx devices or technologies is expressly + * prohibited and immediately terminates your license unless + * covered by a separate agreement. + * + * Xilinx is providing theis design, code, or information + * "as-is" solely for use in developing programs and + * solutions for Xilinx devices, with no obligation on the + * part of Xilinx to provide support. By providing this design, + * code, or information as one possible implementation of + * this feature, application or standard. Xilinx is making no + * representation that this implementation is free from any + * claims of infringement. You are responsible for obtaining + * any rights you may require for your implementation. + * Xilinx expressly disclaims any warranty whatsoever with + * respect to the adequacy of the implementation, including + * but not limited to any warranties or representations that this + * implementation is free from claims of infringement, implied + * warranties of merchantability or fitness for a particular + * purpose. + * + * Xilinx products are not intended for use in life support + * appliances, devices, or systems. Use in such applications is + * expressly prohibited. + * + * This copyright and support notice must be retained as part + * of this text at all times. (c)Copyright 1995-2006 Xilinx, Inc. + * All rights reserved. + * + ******************************************************************************* + * + * Filename: fifo_generator_v4_3_bhv.v + * + * Description: + * The verilog behavioral model for the FIFO generator core. + * + ******************************************************************************* + */ + +`timescale 1ps/1ps + +/******************************************************************************* + * Declaration of top-level module + ******************************************************************************/ +module FIFO_GENERATOR_V4_3 +( + BACKUP, + BACKUP_MARKER, + CLK, + DIN, + PROG_EMPTY_THRESH, + PROG_EMPTY_THRESH_ASSERT, + PROG_EMPTY_THRESH_NEGATE, + PROG_FULL_THRESH, + PROG_FULL_THRESH_ASSERT, + PROG_FULL_THRESH_NEGATE, + RD_CLK, + RD_EN, + RD_RST, + RST, + SRST, + WR_CLK, + WR_EN, + WR_RST, + INT_CLK, + + ALMOST_EMPTY, + ALMOST_FULL, + DATA_COUNT, + DOUT, + EMPTY, + FULL, + OVERFLOW, + PROG_EMPTY, + PROG_FULL, + RD_DATA_COUNT, + UNDERFLOW, + VALID, + WR_ACK, + WR_DATA_COUNT, + SBITERR, + DBITERR + ); + + /**************************************************************************** + * Definition of Ports + * + * + ***************************************************************************** + * Definition of Parameters + * + * + *****************************************************************************/ + + /**************************************************************************** + * Declare user parameters and their defaults + *****************************************************************************/ + parameter C_COMMON_CLOCK = 0; + parameter C_COUNT_TYPE = 0; + parameter C_DATA_COUNT_WIDTH = 2; + parameter C_DEFAULT_VALUE = ""; + parameter C_DIN_WIDTH = 8; + parameter C_DOUT_RST_VAL = ""; + parameter C_DOUT_WIDTH = 8; + parameter C_ENABLE_RLOCS = 0; + + parameter C_FAMILY = "virtex2"; + //Not allowed in Verilog model + + parameter C_HAS_ALMOST_EMPTY = 0; + parameter C_HAS_ALMOST_FULL = 0; + parameter C_HAS_BACKUP = 0; + parameter C_HAS_DATA_COUNT = 0; + parameter C_HAS_MEMINIT_FILE = 0; + parameter C_HAS_OVERFLOW = 0; + parameter C_HAS_RD_DATA_COUNT = 0; + parameter C_HAS_RD_RST = 0; + parameter C_HAS_RST = 0; + parameter C_HAS_SRST = 0; + parameter C_HAS_UNDERFLOW = 0; + parameter C_HAS_VALID = 0; + parameter C_HAS_WR_ACK = 0; + parameter C_HAS_WR_DATA_COUNT = 0; + parameter C_HAS_WR_RST = 0; + parameter C_IMPLEMENTATION_TYPE = 0; + parameter C_INIT_WR_PNTR_VAL = 0; + parameter C_MEMORY_TYPE = 1; + parameter C_MIF_FILE_NAME = ""; + parameter C_OPTIMIZATION_MODE = 0; + parameter C_OVERFLOW_LOW = 0; + parameter C_PRELOAD_LATENCY = 1; + parameter C_PRELOAD_REGS = 0; + parameter C_PRIM_FIFO_TYPE = 512; + parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0; + parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0; + parameter C_PROG_EMPTY_TYPE = 0; + parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0; + parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0; + parameter C_PROG_FULL_TYPE = 0; + parameter C_RD_DATA_COUNT_WIDTH = 2; + parameter C_RD_DEPTH = 256; + parameter C_RD_FREQ = 1; + parameter C_RD_PNTR_WIDTH = 8; + parameter C_UNDERFLOW_LOW = 0; + parameter C_USE_FIFO16_FLAGS = 0; + parameter C_VALID_LOW = 0; + parameter C_WR_ACK_LOW = 0; + parameter C_WR_DATA_COUNT_WIDTH = 2; + parameter C_WR_DEPTH = 256; + parameter C_WR_FREQ = 1; + parameter C_WR_PNTR_WIDTH = 8; + parameter C_WR_RESPONSE_LATENCY = 1; + parameter C_USE_ECC = 0; + parameter C_FULL_FLAGS_RST_VAL = 1; + parameter C_HAS_INT_CLK = 0; + parameter C_USE_EMBEDDED_REG = 0; + parameter C_USE_FWFT_DATA_COUNT = 0; + + //There are 2 Verilog behavioral models + // 0 = Synchronous FIFO/ShiftRam FIFO + // 1 = Asynchronous FIFO + parameter C_VERILOG_IMPL = (C_IMPLEMENTATION_TYPE==0 ? 0 : + (C_IMPLEMENTATION_TYPE==1 ? 0 : + (C_IMPLEMENTATION_TYPE==2 ? 1 : 0))); + + + /****************************************************************************** + * Declare Input and Output Ports + *****************************************************************************/ + input CLK; + input BACKUP; + input BACKUP_MARKER; + input [C_DIN_WIDTH-1:0] DIN; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE; + input RD_CLK; + input RD_EN; + input RD_RST; + input RST; + input SRST; + input WR_CLK; + input WR_EN; + input WR_RST; + input INT_CLK; + + output ALMOST_EMPTY; + output ALMOST_FULL; + output [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT; + output [C_DOUT_WIDTH-1:0] DOUT; + output EMPTY; + output FULL; + output OVERFLOW; + output PROG_EMPTY; + output PROG_FULL; + output VALID; + output [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT; + output UNDERFLOW; + output WR_ACK; + output [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT; + output SBITERR; + output DBITERR; + + + wire ALMOST_EMPTY; + wire ALMOST_FULL; + wire [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT; + wire [C_DOUT_WIDTH-1:0] DOUT; + wire EMPTY; + wire FULL; + wire OVERFLOW; + wire PROG_EMPTY; + wire PROG_FULL; + wire VALID; + wire [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT; + wire UNDERFLOW; + wire WR_ACK; + wire [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT; + + + wire RD_CLK_P0_IN; + wire RST_P0_IN; + wire RD_EN_FIFO_IN; + wire RD_EN_P0_IN; + + wire ALMOST_EMPTY_FIFO_OUT; + wire ALMOST_FULL_FIFO_OUT; + wire [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT_FIFO_OUT; + wire [C_DOUT_WIDTH-1:0] DOUT_FIFO_OUT; + wire EMPTY_FIFO_OUT; + wire FULL_FIFO_OUT; + wire OVERFLOW_FIFO_OUT; + wire PROG_EMPTY_FIFO_OUT; + wire PROG_FULL_FIFO_OUT; + wire VALID_FIFO_OUT; + wire [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT_FIFO_OUT; + wire UNDERFLOW_FIFO_OUT; + wire WR_ACK_FIFO_OUT; + wire [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT_FIFO_OUT; + + + //*************************************************************************** + // Internal Signals + // The core uses either the internal_ wires or the preload0_ wires depending + // on whether the core uses Preload0 or not. + // When using preload0, the internal signals connect the internal core to + // the preload logic, and the external core's interfaces are tied to the + // preload0 signals from the preload logic. + //*************************************************************************** + wire [C_DOUT_WIDTH-1:0] DATA_P0_OUT; + wire VALID_P0_OUT; + wire EMPTY_P0_OUT; + wire ALMOSTEMPTY_P0_OUT; + reg EMPTY_P0_OUT_Q; + reg ALMOSTEMPTY_P0_OUT_Q; + wire UNDERFLOW_P0_OUT; + wire RDEN_P0_OUT; + wire [C_DOUT_WIDTH-1:0] DATA_P0_IN; + wire EMPTY_P0_IN; + + assign SBITERR = 1'b0; + assign DBITERR = 1'b0; + +// choose the base FIFO implementation for simulation +generate +case (C_VERILOG_IMPL) +0 : begin : block1 + fifo_generator_v4_3_bhv_ver_ss + #( + C_COMMON_CLOCK, + C_COUNT_TYPE, + C_DATA_COUNT_WIDTH, + C_DEFAULT_VALUE, + C_DIN_WIDTH, + C_DOUT_RST_VAL, + C_DOUT_WIDTH, + C_ENABLE_RLOCS, + C_FAMILY,//Not allowed in Verilog model + C_HAS_ALMOST_EMPTY, + C_HAS_ALMOST_FULL, + C_HAS_BACKUP, + C_HAS_DATA_COUNT, + C_HAS_MEMINIT_FILE, + C_HAS_OVERFLOW, + C_HAS_RD_DATA_COUNT, + C_HAS_RD_RST, + C_HAS_RST, + C_HAS_SRST, + C_HAS_UNDERFLOW, + C_HAS_VALID, + C_HAS_WR_ACK, + C_HAS_WR_DATA_COUNT, + C_HAS_WR_RST, + C_IMPLEMENTATION_TYPE, + C_INIT_WR_PNTR_VAL, + C_MEMORY_TYPE, + C_MIF_FILE_NAME, + C_OPTIMIZATION_MODE, + C_OVERFLOW_LOW, + C_PRELOAD_LATENCY, + C_PRELOAD_REGS, + C_PROG_EMPTY_THRESH_ASSERT_VAL, + C_PROG_EMPTY_THRESH_NEGATE_VAL, + C_PROG_EMPTY_TYPE, + C_PROG_FULL_THRESH_ASSERT_VAL, + C_PROG_FULL_THRESH_NEGATE_VAL, + C_PROG_FULL_TYPE, + C_RD_DATA_COUNT_WIDTH, + C_RD_DEPTH, + C_RD_PNTR_WIDTH, + C_UNDERFLOW_LOW, + C_VALID_LOW, + C_WR_ACK_LOW, + C_WR_DATA_COUNT_WIDTH, + C_WR_DEPTH, + C_WR_PNTR_WIDTH, + C_WR_RESPONSE_LATENCY, + C_FULL_FLAGS_RST_VAL, + C_USE_EMBEDDED_REG + ) + gen_ss + ( + .CLK (CLK), + .RST (RST), + .SRST (SRST), + .DIN (DIN), + .WR_EN (WR_EN), + .RD_EN (RD_EN_FIFO_IN), + .PROG_EMPTY_THRESH (PROG_EMPTY_THRESH), + .PROG_EMPTY_THRESH_ASSERT (PROG_EMPTY_THRESH_ASSERT), + .PROG_EMPTY_THRESH_NEGATE (PROG_EMPTY_THRESH_NEGATE), + .PROG_FULL_THRESH (PROG_FULL_THRESH), + .PROG_FULL_THRESH_ASSERT (PROG_FULL_THRESH_ASSERT), + .PROG_FULL_THRESH_NEGATE (PROG_FULL_THRESH_NEGATE), + .DOUT (DOUT_FIFO_OUT), + .FULL (FULL_FIFO_OUT), + .ALMOST_FULL (ALMOST_FULL_FIFO_OUT), + .WR_ACK (WR_ACK_FIFO_OUT), + .OVERFLOW (OVERFLOW_FIFO_OUT), + .EMPTY (EMPTY_FIFO_OUT), + .ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT), + .VALID (VALID_FIFO_OUT), + .UNDERFLOW (UNDERFLOW_FIFO_OUT), + .DATA_COUNT (DATA_COUNT_FIFO_OUT), + .PROG_FULL (PROG_FULL_FIFO_OUT), + .PROG_EMPTY (PROG_EMPTY_FIFO_OUT) + ); +end +1 : begin : block1 + fifo_generator_v4_3_bhv_ver_as + #( + C_COMMON_CLOCK, + C_COUNT_TYPE, + C_DATA_COUNT_WIDTH, + C_DEFAULT_VALUE, + C_DIN_WIDTH, + C_DOUT_RST_VAL, + C_DOUT_WIDTH, + C_ENABLE_RLOCS, + C_FAMILY,//Not allowed in Verilog model + C_HAS_ALMOST_EMPTY, + C_HAS_ALMOST_FULL, + C_HAS_BACKUP, + C_HAS_DATA_COUNT, + C_HAS_MEMINIT_FILE, + C_HAS_OVERFLOW, + C_HAS_RD_DATA_COUNT, + C_HAS_RD_RST, + C_HAS_RST, + C_HAS_UNDERFLOW, + C_HAS_VALID, + C_HAS_WR_ACK, + C_HAS_WR_DATA_COUNT, + C_HAS_WR_RST, + C_IMPLEMENTATION_TYPE, + C_INIT_WR_PNTR_VAL, + C_MEMORY_TYPE, + C_MIF_FILE_NAME, + C_OPTIMIZATION_MODE, + C_OVERFLOW_LOW, + C_PRELOAD_LATENCY, + C_PRELOAD_REGS, + C_PROG_EMPTY_THRESH_ASSERT_VAL, + C_PROG_EMPTY_THRESH_NEGATE_VAL, + C_PROG_EMPTY_TYPE, + C_PROG_FULL_THRESH_ASSERT_VAL, + C_PROG_FULL_THRESH_NEGATE_VAL, + C_PROG_FULL_TYPE, + C_RD_DATA_COUNT_WIDTH, + C_RD_DEPTH, + C_RD_PNTR_WIDTH, + C_UNDERFLOW_LOW, + C_VALID_LOW, + C_WR_ACK_LOW, + C_WR_DATA_COUNT_WIDTH, + C_WR_DEPTH, + C_WR_PNTR_WIDTH, + C_WR_RESPONSE_LATENCY, + C_FULL_FLAGS_RST_VAL, + C_USE_FWFT_DATA_COUNT, + C_USE_EMBEDDED_REG + ) + gen_as + ( + .WR_CLK (WR_CLK), + .RD_CLK (RD_CLK), + .RST (RST), + .DIN (DIN), + .WR_EN (WR_EN), + .RD_EN (RD_EN_FIFO_IN), + .PROG_EMPTY_THRESH (PROG_EMPTY_THRESH), + .PROG_EMPTY_THRESH_ASSERT (PROG_EMPTY_THRESH_ASSERT), + .PROG_EMPTY_THRESH_NEGATE (PROG_EMPTY_THRESH_NEGATE), + .PROG_FULL_THRESH (PROG_FULL_THRESH), + .PROG_FULL_THRESH_ASSERT (PROG_FULL_THRESH_ASSERT), + .PROG_FULL_THRESH_NEGATE (PROG_FULL_THRESH_NEGATE), + .DOUT (DOUT_FIFO_OUT), + .FULL (FULL_FIFO_OUT), + .ALMOST_FULL (ALMOST_FULL_FIFO_OUT), + .WR_ACK (WR_ACK_FIFO_OUT), + .OVERFLOW (OVERFLOW_FIFO_OUT), + .EMPTY (EMPTY_FIFO_OUT), + .ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT), + .VALID (VALID_FIFO_OUT), + .UNDERFLOW (UNDERFLOW_FIFO_OUT), + .RD_DATA_COUNT (RD_DATA_COUNT_FIFO_OUT), + .WR_DATA_COUNT (WR_DATA_COUNT_FIFO_OUT), + .PROG_FULL (PROG_FULL_FIFO_OUT), + .PROG_EMPTY (PROG_EMPTY_FIFO_OUT) + ); +end + +default : begin : block1 + fifo_generator_v4_3_bhv_ver_as + #( + C_COMMON_CLOCK, + C_COUNT_TYPE, + C_DATA_COUNT_WIDTH, + C_DEFAULT_VALUE, + C_DIN_WIDTH, + C_DOUT_RST_VAL, + C_DOUT_WIDTH, + C_ENABLE_RLOCS, + C_FAMILY,//Not allowed in Verilog model + C_HAS_ALMOST_EMPTY, + C_HAS_ALMOST_FULL, + C_HAS_BACKUP, + C_HAS_DATA_COUNT, + C_HAS_MEMINIT_FILE, + C_HAS_OVERFLOW, + C_HAS_RD_DATA_COUNT, + C_HAS_RD_RST, + C_HAS_RST, + C_HAS_UNDERFLOW, + C_HAS_VALID, + C_HAS_WR_ACK, + C_HAS_WR_DATA_COUNT, + C_HAS_WR_RST, + C_IMPLEMENTATION_TYPE, + C_INIT_WR_PNTR_VAL, + C_MEMORY_TYPE, + C_MIF_FILE_NAME, + C_OPTIMIZATION_MODE, + C_OVERFLOW_LOW, + C_PRELOAD_LATENCY, + C_PRELOAD_REGS, + C_PROG_EMPTY_THRESH_ASSERT_VAL, + C_PROG_EMPTY_THRESH_NEGATE_VAL, + C_PROG_EMPTY_TYPE, + C_PROG_FULL_THRESH_ASSERT_VAL, + C_PROG_FULL_THRESH_NEGATE_VAL, + C_PROG_FULL_TYPE, + C_RD_DATA_COUNT_WIDTH, + C_RD_DEPTH, + C_RD_PNTR_WIDTH, + C_UNDERFLOW_LOW, + C_VALID_LOW, + C_WR_ACK_LOW, + C_WR_DATA_COUNT_WIDTH, + C_WR_DEPTH, + C_WR_PNTR_WIDTH, + C_WR_RESPONSE_LATENCY, + C_FULL_FLAGS_RST_VAL, + C_USE_FWFT_DATA_COUNT, + C_USE_EMBEDDED_REG + ) + gen_as + ( + .WR_CLK (WR_CLK), + .RD_CLK (RD_CLK), + .RST (RST), + .DIN (DIN), + .WR_EN (WR_EN), + .RD_EN (RD_EN_FIFO_IN), + .PROG_EMPTY_THRESH (PROG_EMPTY_THRESH), + .PROG_EMPTY_THRESH_ASSERT (PROG_EMPTY_THRESH_ASSERT), + .PROG_EMPTY_THRESH_NEGATE (PROG_EMPTY_THRESH_NEGATE), + .PROG_FULL_THRESH (PROG_FULL_THRESH), + .PROG_FULL_THRESH_ASSERT (PROG_FULL_THRESH_ASSERT), + .PROG_FULL_THRESH_NEGATE (PROG_FULL_THRESH_NEGATE), + .DOUT (DOUT_FIFO_OUT), + .FULL (FULL_FIFO_OUT), + .ALMOST_FULL (ALMOST_FULL_FIFO_OUT), + .WR_ACK (WR_ACK_FIFO_OUT), + .OVERFLOW (OVERFLOW_FIFO_OUT), + .EMPTY (EMPTY_FIFO_OUT), + .ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT), + .VALID (VALID_FIFO_OUT), + .UNDERFLOW (UNDERFLOW_FIFO_OUT), + .RD_DATA_COUNT (RD_DATA_COUNT_FIFO_OUT), + .WR_DATA_COUNT (WR_DATA_COUNT_FIFO_OUT), + .PROG_FULL (PROG_FULL_FIFO_OUT), + .PROG_EMPTY (PROG_EMPTY_FIFO_OUT) + ); +end + +endcase +endgenerate + + +//************************************************************************** +// Connect Internal Signals +// (Signals labeled internal_*) +// In the normal case, these signals tie directly to the FIFO's inputs and +// outputs. +// In the case of Preload Latency 0 or 1, there are intermediate +// signals between the internal FIFO and the preload logic. +//************************************************************************** + +generate +if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) + begin : block2 + +fifo_generator_v4_3_bhv_ver_preload0 + #( + C_DOUT_RST_VAL, + C_DOUT_WIDTH, + C_HAS_RST, + C_VALID_LOW, + C_UNDERFLOW_LOW + ) + fgpl0 +( + .RD_CLK (RD_CLK_P0_IN), + .RD_RST (RST_P0_IN), + .RD_EN (RD_EN_P0_IN), + .FIFOEMPTY (EMPTY_P0_IN), + .FIFODATA (DATA_P0_IN), + .USERDATA (DATA_P0_OUT), + .USERVALID (VALID_P0_OUT), + .USEREMPTY (EMPTY_P0_OUT), + .USERALMOSTEMPTY (ALMOSTEMPTY_P0_OUT), + .USERUNDERFLOW (UNDERFLOW_P0_OUT), + .RAMVALID (RAMVALID_P0_OUT), + .FIFORDEN (RDEN_P0_OUT) + ); + + assign RD_CLK_P0_IN = ((C_VERILOG_IMPL == 0) ? CLK : RD_CLK); + assign RST_P0_IN = RST; + assign RD_EN_P0_IN = RD_EN; + + assign RD_EN_FIFO_IN = RDEN_P0_OUT; + + assign DOUT = DATA_P0_OUT; + assign DATA_P0_IN = DOUT_FIFO_OUT; + assign VALID = VALID_P0_OUT ; + assign EMPTY = EMPTY_P0_OUT; + assign ALMOST_EMPTY = ALMOSTEMPTY_P0_OUT; + assign EMPTY_P0_IN = EMPTY_FIFO_OUT; + assign UNDERFLOW = UNDERFLOW_P0_OUT ; + + always @ (posedge RD_CLK or posedge RST) + begin + if (RST) + begin + EMPTY_P0_OUT_Q <= 1; + ALMOSTEMPTY_P0_OUT_Q <= 1; + end + else + begin + EMPTY_P0_OUT_Q <= EMPTY_P0_OUT; + ALMOSTEMPTY_P0_OUT_Q <= ALMOSTEMPTY_P0_OUT; + end + end + + end +else + begin : block2 + + assign RD_CLK_P0_IN = 0; + assign RST_P0_IN = 0; + assign RD_EN_P0_IN = 0; + + assign RD_EN_FIFO_IN = RD_EN; + + assign DOUT = DOUT_FIFO_OUT; + assign DATA_P0_IN = 0; + assign VALID = VALID_FIFO_OUT; + assign EMPTY = EMPTY_FIFO_OUT; + assign ALMOST_EMPTY = ALMOST_EMPTY_FIFO_OUT; + assign EMPTY_P0_IN = 0; + assign UNDERFLOW = UNDERFLOW_FIFO_OUT; + + end +endgenerate + + +//Connect Data Count Signals +generate +if (C_USE_FWFT_DATA_COUNT==1) begin : block3 + assign RD_DATA_COUNT = (EMPTY_P0_OUT_Q | RST) ? 0 : (ALMOSTEMPTY_P0_OUT_Q ? 1 : RD_DATA_COUNT_FIFO_OUT); +end +else begin : block3 + assign RD_DATA_COUNT = RD_DATA_COUNT_FIFO_OUT; +end +endgenerate + +generate +if (C_USE_FWFT_DATA_COUNT==1) begin : block4 + assign WR_DATA_COUNT = WR_DATA_COUNT_FIFO_OUT; +end +else begin : block4 + assign WR_DATA_COUNT = WR_DATA_COUNT_FIFO_OUT; +end +endgenerate + + + assign FULL = FULL_FIFO_OUT; + assign ALMOST_FULL = ALMOST_FULL_FIFO_OUT; + assign WR_ACK = WR_ACK_FIFO_OUT; + assign OVERFLOW = OVERFLOW_FIFO_OUT; + assign PROG_FULL = PROG_FULL_FIFO_OUT; + assign PROG_EMPTY = PROG_EMPTY_FIFO_OUT; + assign DATA_COUNT = DATA_COUNT_FIFO_OUT; + + + // if an asynchronous FIFO has been selected, display a message that the FIFO + // will not be cycle-accurate in simulation + initial begin + //if (C_IMPLEMENTATION_TYPE == 1) begin //bug in v3.1 + if (C_IMPLEMENTATION_TYPE == 2) begin //fixed in v3.2 (IP2_Im) + $display("Warning in %m at time %t: When using an asynchronous configuration for the FIFO Generator, the behavioral model is not cycle-accurate. You may wish to choose the structural simulation model instead of the behavioral model. This will ensure accurate behavior and latencies during simulation. You can enable this from CORE Generator by selecting Project -> Project Options -> Generation tab -> Structural Simulation. See the FIFO Generator User Guide for more information.", $time); + end else if (C_IMPLEMENTATION_TYPE == 3 || C_IMPLEMENTATION_TYPE == 4) begin + $display("Failure in %m at time %t: Use of Virtex-4 and Virtex-5 built-in FIFO configurations is currently not supported. Please use the structural simulation model. You can enable this from CORE Generator by selecting Project -> Project Options -> Generation tab -> Structural Simulation. See the FIFO Generator User Guide for more information.", $time); + $finish; + end + + end + +endmodule //fifo_generator_v4_3_bhv_ver + + + + + + +/******************************************************************************* + * Declaration of asynchronous FIFO Module + ******************************************************************************/ +module fifo_generator_v4_3_bhv_ver_as + ( + WR_CLK, RD_CLK, RST, DIN, WR_EN, RD_EN, + PROG_EMPTY_THRESH, PROG_EMPTY_THRESH_ASSERT, PROG_EMPTY_THRESH_NEGATE, + PROG_FULL_THRESH, PROG_FULL_THRESH_ASSERT, PROG_FULL_THRESH_NEGATE, + DOUT, FULL, ALMOST_FULL, WR_ACK, OVERFLOW, EMPTY, ALMOST_EMPTY, VALID, + UNDERFLOW, RD_DATA_COUNT, WR_DATA_COUNT, PROG_FULL, PROG_EMPTY + ); + + /***************************************************************************** + * Declare user parameters and their defaults + *****************************************************************************/ + parameter C_COMMON_CLOCK = 0; + parameter C_COUNT_TYPE = 0; + parameter C_DATA_COUNT_WIDTH = 2; + parameter C_DEFAULT_VALUE = ""; + parameter C_DIN_WIDTH = 8; + parameter C_DOUT_RST_VAL = ""; + parameter C_DOUT_WIDTH = 8; + parameter C_ENABLE_RLOCS = 0; + parameter C_FAMILY = "virtex2"; //Not allowed in Verilog model + parameter C_HAS_ALMOST_EMPTY = 0; + parameter C_HAS_ALMOST_FULL = 0; + parameter C_HAS_BACKUP = 0; + parameter C_HAS_DATA_COUNT = 0; + parameter C_HAS_MEMINIT_FILE = 0; + parameter C_HAS_OVERFLOW = 0; + parameter C_HAS_RD_DATA_COUNT = 0; + parameter C_HAS_RD_RST = 0; + parameter C_HAS_RST = 0; + parameter C_HAS_UNDERFLOW = 0; + parameter C_HAS_VALID = 0; + parameter C_HAS_WR_ACK = 0; + parameter C_HAS_WR_DATA_COUNT = 0; + parameter C_HAS_WR_RST = 0; + parameter C_IMPLEMENTATION_TYPE = 0; + parameter C_INIT_WR_PNTR_VAL = 0; + parameter C_MEMORY_TYPE = 1; + parameter C_MIF_FILE_NAME = ""; + parameter C_OPTIMIZATION_MODE = 0; + parameter C_OVERFLOW_LOW = 0; + parameter C_PRELOAD_LATENCY = 1; + parameter C_PRELOAD_REGS = 0; + parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0; + parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0; + parameter C_PROG_EMPTY_TYPE = 0; + parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0; + parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0; + parameter C_PROG_FULL_TYPE = 0; + parameter C_RD_DATA_COUNT_WIDTH = 2; + parameter C_RD_DEPTH = 256; + parameter C_RD_PNTR_WIDTH = 8; + parameter C_UNDERFLOW_LOW = 0; + parameter C_VALID_LOW = 0; + parameter C_WR_ACK_LOW = 0; + parameter C_WR_DATA_COUNT_WIDTH = 2; + parameter C_WR_DEPTH = 256; + parameter C_WR_PNTR_WIDTH = 8; + parameter C_WR_RESPONSE_LATENCY = 1; + parameter C_FULL_FLAGS_RST_VAL = 1; + parameter C_USE_FWFT_DATA_COUNT = 0; + parameter C_USE_EMBEDDED_REG = 0; + + /***************************************************************************** + * Declare Input and Output Ports + *****************************************************************************/ + input [C_DIN_WIDTH-1:0] DIN; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE; + input RD_CLK; + input RD_EN; + input RST; + input WR_CLK; + input WR_EN; + output ALMOST_EMPTY; + output ALMOST_FULL; + output [C_DOUT_WIDTH-1:0] DOUT; + output EMPTY; + output FULL; + output OVERFLOW; + output PROG_EMPTY; + output PROG_FULL; + output VALID; + output [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT; + output UNDERFLOW; + output WR_ACK; + output [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT; + + /******************************************************************************* + * Input and output register declarations + ******************************************************************************/ + /******************************************************************************* + * Parameters used as constants + ******************************************************************************/ + //When RST is present, set FULL reset value to '1'. + //If core has no RST, make sure FULL powers-on as '0'. + parameter C_DEPTH_RATIO_WR = + (C_WR_DEPTH>C_RD_DEPTH) ? (C_WR_DEPTH/C_RD_DEPTH) : 1; + parameter C_DEPTH_RATIO_RD = + (C_RD_DEPTH>C_WR_DEPTH) ? (C_RD_DEPTH/C_WR_DEPTH) : 1; + parameter C_FIFO_WR_DEPTH = + (C_COMMON_CLOCK) ? + C_WR_DEPTH : C_WR_DEPTH - 1; + parameter C_FIFO_RD_DEPTH = + (C_COMMON_CLOCK) ? + C_RD_DEPTH : C_RD_DEPTH - 1; + + + // EXTRA_WORDS = 2 * C_DEPTH_RATIO_WR / C_DEPTH_RATIO_RD + // WR_DEPTH : RD_DEPTH = 1:2 => EXTRA_WORDS = 1 + // WR_DEPTH : RD_DEPTH = 1:4 => EXTRA_WORDS = 1 (rounded to ceiling) + // WR_DEPTH : RD_DEPTH = 2:1 => EXTRA_WORDS = 4 + // WR_DEPTH : RD_DEPTH = 4:1 => EXTRA_WORDS = 8 + parameter EXTRA_WORDS = (C_DEPTH_RATIO_RD > 1)? 1:(2 * C_DEPTH_RATIO_WR); + // extra_words_dc = 2 * C_DEPTH_RATIO_WR / C_DEPTH_RATIO_RD + // C_DEPTH_RATIO_WR | C_DEPTH_RATIO_RD | C_PNTR_WIDTH | EXTRA_WORDS_DC + // -----------------|------------------|-----------------|--------------- + // 1 | 8 | C_RD_PNTR_WIDTH | 2 + // 1 | 4 | C_RD_PNTR_WIDTH | 2 + // 1 | 2 | C_RD_PNTR_WIDTH | 2 + // 1 | 1 | C_WR_PNTR_WIDTH | 2 + // 2 | 1 | C_WR_PNTR_WIDTH | 4 + // 4 | 1 | C_WR_PNTR_WIDTH | 8 + // 8 | 1 | C_WR_PNTR_WIDTH | 16 + parameter EXTRA_WORDS_DC = (C_DEPTH_RATIO_WR)? + 2:(2 * C_DEPTH_RATIO_WR/C_DEPTH_RATIO_RD); + + + //Memory which will be used to simulate a FIFO + reg [C_DIN_WIDTH-1:0] memory[C_WR_DEPTH-1:0]; + reg [31:0] num_wr_bits; + reg [31:0] num_rd_bits; + reg [31:0] next_num_wr_bits; + reg [31:0] next_num_rd_bits; + reg [31:0] wr_ptr; + reg [31:0] rd_ptr; + reg [31:0] wr_ptr_rdclk; + reg [31:0] wr_ptr_rdclk_next; + reg [31:0] rd_ptr_wrclk; + reg [31:0] rd_ptr_wrclk_next; + wire [31:0] num_read_words = num_rd_bits/C_DOUT_WIDTH; + wire [31:0] num_read_words_dc_i; + wire [31:0] num_read_words_dc = num_rd_bits/C_DOUT_WIDTH; + wire [31:0] num_read_words_fwft_dc = (num_rd_bits/C_DOUT_WIDTH+2); + wire [31:0] num_read_words_pe = + num_rd_bits/(C_DOUT_WIDTH/C_DEPTH_RATIO_WR); + wire [C_RD_DATA_COUNT_WIDTH-1:0] num_read_words_sized_i; + wire [C_RD_DATA_COUNT_WIDTH-1:0] num_read_words_sized + = num_read_words_dc_i[C_RD_PNTR_WIDTH-1 : C_RD_PNTR_WIDTH-C_RD_DATA_COUNT_WIDTH]; + wire [C_RD_DATA_COUNT_WIDTH-1:0] num_read_words_sized_fwft + = num_read_words_dc_i[C_RD_PNTR_WIDTH : C_RD_PNTR_WIDTH-C_RD_DATA_COUNT_WIDTH+1]; + wire [31:0] num_write_words = num_wr_bits/C_DIN_WIDTH; + wire [31:0] num_write_words_dc_i; + wire [31:0] num_write_words_dc = 1+(num_wr_bits-1)/C_DIN_WIDTH;//roof of num_wr_bits/C_DIN_WIDTH + wire [31:0] num_write_words_fwft_dc = + (num_wr_bits/C_DIN_WIDTH*C_DEPTH_RATIO_RD+2*C_DEPTH_RATIO_WR)/C_DEPTH_RATIO_RD; + wire [31:0] num_write_words_pf = + num_wr_bits/(C_DIN_WIDTH/C_DEPTH_RATIO_RD); + wire [C_WR_DATA_COUNT_WIDTH-1:0] num_write_words_sized_i; + wire [C_WR_DATA_COUNT_WIDTH-1:0] num_write_words_sized + = num_write_words_dc_i[C_WR_PNTR_WIDTH-1 : C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH]; + wire [C_WR_DATA_COUNT_WIDTH-1:0] num_write_words_sized_fwft + = num_write_words_dc_i[C_WR_PNTR_WIDTH : C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH+1]; + wire [31:0] reads_per_write = C_DIN_WIDTH/C_DOUT_WIDTH; + wire [31:0] log2_reads_per_write = log2_val(reads_per_write); + wire [31:0] writes_per_read = C_DOUT_WIDTH/C_DIN_WIDTH; + wire [31:0] log2_writes_per_read = log2_val(writes_per_read); + + /******************************************************************************* + * Internal Registers and wires + ******************************************************************************/ + wire wr_ack_i; + wire overflow_i; + wire underflow_i; + wire valid_i; + wire valid_out; + reg valid_d1; + /******************************************************************************* + * Internal registers and wires for internal reset logics + ******************************************************************************/ + reg rd_rst_asreg =0; + reg rd_rst_asreg_d1 =0; + reg rd_rst_asreg_d2 =0; + reg rd_rst_reg =0; + reg rd_rst_d1 =0; + reg wr_rst_asreg =0; + reg wr_rst_asreg_d1 =0; + reg wr_rst_asreg_d2 =0; + reg wr_rst_reg =0; + reg wr_rst_d1 =0; + wire rd_rst_comb; + wire rd_rst_i; + wire wr_rst_comb; + wire wr_rst_i; + + + + //Special ideal FIFO signals + reg [C_DOUT_WIDTH-1:0] ideal_dout; + wire [C_DOUT_WIDTH-1:0] ideal_dout_out; + reg [C_DOUT_WIDTH-1:0] ideal_dout_d1; + reg ideal_wr_ack; + reg ideal_valid; + reg ideal_overflow; + reg ideal_underflow; + reg ideal_full; + reg ideal_empty; + reg ideal_almost_full; + reg ideal_almost_empty; + reg ideal_prog_full; + reg ideal_prog_empty; + + //MSBs of the counts + reg [C_WR_DATA_COUNT_WIDTH-1 : 0] ideal_wr_count; + reg [C_RD_DATA_COUNT_WIDTH-1 : 0] ideal_rd_count; + + //user specified value for reseting the size of the fifo + reg [C_DOUT_WIDTH-1:0] dout_reset_val; + + //temporary registers for WR_RESPONSE_LATENCY feature + + integer tmp_wr_listsize; + integer tmp_rd_listsize; + + //Signal for registered version of prog full and empty + reg prog_full_d; + reg prog_empty_d; + + //Threshold values for Programmable Flags + integer prog_empty_actual_thresh_assert; + integer prog_empty_actual_thresh_negate; + integer prog_full_actual_thresh_assert; + integer prog_full_actual_thresh_negate; + + + /**************************************************************************** + * Function Declarations + ***************************************************************************/ + + task write_fifo; + begin + memory[wr_ptr] <= DIN; + if (wr_ptr == 0) begin + wr_ptr <= C_WR_DEPTH - 1; + end else begin + wr_ptr <= wr_ptr - 1; + end + end + endtask // write_fifo + + task read_fifo; + integer i; + reg [C_DOUT_WIDTH-1:0] tmp_dout; + reg [C_DIN_WIDTH-1:0] memory_read; + reg [31:0] tmp_rd_ptr; + reg [31:0] rd_ptr_high; + reg [31:0] rd_ptr_low; + begin + // output is wider than input + if (reads_per_write == 0) begin + tmp_dout = 0; + tmp_rd_ptr = (rd_ptr << log2_writes_per_read)+(writes_per_read-1); + for (i = writes_per_read - 1; i >= 0; i = i - 1) begin + tmp_dout = tmp_dout << C_DIN_WIDTH; + tmp_dout = tmp_dout | memory[tmp_rd_ptr]; + if (tmp_rd_ptr == 0) begin + tmp_rd_ptr = C_WR_DEPTH - 1; + end else begin + tmp_rd_ptr = tmp_rd_ptr - 1; + end + end + + // output is symmetric + end else if (reads_per_write == 1) begin + tmp_dout = memory[rd_ptr]; + + // input is wider than output + end else begin + rd_ptr_high = rd_ptr >> log2_reads_per_write; + rd_ptr_low = rd_ptr & (reads_per_write - 1); + memory_read = memory[rd_ptr_high]; + tmp_dout = memory_read >> (rd_ptr_low*C_DOUT_WIDTH); + end + ideal_dout <= tmp_dout; + if (rd_ptr == 0) begin + rd_ptr <= C_RD_DEPTH - 1; + end else begin + rd_ptr <= rd_ptr - 1; + end + end + endtask + + /**************************************************************************** + * log2_val + * Returns the 'log2' value for the input value for the supported ratios + ***************************************************************************/ + function [31:0] log2_val; + input [31:0] binary_val; + + begin + if (binary_val == 8) begin + log2_val = 3; + end else if (binary_val == 4) begin + log2_val = 2; + end else begin + log2_val = 1; + end + end + endfunction + + /************************************************************************* + * hexstr_conv + * Converts a string of type hex to a binary value (for C_DOUT_RST_VAL) + ***********************************************************************/ + function [C_DOUT_WIDTH-1:0] hexstr_conv; + input [(C_DOUT_WIDTH*8)-1:0] def_data; + + integer index,i,j; + reg [3:0] bin; + + begin + index = 0; + hexstr_conv = 'b0; + for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 ) + begin + case (def_data[7:0]) + 8'b00000000 : + begin + bin = 4'b0000; + i = -1; + end + 8'b00110000 : bin = 4'b0000; + 8'b00110001 : bin = 4'b0001; + 8'b00110010 : bin = 4'b0010; + 8'b00110011 : bin = 4'b0011; + 8'b00110100 : bin = 4'b0100; + 8'b00110101 : bin = 4'b0101; + 8'b00110110 : bin = 4'b0110; + 8'b00110111 : bin = 4'b0111; + 8'b00111000 : bin = 4'b1000; + 8'b00111001 : bin = 4'b1001; + 8'b01000001 : bin = 4'b1010; + 8'b01000010 : bin = 4'b1011; + 8'b01000011 : bin = 4'b1100; + 8'b01000100 : bin = 4'b1101; + 8'b01000101 : bin = 4'b1110; + 8'b01000110 : bin = 4'b1111; + 8'b01100001 : bin = 4'b1010; + 8'b01100010 : bin = 4'b1011; + 8'b01100011 : bin = 4'b1100; + 8'b01100100 : bin = 4'b1101; + 8'b01100101 : bin = 4'b1110; + 8'b01100110 : bin = 4'b1111; + default : + begin + bin = 4'bx; + end + endcase + for( j=0; j<4; j=j+1) + begin + if ((index*4)+j < C_DOUT_WIDTH) + begin + hexstr_conv[(index*4)+j] = bin[j]; + end + end + index = index + 1; + def_data = def_data >> 8; + end + end + endfunction + + /************************************************************************* + * Initialize Signals for clean power-on simulation + *************************************************************************/ + initial + begin + num_wr_bits = 0; + num_rd_bits = 0; + next_num_wr_bits = 0; + next_num_rd_bits = 0; + rd_ptr = C_RD_DEPTH - 1; + wr_ptr = C_WR_DEPTH - 1; + rd_ptr_wrclk = rd_ptr; + wr_ptr_rdclk = wr_ptr; + dout_reset_val = hexstr_conv(C_DOUT_RST_VAL); + ideal_dout = dout_reset_val; + ideal_wr_ack = 1'b0; + ideal_valid = 1'b0; + ideal_overflow = 1'b0; + ideal_underflow = 1'b0; + //Modified the start-up value of FULL to '0' in v3.2 (IP2_Im) + //ideal_full = C_FULL_RESET_VAL; //was in v3.1 + ideal_full = 1'b0; //v3.2 + ideal_empty = 1'b1; + //Modified the start-up value of ALMOST_FULL to '0' in v3.2 (IP2_Im) + //ideal_almost_full = C_ALMOST_FULL_RESET_VAL; //was in v3.1 + ideal_almost_full = 1'b0; //v3.2 + ideal_almost_empty = 1'b1; + ideal_wr_count = 0; + ideal_rd_count = 0; + //Modified the start-up value of PROG_FULL to '0' in v3.2 (IP2_Im) + //ideal_prog_full = C_PROG_FULL_RESET_VAL; //was in v3.1 + ideal_prog_full = 1'b0; //v3.2 + ideal_prog_empty = 1'b1; + //Modified the start-up value of PROG_FULL to '0' in v3.2 (IP2_Im) + //Therefore, prog_full_d has to start-up at '0' too + //prog_full_d = C_PROG_FULL_RESET_VAL; //was in v3.1 + prog_full_d = 1'b0; //v3.2 + prog_empty_d = 1'b1; + end + + + + /************************************************************************* + * Assign Internal ideal signals to output ports + *************************************************************************/ + assign ideal_dout_out= (C_PRELOAD_LATENCY==2 && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))? + ideal_dout_d1: ideal_dout; + assign DOUT = ideal_dout_out; + assign FULL = ideal_full; + assign EMPTY = ideal_empty; + assign ALMOST_FULL = ideal_almost_full; + assign ALMOST_EMPTY = ideal_almost_empty; + assign num_write_words_sized_i=C_USE_FWFT_DATA_COUNT? + num_write_words_sized_fwft:num_write_words_sized; + assign num_read_words_sized_i=C_USE_FWFT_DATA_COUNT? + num_read_words_sized_fwft:num_read_words_sized; + assign num_write_words_dc_i = C_USE_FWFT_DATA_COUNT? + num_write_words_fwft_dc: num_write_words_dc; + assign num_read_words_dc_i = C_USE_FWFT_DATA_COUNT? + num_read_words_fwft_dc: num_read_words_dc; + assign WR_DATA_COUNT = ideal_wr_count; + assign RD_DATA_COUNT = ideal_rd_count; + assign PROG_FULL = ideal_prog_full; + assign PROG_EMPTY = ideal_prog_empty; + + //Handshaking signals can be active low, depending on _LOW parameters + assign valid_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & ~EMPTY) : ideal_valid; + assign VALID = valid_out ? !C_VALID_LOW : C_VALID_LOW; + assign valid_out = (C_PRELOAD_LATENCY==2 && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))? + valid_d1: valid_i; + assign underflow_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & EMPTY) : ideal_underflow; + assign UNDERFLOW = underflow_i ? !C_UNDERFLOW_LOW : C_UNDERFLOW_LOW; + + assign WR_ACK = wr_ack_i ? !C_WR_ACK_LOW : C_WR_ACK_LOW; + assign wr_ack_i = (C_WR_RESPONSE_LATENCY==1) ? ideal_wr_ack : + (WR_EN & !FULL); + assign OVERFLOW = overflow_i ? !C_OVERFLOW_LOW : C_OVERFLOW_LOW; + assign overflow_i = (C_WR_RESPONSE_LATENCY==1) ? ideal_overflow : + (WR_EN & FULL); + + /******************************************************************************* + * Internal reset logics + ******************************************************************************/ + assign wr_rst_comb = !wr_rst_asreg_d2 && wr_rst_asreg; + assign rd_rst_comb = !rd_rst_asreg_d2 && rd_rst_asreg; + assign wr_rst_i = C_HAS_RST ? wr_rst_reg : 0; + assign rd_rst_i = C_HAS_RST ? rd_rst_reg : 0; + + + always @(posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i == 1'b1) begin + valid_d1 <= 1'b0; + end else begin + valid_d1 <= valid_i; + end + end + always @(posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i == 1'b1) begin + ideal_dout_d1 <= dout_reset_val; + end else begin + ideal_dout_d1 <= ideal_dout; + end + end + + always @(posedge WR_CLK or posedge RST) begin + if (RST == 1'b1) begin + wr_rst_asreg <= 1'b1; + end else begin + if (wr_rst_asreg_d1 == 1'b1) begin + wr_rst_asreg <= 1'b0; + end else begin + wr_rst_asreg <= wr_rst_asreg; + end + end + end + + always @(posedge WR_CLK) begin + wr_rst_asreg_d1 <= wr_rst_asreg; + wr_rst_asreg_d2 <= wr_rst_asreg_d1; + end + + always @(posedge WR_CLK or posedge wr_rst_comb) begin + if (wr_rst_comb == 1'b1) begin + wr_rst_reg <= 1'b1; + end else begin + wr_rst_reg <= 1'b0; + end + end + + always @(posedge WR_CLK or posedge wr_rst_i) begin + if (wr_rst_i == 1'b1) begin + wr_rst_d1 <= 1'b1; + end else begin + wr_rst_d1 <= wr_rst_i; + end + end + always @(posedge RD_CLK or posedge RST) begin + if (RST == 1'b1) begin + rd_rst_asreg <= 1'b1; + end else begin + if (rd_rst_asreg_d1 == 1'b1) begin + rd_rst_asreg <= 1'b0; + end else begin + rd_rst_asreg <= rd_rst_asreg; + end + end + end + + always @(posedge RD_CLK) begin + rd_rst_asreg_d1 <= rd_rst_asreg; + rd_rst_asreg_d2 <= rd_rst_asreg_d1; + end + + always @(posedge RD_CLK or posedge rd_rst_comb) begin + if (rd_rst_comb == 1'b1) begin + rd_rst_reg <= 1'b1; + end else begin + rd_rst_reg <= 1'b0; + end + end + + //Generate overflow and underflow flags seperately + //because they don't support async rst + always @(posedge WR_CLK) begin + ideal_overflow <= WR_EN & ideal_full; + end + always @(posedge RD_CLK) begin + ideal_underflow <= ideal_empty & RD_EN; + end + + /******************************************************************************* + * Write and Read Logics + ******************************************************************************/ + always @(posedge WR_CLK or posedge wr_rst_i) begin : gen_fifo_w + + /****** Reset fifo (case 1)***************************************/ + if (wr_rst_i == 1'b1) begin + num_wr_bits <= 0; + next_num_wr_bits <= 0; + wr_ptr <= C_WR_DEPTH - 1; + rd_ptr_wrclk <= C_RD_DEPTH - 1; + ideal_wr_ack <= 0; + ideal_full <= C_FULL_FLAGS_RST_VAL; + ideal_almost_full <= C_FULL_FLAGS_RST_VAL; + ideal_wr_count <= 0; + + ideal_prog_full <= C_FULL_FLAGS_RST_VAL; + prog_full_d <= C_FULL_FLAGS_RST_VAL; + + end else begin //wr_rst_i==0 + + //Determine the current number of words in the FIFO + tmp_wr_listsize = (C_DEPTH_RATIO_RD > 1) ? num_wr_bits/C_DOUT_WIDTH : + num_wr_bits/C_DIN_WIDTH; + rd_ptr_wrclk_next = rd_ptr; + if (rd_ptr_wrclk < rd_ptr_wrclk_next) begin + next_num_wr_bits = num_wr_bits - + C_DOUT_WIDTH*(rd_ptr_wrclk + C_RD_DEPTH + - rd_ptr_wrclk_next); + end else begin + next_num_wr_bits = num_wr_bits - + C_DOUT_WIDTH*(rd_ptr_wrclk - rd_ptr_wrclk_next); + end + + //If this is a write, handle the write by adding the value + // to the linked list, and updating all outputs appropriately + if (WR_EN == 1'b1) begin + if (ideal_full == 1'b1) begin + + //If the FIFO is full, do NOT perform the write, + // update flags accordingly + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD + >= C_FIFO_WR_DEPTH) begin + //write unsuccessful - do not change contents + + //Do not acknowledge the write + ideal_wr_ack <= 0; + //Reminder that FIFO is still full + ideal_full <= 1'b1; + ideal_almost_full <= 1'b1; + + ideal_wr_count <= num_write_words_sized_i; + + //If the FIFO is one from full, but reporting full + end else if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD == + C_FIFO_WR_DEPTH-1) begin + //No change to FIFO + + //Write not successful + ideal_wr_ack <= 0; + //With DEPTH-1 words in the FIFO, it is almost_full + ideal_full <= 1'b0; + ideal_almost_full <= 1'b1; + + ideal_wr_count <= num_write_words_sized_i; + + + //If the FIFO is completely empty, but it is + // reporting FULL for some reason (like reset) + end else if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD <= + C_FIFO_WR_DEPTH-2) begin + //No change to FIFO + + //Write not successful + ideal_wr_ack <= 0; + //FIFO is really not close to full, so change flag status. + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + ideal_wr_count <= num_write_words_sized_i; + end //(tmp_wr_listsize == 0) + + end else begin + + //If the FIFO is full, do NOT perform the write, + // update flags accordingly + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD >= + C_FIFO_WR_DEPTH) begin + //write unsuccessful - do not change contents + + //Do not acknowledge the write + ideal_wr_ack <= 0; + //Reminder that FIFO is still full + ideal_full <= 1'b1; + ideal_almost_full <= 1'b1; + + ideal_wr_count <= num_write_words_sized_i; + + //If the FIFO is one from full + end else if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD == + C_FIFO_WR_DEPTH-1) begin + //Add value on DIN port to FIFO + write_fifo; + next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH; + + //Write successful, so issue acknowledge + // and no error + ideal_wr_ack <= 1; + //This write is CAUSING the FIFO to go full + ideal_full <= 1'b1; + ideal_almost_full <= 1'b1; + + ideal_wr_count <= num_write_words_sized_i; + + //If the FIFO is 2 from full + end else if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD == + C_FIFO_WR_DEPTH-2) begin + //Add value on DIN port to FIFO + write_fifo; + next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH; + //Write successful, so issue acknowledge + // and no error + ideal_wr_ack <= 1; + //Still 2 from full + ideal_full <= 1'b0; + //2 from full, and writing, so set almost_full + ideal_almost_full <= 1'b1; + + ideal_wr_count <= num_write_words_sized_i; + + //If the FIFO is not close to being full + end else if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD < + C_FIFO_WR_DEPTH-2) begin + //Add value on DIN port to FIFO + write_fifo; + next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH; + //Write successful, so issue acknowledge + // and no error + ideal_wr_ack <= 1; + //Not even close to full. + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + ideal_wr_count <= num_write_words_sized_i; + + end + + end + + end else begin //(WR_EN == 1'b1) + + //If user did not attempt a write, then do not + // give ack or err + ideal_wr_ack <= 0; + + //Implied statements: + //ideal_empty <= ideal_empty; + //ideal_almost_empty <= ideal_almost_empty; + + //Check for full + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD >= C_FIFO_WR_DEPTH) + ideal_full <= 1'b1; + else + ideal_full <= 1'b0; + + //Check for almost_full + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD >= C_FIFO_WR_DEPTH-1) + ideal_almost_full <= 1'b1; + else + ideal_almost_full <= 1'b0; + + ideal_wr_count <= num_write_words_sized_i; + end + + /********************************************************* + * Programmable FULL flags + *********************************************************/ + //Single Programmable Full Constant Threshold + if (C_PROG_FULL_TYPE==1) begin + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + prog_full_actual_thresh_assert = C_PROG_FULL_THRESH_ASSERT_VAL-EXTRA_WORDS; + prog_full_actual_thresh_negate = C_PROG_FULL_THRESH_ASSERT_VAL-EXTRA_WORDS; + end else begin + prog_full_actual_thresh_assert = C_PROG_FULL_THRESH_ASSERT_VAL; + prog_full_actual_thresh_negate = C_PROG_FULL_THRESH_ASSERT_VAL; + end + + //Two Programmable Full Constant Thresholds + end else if (C_PROG_FULL_TYPE==2) begin + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + prog_full_actual_thresh_assert = C_PROG_FULL_THRESH_ASSERT_VAL-EXTRA_WORDS; + prog_full_actual_thresh_negate = C_PROG_FULL_THRESH_NEGATE_VAL-EXTRA_WORDS; + end else begin + prog_full_actual_thresh_assert = C_PROG_FULL_THRESH_ASSERT_VAL; + prog_full_actual_thresh_negate = C_PROG_FULL_THRESH_NEGATE_VAL; + end + + //Single Programmable Full Threshold Input + end else if (C_PROG_FULL_TYPE==3) begin + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + prog_full_actual_thresh_assert = PROG_FULL_THRESH-EXTRA_WORDS; + prog_full_actual_thresh_negate = PROG_FULL_THRESH-EXTRA_WORDS; + end else begin + prog_full_actual_thresh_assert = PROG_FULL_THRESH; + prog_full_actual_thresh_negate = PROG_FULL_THRESH; + end + + //Two Programmable Full Threshold Inputs + end else if (C_PROG_FULL_TYPE==4) begin + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + prog_full_actual_thresh_assert = PROG_FULL_THRESH_ASSERT-EXTRA_WORDS; + prog_full_actual_thresh_negate = PROG_FULL_THRESH_NEGATE-EXTRA_WORDS; + end else begin + prog_full_actual_thresh_assert = PROG_FULL_THRESH_ASSERT; + prog_full_actual_thresh_negate = PROG_FULL_THRESH_NEGATE; + end + end //C_PROG_FULL_TYPE + + if (num_write_words_pf==0) begin + prog_full_d <= 1'b0; + end else begin + if (((1+(num_write_words_pf-1)/C_DEPTH_RATIO_RD) + == prog_full_actual_thresh_assert-1) && WR_EN) begin + prog_full_d <= 1'b1; + end else if ((1+(num_write_words_pf-1)/C_DEPTH_RATIO_RD) + >= prog_full_actual_thresh_assert) begin + prog_full_d <= 1'b1; + end else if ((1+(num_write_words_pf-1)/C_DEPTH_RATIO_RD) + < prog_full_actual_thresh_negate) begin + prog_full_d <= 1'b0; + end + end + + if (wr_rst_d1==1 && wr_rst_i==0) begin + ideal_prog_full <= 0; + end else begin + ideal_prog_full <= prog_full_d; + end + num_wr_bits <= next_num_wr_bits; + rd_ptr_wrclk <= rd_ptr; + + end //wr_rst_i==0 + end // write always + + always @(posedge RD_CLK or posedge rd_rst_i) begin : gen_fifo_r + + /****** Reset fifo (case 1)***************************************/ + if (rd_rst_i) begin + num_rd_bits <= 0; + next_num_rd_bits <= 0; + rd_ptr <= C_RD_DEPTH -1; + wr_ptr_rdclk <= C_WR_DEPTH -1; + ideal_dout <= dout_reset_val; + ideal_valid <= 1'b0; + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + ideal_rd_count <= 0; + + ideal_prog_empty <= 1'b1; + prog_empty_d <= 1; + + + end else begin //rd_rst_i==0 + + //Determine the current number of words in the FIFO + tmp_rd_listsize = (C_DEPTH_RATIO_WR > 1) ? num_rd_bits/C_DIN_WIDTH : + num_rd_bits/C_DOUT_WIDTH; + wr_ptr_rdclk_next = wr_ptr; + + if (wr_ptr_rdclk < wr_ptr_rdclk_next) begin + next_num_rd_bits = num_rd_bits + + C_DIN_WIDTH*(wr_ptr_rdclk +C_WR_DEPTH + - wr_ptr_rdclk_next); + end else begin + next_num_rd_bits = num_rd_bits + + C_DIN_WIDTH*(wr_ptr_rdclk - wr_ptr_rdclk_next); + end + + /*****************************************************************/ + // Read Operation - Read Latency 1 + /*****************************************************************/ + if (C_PRELOAD_LATENCY==1 || C_PRELOAD_LATENCY==2) begin + + if (RD_EN == 1'b1) begin + + if (ideal_empty == 1'b1) begin + + //If the FIFO is completely empty, and is reporting empty + if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Reminder that FIFO is still empty + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + end // if (tmp_rd_listsize <= 0) + + //If the FIFO is one from empty, but it is reporting empty + else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Note that FIFO is no longer empty, but is almost empty (has one word left) + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + end // if (tmp_rd_listsize == 1) + + //If the FIFO is two from empty, and is reporting empty + else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Fifo has two words, so is neither empty or almost empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + end // if (tmp_rd_listsize == 2) + + //If the FIFO is not close to empty, but is reporting that it is + // Treat the FIFO as empty this time, but unset EMPTY flags. + if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && (tmp_rd_listsize/C_DEPTH_RATIO_WR<C_FIFO_RD_DEPTH)) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Note that the FIFO is No Longer Empty or Almost Empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1)) + end // else: if(ideal_empty == 1'b1) + + else //if (ideal_empty == 1'b0) + begin + + //If the FIFO is completely full, and we are successfully reading from it + if (tmp_rd_listsize/C_DEPTH_RATIO_WR >= C_FIFO_RD_DEPTH) + begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= 1'b1; + //Not close to empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + end // if (tmp_rd_listsize == C_FIFO_RD_DEPTH) + + //If the FIFO is not close to being empty + else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && (tmp_rd_listsize/C_DEPTH_RATIO_WR<=C_FIFO_RD_DEPTH)) + begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= 1'b1; + //Not close to empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1)) + + //If the FIFO is two from empty + else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) + begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= 1'b1; + //Fifo is not yet empty. It is going almost_empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + end // if (tmp_rd_listsize == 2) + + //If the FIFO is one from empty + else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR == 1)) + begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= 1'b1; + //Note that FIFO is GOING empty + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + end // if (tmp_rd_listsize == 1) + + + //If the FIFO is completely empty + else if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Reminder that FIFO is still empty + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + end // if (tmp_rd_listsize <= 0) + + end // if (ideal_empty == 1'b0) + + end //(RD_EN == 1'b1) + + else //if (RD_EN == 1'b0) + begin + //If user did not attempt a read, do not give an ack or err + ideal_valid <= 1'b0; + + //Check for empty + if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) + ideal_empty <= 1'b1; + else + ideal_empty <= 1'b0; + + //Check for almost_empty + if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 1) + ideal_almost_empty <= 1'b1; + else + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + end // else: !if(RD_EN == 1'b1) + + /*****************************************************************/ + // Read Operation - Read Latency 0 + /*****************************************************************/ + end else if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + if (RD_EN == 1'b1) begin + + if (ideal_empty == 1'b1) begin + + //If the FIFO is completely empty, and is reporting empty + if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Reminder that FIFO is still empty + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + //If the FIFO is one from empty, but it is reporting empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Note that FIFO is no longer empty, but is almost empty (has one word left) + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + //If the FIFO is two from empty, and is reporting empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Fifo has two words, so is neither empty or almost empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + //If the FIFO is not close to empty, but is reporting that it is + // Treat the FIFO as empty this time, but unset EMPTY flags. + end else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && + (tmp_rd_listsize/C_DEPTH_RATIO_WR<C_FIFO_RD_DEPTH)) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Note that the FIFO is No Longer Empty or Almost Empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1)) + + end else begin + + //If the FIFO is completely full, and we are successfully reading from it + if (tmp_rd_listsize/C_DEPTH_RATIO_WR >= C_FIFO_RD_DEPTH) begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= 1'b1; + //Not close to empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + //If the FIFO is not close to being empty + end else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && + (tmp_rd_listsize/C_DEPTH_RATIO_WR<=C_FIFO_RD_DEPTH)) begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= 1'b1; + //Not close to empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + //If the FIFO is two from empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= 1'b1; + //Fifo is not yet empty. It is going almost_empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + //If the FIFO is one from empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1) begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= 1'b1; + //Note that FIFO is GOING empty + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + //If the FIFO is completely empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= 1'b0; + //Reminder that FIFO is still empty + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + ideal_rd_count <= num_read_words_sized_i; + + end // if (tmp_rd_listsize <= 0) + + end // if (ideal_empty == 1'b0) + + end else begin//(RD_EN == 1'b0) + + + //If user did not attempt a read, do not give an ack or err + ideal_valid <= 1'b0; + + //Check for empty + if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) + ideal_empty <= 1'b1; + else + ideal_empty <= 1'b0; + + //Check for almost_empty + if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 1) + ideal_almost_empty <= 1'b1; + else + ideal_almost_empty <= 1'b0; + + ideal_rd_count <= num_read_words_sized_i; + + end // else: !if(RD_EN == 1'b1) + end //if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) + + + /********************************************************* + * Programmable EMPTY flags + *********************************************************/ + //Determine the Assert and Negate thresholds for Programmable Empty + // (Subtract 2 read-sized words when using Preload 0) + + //Single Programmable Empty Constant Threshold + if (C_PROG_EMPTY_TYPE==1) begin + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + prog_empty_actual_thresh_assert = C_PROG_EMPTY_THRESH_ASSERT_VAL-2; + prog_empty_actual_thresh_negate = C_PROG_EMPTY_THRESH_ASSERT_VAL-2; + end + else begin + prog_empty_actual_thresh_assert = C_PROG_EMPTY_THRESH_ASSERT_VAL; + prog_empty_actual_thresh_negate = C_PROG_EMPTY_THRESH_ASSERT_VAL; + end + + //Two Programmable Empty Constant Thresholds + end else if (C_PROG_EMPTY_TYPE==2) begin + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + prog_empty_actual_thresh_assert = C_PROG_EMPTY_THRESH_ASSERT_VAL-2; + prog_empty_actual_thresh_negate = C_PROG_EMPTY_THRESH_NEGATE_VAL-2; + end + else begin + prog_empty_actual_thresh_assert = C_PROG_EMPTY_THRESH_ASSERT_VAL; + prog_empty_actual_thresh_negate = C_PROG_EMPTY_THRESH_NEGATE_VAL; + end + + //Single Programmable Empty Constant Threshold + end else if (C_PROG_EMPTY_TYPE==3) begin + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + prog_empty_actual_thresh_assert = PROG_EMPTY_THRESH-2; + prog_empty_actual_thresh_negate = PROG_EMPTY_THRESH-2; + end + else begin + prog_empty_actual_thresh_assert = PROG_EMPTY_THRESH; + prog_empty_actual_thresh_negate = PROG_EMPTY_THRESH; + + end + //Two Programmable Empty Constant Thresholds + end else if (C_PROG_EMPTY_TYPE==4) begin + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + prog_empty_actual_thresh_assert = PROG_EMPTY_THRESH_ASSERT-2; + prog_empty_actual_thresh_negate = PROG_EMPTY_THRESH_NEGATE-2; + end + else begin + prog_empty_actual_thresh_assert = PROG_EMPTY_THRESH_ASSERT; + prog_empty_actual_thresh_negate = PROG_EMPTY_THRESH_NEGATE; + end + end + + if ((num_read_words_pe/C_DEPTH_RATIO_WR == prog_empty_actual_thresh_assert+1) + && RD_EN) begin + prog_empty_d <= 1'b1; + end else if (num_read_words_pe/C_DEPTH_RATIO_WR + <= prog_empty_actual_thresh_assert) begin + prog_empty_d <= 1'b1; + end else if (num_read_words_pe/C_DEPTH_RATIO_WR + > prog_empty_actual_thresh_negate) begin + prog_empty_d <= 1'b0; + end + + + ideal_prog_empty <= prog_empty_d; + num_rd_bits <= next_num_rd_bits; + wr_ptr_rdclk <= wr_ptr; + end //rd_rst_i==0 + end //always + +endmodule // fifo_generator_v4_3_bhv_ver_as + + +/******************************************************************************* + * Declaration of top-level module + ******************************************************************************/ +module fifo_generator_v4_3_bhv_ver_ss + ( + CLK, RST, SRST, DIN, WR_EN, RD_EN, + PROG_FULL_THRESH, PROG_FULL_THRESH_ASSERT, PROG_FULL_THRESH_NEGATE, + PROG_EMPTY_THRESH, PROG_EMPTY_THRESH_ASSERT, PROG_EMPTY_THRESH_NEGATE, + DOUT, FULL, ALMOST_FULL, WR_ACK, OVERFLOW, EMPTY, + ALMOST_EMPTY, VALID, UNDERFLOW, DATA_COUNT, + PROG_FULL, PROG_EMPTY + ); + +/****************************************************************************** + * Declare user parameters and their defaults + *****************************************************************************/ + parameter C_COMMON_CLOCK = 0; + parameter C_COUNT_TYPE = 0; + parameter C_DATA_COUNT_WIDTH = 2; + parameter C_DEFAULT_VALUE = ""; + parameter C_DIN_WIDTH = 8; + parameter C_DOUT_RST_VAL = ""; + parameter C_DOUT_WIDTH = 8; + parameter C_ENABLE_RLOCS = 0; + parameter C_FAMILY = "virtex2"; //Not allowed in Verilog model + parameter C_HAS_ALMOST_EMPTY = 0; + parameter C_HAS_ALMOST_FULL = 0; + parameter C_HAS_BACKUP = 0; + parameter C_HAS_DATA_COUNT = 0; + parameter C_HAS_MEMINIT_FILE = 0; + parameter C_HAS_OVERFLOW = 0; + parameter C_HAS_RD_DATA_COUNT = 0; + parameter C_HAS_RD_RST = 0; + parameter C_HAS_RST = 0; + parameter C_HAS_SRST = 0; + parameter C_HAS_UNDERFLOW = 0; + parameter C_HAS_VALID = 0; + parameter C_HAS_WR_ACK = 0; + parameter C_HAS_WR_DATA_COUNT = 0; + parameter C_HAS_WR_RST = 0; + parameter C_IMPLEMENTATION_TYPE = 0; + parameter C_INIT_WR_PNTR_VAL = 0; + parameter C_MEMORY_TYPE = 1; + parameter C_MIF_FILE_NAME = ""; + parameter C_OPTIMIZATION_MODE = 0; + parameter C_OVERFLOW_LOW = 0; + parameter C_PRELOAD_LATENCY = 1; + parameter C_PRELOAD_REGS = 0; + parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0; + parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0; + parameter C_PROG_EMPTY_TYPE = 0; + parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0; + parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0; + parameter C_PROG_FULL_TYPE = 0; + parameter C_RD_DATA_COUNT_WIDTH = 2; + parameter C_RD_DEPTH = 256; + parameter C_RD_PNTR_WIDTH = 8; + parameter C_UNDERFLOW_LOW = 0; + parameter C_VALID_LOW = 0; + parameter C_WR_ACK_LOW = 0; + parameter C_WR_DATA_COUNT_WIDTH = 2; + parameter C_WR_DEPTH = 256; + parameter C_WR_PNTR_WIDTH = 8; + parameter C_WR_RESPONSE_LATENCY = 1; + parameter C_FULL_FLAGS_RST_VAL = 1; + parameter C_USE_EMBEDDED_REG = 0; + + +/****************************************************************************** + * Declare Input and Output Ports + *****************************************************************************/ + input CLK; + input [C_DIN_WIDTH-1:0] DIN; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT; + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT; + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE; + input RD_EN; + input RST; + input SRST; + input WR_EN; + output ALMOST_EMPTY; + output ALMOST_FULL; + output [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT; + output [C_DOUT_WIDTH-1:0] DOUT; + output EMPTY; + output FULL; + output OVERFLOW; + output PROG_EMPTY; + output PROG_FULL; + output VALID; + output UNDERFLOW; + output WR_ACK; + +/******************************************************************************* + * Input and output register declarations + ******************************************************************************/ +/******************************************************************************* + * Parameters used as constants + ******************************************************************************/ + //When RST is present, set FULL reset value to '1'. + //If core has no RST, make sure FULL powers-on as '0'. + //The reset value assignments for FULL, ALMOST_FULL, and PROG_FULL are not + //changed for v3.2(IP2_Im). When the core has Sync Reset, C_HAS_SRST=1 and C_HAS_RST=0. + // Therefore, during SRST, all the FULL flags reset to 0. + parameter C_HAS_FAST_FIFO = 0; + parameter C_FIFO_WR_DEPTH = (C_COMMON_CLOCK) ? C_WR_DEPTH : C_WR_DEPTH - 1; + parameter C_FIFO_RD_DEPTH = (C_COMMON_CLOCK) ? C_RD_DEPTH : C_RD_DEPTH - 1; + + /**************************************************************************** + * Internal Registers and wires + ***************************************************************************/ + wire wr_ack_i; + wire overflow_i; + wire underflow_i; + wire valid_i; + wire valid_out; + reg valid_d1; + wire srst_i; + /******************************************************************************* + * Internal registers and wires for internal reset logics + ******************************************************************************/ + reg rst_asreg =0; + reg rst_asreg_d1 =0; + reg rst_asreg_d2 =0; + reg rst_reg =0; + reg rst_d1 =0; + wire rst_comb; + wire rst_i; + + + //Memory which will be used to simulate a FIFO + reg [C_DIN_WIDTH-1:0] memory[C_WR_DEPTH-1:0]; + reg [31:0] num_bits; + reg [31:0] wr_ptr; + reg [31:0] rd_ptr; + wire [31:0] num_read_words = num_bits/C_DOUT_WIDTH; + reg [31:0] num_read_words_q; + wire [31:0] num_write_words = num_bits/C_DIN_WIDTH; + reg [31:0] num_write_words_q; + //Removed power_on_timer in v3.2 (IP2_Im). For all reset types (Async, Sync, or no reset), the power-on values of the flags in the core are modified so that the core is ready to use from the very first clock cycle. + //reg [3:0] power_on_timer; + + //Special ideal FIFO signals + reg [C_DOUT_WIDTH-1:0] ideal_dout; + reg [C_DOUT_WIDTH-1:0] ideal_dout_d1; + wire [C_DOUT_WIDTH-1:0] ideal_dout_out; + reg ideal_wr_ack; + reg ideal_valid; + reg ideal_overflow; + reg ideal_underflow; + reg ideal_full; + reg ideal_empty; + reg ideal_almost_full; + reg ideal_almost_empty; + reg ideal_prog_full; + reg ideal_prog_empty; + + + //MSBs of the counts + wire [C_DATA_COUNT_WIDTH-1:0] ideal_d_count; + + //user specified value for reseting the size of the fifo + reg [C_DOUT_WIDTH-1:0] dout_reset_val; + + + //temporary registers for WR_RESPONSE_LATENCY feature + reg ideal_wr_ack_q; + reg ideal_overflow_q; + + reg prog_full_d; + reg prog_empty_d; + + //Delayed version of RST + reg rst_q; + reg rst_qq; + + /**************************************************************************** + * Function Declarations + ***************************************************************************/ + task write_fifo; + begin + memory[wr_ptr] <= DIN; + if (wr_ptr == 0) begin + wr_ptr <= C_WR_DEPTH - 1; + end else begin + wr_ptr <= wr_ptr - 1; + end + end + endtask // write_fifo + + task read_fifo; + begin + ideal_dout <= memory[rd_ptr]; + if (rd_ptr == 0) begin + rd_ptr <= C_RD_DEPTH - 1; + end else begin + rd_ptr <= rd_ptr - 1; + end + end + endtask + + /**************************************************************************** + * log2_val + * Returns the 'log2' value for the input value for the supported ratios + ***************************************************************************/ + function [31:0] log2_val; + input [31:0] binary_val; + + begin + if (binary_val == 8) begin + log2_val = 3; + end else if (binary_val == 4) begin + log2_val = 2; + end else begin + log2_val = 1; + end + end + endfunction + + /**************************************************************************** + * hexstr_conv + * Converts a string of type hex to a binary value (for C_DOUT_RST_VAL) + ***************************************************************************/ + function [C_DOUT_WIDTH-1:0] hexstr_conv; + input [(C_DOUT_WIDTH*8)-1:0] def_data; + + integer index,i,j; + reg [3:0] bin; + + begin + index = 0; + hexstr_conv = 'b0; + for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 ) + begin + case (def_data[7:0]) + 8'b00000000 : + begin + bin = 4'b0000; + i = -1; + end + 8'b00110000 : bin = 4'b0000; + 8'b00110001 : bin = 4'b0001; + 8'b00110010 : bin = 4'b0010; + 8'b00110011 : bin = 4'b0011; + 8'b00110100 : bin = 4'b0100; + 8'b00110101 : bin = 4'b0101; + 8'b00110110 : bin = 4'b0110; + 8'b00110111 : bin = 4'b0111; + 8'b00111000 : bin = 4'b1000; + 8'b00111001 : bin = 4'b1001; + 8'b01000001 : bin = 4'b1010; + 8'b01000010 : bin = 4'b1011; + 8'b01000011 : bin = 4'b1100; + 8'b01000100 : bin = 4'b1101; + 8'b01000101 : bin = 4'b1110; + 8'b01000110 : bin = 4'b1111; + 8'b01100001 : bin = 4'b1010; + 8'b01100010 : bin = 4'b1011; + 8'b01100011 : bin = 4'b1100; + 8'b01100100 : bin = 4'b1101; + 8'b01100101 : bin = 4'b1110; + 8'b01100110 : bin = 4'b1111; + default : + begin + bin = 4'bx; + end + endcase + for( j=0; j<4; j=j+1) + begin + if ((index*4)+j < C_DOUT_WIDTH) + begin + hexstr_conv[(index*4)+j] = bin[j]; + end + end + index = index + 1; + def_data = def_data >> 8; + end + end + endfunction + + /***************************************************************************** + * Initialize Signals + ****************************************************************************/ + initial begin + num_bits = 0; + num_read_words_q = 0; + num_write_words_q = 0; + rd_ptr = C_RD_DEPTH -1; + wr_ptr = C_WR_DEPTH -1; + dout_reset_val = hexstr_conv(C_DOUT_RST_VAL); + ideal_dout = dout_reset_val; + ideal_wr_ack = 1'b0; + ideal_valid = 1'b0; + valid_d1 = 1'b0; + ideal_overflow = 1'b0; + ideal_underflow = 1'b0; + //Modified the start-up value of FULL to '0' in v3.2 (IP2_Im) + //ideal_full = C_FULL_RESET_VAL; //was in v3.1 + ideal_full = 1'b0; //v3.2 + ideal_empty = 1'b1; + //Modified the start-up value of ALMOST_FULL to '0' in v3.2 (IP2_Im) + //ideal_almost_full = C_ALMOST_FULL_RESET_VAL; //was in v3.1 + ideal_almost_full = 1'b0; + ideal_almost_empty = 1'b1; + //Modified the start-up value of PROG_FULL to '0' in v3.2 (IP2_Im) + //ideal_prog_full = C_PROG_FULL_RESET_VAL; //was in v3.1 + ideal_prog_full = 1'b0; //v3.2 + ideal_prog_empty = 1'b1; + + //Modified the start-up value of PROG_FULL to '0' in v3.2 (IP2_Im) + //Therefore, prog_full_d is also changed + //prog_full_d = C_PROG_FULL_RESET_VAL; //was in v3.1 + prog_full_d = 1'b0; //v3.2 + prog_empty_d = 1'b1; + + //Removed in v3.2 + //power_on_timer = C_HAS_RST ? 4'h3 : 4'h0; + + //Added these initial values in v3.2 to make it consistent with the synchronization flop stages in the core. + rst_q = 1'b0; + rst_qq = 1'b0; + end + + + /***************************************************************************** + * Assign Internal ideal signals to output ports + ****************************************************************************/ + assign ideal_dout_out= (C_USE_EMBEDDED_REG==1 && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))? + ideal_dout_d1: ideal_dout; + assign DOUT = ideal_dout_out; + //was in v3.1 + //assign FULL = (power_on_timer) ? C_FULL_RESET_VAL : ideal_full; + //v3.2 + assign FULL = ideal_full; + + assign EMPTY = ideal_empty; + //was in v3.1 + //assign ALMOST_FULL = (power_on_timer) ? C_ALMOST_FULL_RESET_VAL : ideal_almost_full; + //v3.2 + assign ALMOST_FULL = ideal_almost_full; + + assign ALMOST_EMPTY = ideal_almost_empty; + + assign ideal_d_count = num_read_words[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_DATA_COUNT_WIDTH]; + assign DATA_COUNT = ideal_d_count; + + //was in v3.1 + //assign PROG_FULL = (power_on_timer) ? C_PROG_FULL_RESET_VAL : ideal_prog_full; + //v3.2 + assign PROG_FULL = ideal_prog_full; + + assign PROG_EMPTY = ideal_prog_empty; + + //Handshaking signals can be active low, depending on _LOW parameters + assign valid_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & ~EMPTY) : ideal_valid; + assign VALID = valid_out ? !C_VALID_LOW : C_VALID_LOW; + assign valid_out = (C_PRELOAD_LATENCY==2 && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))? + valid_d1: valid_i; + assign underflow_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & EMPTY) : ideal_underflow; + assign UNDERFLOW = underflow_i ? !C_UNDERFLOW_LOW : C_UNDERFLOW_LOW; + + assign WR_ACK = wr_ack_i ? !C_WR_ACK_LOW : C_WR_ACK_LOW; + assign wr_ack_i = (C_WR_RESPONSE_LATENCY==2) ? ideal_wr_ack_q : + (C_WR_RESPONSE_LATENCY==1) ? ideal_wr_ack : + (WR_EN & !FULL); + assign OVERFLOW = overflow_i ? !C_OVERFLOW_LOW : C_OVERFLOW_LOW; + assign overflow_i = (C_WR_RESPONSE_LATENCY==2) ? ideal_overflow_q : + (C_WR_RESPONSE_LATENCY==1) ? ideal_overflow : + (WR_EN & FULL); + + assign srst_i = C_HAS_SRST ? SRST : 0; + + /******************************************************************************* + * Internal reset logics + ******************************************************************************/ + assign rst_comb = !rst_asreg_d2 && rst_asreg; + assign rst_i = C_HAS_RST ? rst_reg : 0; + + always @(posedge CLK or posedge rst_i) begin + if (rst_i == 1'b1) begin + valid_d1 <= 1'b0; + end else begin + if (srst_i) begin + valid_d1 <= 1'b0; + end else begin + valid_d1 <= valid_i; + end + end + end + always @(posedge CLK or posedge rst_i) begin + if (rst_i == 1'b1) begin + ideal_dout_d1 <= dout_reset_val; + end else begin + if (srst_i) begin + ideal_dout_d1 <= dout_reset_val; + end else begin + ideal_dout_d1 <= ideal_dout; + end + end + end + + always @(posedge CLK or posedge RST) begin + if (RST == 1'b1) begin + rst_asreg <= 1'b1; + end else begin + if (rst_asreg_d1 == 1'b1) begin + rst_asreg <= 1'b0; + end else begin + rst_asreg <= rst_asreg; + end + end + end + + always @(posedge CLK) begin + rst_asreg_d1 <= rst_asreg; + rst_asreg_d2 <= rst_asreg_d1; + end + + always @(posedge CLK or posedge rst_comb) begin + if (rst_comb == 1'b1) begin + rst_reg <= 1'b1; + end else begin + rst_reg <= 1'b0; + end + end + + + /******************************************************************************* + * Write and Read Logics + ******************************************************************************/ + + always @(posedge CLK or posedge rst_i) + begin : gen_wr_ack_resp + + //Register reset + rst_q <= rst_i; + rst_qq <= rst_q; + + //Register output signals to achieve desired WR_RESPONSE latency + if (C_WR_RESPONSE_LATENCY == 2) begin + if (rst_i == 1) begin + ideal_wr_ack_q <= 0; + ideal_overflow_q <= 0; + end else begin + ideal_wr_ack_q <= ideal_wr_ack; + ideal_overflow_q <= ideal_overflow; + end + end + + //Removed in v3.2 + /* + if (rst_i == 1) begin + power_on_timer <= 0; + end else if (power_on_timer > 0) begin + power_on_timer <= power_on_timer -1; + end else begin + power_on_timer <= 0; + end + */ + end // block: gen_wr_ack_resp + + // block memory has a synchronous reset + always @(posedge CLK) begin : gen_fifo_blkmemdout + //Changed the latency of during async reset to '1' instead of '2' to make it consistent with the core. + //if (rst_i || rst_q || rst_qq) begin //was in v3.1 + if (rst_i || rst_q || srst_i) begin //v3.2 + /******Initialize Read Domain Signals************************************/ + if (C_MEMORY_TYPE == 1) begin + ideal_dout <= dout_reset_val; + end + //v3.2 + //end else begin + //if (C_MEMORY_TYPE == 1 && power_on_timer >= 2) begin //was in v3.1 + // if (C_MEMORY_TYPE == 1) begin //v3.2 + // ideal_dout <= dout_reset_val; + // end + end + end + + always @(posedge CLK or posedge rst_i) begin : gen_fifo + + /****** Reset fifo - Asynchronous Reset*************************************/ + //Changed the latency of during async reset to '1' instead of '2' to make it consistent with the core. + //if (rst_i || rst_q || rst_qq) begin //was in v3.1 + //if (rst_i || rst_q) begin //v3.2 + if (rst_i ) begin //v3.2 + /******Initialize Generic FIFO constructs********************************/ + num_bits <= 0; + wr_ptr <= C_WR_DEPTH - 1; + rd_ptr <= C_RD_DEPTH - 1; + num_read_words_q <= 0; + num_write_words_q <= 0; + + + /******Initialize Write Domain Signals***********************************/ + ideal_wr_ack <= 0; + ideal_full <= C_FULL_FLAGS_RST_VAL; + ideal_almost_full <= C_FULL_FLAGS_RST_VAL; + + /******Initialize Read Domain Signals************************************/ + if (C_MEMORY_TYPE != 1) begin + ideal_dout <= dout_reset_val; + end + ideal_valid <= 1'b0; + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + end else begin + if (srst_i) begin + // SRST is available only for Sync BRAM and Sync DRAM. Not for SSHFT. + if (C_MEMORY_TYPE == 1 || C_MEMORY_TYPE == 2) begin + /******Initialize Generic FIFO constructs********************************/ + num_bits <= 0; + wr_ptr <= C_WR_DEPTH - 1; + rd_ptr <= C_RD_DEPTH - 1; + num_read_words_q <= 0; + num_write_words_q <= 0; + + /******Initialize Write Domain Signals***********************************/ + ideal_wr_ack <= 0; + ideal_full <= 0; //'0' + ideal_almost_full <= 0; //'0' + + /******Initialize Read Domain Signals************************************/ + //Reset DOUT of Sync DRAM. Sync BRAM DOUT was reset in the above always block. + if (C_MEMORY_TYPE == 2) begin + ideal_dout <= dout_reset_val; + end + ideal_valid <= 1'b0; + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + end + + end else begin //normal operating conditions + /**********************************************************************/ + // Synchronous FIFO Condition #1 : Writing and not reading + /**********************************************************************/ + if (WR_EN & ~RD_EN) begin + + /*********************************/ + //If the FIFO is full, do NOT perform the write, + // update flags accordingly + /*********************************/ + if (num_write_words >= C_FIFO_WR_DEPTH) begin + ideal_wr_ack <= 0; + + //still full + ideal_full <= 1'b1; + ideal_almost_full <= 1'b1; + + //write unsuccessful - do not change contents + + // no read attempted + ideal_valid <= 1'b0; + + //Not near empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + + /*********************************/ + //If the FIFO is reporting FULL + // (Startup condition) + /*********************************/ + end else if ((num_write_words < C_FIFO_WR_DEPTH) && (ideal_full == 1'b1)) begin + ideal_wr_ack <= 0; + + //still full + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //write unsuccessful - do not change contents + + // no read attempted + ideal_valid <= 1'b0; + + //FIFO EMPTY in this state can not be determined + //ideal_empty <= 1'b0; + //ideal_almost_empty <= 1'b0; + + + /*********************************/ + //If the FIFO is one from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-1) begin + //good write + ideal_wr_ack <= 1; + + //FIFO is one from FULL and going FULL + ideal_full <= 1'b1; + ideal_almost_full <= 1'b1; + + //Add input data + write_fifo; + + // no read attempted + ideal_valid <= 1'b0; + + //Not near empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + num_bits <= num_bits + C_DIN_WIDTH; + + /*********************************/ + //If the FIFO is 2 from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-2) begin + //good write + ideal_wr_ack <= 1; + + //2 from full, and writing, so set almost_full + ideal_full <= 1'b0; + ideal_almost_full <= 1'b1; + + //Add input data + write_fifo; + + //no read attempted + ideal_valid <= 1'b0; + + //Not near empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + num_bits <= num_bits + C_DIN_WIDTH; + + /*********************************/ + //If the FIFO is ALMOST EMPTY + /*********************************/ + end else if (num_read_words == 1) begin + //good write + ideal_wr_ack <= 1; + + //Not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Add input data + write_fifo; + + // no read attempted + ideal_valid <= 1'b0; + + //Leaving ALMOST_EMPTY + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + num_bits <= num_bits + C_DIN_WIDTH; + + /*********************************/ + //If the FIFO is EMPTY + /*********************************/ + end else if (num_read_words == 0) begin + // good write + ideal_wr_ack <= 1; + + //Not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Add input data + write_fifo; + + // no read attempted + ideal_valid <= 1'b0; + + //Leaving EMPTY (still ALMOST_EMPTY) + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + num_bits <= num_bits + C_DIN_WIDTH; + + /*********************************/ + //If the FIFO is not near EMPTY or FULL + /*********************************/ + end else begin + // good write + ideal_wr_ack <= 1; + + //Not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Add input data + write_fifo; + + // no read attempted + ideal_valid <= 1'b0; + + //Not near EMPTY + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + num_bits <= num_bits + C_DIN_WIDTH; + + end // average case + + + /**********************************************************************/ + // Synchronous FIFO Condition #2 : Reading and not writing + /**********************************************************************/ + end else if (~WR_EN & RD_EN) begin + + /*********************************/ + //If the FIFO is EMPTY + /*********************************/ + if ((num_read_words == 0) || (ideal_empty == 1'b1)) begin + //no write attemped + ideal_wr_ack <= 0; + + //FIFO is not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Read will fail + ideal_valid <= 1'b0; + + //FIFO is still empty + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + //No read + + /*********************************/ + //If the FIFO is ALMOST EMPTY + /*********************************/ + end else if (num_read_words == 1) begin + //no write attempted + ideal_wr_ack <= 0; + + //FIFO is not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Read successful + ideal_valid <= 1'b1; + + //This read will make FIFO go empty + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + //Get the data from the FIFO + read_fifo; + num_bits <= num_bits - C_DIN_WIDTH; + + + /*********************************/ + //If the FIFO is 2 from EMPTY + /*********************************/ + end else if (num_read_words == 2) begin + + //no write attempted + ideal_wr_ack <= 0; + + //FIFO is not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Read successful + ideal_valid <= 1'b1; + + //FIFO is going ALMOST_EMPTY + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + //Get the data from the FIFO + read_fifo; + num_bits <= num_bits - C_DOUT_WIDTH; + + + + /*********************************/ + //If the FIFO is one from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-1) begin + + //no write attempted + ideal_wr_ack <= 0; + + //FIFO is leaving ALMOST FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Read successful + ideal_valid <= 1'b1; + + //Not near empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= num_bits - C_DOUT_WIDTH; + + + /*********************************/ + // FIFO is FULL + /*********************************/ + end else if (num_write_words >= C_FIFO_WR_DEPTH) + begin + //no write attempted + ideal_wr_ack <= 0; + + //FIFO is leaving FULL, but is still ALMOST_FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b1; + + //Read successful + ideal_valid <= 1'b1; + + //Not near empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= num_bits - C_DOUT_WIDTH; + + /*********************************/ + //If the FIFO is not near EMPTY or FULL + /*********************************/ + end else begin + //no write attemped + ideal_wr_ack <= 0; + + //Not near empty + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Read successful + ideal_valid <= 1'b1; + + //Not near empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= num_bits - C_DOUT_WIDTH; + + + end // average read + + + /**********************************************************************/ + // Synchronous FIFO Condition #3 : Reading and writing + /**********************************************************************/ + end else if (WR_EN & RD_EN) begin + + /*********************************/ + // FIFO is FULL + /*********************************/ + if (num_write_words >= C_FIFO_WR_DEPTH) begin + + ideal_wr_ack <= 0; + + //Read will be successful, so FIFO will leave FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b1; + + //Read successful + ideal_valid <= 1'b1; + + //Not near empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= num_bits - C_DOUT_WIDTH; + + + /*********************************/ + // FIFO is reporting FULL, but it is empty + // (This is a special case, when coming out of RST + /*********************************/ + end else if ((num_write_words == 0) && (ideal_full == 1'b1)) begin + + ideal_wr_ack <= 0; + + //Read will be successful, so FIFO will leave FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //Read unsuccessful + ideal_valid <= 1'b0; + + //Report empty condition + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + //Do not read from empty FIFO + // Read from the FIFO + + + /*********************************/ + //If the FIFO is one from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-1) begin + + //Write successful + ideal_wr_ack <= 1; + + //FIFO will remain ALMOST_FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b1; + + // put the data into the FIFO + write_fifo; + + //Read successful + ideal_valid <= 1'b1; + + //Not near empty + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= num_bits + C_DIN_WIDTH - C_DOUT_WIDTH; + + /*********************************/ + //If the FIFO is ALMOST EMPTY + /*********************************/ + end else if (num_read_words == 1) begin + + //Write successful + ideal_wr_ack <= 1; + + // Not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + // put the data into the FIFO + write_fifo; + + //Read successful + ideal_valid <= 1'b1; + + //FIFO will stay ALMOST_EMPTY + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + //Read from the FIFO + read_fifo; + num_bits <= num_bits + C_DIN_WIDTH - C_DOUT_WIDTH; + + + /*********************************/ + //If the FIFO is EMPTY + /*********************************/ + end else if (num_read_words == 0) begin + + //Write successful + ideal_wr_ack <= 1; + + // Not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + // put the data into the FIFO + write_fifo; + + //Read will fail + ideal_valid <= 1'b0; + + //FIFO will leave EMPTY + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + // No read + num_bits <= num_bits + C_DIN_WIDTH; + + + /*********************************/ + //If the FIFO is not near EMPTY or FULL + /*********************************/ + end else begin + + //Write successful + ideal_wr_ack <= 1; + + // Not near FULL + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + // put the data into the FIFO + write_fifo; + + //Read successful + ideal_valid <= 1'b1; + + // Not near EMPTY + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= num_bits + C_DIN_WIDTH - C_DOUT_WIDTH; + + end // average case + + /**********************************************************************/ + // Synchronous FIFO Condition #4 : Not reading or writing + /*** + *******************************************************************/ + end else begin + + /*********************************/ + // FIFO is FULL + /*********************************/ + if (num_write_words >= C_FIFO_WR_DEPTH) begin + + //No write + ideal_wr_ack <= 0; + ideal_full <= 1'b1; + ideal_almost_full <= 1'b1; + + //No read + ideal_valid <= 1'b0; + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //No change to memory + + /*********************************/ + //If the FIFO is one from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-1) begin + + //No write + ideal_wr_ack <= 0; + ideal_full <= 1'b0; + ideal_almost_full <= 1'b1; + + //No read + ideal_valid <= 1'b0; + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //No change to memory + + /*********************************/ + //If the FIFO is ALMOST EMPTY + /*********************************/ + end else if (num_read_words == 1) begin + //No write + ideal_wr_ack <= 0; + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //No read + ideal_valid <= 1'b0; + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b1; + + //No change to memory + + end // almost empty + + + /*********************************/ + //If the FIFO is EMPTY + /*********************************/ + else if (num_read_words == 0) + begin + //No write + ideal_wr_ack <= 0; + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //No read + ideal_valid <= 1'b0; + ideal_empty <= 1'b1; + ideal_almost_empty <= 1'b1; + + //No change to memory + + /*********************************/ + //If the FIFO is not near EMPTY or FULL + /*********************************/ + end else begin + + //No write + ideal_wr_ack <= 0; + ideal_full <= 1'b0; + ideal_almost_full <= 1'b0; + + //No read + ideal_valid <= 1'b0; + ideal_empty <= 1'b0; + ideal_almost_empty <= 1'b0; + + //No change to memory + + end // average case + + end // neither reading or writing + + num_read_words_q <= num_read_words; + num_write_words_q <= num_write_words; + + end //normal operating conditions + end + + end // block: gen_fifo + + //Generate overflow and underflow flags seperately + //because they don't support async rst + always @(posedge CLK) begin + ideal_overflow <= WR_EN & ideal_full; + ideal_underflow <= ideal_empty & RD_EN; + end + + always @(posedge CLK or posedge rst_i) begin : gen_fifo_p + + /****** Reset fifo - Async Reset****************************************/ + //The latency of de-assertion of the flags is reduced by 1 to be consistent with the core. + //if (rst_i || rst_q) begin //was in v3.1 + if (rst_i) begin //v3.2 + ideal_prog_full <= C_FULL_FLAGS_RST_VAL; + ideal_prog_empty <= 1'b1; + prog_full_d <= C_FULL_FLAGS_RST_VAL; + prog_empty_d <= 1'b1; + + end else begin + if (srst_i) begin + //SRST is available only for Sync BRAM and Sync DRAM. Not for SSHFT. + if (C_MEMORY_TYPE == 1 || C_MEMORY_TYPE == 2) begin + ideal_prog_full <= 1'b0; + ideal_prog_empty <= 1'b1; + prog_full_d <= 1'b0; + prog_empty_d <= 1'b1; + end + end else begin + + /***************************************************************** + * Programmable FULL flags + ****************************************************************/ + //Single constant threshold + if (C_PROG_FULL_TYPE == 1) begin + if ((num_write_words >= C_PROG_FULL_THRESH_ASSERT_VAL-1) + && WR_EN && !RD_EN) begin + prog_full_d <= 1'b1; + end else if (((num_write_words == C_PROG_FULL_THRESH_ASSERT_VAL) + && RD_EN && !WR_EN) || (rst_q && !rst_i)) begin //v3.2 + prog_full_d <= 1'b0; + end + + //Dual constant thresholds + end else if (C_PROG_FULL_TYPE == 2) begin + if ((num_write_words == C_PROG_FULL_THRESH_ASSERT_VAL-1) + && WR_EN && !RD_EN) begin + prog_full_d <= 1'b1; + end else if ((num_write_words == C_PROG_FULL_THRESH_NEGATE_VAL) + && RD_EN && !WR_EN) begin + prog_full_d <= 1'b0; + end + + //Single input threshold + end else if (C_PROG_FULL_TYPE == 3) begin + if ((num_write_words == PROG_FULL_THRESH-1) + && WR_EN && !RD_EN) begin + prog_full_d <= 1'b1; + end else if ((num_write_words == PROG_FULL_THRESH) + && !WR_EN && RD_EN) begin + prog_full_d <= 1'b0; + end else if (num_write_words >= PROG_FULL_THRESH) begin + prog_full_d <= 1'b1; + end else if (num_write_words < PROG_FULL_THRESH) begin + prog_full_d <= 1'b0; + end + + //Dual input thresholds + end else begin + if ((num_write_words == PROG_FULL_THRESH_ASSERT-1) + && WR_EN && !RD_EN) begin + prog_full_d <= 1'b1; + end else if ((num_write_words == PROG_FULL_THRESH_NEGATE) + && !WR_EN && RD_EN)begin + prog_full_d <= 1'b0; + end else if (num_write_words >= PROG_FULL_THRESH_ASSERT) begin + prog_full_d <= 1'b1; + end else if (num_write_words < PROG_FULL_THRESH_NEGATE) begin + prog_full_d <= 1'b0; + end + end + + /***************************************************************** + * Programmable EMPTY flags + ****************************************************************/ + //Single constant threshold + if (C_PROG_EMPTY_TYPE == 1) begin + if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL+1) + && RD_EN && !WR_EN) begin + prog_empty_d <= 1'b1; + end else if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL) + && WR_EN && !RD_EN) begin + prog_empty_d <= 1'b0; + end + //Dual constant thresholds + end else if (C_PROG_EMPTY_TYPE == 2) begin + if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL+1) + && RD_EN && !WR_EN) begin + prog_empty_d <= 1'b1; + end else if ((num_read_words == C_PROG_EMPTY_THRESH_NEGATE_VAL) + && !RD_EN && WR_EN) begin + prog_empty_d <= 1'b0; + end + + //Single input threshold + end else if (C_PROG_EMPTY_TYPE == 3) begin + if ((num_read_words == PROG_EMPTY_THRESH+1) + && RD_EN && !WR_EN) begin + prog_empty_d <= 1'b1; + end else if ((num_read_words == PROG_EMPTY_THRESH) + && !RD_EN && WR_EN) begin + prog_empty_d <= 1'b0; + end else if (num_read_words <= PROG_EMPTY_THRESH) begin + prog_empty_d <= 1'b1; + end else if (num_read_words > PROG_EMPTY_THRESH)begin + prog_empty_d <= 1'b0; + end + + //Dual input thresholds + end else begin + if (num_read_words <= PROG_EMPTY_THRESH_ASSERT) begin + prog_empty_d <= 1'b1; + end else if ((num_read_words == PROG_EMPTY_THRESH_ASSERT+1) + && RD_EN && !WR_EN) begin + prog_empty_d <= 1'b1; + end else if (num_read_words > PROG_EMPTY_THRESH_NEGATE)begin + prog_empty_d <= 1'b0; + end else if ((num_read_words == PROG_EMPTY_THRESH_NEGATE) + && !RD_EN && WR_EN) begin + prog_empty_d <= 1'b0; + end + end + + ideal_prog_empty <= prog_empty_d; + if (rst_q && !rst_i) begin + ideal_prog_full <= 1'b0; + end else begin + ideal_prog_full <= prog_full_d; + end + + end //if (srst_i) begin + end //if (rst_i) begin + end //always @(posedge CLK or posedge rst_i) begin : gen_fifo_p +endmodule // fifo_generator_v4_3_bhv_ver_ss + + +module fifo_generator_v4_3_bhv_ver_preload0 + ( + RD_CLK, + RD_RST, + RD_EN, + FIFOEMPTY, + FIFODATA, + USERDATA, + USERVALID, + USERUNDERFLOW, + USEREMPTY, + USERALMOSTEMPTY, + RAMVALID, + FIFORDEN + ); + + + parameter C_DOUT_RST_VAL = ""; + parameter C_DOUT_WIDTH = 8; + parameter C_HAS_RST = 0; + parameter C_USERVALID_LOW = 0; + parameter C_USERUNDERFLOW_LOW = 0; + + + input RD_CLK; + input RD_RST; + input RD_EN; + input FIFOEMPTY; + input [C_DOUT_WIDTH-1:0] FIFODATA; + output [C_DOUT_WIDTH-1:0] USERDATA; + output USERVALID; + output USERUNDERFLOW; + output USEREMPTY; + output USERALMOSTEMPTY; + output RAMVALID; + output FIFORDEN; + + wire RD_CLK; + wire RD_RST; + wire RD_EN; + wire FIFOEMPTY; + wire [C_DOUT_WIDTH-1:0] FIFODATA; + reg [C_DOUT_WIDTH-1:0] USERDATA; + wire USERVALID; + wire USERUNDERFLOW; + wire USEREMPTY; + wire USERALMOSTEMPTY; + wire RAMVALID; + wire FIFORDEN; + + wire preloadstage1; + wire preloadstage2; + reg ram_valid_i; + reg read_data_valid_i; + wire ram_regout_en; + wire ram_rd_en; + reg empty_i = 1'b1; + reg empty_q = 1'b1; + reg rd_en_q = 1'b0; //Fix for CR:236270 in v3.2 //prasanna + reg almost_empty_i = 1'b1; + reg almost_empty_q = 1'b1; + wire rd_rst_i; + + +/************************************************************************* +* FUNCTIONS +*************************************************************************/ + + /************************************************************************* + * hexstr_conv + * Converts a string of type hex to a binary value (for C_DOUT_RST_VAL) + ***********************************************************************/ + function [C_DOUT_WIDTH-1:0] hexstr_conv; + input [(C_DOUT_WIDTH*8)-1:0] def_data; + + integer index,i,j; + reg [3:0] bin; + + begin + index = 0; + hexstr_conv = 'b0; + for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 ) + begin + case (def_data[7:0]) + 8'b00000000 : + begin + bin = 4'b0000; + i = -1; + end + 8'b00110000 : bin = 4'b0000; + 8'b00110001 : bin = 4'b0001; + 8'b00110010 : bin = 4'b0010; + 8'b00110011 : bin = 4'b0011; + 8'b00110100 : bin = 4'b0100; + 8'b00110101 : bin = 4'b0101; + 8'b00110110 : bin = 4'b0110; + 8'b00110111 : bin = 4'b0111; + 8'b00111000 : bin = 4'b1000; + 8'b00111001 : bin = 4'b1001; + 8'b01000001 : bin = 4'b1010; + 8'b01000010 : bin = 4'b1011; + 8'b01000011 : bin = 4'b1100; + 8'b01000100 : bin = 4'b1101; + 8'b01000101 : bin = 4'b1110; + 8'b01000110 : bin = 4'b1111; + 8'b01100001 : bin = 4'b1010; + 8'b01100010 : bin = 4'b1011; + 8'b01100011 : bin = 4'b1100; + 8'b01100100 : bin = 4'b1101; + 8'b01100101 : bin = 4'b1110; + 8'b01100110 : bin = 4'b1111; + default : + begin + bin = 4'bx; + end + endcase + for( j=0; j<4; j=j+1) + begin + if ((index*4)+j < C_DOUT_WIDTH) + begin + hexstr_conv[(index*4)+j] = bin[j]; + end + end + index = index + 1; + def_data = def_data >> 8; + end + end + endfunction + +initial + begin + ram_valid_i = 1'b0; + read_data_valid_i = 1'b0; + USERDATA = hexstr_conv(C_DOUT_RST_VAL); + end + + + //****************************************************************************** + // connect up optional reset + //****************************************************************************** + assign rd_rst_i = C_HAS_RST ? RD_RST : 0; + + + //****************************************************************************** + // preloadstage2 indicates that stage2 needs to be updated. This is true + // whenever read_data_valid is false, and RAM_valid is true. + //****************************************************************************** + assign preloadstage2 = ram_valid_i & (~read_data_valid_i | RD_EN); + + //****************************************************************************** + // preloadstage1 indicates that stage1 needs to be updated. This is true + // whenever the RAM has data (RAM_EMPTY is false), and either RAM_Valid is + // false (indicating that Stage1 needs updating), or preloadstage2 is active + // (indicating that Stage2 is going to update, so Stage1, therefore, must + // also be updated to keep it valid. + //****************************************************************************** + assign preloadstage1 = ((~ram_valid_i | preloadstage2) & ~FIFOEMPTY); + + //****************************************************************************** + // Calculate RAM_REGOUT_EN + // The output registers are controlled by the ram_regout_en signal. + // These registers should be updated either when the output in Stage2 is + // invalid (preloadstage2), OR when the user is reading, in which case the + // Stage2 value will go invalid unless it is replenished. + //****************************************************************************** + assign ram_regout_en = preloadstage2; + + //****************************************************************************** + // Calculate RAM_RD_EN + // RAM_RD_EN will be asserted whenever the RAM needs to be read in order to + // update the value in Stage1. + // One case when this happens is when preloadstage1=true, which indicates + // that the data in Stage1 or Stage2 is invalid, and needs to automatically + // be updated. + // The other case is when the user is reading from the FIFO, which guarantees + // that Stage1 or Stage2 will be invalid on the next clock cycle, unless it is + // replinished by data from the memory. So, as long as the RAM has data in it, + // a read of the RAM should occur. + //****************************************************************************** + assign ram_rd_en = (RD_EN & ~FIFOEMPTY) | preloadstage1; + + //****************************************************************************** + // Calculate RAMVALID_P0_OUT + // RAMVALID_P0_OUT indicates that the data in Stage1 is valid. + // + // If the RAM is being read from on this clock cycle (ram_rd_en=1), then + // RAMVALID_P0_OUT is certainly going to be true. + // If the RAM is not being read from, but the output registers are being + // updated to fill Stage2 (ram_regout_en=1), then Stage1 will be emptying, + // therefore causing RAMVALID_P0_OUT to be false. + // Otherwise, RAMVALID_P0_OUT will remain unchanged. + //****************************************************************************** + always @ (posedge RD_CLK or posedge rd_rst_i) + begin // PROCESS regout_valid + if (rd_rst_i) // asynchronous reset (active high) + ram_valid_i <= 1'b0; + else + begin + if (ram_rd_en == 1'b1) + ram_valid_i <= 1'b1; + else + if (ram_regout_en == 1'b1) + ram_valid_i <= 1'b0; + else + ram_valid_i <= ram_valid_i; + end //rd_rst_i + end //always + + //****************************************************************************** + // Calculate READ_DATA_VALID + // READ_DATA_VALID indicates whether the value in Stage2 is valid or not. + // Stage2 has valid data whenever Stage1 had valid data and ram_regout_en_i=1, + // such that the data in Stage1 is propogated into Stage2. + //****************************************************************************** + always @ (posedge RD_CLK or posedge rd_rst_i) + begin + if (rd_rst_i) + read_data_valid_i <= 1'b0; + else + read_data_valid_i <= ram_valid_i | (read_data_valid_i & ~RD_EN); + end //always + + + //***************************************************************************** + // Calculate EMPTY + // Defined as the inverse of READ_DATA_VALID + // + // Description: + // + // If read_data_valid_i indicates that the output is not valid, + // and there is no valid data on the output of the ram to preload it + // with, then we will report empty. + // + // If there is no valid data on the output of the ram and we are + // reading, then the FIFO will go empty. + // + //***************************************************************************** + always @ (posedge RD_CLK or posedge rd_rst_i) + begin + if (rd_rst_i) // asynchronous reset (active high) + begin + empty_i <= 1'b1; + empty_q <= 1'b1; + end + else // rising clock edge + begin + empty_i <= (~ram_valid_i & ~read_data_valid_i) | (~ram_valid_i & RD_EN); + empty_q <= empty_i; + end + end //always + + //Fix for CR:236270 //prasanna + //Register RD_EN from user to calculate USERUNDERFLOW. + always @ (posedge RD_CLK or posedge rd_rst_i) + begin + if (rd_rst_i) // asynchronous reset (active high) + begin + rd_en_q <= 1'b0; + end + else // rising clock edge + begin + rd_en_q <= RD_EN; + end + end //always + + + //***************************************************************************** + // Calculate user_almost_empty + // user_almost_empty is defined such that, unless more words are written + // to the FIFO, the next read will cause the FIFO to go EMPTY. + // + // In most cases, whenever the output registers are updated (due to a user + // read or a preload condition), then user_almost_empty will update to + // whatever RAM_EMPTY is. + // + // The exception is when the output is valid, the user is not reading, and + // Stage1 is not empty. In this condition, Stage1 will be preloaded from the + // memory, so we need to make sure user_almost_empty deasserts properly under + // this condition. + //***************************************************************************** + always @ (posedge RD_CLK or posedge rd_rst_i) + begin + if (rd_rst_i) // asynchronous reset (active high) + begin + almost_empty_i <= 1'b1; + almost_empty_q <= 1'b1; + end + else // rising clock edge + begin + if ((ram_regout_en) | (~FIFOEMPTY & read_data_valid_i & ~RD_EN)) + begin + almost_empty_i <= FIFOEMPTY; + end + almost_empty_q <= empty_i; + end + end //always + + + assign USEREMPTY = empty_i; + assign USERALMOSTEMPTY = almost_empty_i; + assign FIFORDEN = ram_rd_en; + assign RAMVALID = ram_valid_i; + assign USERVALID = C_USERVALID_LOW ? ~read_data_valid_i : read_data_valid_i; + //assign USERUNDERFLOW = C_USERUNDERFLOW_LOW ? ~(empty_q & RD_EN) : empty_q & RD_EN; //Bug in v3.1 (CR:236270) + assign USERUNDERFLOW = C_USERUNDERFLOW_LOW ? ~(empty_q & rd_en_q) : empty_q & rd_en_q; //Fix for CR:236270 in v3.2 //prasanna + + always @ (posedge RD_CLK or posedge rd_rst_i) + begin + if (rd_rst_i) // asynchronous reset (active high) + USERDATA <= hexstr_conv(C_DOUT_RST_VAL); + else // rising clock edge + if (ram_regout_en) + USERDATA <= FIFODATA; + end //always + + + + + +endmodule diff --git a/fpga/usrp2/models/FIFO_GENERATOR_V6_1.v b/fpga/usrp2/models/FIFO_GENERATOR_V6_1.v new file mode 100644 index 000000000..65bbac447 --- /dev/null +++ b/fpga/usrp2/models/FIFO_GENERATOR_V6_1.v @@ -0,0 +1,4575 @@ +/* + ******************************************************************************* + * + * FIFO Generator - Verilog Behavioral Model + * + ******************************************************************************* + * + * (c) Copyright 1995 - 2009 Xilinx, Inc. All rights reserved. + * + * This file contains confidential and proprietary information + * of Xilinx, Inc. and is protected under U.S. and + * international copyright and other intellectual property + * laws. + * + * DISCLAIMER + * This disclaimer is not a license and does not grant any + * rights to the materials distributed herewith. Except as + * otherwise provided in a valid license issued to you by + * Xilinx, and to the maximum extent permitted by applicable + * law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND + * WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES + * AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING + * BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- + * INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and + * (2) Xilinx shall not be liable (whether in contract or tort, + * including negligence, or under any other theory of + * liability) for any loss or damage of any kind or nature + * related to, arising under or in connection with these + * materials, including for any direct, or any indirect, + * special, incidental, or consequential loss or damage + * (including loss of data, profits, goodwill, or any type of + * loss or damage suffered as a result of any action brought + * by a third party) even if such damage or loss was + * reasonably foreseeable or Xilinx had been advised of the + * possibility of the same. + * + * CRITICAL APPLICATIONS + * Xilinx products are not designed or intended to be fail- + * safe, or for use in any application requiring fail-safe + * performance, such as life-support or safety devices or + * systems, Class III medical devices, nuclear facilities, + * applications related to the deployment of airbags, or any + * other applications that could lead to death, personal + * injury, or severe property or environmental damage + * (individually and collectively, "Critical + * Applications"). Customer assumes the sole risk and + * liability of any use of Xilinx products in Critical + * Applications, subject only to applicable laws and + * regulations governing limitations on product liability. + * + * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS + * PART OF THIS FILE AT ALL TIMES. + * + ******************************************************************************* + ******************************************************************************* + * + * Filename: FIFO_GENERATOR_V6_1.v + * + * Author : Xilinx + * + ******************************************************************************* + * Structure: + * + * fifo_generator_v6_1.vhd + * | + * +-fifo_generator_v6_1_bhv_ver_as + * | + * +-fifo_generator_v6_1_bhv_ver_ss + * | + * +-fifo_generator_v6_1_bhv_ver_preload0 + * + ******************************************************************************* + * Description: + * + * The Verilog behavioral model for the FIFO Generator. + * + * The behavioral model has three parts: + * - The behavioral model for independent clocks FIFOs (_as) + * - The behavioral model for common clock FIFOs (_ss) + * - The "preload logic" block which implements First-word Fall-through + * + ******************************************************************************* + * Description: + * The verilog behavioral model for the FIFO generator core. + * + ******************************************************************************* + */ + +`timescale 1ps/1ps +`ifndef TCQ + `define TCQ 100 +`endif + + +/******************************************************************************* + * Declaration of top-level module + ******************************************************************************/ +module FIFO_GENERATOR_V6_1 + #( + parameter C_COMMON_CLOCK = 0, + parameter C_COUNT_TYPE = 0, + parameter C_DATA_COUNT_WIDTH = 2, + parameter C_DEFAULT_VALUE = "", + parameter C_DIN_WIDTH = 8, + parameter C_DOUT_RST_VAL = "", + parameter C_DOUT_WIDTH = 8, + parameter C_ENABLE_RLOCS = 0, + parameter C_FAMILY = "virtex6", //Not allowed in Verilog model + parameter C_FULL_FLAGS_RST_VAL = 1, + parameter C_HAS_ALMOST_EMPTY = 0, + parameter C_HAS_ALMOST_FULL = 0, + parameter C_HAS_BACKUP = 0, + parameter C_HAS_DATA_COUNT = 0, + parameter C_HAS_INT_CLK = 0, + parameter C_HAS_MEMINIT_FILE = 0, + parameter C_HAS_OVERFLOW = 0, + parameter C_HAS_RD_DATA_COUNT = 0, + parameter C_HAS_RD_RST = 0, + parameter C_HAS_RST = 0, + parameter C_HAS_SRST = 0, + parameter C_HAS_UNDERFLOW = 0, + parameter C_HAS_VALID = 0, + parameter C_HAS_WR_ACK = 0, + parameter C_HAS_WR_DATA_COUNT = 0, + parameter C_HAS_WR_RST = 0, + parameter C_IMPLEMENTATION_TYPE = 0, + parameter C_INIT_WR_PNTR_VAL = 0, + parameter C_MEMORY_TYPE = 1, + parameter C_MIF_FILE_NAME = "", + parameter C_OPTIMIZATION_MODE = 0, + parameter C_OVERFLOW_LOW = 0, + parameter C_PRELOAD_LATENCY = 1, + parameter C_PRELOAD_REGS = 0, + parameter C_PRIM_FIFO_TYPE = "", + parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0, + parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0, + parameter C_PROG_EMPTY_TYPE = 0, + parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0, + parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0, + parameter C_PROG_FULL_TYPE = 0, + parameter C_RD_DATA_COUNT_WIDTH = 2, + parameter C_RD_DEPTH = 256, + parameter C_RD_FREQ = 1, + parameter C_RD_PNTR_WIDTH = 8, + parameter C_UNDERFLOW_LOW = 0, + parameter C_USE_DOUT_RST = 0, + parameter C_USE_ECC = 0, + parameter C_USE_EMBEDDED_REG = 0, + parameter C_USE_FIFO16_FLAGS = 0, + parameter C_USE_FWFT_DATA_COUNT = 0, + parameter C_VALID_LOW = 0, + parameter C_WR_ACK_LOW = 0, + parameter C_WR_DATA_COUNT_WIDTH = 2, + parameter C_WR_DEPTH = 256, + parameter C_WR_FREQ = 1, + parameter C_WR_PNTR_WIDTH = 8, + parameter C_WR_RESPONSE_LATENCY = 1, + parameter C_MSGON_VAL = 1, + parameter C_ENABLE_RST_SYNC = 1, + parameter C_ERROR_INJECTION_TYPE = 0 + ) + + ( + input BACKUP, + input BACKUP_MARKER, + input CLK, + input RST, + input SRST, + input WR_CLK, + input WR_RST, + input RD_CLK, + input RD_RST, + input [C_DIN_WIDTH-1:0] DIN, + input WR_EN, + input RD_EN, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE, + input INT_CLK, + input INJECTDBITERR, + input INJECTSBITERR, + + output [C_DOUT_WIDTH-1:0] DOUT, + output FULL, + output ALMOST_FULL, + output WR_ACK, + output OVERFLOW, + output EMPTY, + output ALMOST_EMPTY, + output VALID, + output UNDERFLOW, + output [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT, + output [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT, + output [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT, + output PROG_FULL, + output PROG_EMPTY, + output SBITERR, + output DBITERR + ); + +/* + ****************************************************************************** + * Definition of Parameters + ****************************************************************************** + * C_COMMON_CLOCK : Common Clock (1), Independent Clocks (0) + * C_COUNT_TYPE : *not used + * C_DATA_COUNT_WIDTH : Width of DATA_COUNT bus + * C_DEFAULT_VALUE : *not used + * C_DIN_WIDTH : Width of DIN bus + * C_DOUT_RST_VAL : Reset value of DOUT + * C_DOUT_WIDTH : Width of DOUT bus + * C_ENABLE_RLOCS : *not used + * C_FAMILY : not used in bhv model + * C_FULL_FLAGS_RST_VAL : Full flags rst val (0 or 1) + * C_HAS_ALMOST_EMPTY : 1=Core has ALMOST_EMPTY flag + * C_HAS_ALMOST_FULL : 1=Core has ALMOST_FULL flag + * C_HAS_BACKUP : *not used + * C_HAS_DATA_COUNT : 1=Core has DATA_COUNT bus + * C_HAS_INT_CLK : not used in bhv model + * C_HAS_MEMINIT_FILE : *not used + * C_HAS_OVERFLOW : 1=Core has OVERFLOW flag + * C_HAS_RD_DATA_COUNT : 1=Core has RD_DATA_COUNT bus + * C_HAS_RD_RST : *not used + * C_HAS_RST : 1=Core has Async Rst + * C_HAS_SRST : 1=Core has Sync Rst + * C_HAS_UNDERFLOW : 1=Core has UNDERFLOW flag + * C_HAS_VALID : 1=Core has VALID flag + * C_HAS_WR_ACK : 1=Core has WR_ACK flag + * C_HAS_WR_DATA_COUNT : 1=Core has WR_DATA_COUNT bus + * C_HAS_WR_RST : *not used + * C_IMPLEMENTATION_TYPE : 0=Common-Clock Bram/Dram + * 1=Common-Clock ShiftRam + * 2=Indep. Clocks Bram/Dram + * 3=Virtex-4 Built-in + * 4=Virtex-5 Built-in + * C_INIT_WR_PNTR_VAL : *not used + * C_MEMORY_TYPE : 1=Block RAM + * 2=Distributed RAM + * 3=Shift RAM + * 4=Built-in FIFO + * C_MIF_FILE_NAME : *not used + * C_OPTIMIZATION_MODE : *not used + * C_OVERFLOW_LOW : 1=OVERFLOW active low + * C_PRELOAD_LATENCY : Latency of read: 0, 1, 2 + * C_PRELOAD_REGS : 1=Use output registers + * C_PRIM_FIFO_TYPE : not used in bhv model + * C_PROG_EMPTY_THRESH_ASSERT_VAL: PROG_EMPTY assert threshold + * C_PROG_EMPTY_THRESH_NEGATE_VAL: PROG_EMPTY negate threshold + * C_PROG_EMPTY_TYPE : 0=No programmable empty + * 1=Single prog empty thresh constant + * 2=Multiple prog empty thresh constants + * 3=Single prog empty thresh input + * 4=Multiple prog empty thresh inputs + * C_PROG_FULL_THRESH_ASSERT_VAL : PROG_FULL assert threshold + * C_PROG_FULL_THRESH_NEGATE_VAL : PROG_FULL negate threshold + * C_PROG_FULL_TYPE : 0=No prog full + * 1=Single prog full thresh constant + * 2=Multiple prog full thresh constants + * 3=Single prog full thresh input + * 4=Multiple prog full thresh inputs + * C_RD_DATA_COUNT_WIDTH : Width of RD_DATA_COUNT bus + * C_RD_DEPTH : Depth of read interface (2^N) + * C_RD_FREQ : not used in bhv model + * C_RD_PNTR_WIDTH : always log2(C_RD_DEPTH) + * C_UNDERFLOW_LOW : 1=UNDERFLOW active low + * C_USE_DOUT_RST : 1=Resets DOUT on RST + * C_USE_ECC : Used for error injection purpose + * C_USE_EMBEDDED_REG : 1=Use BRAM embedded output register + * C_USE_FIFO16_FLAGS : not used in bhv model + * C_USE_FWFT_DATA_COUNT : 1=Use extra logic for FWFT data count + * C_VALID_LOW : 1=VALID active low + * C_WR_ACK_LOW : 1=WR_ACK active low + * C_WR_DATA_COUNT_WIDTH : Width of WR_DATA_COUNT bus + * C_WR_DEPTH : Depth of write interface (2^N) + * C_WR_FREQ : not used in bhv model + * C_WR_PNTR_WIDTH : always log2(C_WR_DEPTH) + * C_WR_RESPONSE_LATENCY : *not used + * C_MSGON_VAL : *not used by bhv model + * C_ENABLE_RST_SYNC : 0 = Use WR_RST & RD_RST + * 1 = Use RST + * C_ERROR_INJECTION_TYPE : 0 = No error injection + * 1 = Single bit error injection only + * 2 = Double bit error injection only + * 3 = Single and double bit error injection + ****************************************************************************** + * Definition of Ports + ****************************************************************************** + * BACKUP : Not used + * BACKUP_MARKER: Not used + * CLK : Clock + * DIN : Input data bus + * PROG_EMPTY_THRESH : Threshold for Programmable Empty Flag + * PROG_EMPTY_THRESH_ASSERT: Threshold for Programmable Empty Flag + * PROG_EMPTY_THRESH_NEGATE: Threshold for Programmable Empty Flag + * PROG_FULL_THRESH : Threshold for Programmable Full Flag + * PROG_FULL_THRESH_ASSERT : Threshold for Programmable Full Flag + * PROG_FULL_THRESH_NEGATE : Threshold for Programmable Full Flag + * RD_CLK : Read Domain Clock + * RD_EN : Read enable + * RD_RST : Read Reset + * RST : Asynchronous Reset + * SRST : Synchronous Reset + * WR_CLK : Write Domain Clock + * WR_EN : Write enable + * WR_RST : Write Reset + * INT_CLK : Internal Clock + * INJECTSBITERR: Inject Signle bit error + * INJECTDBITERR: Inject Double bit error + * ALMOST_EMPTY : One word remaining in FIFO + * ALMOST_FULL : One empty space remaining in FIFO + * DATA_COUNT : Number of data words in fifo( synchronous to CLK) + * DOUT : Output data bus + * EMPTY : Empty flag + * FULL : Full flag + * OVERFLOW : Last write rejected + * PROG_EMPTY : Programmable Empty Flag + * PROG_FULL : Programmable Full Flag + * RD_DATA_COUNT: Number of data words in fifo (synchronous to RD_CLK) + * UNDERFLOW : Last read rejected + * VALID : Last read acknowledged, DOUT bus VALID + * WR_ACK : Last write acknowledged + * WR_DATA_COUNT: Number of data words in fifo (synchronous to WR_CLK) + * SBITERR : Single Bit ECC Error Detected + * DBITERR : Double Bit ECC Error Detected + ****************************************************************************** + */ + + + /***************************************************************************** + * Derived parameters + ****************************************************************************/ + //There are 2 Verilog behavioral models + // 0 = Common-Clock FIFO/ShiftRam FIFO + // 1 = Independent Clocks FIFO + parameter C_VERILOG_IMPL = (C_IMPLEMENTATION_TYPE == 2) ? 1 : 0; + + //Internal reset signals + reg rd_rst_asreg = 0; + reg rd_rst_asreg_d1 = 0; + reg rd_rst_asreg_d2 = 0; + reg rd_rst_reg = 0; + wire rd_rst_comb; + reg rd_rst_d1 = 0; + reg wr_rst_asreg = 0; + reg wr_rst_asreg_d1 = 0; + reg wr_rst_asreg_d2 = 0; + reg wr_rst_reg = 0; + wire wr_rst_comb; + wire wr_rst_i; + wire rd_rst_i; + wire rst_i; + + //Internal reset signals + reg rst_asreg = 0; + reg rst_asreg_d1 = 0; + reg rst_asreg_d2 = 0; + reg rst_reg = 0; + wire rst_comb; + wire rst_full_gen_i; + wire rst_full_ff_i; + + wire RD_CLK_P0_IN; + wire RST_P0_IN; + wire RD_EN_FIFO_IN; + wire RD_EN_P0_IN; + + wire ALMOST_EMPTY_FIFO_OUT; + wire ALMOST_FULL_FIFO_OUT; + wire [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT_FIFO_OUT; + wire [C_DOUT_WIDTH-1:0] DOUT_FIFO_OUT; + wire EMPTY_FIFO_OUT; + wire FULL_FIFO_OUT; + wire OVERFLOW_FIFO_OUT; + wire PROG_EMPTY_FIFO_OUT; + wire PROG_FULL_FIFO_OUT; + wire VALID_FIFO_OUT; + wire [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT_FIFO_OUT; + wire UNDERFLOW_FIFO_OUT; + wire WR_ACK_FIFO_OUT; + wire [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT_FIFO_OUT; + + + //*************************************************************************** + // Internal Signals + // The core uses either the internal_ wires or the preload0_ wires depending + // on whether the core uses Preload0 or not. + // When using preload0, the internal signals connect the internal core to + // the preload logic, and the external core's interfaces are tied to the + // preload0 signals from the preload logic. + //*************************************************************************** + wire [C_DOUT_WIDTH-1:0] DATA_P0_OUT; + wire VALID_P0_OUT; + wire EMPTY_P0_OUT; + wire ALMOSTEMPTY_P0_OUT; + reg EMPTY_P0_OUT_Q; + reg ALMOSTEMPTY_P0_OUT_Q; + wire UNDERFLOW_P0_OUT; + wire RDEN_P0_OUT; + wire [C_DOUT_WIDTH-1:0] DATA_P0_IN; + wire EMPTY_P0_IN; + reg [31:0] DATA_COUNT_FWFT; + reg SS_FWFT_WR ; + reg SS_FWFT_RD ; + + wire sbiterr_fifo_out; + wire dbiterr_fifo_out; + + // Assign 0 if not selected to avoid 'X' propogation to S/DBITERR. + assign inject_sbit_err = ((C_ERROR_INJECTION_TYPE == 1) || (C_ERROR_INJECTION_TYPE == 3)) ? + INJECTSBITERR : 0; + assign inject_dbit_err = ((C_ERROR_INJECTION_TYPE == 2) || (C_ERROR_INJECTION_TYPE == 3)) ? + INJECTDBITERR : 0; + + +// Choose the behavioral model to instantiate based on the C_VERILOG_IMPL +// parameter (1=Independent Clocks, 0=Common Clock) + + localparam FULL_FLAGS_RST_VAL = (C_HAS_SRST == 1) ? 0 : C_FULL_FLAGS_RST_VAL; +generate +case (C_VERILOG_IMPL) +0 : begin : block1 + //Common Clock Behavioral Model + fifo_generator_v6_1_bhv_ver_ss + #( + C_DATA_COUNT_WIDTH, + C_DIN_WIDTH, + C_DOUT_RST_VAL, + C_DOUT_WIDTH, +// C_FULL_FLAGS_RST_VAL, + FULL_FLAGS_RST_VAL, + C_HAS_ALMOST_EMPTY, + C_HAS_ALMOST_FULL, + C_HAS_DATA_COUNT, + C_HAS_OVERFLOW, + C_HAS_RD_DATA_COUNT, + C_HAS_RST, + C_HAS_SRST, + C_HAS_UNDERFLOW, + C_HAS_VALID, + C_HAS_WR_ACK, + C_HAS_WR_DATA_COUNT, + C_IMPLEMENTATION_TYPE, + C_MEMORY_TYPE, + C_OVERFLOW_LOW, + C_PRELOAD_LATENCY, + C_PRELOAD_REGS, + C_PROG_EMPTY_THRESH_ASSERT_VAL, + C_PROG_EMPTY_THRESH_NEGATE_VAL, + C_PROG_EMPTY_TYPE, + C_PROG_FULL_THRESH_ASSERT_VAL, + C_PROG_FULL_THRESH_NEGATE_VAL, + C_PROG_FULL_TYPE, + C_RD_DATA_COUNT_WIDTH, + C_RD_DEPTH, + C_RD_PNTR_WIDTH, + C_UNDERFLOW_LOW, + C_USE_DOUT_RST, + C_USE_EMBEDDED_REG, + C_USE_FWFT_DATA_COUNT, + C_VALID_LOW, + C_WR_ACK_LOW, + C_WR_DATA_COUNT_WIDTH, + C_WR_DEPTH, + C_WR_PNTR_WIDTH, + C_USE_ECC, + C_ENABLE_RST_SYNC, + C_ERROR_INJECTION_TYPE + ) + gen_ss + ( + .CLK (CLK), + .RST (rst_i), + .SRST (SRST), + .RST_FULL_GEN (rst_full_gen_i), + .RST_FULL_FF (rst_full_ff_i), + .DIN (DIN), + .WR_EN (WR_EN), + .RD_EN (RD_EN_FIFO_IN), + .PROG_EMPTY_THRESH (PROG_EMPTY_THRESH), + .PROG_EMPTY_THRESH_ASSERT (PROG_EMPTY_THRESH_ASSERT), + .PROG_EMPTY_THRESH_NEGATE (PROG_EMPTY_THRESH_NEGATE), + .PROG_FULL_THRESH (PROG_FULL_THRESH), + .PROG_FULL_THRESH_ASSERT (PROG_FULL_THRESH_ASSERT), + .PROG_FULL_THRESH_NEGATE (PROG_FULL_THRESH_NEGATE), + .INJECTSBITERR (inject_sbit_err), + .INJECTDBITERR (inject_dbit_err), + .DOUT (DOUT_FIFO_OUT), + .FULL (FULL_FIFO_OUT), + .ALMOST_FULL (ALMOST_FULL_FIFO_OUT), + .WR_ACK (WR_ACK_FIFO_OUT), + .OVERFLOW (OVERFLOW_FIFO_OUT), + .EMPTY (EMPTY_FIFO_OUT), + .ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT), + .VALID (VALID_FIFO_OUT), + .UNDERFLOW (UNDERFLOW_FIFO_OUT), + .DATA_COUNT (DATA_COUNT_FIFO_OUT), + .PROG_FULL (PROG_FULL_FIFO_OUT), + .PROG_EMPTY (PROG_EMPTY_FIFO_OUT), + .SBITERR (sbiterr_fifo_out), + .DBITERR (dbiterr_fifo_out) + ); +end +1 : begin : block1 + //Independent Clocks Behavioral Model + fifo_generator_v6_1_bhv_ver_as + #( + C_DATA_COUNT_WIDTH, + C_DIN_WIDTH, + C_DOUT_RST_VAL, + C_DOUT_WIDTH, + C_FULL_FLAGS_RST_VAL, + C_HAS_ALMOST_EMPTY, + C_HAS_ALMOST_FULL, + C_HAS_DATA_COUNT, + C_HAS_OVERFLOW, + C_HAS_RD_DATA_COUNT, + C_HAS_RST, + C_HAS_UNDERFLOW, + C_HAS_VALID, + C_HAS_WR_ACK, + C_HAS_WR_DATA_COUNT, + C_IMPLEMENTATION_TYPE, + C_MEMORY_TYPE, + C_OVERFLOW_LOW, + C_PRELOAD_LATENCY, + C_PRELOAD_REGS, + C_PROG_EMPTY_THRESH_ASSERT_VAL, + C_PROG_EMPTY_THRESH_NEGATE_VAL, + C_PROG_EMPTY_TYPE, + C_PROG_FULL_THRESH_ASSERT_VAL, + C_PROG_FULL_THRESH_NEGATE_VAL, + C_PROG_FULL_TYPE, + C_RD_DATA_COUNT_WIDTH, + C_RD_DEPTH, + C_RD_PNTR_WIDTH, + C_UNDERFLOW_LOW, + C_USE_DOUT_RST, + C_USE_EMBEDDED_REG, + C_USE_FWFT_DATA_COUNT, + C_VALID_LOW, + C_WR_ACK_LOW, + C_WR_DATA_COUNT_WIDTH, + C_WR_DEPTH, + C_WR_PNTR_WIDTH, + C_USE_ECC, + C_ENABLE_RST_SYNC, + C_ERROR_INJECTION_TYPE + ) + gen_as + ( + .WR_CLK (WR_CLK), + .RD_CLK (RD_CLK), + .RST (rst_i), + .RST_FULL_GEN (rst_full_gen_i), + .RST_FULL_FF (rst_full_ff_i), + .WR_RST (wr_rst_i), + .RD_RST (rd_rst_i), + .DIN (DIN), + .WR_EN (WR_EN), + .RD_EN (RD_EN_FIFO_IN), + .RD_EN_USER (RD_EN), + .PROG_EMPTY_THRESH (PROG_EMPTY_THRESH), + .PROG_EMPTY_THRESH_ASSERT (PROG_EMPTY_THRESH_ASSERT), + .PROG_EMPTY_THRESH_NEGATE (PROG_EMPTY_THRESH_NEGATE), + .PROG_FULL_THRESH (PROG_FULL_THRESH), + .PROG_FULL_THRESH_ASSERT (PROG_FULL_THRESH_ASSERT), + .PROG_FULL_THRESH_NEGATE (PROG_FULL_THRESH_NEGATE), + .INJECTSBITERR (inject_sbit_err), + .INJECTDBITERR (inject_dbit_err), + .USER_EMPTY_FB (EMPTY_P0_OUT), + .DOUT (DOUT_FIFO_OUT), + .FULL (FULL_FIFO_OUT), + .ALMOST_FULL (ALMOST_FULL_FIFO_OUT), + .WR_ACK (WR_ACK_FIFO_OUT), + .OVERFLOW (OVERFLOW_FIFO_OUT), + .EMPTY (EMPTY_FIFO_OUT), + .ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT), + .VALID (VALID_FIFO_OUT), + .UNDERFLOW (UNDERFLOW_FIFO_OUT), + .RD_DATA_COUNT (RD_DATA_COUNT_FIFO_OUT), + .WR_DATA_COUNT (WR_DATA_COUNT_FIFO_OUT), + .PROG_FULL (PROG_FULL_FIFO_OUT), + .PROG_EMPTY (PROG_EMPTY_FIFO_OUT), + .SBITERR (sbiterr_fifo_out), + .DBITERR (dbiterr_fifo_out) + ); +end + +default : begin : block1 + //Independent Clocks Behavioral Model + fifo_generator_v6_1_bhv_ver_as + #( + C_DATA_COUNT_WIDTH, + C_DIN_WIDTH, + C_DOUT_RST_VAL, + C_DOUT_WIDTH, + C_FULL_FLAGS_RST_VAL, + C_HAS_ALMOST_EMPTY, + C_HAS_ALMOST_FULL, + C_HAS_DATA_COUNT, + C_HAS_OVERFLOW, + C_HAS_RD_DATA_COUNT, + C_HAS_RST, + C_HAS_UNDERFLOW, + C_HAS_VALID, + C_HAS_WR_ACK, + C_HAS_WR_DATA_COUNT, + C_IMPLEMENTATION_TYPE, + C_MEMORY_TYPE, + C_OVERFLOW_LOW, + C_PRELOAD_LATENCY, + C_PRELOAD_REGS, + C_PROG_EMPTY_THRESH_ASSERT_VAL, + C_PROG_EMPTY_THRESH_NEGATE_VAL, + C_PROG_EMPTY_TYPE, + C_PROG_FULL_THRESH_ASSERT_VAL, + C_PROG_FULL_THRESH_NEGATE_VAL, + C_PROG_FULL_TYPE, + C_RD_DATA_COUNT_WIDTH, + C_RD_DEPTH, + C_RD_PNTR_WIDTH, + C_UNDERFLOW_LOW, + C_USE_DOUT_RST, + C_USE_EMBEDDED_REG, + C_USE_FWFT_DATA_COUNT, + C_VALID_LOW, + C_WR_ACK_LOW, + C_WR_DATA_COUNT_WIDTH, + C_WR_DEPTH, + C_WR_PNTR_WIDTH, + C_USE_ECC, + C_ENABLE_RST_SYNC, + C_ERROR_INJECTION_TYPE + ) + gen_as + ( + .WR_CLK (WR_CLK), + .RD_CLK (RD_CLK), + .RST (rst_i), + .RST_FULL_GEN (rst_full_gen_i), + .RST_FULL_FF (rst_full_ff_i), + .WR_RST (wr_rst_i), + .RD_RST (rd_rst_i), + .DIN (DIN), + .WR_EN (WR_EN), + .RD_EN (RD_EN_FIFO_IN), + .RD_EN_USER (RD_EN), + .PROG_EMPTY_THRESH (PROG_EMPTY_THRESH), + .PROG_EMPTY_THRESH_ASSERT (PROG_EMPTY_THRESH_ASSERT), + .PROG_EMPTY_THRESH_NEGATE (PROG_EMPTY_THRESH_NEGATE), + .PROG_FULL_THRESH (PROG_FULL_THRESH), + .PROG_FULL_THRESH_ASSERT (PROG_FULL_THRESH_ASSERT), + .PROG_FULL_THRESH_NEGATE (PROG_FULL_THRESH_NEGATE), + .INJECTSBITERR (inject_sbit_err), + .INJECTDBITERR (inject_dbit_err), + .USER_EMPTY_FB (EMPTY_P0_OUT), + .DOUT (DOUT_FIFO_OUT), + .FULL (FULL_FIFO_OUT), + .ALMOST_FULL (ALMOST_FULL_FIFO_OUT), + .WR_ACK (WR_ACK_FIFO_OUT), + .OVERFLOW (OVERFLOW_FIFO_OUT), + .EMPTY (EMPTY_FIFO_OUT), + .ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT), + .VALID (VALID_FIFO_OUT), + .UNDERFLOW (UNDERFLOW_FIFO_OUT), + .RD_DATA_COUNT (RD_DATA_COUNT_FIFO_OUT), + .WR_DATA_COUNT (WR_DATA_COUNT_FIFO_OUT), + .PROG_FULL (PROG_FULL_FIFO_OUT), + .PROG_EMPTY (PROG_EMPTY_FIFO_OUT), + .SBITERR (sbiterr_fifo_out), + .DBITERR (dbiterr_fifo_out) + ); +end + +endcase +endgenerate + + + //************************************************************************** + // Connect Internal Signals + // (Signals labeled internal_*) + // In the normal case, these signals tie directly to the FIFO's inputs and + // outputs. + // In the case of Preload Latency 0 or 1, there are intermediate + // signals between the internal FIFO and the preload logic. + //************************************************************************** + + + //*********************************************** + // If First-Word Fall-Through, instantiate + // the preload0 (FWFT) module + //*********************************************** + generate + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin : block2 + + + fifo_generator_v6_1_bhv_ver_preload0 + #( + C_DOUT_RST_VAL, + C_DOUT_WIDTH, + C_HAS_RST, + C_ENABLE_RST_SYNC, + C_HAS_SRST, + C_USE_DOUT_RST, + C_USE_ECC, + C_VALID_LOW, + C_UNDERFLOW_LOW, + C_MEMORY_TYPE + ) + fgpl0 + ( + .RD_CLK (RD_CLK_P0_IN), + .RD_RST (RST_P0_IN), + .SRST (SRST), + .RD_EN (RD_EN_P0_IN), + .FIFOEMPTY (EMPTY_P0_IN), + .FIFODATA (DATA_P0_IN), + .FIFOSBITERR (sbiterr_fifo_out), + .FIFODBITERR (dbiterr_fifo_out), + .USERDATA (DATA_P0_OUT), + .USERVALID (VALID_P0_OUT), + .USEREMPTY (EMPTY_P0_OUT), + .USERALMOSTEMPTY (ALMOSTEMPTY_P0_OUT), + .USERUNDERFLOW (UNDERFLOW_P0_OUT), + .RAMVALID (RAMVALID_P0_OUT), + .FIFORDEN (RDEN_P0_OUT), + .USERSBITERR (SBITERR), + .USERDBITERR (DBITERR) + ); + + + //*********************************************** + // Connect inputs to preload (FWFT) module + //*********************************************** + //Connect the RD_CLK of the Preload (FWFT) module to CLK if we + // have a common-clock FIFO, or RD_CLK if we have an + // independent clock FIFO + assign RD_CLK_P0_IN = ((C_VERILOG_IMPL == 0) ? CLK : RD_CLK); + assign RST_P0_IN = (C_COMMON_CLOCK == 0) ? rd_rst_i : (C_HAS_RST == 1) ? rst_i : 0; + assign RD_EN_P0_IN = RD_EN; + assign EMPTY_P0_IN = EMPTY_FIFO_OUT; + assign DATA_P0_IN = DOUT_FIFO_OUT; + + //*********************************************** + // Connect outputs from preload (FWFT) module + //*********************************************** + assign DOUT = DATA_P0_OUT; + assign VALID = VALID_P0_OUT ; + assign EMPTY = EMPTY_P0_OUT; + assign ALMOST_EMPTY = ALMOSTEMPTY_P0_OUT; + assign UNDERFLOW = UNDERFLOW_P0_OUT ; + + assign RD_EN_FIFO_IN = RDEN_P0_OUT; + + + //*********************************************** + // Create DATA_COUNT from First-Word Fall-Through + // data count + //*********************************************** + assign DATA_COUNT = (C_USE_FWFT_DATA_COUNT == 0)? DATA_COUNT_FIFO_OUT: + (C_DATA_COUNT_WIDTH>C_RD_PNTR_WIDTH) ? DATA_COUNT_FWFT[C_RD_PNTR_WIDTH:0] : + DATA_COUNT_FWFT[C_RD_PNTR_WIDTH:C_RD_PNTR_WIDTH-C_DATA_COUNT_WIDTH+1]; + + //*********************************************** + // Create DATA_COUNT from First-Word Fall-Through + // data count + //*********************************************** + always @ (posedge RD_CLK or posedge RST_P0_IN) begin + if (RST_P0_IN) begin + EMPTY_P0_OUT_Q <= #`TCQ 1; + ALMOSTEMPTY_P0_OUT_Q <= #`TCQ 1; + end else begin + EMPTY_P0_OUT_Q <= #`TCQ EMPTY_P0_OUT; + ALMOSTEMPTY_P0_OUT_Q <= #`TCQ ALMOSTEMPTY_P0_OUT; + end + end //always + + + //*********************************************** + // logic for common-clock data count when FWFT is selected + //*********************************************** + initial begin + SS_FWFT_RD = 1'b0; + DATA_COUNT_FWFT = 0 ; + SS_FWFT_WR = 1'b0 ; + end //initial + + + //*********************************************** + // common-clock data count is implemented as an + // up-down counter. SS_FWFT_WR and SS_FWFT_RD + // are the up/down enables for the counter. + //*********************************************** + always @ (RD_EN or VALID_P0_OUT or WR_EN or FULL_FIFO_OUT) begin + if (C_VALID_LOW == 1) begin + SS_FWFT_RD = RD_EN && ~VALID_P0_OUT ; + end else begin + SS_FWFT_RD = RD_EN && VALID_P0_OUT ; + end + SS_FWFT_WR = (WR_EN && (~FULL_FIFO_OUT)) ; + end + + //*********************************************** + // common-clock data count is implemented as an + // up-down counter for FWFT. This always block + // calculates the counter. + //*********************************************** + always @ (posedge RD_CLK_P0_IN or posedge RST_P0_IN) begin + if (RST_P0_IN) begin + DATA_COUNT_FWFT <= #`TCQ 0; + end else begin + if (SRST && (C_HAS_SRST == 1) ) begin + DATA_COUNT_FWFT <= #`TCQ 0; + end else begin + case ( {SS_FWFT_WR, SS_FWFT_RD}) + 2'b00: DATA_COUNT_FWFT <= #`TCQ DATA_COUNT_FWFT ; + 2'b01: DATA_COUNT_FWFT <= #`TCQ DATA_COUNT_FWFT - 1 ; + 2'b10: DATA_COUNT_FWFT <= #`TCQ DATA_COUNT_FWFT + 1 ; + 2'b11: DATA_COUNT_FWFT <= #`TCQ DATA_COUNT_FWFT ; + endcase + end //if SRST + end //IF RST + end //always + + + end else begin : block2 //if !(C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) + + //*********************************************** + // If NOT First-Word Fall-Through, wire the outputs + // of the internal _ss or _as FIFO directly to the + // output, and do not instantiate the preload0 + // module. + //*********************************************** + + assign RD_CLK_P0_IN = 0; + assign RST_P0_IN = 0; + assign RD_EN_P0_IN = 0; + + assign RD_EN_FIFO_IN = RD_EN; + + assign DOUT = DOUT_FIFO_OUT; + assign DATA_P0_IN = 0; + assign VALID = VALID_FIFO_OUT; + assign EMPTY = EMPTY_FIFO_OUT; + assign ALMOST_EMPTY = ALMOST_EMPTY_FIFO_OUT; + assign EMPTY_P0_IN = 0; + assign UNDERFLOW = UNDERFLOW_FIFO_OUT; + assign DATA_COUNT = DATA_COUNT_FIFO_OUT; + assign SBITERR = sbiterr_fifo_out; + assign DBITERR = dbiterr_fifo_out; + + end //if !(C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) + endgenerate + + + //*********************************************** + // Connect user flags to internal signals + //*********************************************** + + //If we are using extra logic for the FWFT data count, then override the + //RD_DATA_COUNT output when we are EMPTY or ALMOST_EMPTY. + //RD_DATA_COUNT is 0 when EMPTY and 1 when ALMOST_EMPTY. + generate + if (C_USE_FWFT_DATA_COUNT==1 && (C_RD_DATA_COUNT_WIDTH>C_RD_PNTR_WIDTH) ) begin : block3 + assign RD_DATA_COUNT = (EMPTY_P0_OUT_Q | RST_P0_IN) ? 0 : (ALMOSTEMPTY_P0_OUT_Q ? 1 : RD_DATA_COUNT_FIFO_OUT); + end //block3 + endgenerate + + //If we are using extra logic for the FWFT data count, then override the + //RD_DATA_COUNT output when we are EMPTY or ALMOST_EMPTY. + //Due to asymmetric ports, RD_DATA_COUNT is 0 when EMPTY or ALMOST_EMPTY. + generate + if (C_USE_FWFT_DATA_COUNT==1 && (C_RD_DATA_COUNT_WIDTH <=C_RD_PNTR_WIDTH) ) begin : block30 + assign RD_DATA_COUNT = (EMPTY_P0_OUT_Q | RST_P0_IN) ? 0 : (ALMOSTEMPTY_P0_OUT_Q ? 0 : RD_DATA_COUNT_FIFO_OUT); + end //block30 + endgenerate + + //If we are not using extra logic for the FWFT data count, + //then connect RD_DATA_COUNT to the RD_DATA_COUNT from the + //internal FIFO instance + generate + if (C_USE_FWFT_DATA_COUNT==0 ) begin : block31 + assign RD_DATA_COUNT = RD_DATA_COUNT_FIFO_OUT; + end + endgenerate + + //Always connect WR_DATA_COUNT to the WR_DATA_COUNT from the internal + //FIFO instance + generate + if (C_USE_FWFT_DATA_COUNT==1) begin : block4 + assign WR_DATA_COUNT = WR_DATA_COUNT_FIFO_OUT; + end + else begin : block4 + assign WR_DATA_COUNT = WR_DATA_COUNT_FIFO_OUT; + end + endgenerate + + + //Connect other flags to the internal FIFO instance + assign FULL = FULL_FIFO_OUT; + assign ALMOST_FULL = ALMOST_FULL_FIFO_OUT; + assign WR_ACK = WR_ACK_FIFO_OUT; + assign OVERFLOW = OVERFLOW_FIFO_OUT; + assign PROG_FULL = PROG_FULL_FIFO_OUT; + assign PROG_EMPTY = PROG_EMPTY_FIFO_OUT; + + + // if an asynchronous FIFO has been selected, display a message that the FIFO + // will not be cycle-accurate in simulation + initial begin + if (C_IMPLEMENTATION_TYPE == 2) begin + $display("WARNING: Behavioral models for independent clock FIFO configurations are not cycle-accurate. You may wish to choose the structural simulation model instead of the behavioral model. This will ensure accurate behavior and latencies during simulation. You can enable this from CORE Generator by selecting Project -> Project Options -> Generation tab -> Structural Simulation. See the FIFO Generator User Guide for more information."); + end else if (C_MEMORY_TYPE == 4) begin + $display("FAILURE : Behavioral models for Virtex-4, Virtex-5 and Virtex-6 built-in FIFO configurations is currently not supported. Please select the structural simulation model option in CORE Generator. You can enable this in CORE Generator by selecting Project -> Project Options -> Generation tab -> Structural Simulation. See the FIFO Generator User Guide for more information."); + $finish; + end + end //initial + + /************************************************************************** + * Internal reset logic + **************************************************************************/ + assign wr_rst_i = (C_HAS_RST == 1 || C_ENABLE_RST_SYNC == 0) ? wr_rst_reg : 0; + assign rd_rst_i = (C_HAS_RST == 1 || C_ENABLE_RST_SYNC == 0) ? rd_rst_reg : 0; + assign rst_i = C_HAS_RST ? rst_reg : 0; + + wire rst_2_sync; + wire clk_2_sync = (C_COMMON_CLOCK == 1) ? CLK : WR_CLK; + generate + if (C_ENABLE_RST_SYNC == 0) begin : gnrst_sync + always @* begin + wr_rst_reg <= WR_RST; + rd_rst_reg <= RD_RST; + rst_reg <= 1'b0; + end + assign rst_2_sync = WR_RST; + end else if (C_HAS_RST == 1 && C_COMMON_CLOCK == 0) begin : gic_rst + assign wr_rst_comb = !wr_rst_asreg_d2 && wr_rst_asreg; + assign rd_rst_comb = !rd_rst_asreg_d2 && rd_rst_asreg; + assign rst_2_sync = RST; + + always @(posedge WR_CLK or posedge RST) begin + if (RST == 1'b1) begin + wr_rst_asreg <= #`TCQ 1'b1; + end else begin + if (wr_rst_asreg_d1 == 1'b1) begin + wr_rst_asreg <= #`TCQ 1'b0; + end else begin + wr_rst_asreg <= #`TCQ wr_rst_asreg; + end + end + end + + always @(posedge WR_CLK) begin + wr_rst_asreg_d1 <= #`TCQ wr_rst_asreg; + wr_rst_asreg_d2 <= #`TCQ wr_rst_asreg_d1; + end + + always @(posedge WR_CLK or posedge wr_rst_comb) begin + if (wr_rst_comb == 1'b1) begin + wr_rst_reg <= #`TCQ 1'b1; + end else begin + wr_rst_reg <= #`TCQ 1'b0; + end + end + + always @(posedge RD_CLK or posedge RST) begin + if (RST == 1'b1) begin + rd_rst_asreg <= #`TCQ 1'b1; + end else begin + if (rd_rst_asreg_d1 == 1'b1) begin + rd_rst_asreg <= #`TCQ 1'b0; + end else begin + rd_rst_asreg <= #`TCQ rd_rst_asreg; + end + end + end + + always @(posedge RD_CLK) begin + rd_rst_asreg_d1 <= #`TCQ rd_rst_asreg; + rd_rst_asreg_d2 <= #`TCQ rd_rst_asreg_d1; + end + + always @(posedge RD_CLK or posedge rd_rst_comb) begin + if (rd_rst_comb == 1'b1) begin + rd_rst_reg <= #`TCQ 1'b1; + end else begin + rd_rst_reg <= #`TCQ 1'b0; + end + end + end else if (C_HAS_RST == 1 && C_COMMON_CLOCK == 1) begin : gcc_rst + assign rst_comb = !rst_asreg_d2 && rst_asreg; + assign rst_2_sync = RST; + + always @(posedge CLK or posedge RST) begin + if (RST == 1'b1) begin + rst_asreg <= #`TCQ 1'b1; + end else begin + if (rst_asreg_d1 == 1'b1) begin + rst_asreg <= #`TCQ 1'b0; + end else begin + rst_asreg <= #`TCQ rst_asreg; + end + end + end + + always @(posedge CLK) begin + rst_asreg_d1 <= #`TCQ rst_asreg; + rst_asreg_d2 <= #`TCQ rst_asreg_d1; + end + + always @(posedge CLK or posedge rst_comb) begin + if (rst_comb == 1'b1) begin + rst_reg <= #`TCQ 1'b1; + end else begin + rst_reg <= #`TCQ 1'b0; + end + end + end + endgenerate + + reg rst_d1 = 1'b0; + reg rst_d2 = 1'b0; + reg rst_d3 = 1'b0; + reg rst_d4 = 1'b0; + generate + if ((C_HAS_RST == 1 || C_HAS_SRST == 1 || C_ENABLE_RST_SYNC == 0) && C_FULL_FLAGS_RST_VAL == 1) begin : grstd1 + // RST_FULL_GEN replaces the reset falling edge detection used to de-assert + // FULL, ALMOST_FULL & PROG_FULL flags if C_FULL_FLAGS_RST_VAL = 1. + + // RST_FULL_FF goes to the reset pin of the final flop of FULL, ALMOST_FULL & + // PROG_FULL + + always @ (posedge rst_2_sync or posedge clk_2_sync) begin + if (rst_2_sync) begin + rst_d1 <= 1'b1; + rst_d2 <= 1'b1; + rst_d3 <= 1'b1; + rst_d4 <= 1'b0; + end else begin + if (SRST) begin + rst_d1 <= #`TCQ 1'b1; + rst_d2 <= #`TCQ 1'b1; + rst_d3 <= #`TCQ 1'b1; + rst_d4 <= #`TCQ 1'b0; + end else begin + rst_d1 <= #`TCQ 1'b0; + rst_d2 <= #`TCQ rst_d1; + rst_d3 <= #`TCQ rst_d2; + rst_d4 <= #`TCQ rst_d3; + end + end + end + assign rst_full_ff_i = (C_HAS_SRST == 0) ? rst_d2 : 1'b0 ; + assign rst_full_gen_i = rst_d4; + + end else if ((C_HAS_RST == 1 || C_HAS_SRST == 1 || C_ENABLE_RST_SYNC == 0) && C_FULL_FLAGS_RST_VAL == 0) begin : gnrst_full + assign rst_full_gen_i = 1'b0; + assign rst_full_ff_i = (C_COMMON_CLOCK == 0) ? wr_rst_i : rst_i; + end + endgenerate + +endmodule //FIFO_GENERATOR_V6_1 + + + +/******************************************************************************* + * Declaration of Independent-Clocks FIFO Module + ******************************************************************************/ +module fifo_generator_v6_1_bhv_ver_as + + /*************************************************************************** + * Declare user parameters and their defaults + ***************************************************************************/ + #( + parameter C_DATA_COUNT_WIDTH = 2, + parameter C_DIN_WIDTH = 8, + parameter C_DOUT_RST_VAL = "", + parameter C_DOUT_WIDTH = 8, + parameter C_FULL_FLAGS_RST_VAL = 1, + parameter C_HAS_ALMOST_EMPTY = 0, + parameter C_HAS_ALMOST_FULL = 0, + parameter C_HAS_DATA_COUNT = 0, + parameter C_HAS_OVERFLOW = 0, + parameter C_HAS_RD_DATA_COUNT = 0, + parameter C_HAS_RST = 0, + parameter C_HAS_UNDERFLOW = 0, + parameter C_HAS_VALID = 0, + parameter C_HAS_WR_ACK = 0, + parameter C_HAS_WR_DATA_COUNT = 0, + parameter C_IMPLEMENTATION_TYPE = 0, + parameter C_MEMORY_TYPE = 1, + parameter C_OVERFLOW_LOW = 0, + parameter C_PRELOAD_LATENCY = 1, + parameter C_PRELOAD_REGS = 0, + parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0, + parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0, + parameter C_PROG_EMPTY_TYPE = 0, + parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0, + parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0, + parameter C_PROG_FULL_TYPE = 0, + parameter C_RD_DATA_COUNT_WIDTH = 2, + parameter C_RD_DEPTH = 256, + parameter C_RD_PNTR_WIDTH = 8, + parameter C_UNDERFLOW_LOW = 0, + parameter C_USE_DOUT_RST = 0, + parameter C_USE_EMBEDDED_REG = 0, + parameter C_USE_FWFT_DATA_COUNT = 0, + parameter C_VALID_LOW = 0, + parameter C_WR_ACK_LOW = 0, + parameter C_WR_DATA_COUNT_WIDTH = 2, + parameter C_WR_DEPTH = 256, + parameter C_WR_PNTR_WIDTH = 8, + parameter C_USE_ECC = 0, + parameter C_ENABLE_RST_SYNC = 1, + parameter C_ERROR_INJECTION_TYPE = 0 + ) + + /*************************************************************************** + * Declare Input and Output Ports + ***************************************************************************/ + ( + input [C_DIN_WIDTH-1:0] DIN, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE, + input RD_CLK, + input RD_EN, + input RD_EN_USER, + input RST, + input RST_FULL_GEN, + input RST_FULL_FF, + input WR_RST, + input RD_RST, + input WR_CLK, + input WR_EN, + input INJECTDBITERR, + input INJECTSBITERR, + input USER_EMPTY_FB, + output reg ALMOST_EMPTY = 1'b1, + output reg ALMOST_FULL = C_FULL_FLAGS_RST_VAL, + output [C_DOUT_WIDTH-1:0] DOUT, + output reg EMPTY = 1'b1, + output reg FULL = C_FULL_FLAGS_RST_VAL, + output OVERFLOW, + output PROG_EMPTY, + output PROG_FULL, + output VALID, + output [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT, + output UNDERFLOW, + output WR_ACK, + output [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT, + output SBITERR, + output DBITERR + ); + + reg [C_RD_PNTR_WIDTH:0] rd_data_count_int = 0; + reg [C_WR_PNTR_WIDTH:0] wr_data_count_int = 0; + reg [C_WR_PNTR_WIDTH:0] wdc_fwft_ext_as = 0; + + + /*************************************************************************** + * Parameters used as constants + **************************************************************************/ + //When RST is present, set FULL reset value to '1'. + //If core has no RST, make sure FULL powers-on as '0'. + parameter C_DEPTH_RATIO_WR = + (C_WR_DEPTH>C_RD_DEPTH) ? (C_WR_DEPTH/C_RD_DEPTH) : 1; + parameter C_DEPTH_RATIO_RD = + (C_RD_DEPTH>C_WR_DEPTH) ? (C_RD_DEPTH/C_WR_DEPTH) : 1; + parameter C_FIFO_WR_DEPTH = C_WR_DEPTH - 1; + parameter C_FIFO_RD_DEPTH = C_RD_DEPTH - 1; + + // C_DEPTH_RATIO_WR | C_DEPTH_RATIO_RD | C_PNTR_WIDTH | EXTRA_WORDS_DC + // -----------------|------------------|-----------------|--------------- + // 1 | 8 | C_RD_PNTR_WIDTH | 2 + // 1 | 4 | C_RD_PNTR_WIDTH | 2 + // 1 | 2 | C_RD_PNTR_WIDTH | 2 + // 1 | 1 | C_WR_PNTR_WIDTH | 2 + // 2 | 1 | C_WR_PNTR_WIDTH | 4 + // 4 | 1 | C_WR_PNTR_WIDTH | 8 + // 8 | 1 | C_WR_PNTR_WIDTH | 16 + + localparam C_PNTR_WIDTH = (C_WR_PNTR_WIDTH>=C_RD_PNTR_WIDTH) ? C_WR_PNTR_WIDTH : C_RD_PNTR_WIDTH; + wire [C_PNTR_WIDTH:0] EXTRA_WORDS_DC = (C_DEPTH_RATIO_WR == 1) ? 2 : (2 * C_DEPTH_RATIO_WR/C_DEPTH_RATIO_RD); + + parameter [31:0] reads_per_write = C_DIN_WIDTH/C_DOUT_WIDTH; + + parameter [31:0] log2_reads_per_write = log2_val(reads_per_write); + + parameter [31:0] writes_per_read = C_DOUT_WIDTH/C_DIN_WIDTH; + + parameter [31:0] log2_writes_per_read = log2_val(writes_per_read); + + + + /************************************************************************** + * FIFO Contents Tracking and Data Count Calculations + *************************************************************************/ + + // Memory which will be used to simulate a FIFO + reg [C_DIN_WIDTH-1:0] memory[C_WR_DEPTH-1:0]; + // Local parameters used to determine whether to inject ECC error or not + localparam SYMMETRIC_PORT = (C_DIN_WIDTH == C_DOUT_WIDTH) ? 1 : 0; + localparam ERR_INJECTION = (C_ERROR_INJECTION_TYPE != 0) ? 1 : 0; + localparam ENABLE_ERR_INJECTION = C_USE_ECC && SYMMETRIC_PORT && ERR_INJECTION; + // Array that holds the error injection type (single/double bit error) on + // a specific write operation, which is returned on read to corrupt the + // output data. + reg [1:0] ecc_err[C_WR_DEPTH-1:0]; + + //The amount of data stored in the FIFO at any time is given + // by num_wr_bits (in the WR_CLK domain) and num_rd_bits (in the RD_CLK + // domain. + //num_wr_bits is calculated by considering the total words in the FIFO, + // and the state of the read pointer (which may not have yet crossed clock + // domains.) + //num_rd_bits is calculated by considering the total words in the FIFO, + // and the state of the write pointer (which may not have yet crossed clock + // domains.) + reg [31:0] num_wr_bits; + reg [31:0] num_rd_bits; + reg [31:0] next_num_wr_bits; + reg [31:0] next_num_rd_bits; + + //The write pointer - tracks write operations + // (Works opposite to core: wr_ptr is a DOWN counter) + reg [31:0] wr_ptr; + reg [C_WR_PNTR_WIDTH-1:0] wr_pntr = 0; // UP counter: Rolls back to 0 when reaches to max value. + reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd1 = 0; + reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd2 = 0; + reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd3 = 0; + wire [C_RD_PNTR_WIDTH-1:0] adj_wr_pntr_rd; + reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd = 0; + wire wr_rst_i = WR_RST; + reg wr_rst_d1 =0; + + //The read pointer - tracks read operations + // (rd_ptr Works opposite to core: rd_ptr is a DOWN counter) + reg [31:0] rd_ptr; + reg [C_RD_PNTR_WIDTH-1:0] rd_pntr = 0; // UP counter: Rolls back to 0 when reaches to max value. + reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr1 = 0; + reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr2 = 0; + reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr3 = 0; + reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr4 = 0; + wire [C_WR_PNTR_WIDTH-1:0] adj_rd_pntr_wr; + reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr = 0; + wire rd_rst_i = RD_RST; + wire ram_rd_en; + reg ram_rd_en_d1 = 1'b0; + + + // Delayed ram_rd_en is needed only for STD Embedded register option + generate + if (C_PRELOAD_LATENCY == 2) begin : grd_d + always @ (posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i) + ram_rd_en_d1 <= #`TCQ 1'b0; + else + ram_rd_en_d1 <= #`TCQ ram_rd_en; + end + end + endgenerate + + // Write pointer adjustment based on pointers width for EMPTY/ALMOST_EMPTY generation + generate + if (C_RD_PNTR_WIDTH > C_WR_PNTR_WIDTH) begin : rdg // Read depth greater than write depth + assign adj_wr_pntr_rd[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH] = wr_pntr_rd; + assign adj_wr_pntr_rd[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1:0] = 0; + end else begin : rdl // Read depth lesser than or equal to write depth + assign adj_wr_pntr_rd = wr_pntr_rd[C_WR_PNTR_WIDTH-1:C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH]; + end + endgenerate + + // Generate Empty and Almost Empty + // ram_rd_en used to determine EMPTY should depend on the EMPTY. + assign ram_rd_en = RD_EN & !EMPTY; + assign empty_int = ((adj_wr_pntr_rd == rd_pntr) || (ram_rd_en && (adj_wr_pntr_rd == (rd_pntr+1'h1)))); + assign almost_empty_int = ((adj_wr_pntr_rd == (rd_pntr+1'h1)) || (ram_rd_en && (adj_wr_pntr_rd == (rd_pntr+2'h2)))); + + // Register Empty and Almost Empty + always @ (posedge RD_CLK or posedge rd_rst_i) + begin + if (rd_rst_i) begin + EMPTY <= #`TCQ 1'b1; + ALMOST_EMPTY <= #`TCQ 1'b1; + rd_data_count_int <= #`TCQ {C_RD_PNTR_WIDTH-1{1'b0}}; + end else begin + rd_data_count_int <= #`TCQ {(adj_wr_pntr_rd[C_RD_PNTR_WIDTH-1:0] - rd_pntr[C_RD_PNTR_WIDTH-1:0]), 1'b0}; + + if (empty_int) + EMPTY <= #`TCQ 1'b1; + else + EMPTY <= #`TCQ 1'b0; + + if (!EMPTY) begin + if (almost_empty_int) + ALMOST_EMPTY <= #`TCQ 1'b1; + else + ALMOST_EMPTY <= #`TCQ 1'b0; + end + end // rd_rst_i + end // always + + // Read pointer adjustment based on pointers width for EMPTY/ALMOST_EMPTY generation + generate + if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : wdg // Write depth greater than read depth + assign adj_rd_pntr_wr[C_WR_PNTR_WIDTH-1:C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH] = rd_pntr_wr; + assign adj_rd_pntr_wr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1:0] = 0; + end else begin : wdl // Write depth lesser than or equal to read depth + assign adj_rd_pntr_wr = rd_pntr_wr[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH]; + end + endgenerate + + // Generate FULL and ALMOST_FULL + // ram_wr_en used to determine FULL should depend on the FULL. + assign ram_wr_en = WR_EN & !FULL; + assign full_int = ((adj_rd_pntr_wr == (wr_pntr+1'h1)) || (ram_wr_en && (adj_rd_pntr_wr == (wr_pntr+2'h2)))); + assign almost_full_int = ((adj_rd_pntr_wr == (wr_pntr+2'h2)) || (ram_wr_en && (adj_rd_pntr_wr == (wr_pntr+3'h3)))); + + // Register FULL and ALMOST_FULL Empty + always @ (posedge WR_CLK or posedge RST_FULL_FF) + begin + if (RST_FULL_FF) begin + FULL <= #`TCQ C_FULL_FLAGS_RST_VAL; + ALMOST_FULL <= #`TCQ C_FULL_FLAGS_RST_VAL; + wr_data_count_int <= #`TCQ {C_WR_DATA_COUNT_WIDTH-1{1'b0}}; + end else begin + wr_data_count_int <= #`TCQ {(wr_pntr[C_WR_PNTR_WIDTH-1:0] - adj_rd_pntr_wr[C_WR_PNTR_WIDTH-1:0]), 1'b0}; + if (full_int) begin + FULL <= #`TCQ 1'b1; + end else begin + FULL <= #`TCQ 1'b0; + end + + if (RST_FULL_GEN) begin + ALMOST_FULL <= #`TCQ 1'b0; + end else if (!FULL) begin + if (almost_full_int) + ALMOST_FULL <= #`TCQ 1'b1; + else + ALMOST_FULL <= #`TCQ 1'b0; + end + end // wr_rst_i + end // always + + // Determine which stage in FWFT registers are valid + reg stage1_valid = 0; + reg stage2_valid = 0; + generate + if (C_PRELOAD_LATENCY == 0) begin : grd_fwft_proc + always @ (posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i) begin + stage1_valid <= #`TCQ 0; + stage2_valid <= #`TCQ 0; + end else begin + + if (!stage1_valid && !stage2_valid) begin + if (!EMPTY) + stage1_valid <= #`TCQ 1'b1; + else + stage1_valid <= #`TCQ 1'b0; + end else if (stage1_valid && !stage2_valid) begin + if (EMPTY) begin + stage1_valid <= #`TCQ 1'b0; + stage2_valid <= #`TCQ 1'b1; + end else begin + stage1_valid <= #`TCQ 1'b1; + stage2_valid <= #`TCQ 1'b1; + end + end else if (!stage1_valid && stage2_valid) begin + if (EMPTY && RD_EN_USER) begin + stage1_valid <= #`TCQ 1'b0; + stage2_valid <= #`TCQ 1'b0; + end else if (!EMPTY && RD_EN_USER) begin + stage1_valid <= #`TCQ 1'b1; + stage2_valid <= #`TCQ 1'b0; + end else if (!EMPTY && !RD_EN_USER) begin + stage1_valid <= #`TCQ 1'b1; + stage2_valid <= #`TCQ 1'b1; + end else begin + stage1_valid <= #`TCQ 1'b0; + stage2_valid <= #`TCQ 1'b1; + end + end else if (stage1_valid && stage2_valid) begin + if (EMPTY && RD_EN_USER) begin + stage1_valid <= #`TCQ 1'b0; + stage2_valid <= #`TCQ 1'b1; + end else begin + stage1_valid <= #`TCQ 1'b1; + stage2_valid <= #`TCQ 1'b1; + end + end else begin + stage1_valid <= #`TCQ 1'b0; + stage2_valid <= #`TCQ 1'b0; + end + end // rd_rst_i + end // always + end + endgenerate + + //Pointers passed into opposite clock domain + reg [31:0] wr_ptr_rdclk; + reg [31:0] wr_ptr_rdclk_next; + reg [31:0] rd_ptr_wrclk; + reg [31:0] rd_ptr_wrclk_next; + + //Amount of data stored in the FIFO scaled to the narrowest (deepest) port + // (Do not include data in FWFT stages) + //Used to calculate PROG_EMPTY. + wire [31:0] num_read_words_pe = + num_rd_bits/(C_DOUT_WIDTH/C_DEPTH_RATIO_WR); + + //Amount of data stored in the FIFO scaled to the narrowest (deepest) port + // (Do not include data in FWFT stages) + //Used to calculate PROG_FULL. + wire [31:0] num_write_words_pf = + num_wr_bits/(C_DIN_WIDTH/C_DEPTH_RATIO_RD); + + /************************** + * Read Data Count + *************************/ + + reg [31:0] num_read_words_dc; + reg [C_RD_DATA_COUNT_WIDTH-1:0] num_read_words_sized_i; + + always @(num_rd_bits) begin + if (C_USE_FWFT_DATA_COUNT) begin + + //If using extra logic for FWFT Data Counts, + // then scale FIFO contents to read domain, + // and add two read words for FWFT stages + //This value is only a temporary value and not used in the code. + num_read_words_dc = (num_rd_bits/C_DOUT_WIDTH+2); + + //Trim the read words for use with RD_DATA_COUNT + num_read_words_sized_i = + num_read_words_dc[C_RD_PNTR_WIDTH : C_RD_PNTR_WIDTH-C_RD_DATA_COUNT_WIDTH+1]; + + end else begin + + //If not using extra logic for FWFT Data Counts, + // then scale FIFO contents to read domain. + //This value is only a temporary value and not used in the code. + num_read_words_dc = num_rd_bits/C_DOUT_WIDTH; + + //Trim the read words for use with RD_DATA_COUNT + num_read_words_sized_i = + num_read_words_dc[C_RD_PNTR_WIDTH-1 : C_RD_PNTR_WIDTH-C_RD_DATA_COUNT_WIDTH]; + + end //if (C_USE_FWFT_DATA_COUNT) + end //always + + + /************************** + * Write Data Count + *************************/ + + reg [31:0] num_write_words_dc; + reg [C_WR_DATA_COUNT_WIDTH-1:0] num_write_words_sized_i; + + always @(num_wr_bits) begin + if (C_USE_FWFT_DATA_COUNT) begin + + //Calculate the Data Count value for the number of write words, + // when using First-Word Fall-Through with extra logic for Data + // Counts. This takes into consideration the number of words that + // are expected to be stored in the FWFT register stages (it always + // assumes they are filled). + //This value is scaled to the Write Domain. + //The expression (((A-1)/B))+1 divides A/B, but takes the + // ceiling of the result. + //When num_wr_bits==0, set the result manually to prevent + // division errors. + //EXTRA_WORDS_DC is the number of words added to write_words + // due to FWFT. + //This value is only a temporary value and not used in the code. + num_write_words_dc = (num_wr_bits==0) ? EXTRA_WORDS_DC : (((num_wr_bits-1)/C_DIN_WIDTH)+1) + EXTRA_WORDS_DC ; + + //Trim the write words for use with WR_DATA_COUNT + num_write_words_sized_i = + num_write_words_dc[C_WR_PNTR_WIDTH : C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH+1]; + + end else begin + + //Calculate the Data Count value for the number of write words, when NOT + // using First-Word Fall-Through with extra logic for Data Counts. This + // calculates only the number of words in the internal FIFO. + //The expression (((A-1)/B))+1 divides A/B, but takes the + // ceiling of the result. + //This value is scaled to the Write Domain. + //When num_wr_bits==0, set the result manually to prevent + // division errors. + //This value is only a temporary value and not used in the code. + num_write_words_dc = (num_wr_bits==0) ? 0 : ((num_wr_bits-1)/C_DIN_WIDTH)+1; + + //Trim the read words for use with RD_DATA_COUNT + num_write_words_sized_i = + num_write_words_dc[C_WR_PNTR_WIDTH-1 : C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH]; + + end //if (C_USE_FWFT_DATA_COUNT) + end //always + + + + /*************************************************************************** + * Internal registers and wires + **************************************************************************/ + + //Temporary signals used for calculating the model's outputs. These + //are only used in the assign statements immediately following wire, + //parameter, and function declarations. + wire [C_DOUT_WIDTH-1:0] ideal_dout_out; + wire valid_i; + wire valid_out; + wire underflow_i; + + //Ideal FIFO signals. These are the raw output of the behavioral model, + //which behaves like an ideal FIFO. + reg [1:0] err_type = 0; + reg [1:0] err_type_d1 = 0; + reg [C_DOUT_WIDTH-1:0] ideal_dout = 0; + reg [C_DOUT_WIDTH-1:0] ideal_dout_d1 = 0; + reg ideal_wr_ack = 0; + reg ideal_valid = 0; + reg ideal_overflow = 0; + reg ideal_underflow = 0; + reg ideal_prog_full = 0; + reg ideal_prog_empty = 1; + reg [C_WR_DATA_COUNT_WIDTH-1 : 0] ideal_wr_count = 0; + reg [C_RD_DATA_COUNT_WIDTH-1 : 0] ideal_rd_count = 0; + + //Assorted reg values for delayed versions of signals + reg valid_d1 = 0; + + + //user specified value for reseting the size of the fifo + reg [C_DOUT_WIDTH-1:0] dout_reset_val = 0; + + //temporary registers for WR_RESPONSE_LATENCY feature + + integer tmp_wr_listsize; + integer tmp_rd_listsize; + + //Signal for registered version of prog full and empty + + //Threshold values for Programmable Flags + integer prog_empty_actual_thresh_assert; + integer prog_empty_actual_thresh_negate; + integer prog_full_actual_thresh_assert; + integer prog_full_actual_thresh_negate; + + + /**************************************************************************** + * Function Declarations + ***************************************************************************/ + + /************************************************************************** + * write_fifo + * This task writes a word to the FIFO memory and updates the + * write pointer. + * FIFO size is relative to write domain. + ***************************************************************************/ + task write_fifo; + begin + memory[wr_ptr] <= DIN; + wr_pntr <= #`TCQ wr_pntr + 1; + // Store the type of error injection (double/single) on write + case (C_ERROR_INJECTION_TYPE) + 3: ecc_err[wr_ptr] <= {INJECTDBITERR,INJECTSBITERR}; + 2: ecc_err[wr_ptr] <= {INJECTDBITERR,1'b0}; + 1: ecc_err[wr_ptr] <= {1'b0,INJECTSBITERR}; + default: ecc_err[wr_ptr] <= 0; + endcase + // (Works opposite to core: wr_ptr is a DOWN counter) + if (wr_ptr == 0) begin + wr_ptr <= C_WR_DEPTH - 1; + end else begin + wr_ptr <= wr_ptr - 1; + end + end + endtask // write_fifo + + /************************************************************************** + * read_fifo + * This task reads a word from the FIFO memory and updates the read + * pointer. It's output is the ideal_dout bus. + * FIFO size is relative to write domain. + ***************************************************************************/ + task read_fifo; + integer i; + reg [C_DOUT_WIDTH-1:0] tmp_dout; + reg [C_DIN_WIDTH-1:0] memory_read; + reg [31:0] tmp_rd_ptr; + reg [31:0] rd_ptr_high; + reg [31:0] rd_ptr_low; + reg [1:0] tmp_ecc_err; + begin + rd_pntr <= #`TCQ rd_pntr + 1; + // output is wider than input + if (reads_per_write == 0) begin + tmp_dout = 0; + tmp_rd_ptr = (rd_ptr << log2_writes_per_read)+(writes_per_read-1); + for (i = writes_per_read - 1; i >= 0; i = i - 1) begin + tmp_dout = tmp_dout << C_DIN_WIDTH; + tmp_dout = tmp_dout | memory[tmp_rd_ptr]; + + // (Works opposite to core: rd_ptr is a DOWN counter) + if (tmp_rd_ptr == 0) begin + tmp_rd_ptr = C_WR_DEPTH - 1; + end else begin + tmp_rd_ptr = tmp_rd_ptr - 1; + end + end + + // output is symmetric + end else if (reads_per_write == 1) begin + tmp_dout = memory[rd_ptr][C_DIN_WIDTH-1:0]; + // Retreive the error injection type. Based on the error injection type + // corrupt the output data. + tmp_ecc_err = ecc_err[rd_ptr]; + if (ENABLE_ERR_INJECTION && C_DIN_WIDTH == C_DOUT_WIDTH) begin + if (tmp_ecc_err[1]) begin // Corrupt the output data only for double bit error + if (C_DOUT_WIDTH == 1) + tmp_dout = tmp_dout[C_DOUT_WIDTH-1:0]; + else if (C_DOUT_WIDTH == 2) + tmp_dout = {~tmp_dout[C_DOUT_WIDTH-1],~tmp_dout[C_DOUT_WIDTH-2]}; + else + tmp_dout = {~tmp_dout[C_DOUT_WIDTH-1],~tmp_dout[C_DOUT_WIDTH-2],(tmp_dout << 2)}; + end else begin + tmp_dout = tmp_dout[C_DOUT_WIDTH-1:0]; + end + err_type <= {tmp_ecc_err[1], tmp_ecc_err[0] & !tmp_ecc_err[1]}; + end else begin + err_type <= 0; + end + + // input is wider than output + end else begin + rd_ptr_high = rd_ptr >> log2_reads_per_write; + rd_ptr_low = rd_ptr & (reads_per_write - 1); + memory_read = memory[rd_ptr_high]; + tmp_dout = memory_read >> (rd_ptr_low*C_DOUT_WIDTH); + end + ideal_dout <= tmp_dout; + + // (Works opposite to core: rd_ptr is a DOWN counter) + if (rd_ptr == 0) begin + rd_ptr <= C_RD_DEPTH - 1; + end else begin + rd_ptr <= rd_ptr - 1; + end + end + endtask + + /************************************************************************** + * log2_val + * Returns the 'log2' value for the input value for the supported ratios + ***************************************************************************/ + function [31:0] log2_val; + input [31:0] binary_val; + + begin + if (binary_val == 8) begin + log2_val = 3; + end else if (binary_val == 4) begin + log2_val = 2; + end else begin + log2_val = 1; + end + end + endfunction + + /*********************************************************************** + * hexstr_conv + * Converts a string of type hex to a binary value (for C_DOUT_RST_VAL) + ***********************************************************************/ + function [C_DOUT_WIDTH-1:0] hexstr_conv; + input [(C_DOUT_WIDTH*8)-1:0] def_data; + + integer index,i,j; + reg [3:0] bin; + + begin + index = 0; + hexstr_conv = 'b0; + for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 ) + begin + case (def_data[7:0]) + 8'b00000000 : + begin + bin = 4'b0000; + i = -1; + end + 8'b00110000 : bin = 4'b0000; + 8'b00110001 : bin = 4'b0001; + 8'b00110010 : bin = 4'b0010; + 8'b00110011 : bin = 4'b0011; + 8'b00110100 : bin = 4'b0100; + 8'b00110101 : bin = 4'b0101; + 8'b00110110 : bin = 4'b0110; + 8'b00110111 : bin = 4'b0111; + 8'b00111000 : bin = 4'b1000; + 8'b00111001 : bin = 4'b1001; + 8'b01000001 : bin = 4'b1010; + 8'b01000010 : bin = 4'b1011; + 8'b01000011 : bin = 4'b1100; + 8'b01000100 : bin = 4'b1101; + 8'b01000101 : bin = 4'b1110; + 8'b01000110 : bin = 4'b1111; + 8'b01100001 : bin = 4'b1010; + 8'b01100010 : bin = 4'b1011; + 8'b01100011 : bin = 4'b1100; + 8'b01100100 : bin = 4'b1101; + 8'b01100101 : bin = 4'b1110; + 8'b01100110 : bin = 4'b1111; + default : + begin + bin = 4'bx; + end + endcase + for( j=0; j<4; j=j+1) + begin + if ((index*4)+j < C_DOUT_WIDTH) + begin + hexstr_conv[(index*4)+j] = bin[j]; + end + end + index = index + 1; + def_data = def_data >> 8; + end + end + endfunction + + /************************************************************************* + * Initialize Signals for clean power-on simulation + *************************************************************************/ + initial begin + num_wr_bits = 0; + num_rd_bits = 0; + next_num_wr_bits = 0; + next_num_rd_bits = 0; + rd_ptr = C_RD_DEPTH - 1; + wr_ptr = C_WR_DEPTH - 1; + wr_pntr = 0; + rd_pntr = 0; + rd_ptr_wrclk = rd_ptr; + wr_ptr_rdclk = wr_ptr; + dout_reset_val = hexstr_conv(C_DOUT_RST_VAL); + ideal_dout = dout_reset_val; + err_type = 0; + ideal_dout_d1 = dout_reset_val; + ideal_wr_ack = 1'b0; + ideal_valid = 1'b0; + valid_d1 = 1'b0; + ideal_overflow = 1'b0; + ideal_underflow = 1'b0; + ideal_wr_count = 0; + ideal_rd_count = 0; + ideal_prog_full = 1'b0; + ideal_prog_empty = 1'b1; + end + + + /************************************************************************* + * Connect the module inputs and outputs to the internal signals of the + * behavioral model. + *************************************************************************/ + //Inputs + /* + wire [C_DIN_WIDTH-1:0] DIN; + wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH; + wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT; + wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE; + wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH; + wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT; + wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE; + wire RD_CLK; + wire RD_EN; + wire RST; + wire WR_CLK; + wire WR_EN; + */ + + //*************************************************************************** + // Dout may change behavior based on latency + //*************************************************************************** + assign ideal_dout_out[C_DOUT_WIDTH-1:0] = (C_PRELOAD_LATENCY==2 && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))? + ideal_dout_d1: ideal_dout; + assign DOUT[C_DOUT_WIDTH-1:0] = ideal_dout_out; + + //*************************************************************************** + // Assign SBITERR and DBITERR based on latency + //*************************************************************************** + assign SBITERR = (C_ERROR_INJECTION_TYPE == 1 || C_ERROR_INJECTION_TYPE == 3) && + (C_PRELOAD_LATENCY == 2 && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1)) ? + err_type_d1[0]: err_type[0]; + assign DBITERR = (C_ERROR_INJECTION_TYPE == 2 || C_ERROR_INJECTION_TYPE == 3) && + (C_PRELOAD_LATENCY==2 && (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1)) ? + err_type_d1[1]: err_type[1]; + + + //*************************************************************************** + // Overflow may be active-low + //*************************************************************************** + generate + if (C_HAS_OVERFLOW==1) begin : blockOF1 + assign OVERFLOW = ideal_overflow ? !C_OVERFLOW_LOW : C_OVERFLOW_LOW; + end + endgenerate + + assign PROG_EMPTY = ideal_prog_empty; + assign PROG_FULL = ideal_prog_full; + + //*************************************************************************** + // Valid may change behavior based on latency or active-low + //*************************************************************************** + generate + if (C_HAS_VALID==1) begin : blockVL1 + assign valid_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & ~EMPTY) : ideal_valid; + assign valid_out = (C_PRELOAD_LATENCY==2 && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))? + valid_d1: valid_i; + assign VALID = valid_out ? !C_VALID_LOW : C_VALID_LOW; + end + endgenerate + + + //*************************************************************************** + // Underflow may change behavior based on latency or active-low + //*************************************************************************** + generate + if (C_HAS_UNDERFLOW==1) begin : blockUF1 + assign underflow_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & EMPTY) : ideal_underflow; + assign UNDERFLOW = underflow_i ? !C_UNDERFLOW_LOW : C_UNDERFLOW_LOW; + end + endgenerate + + //*************************************************************************** + // Write acknowledge may be active low + //*************************************************************************** + generate + if (C_HAS_WR_ACK==1) begin : blockWK1 + assign WR_ACK = ideal_wr_ack ? !C_WR_ACK_LOW : C_WR_ACK_LOW; + end + endgenerate + + + //*************************************************************************** + // Generate RD_DATA_COUNT if Use Extra Logic option is selected + //*************************************************************************** + generate + if (C_HAS_WR_DATA_COUNT == 1 && C_USE_FWFT_DATA_COUNT == 1) begin : wdc_fwft_ext + + reg [C_PNTR_WIDTH-1:0] adjusted_wr_pntr = 0; + reg [C_PNTR_WIDTH-1:0] adjusted_rd_pntr = 0; + wire [C_PNTR_WIDTH-1:0] diff_wr_rd_tmp; + wire [C_PNTR_WIDTH:0] diff_wr_rd; + reg [C_PNTR_WIDTH:0] wr_data_count_i = 0; + always @* begin + if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin + adjusted_wr_pntr = wr_pntr; + adjusted_rd_pntr = 0; + adjusted_rd_pntr[C_PNTR_WIDTH-1:C_PNTR_WIDTH-C_RD_PNTR_WIDTH] = rd_pntr_wr; + end else if (C_WR_PNTR_WIDTH < C_RD_PNTR_WIDTH) begin + adjusted_rd_pntr = rd_pntr_wr; + adjusted_wr_pntr = 0; + adjusted_wr_pntr[C_PNTR_WIDTH-1:C_PNTR_WIDTH-C_WR_PNTR_WIDTH] = wr_pntr; + end else begin + adjusted_wr_pntr = wr_pntr; + adjusted_rd_pntr = rd_pntr_wr; + end + end // always @* + + assign diff_wr_rd_tmp = adjusted_wr_pntr - adjusted_rd_pntr; + assign diff_wr_rd = {1'b0,diff_wr_rd_tmp}; + + always @ (posedge wr_rst_i or posedge WR_CLK) + begin + if (wr_rst_i) + wr_data_count_i <= #`TCQ 0; + else + wr_data_count_i <= #`TCQ diff_wr_rd + EXTRA_WORDS_DC; + end // always @ (posedge WR_CLK or posedge WR_CLK) + + always @* begin + if (C_WR_PNTR_WIDTH >= C_RD_PNTR_WIDTH) + wdc_fwft_ext_as = wr_data_count_i[C_PNTR_WIDTH:0]; + else + wdc_fwft_ext_as = wr_data_count_i[C_PNTR_WIDTH:C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH]; + end // always @* + end // wdc_fwft_ext + endgenerate + + //*************************************************************************** + // Generate RD_DATA_COUNT if Use Extra Logic option is selected + //*************************************************************************** + reg [C_RD_PNTR_WIDTH:0] rdc_fwft_ext_as = 0; + + generate + if (C_HAS_RD_DATA_COUNT == 1 && C_USE_FWFT_DATA_COUNT == 1) begin : rdc_fwft_ext + reg [C_RD_PNTR_WIDTH-1:0] adjusted_wr_pntr_rd = 0; + wire [C_RD_PNTR_WIDTH-1:0] diff_rd_wr_tmp; + wire [C_RD_PNTR_WIDTH:0] diff_rd_wr; + always @* begin + if (C_RD_PNTR_WIDTH > C_WR_PNTR_WIDTH) begin + adjusted_wr_pntr_rd = 0; + adjusted_wr_pntr_rd[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH] = wr_pntr_rd; + end else begin + adjusted_wr_pntr_rd = wr_pntr_rd[C_WR_PNTR_WIDTH-1:C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH]; + end + end // always @* + + assign diff_rd_wr_tmp = adjusted_wr_pntr_rd - rd_pntr; + assign diff_rd_wr = {1'b0,diff_rd_wr_tmp}; + + always @ (posedge rd_rst_i or posedge RD_CLK) + begin + if (rd_rst_i) begin + rdc_fwft_ext_as <= #`TCQ 0; + end else begin + if (!stage2_valid) + rdc_fwft_ext_as <= #`TCQ 0; + else if (!stage1_valid && stage2_valid) + rdc_fwft_ext_as <= #`TCQ 1; + else + rdc_fwft_ext_as <= #`TCQ diff_rd_wr + 2'h2; + end + end // always @ (posedge WR_CLK or posedge WR_CLK) + end // rdc_fwft_ext + endgenerate + + //*************************************************************************** + // Assign the read data count value only if it is selected, + // otherwise output zeros. + //*************************************************************************** + generate + if (C_HAS_RD_DATA_COUNT == 1) begin : grdc + assign RD_DATA_COUNT[C_RD_DATA_COUNT_WIDTH-1:0] = C_USE_FWFT_DATA_COUNT ? + rdc_fwft_ext_as[C_RD_PNTR_WIDTH:C_RD_PNTR_WIDTH+1-C_RD_DATA_COUNT_WIDTH] : + rd_data_count_int[C_RD_PNTR_WIDTH:C_RD_PNTR_WIDTH+1-C_RD_DATA_COUNT_WIDTH]; + end + endgenerate + + generate + if (C_HAS_RD_DATA_COUNT == 0) begin : gnrdc + assign RD_DATA_COUNT[C_RD_DATA_COUNT_WIDTH-1:0] = {C_RD_DATA_COUNT_WIDTH-1{1'b0}}; + end + endgenerate + + //*************************************************************************** + // Assign the write data count value only if it is selected, + // otherwise output zeros + //*************************************************************************** + generate + if (C_HAS_WR_DATA_COUNT == 1) begin : gwdc + assign WR_DATA_COUNT[C_WR_DATA_COUNT_WIDTH-1:0] = (C_USE_FWFT_DATA_COUNT == 1) ? + wdc_fwft_ext_as[C_WR_PNTR_WIDTH:C_WR_PNTR_WIDTH+1-C_WR_DATA_COUNT_WIDTH] : + wr_data_count_int[C_WR_PNTR_WIDTH:C_WR_PNTR_WIDTH+1-C_WR_DATA_COUNT_WIDTH]; + end + endgenerate + + generate + if (C_HAS_WR_DATA_COUNT == 0) begin : gnwdc + assign WR_DATA_COUNT[C_WR_DATA_COUNT_WIDTH-1:0] = {C_WR_DATA_COUNT_WIDTH-1{1'b0}}; + end + endgenerate + + + /************************************************************************** + * Assorted registers for delayed versions of signals + **************************************************************************/ + //Capture delayed version of valid + generate + if (C_HAS_VALID==1) begin : blockVL2 + always @(posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i == 1'b1) begin + valid_d1 <= #`TCQ 1'b0; + end else begin + valid_d1 <= #`TCQ valid_i; + end + end + end + endgenerate + + //Capture delayed version of dout + always @(posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i == 1'b1) begin + // Reset err_type only if ECC is not selected + if (C_USE_ECC == 0) + err_type_d1 <= #`TCQ 0; + end else if (ram_rd_en_d1) begin + ideal_dout_d1 <= #`TCQ ideal_dout; + err_type_d1 <= #`TCQ err_type; + end + end + + /************************************************************************** + * Overflow and Underflow Flag calculation + * (handled separately because they don't support rst) + **************************************************************************/ + generate + if (C_HAS_OVERFLOW==1) begin : blockOF2 + always @(posedge WR_CLK) begin + ideal_overflow <= #`TCQ WR_EN & FULL; + end + end + endgenerate + + generate + if (C_HAS_UNDERFLOW==1) begin : blockUF2 + always @(posedge RD_CLK) begin + ideal_underflow <= #`TCQ EMPTY & RD_EN; + end + end + endgenerate + + /************************************************************************** + * Write Domain Logic + **************************************************************************/ + reg [C_WR_PNTR_WIDTH-1:0] diff_pntr = 0; + always @(posedge WR_CLK or posedge wr_rst_i) begin : gen_fifo_w + + /****** Reset fifo (case 1)***************************************/ + if (wr_rst_i == 1'b1) begin + num_wr_bits <= #`TCQ 0; + next_num_wr_bits = #`TCQ 0; + wr_ptr <= #`TCQ C_WR_DEPTH - 1; + rd_ptr_wrclk <= #`TCQ C_RD_DEPTH - 1; + ideal_wr_ack <= #`TCQ 0; + ideal_wr_count <= #`TCQ 0; + tmp_wr_listsize = #`TCQ 0; + rd_ptr_wrclk_next <= #`TCQ 0; + wr_pntr <= #`TCQ 0; + wr_pntr_rd1 <= #`TCQ 0; + rd_pntr_wr2 <= #`TCQ 0; + rd_pntr_wr3 <= #`TCQ 0; + rd_pntr_wr4 <= #`TCQ 0; + rd_pntr_wr <= #`TCQ 0; + + + end else begin //wr_rst_i==0 + + wr_pntr_rd1 <= #`TCQ wr_pntr; + + // Synchronize the rd_pntr in read domain + rd_pntr_wr2 <= #`TCQ rd_pntr_wr1; + rd_pntr_wr3 <= #`TCQ rd_pntr_wr2; + rd_pntr_wr4 <= #`TCQ rd_pntr_wr2; + rd_pntr_wr <= #`TCQ rd_pntr_wr4; + + + + //Determine the current number of words in the FIFO + tmp_wr_listsize = (C_DEPTH_RATIO_RD > 1) ? num_wr_bits/C_DOUT_WIDTH : + num_wr_bits/C_DIN_WIDTH; + rd_ptr_wrclk_next = rd_ptr; + if (rd_ptr_wrclk < rd_ptr_wrclk_next) begin + next_num_wr_bits = num_wr_bits - + C_DOUT_WIDTH*(rd_ptr_wrclk + C_RD_DEPTH + - rd_ptr_wrclk_next); + end else begin + next_num_wr_bits = num_wr_bits - + C_DOUT_WIDTH*(rd_ptr_wrclk - rd_ptr_wrclk_next); + end + + //If this is a write, handle the write by adding the value + // to the linked list, and updating all outputs appropriately + if (WR_EN == 1'b1) begin + if (FULL == 1'b1) begin + + //If the FIFO is full, do NOT perform the write, + // update flags accordingly + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD + >= C_FIFO_WR_DEPTH) begin + //write unsuccessful - do not change contents + + //Do not acknowledge the write + ideal_wr_ack <= #`TCQ 0; + //Reminder that FIFO is still full + + ideal_wr_count <= #`TCQ num_write_words_sized_i; + + //If the FIFO is one from full, but reporting full + end else + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD == + C_FIFO_WR_DEPTH-1) begin + //No change to FIFO + + //Write not successful + ideal_wr_ack <= #`TCQ 0; + //With DEPTH-1 words in the FIFO, it is almost_full + + ideal_wr_count <= #`TCQ num_write_words_sized_i; + + + //If the FIFO is completely empty, but it is + // reporting FULL for some reason (like reset) + end else + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD <= + C_FIFO_WR_DEPTH-2) begin + //No change to FIFO + + //Write not successful + ideal_wr_ack <= #`TCQ 0; + //FIFO is really not close to full, so change flag status. + + ideal_wr_count <= #`TCQ num_write_words_sized_i; + end //(tmp_wr_listsize == 0) + + end else begin + + //If the FIFO is full, do NOT perform the write, + // update flags accordingly + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD >= + C_FIFO_WR_DEPTH) begin + //write unsuccessful - do not change contents + + //Do not acknowledge the write + ideal_wr_ack <= #`TCQ 0; + //Reminder that FIFO is still full + + ideal_wr_count <= #`TCQ num_write_words_sized_i; + + //If the FIFO is one from full + end else + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD == + C_FIFO_WR_DEPTH-1) begin + //Add value on DIN port to FIFO + write_fifo; + next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH; + + //Write successful, so issue acknowledge + // and no error + ideal_wr_ack <= #`TCQ 1; + //This write is CAUSING the FIFO to go full + + ideal_wr_count <= #`TCQ num_write_words_sized_i; + + //If the FIFO is 2 from full + end else + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD == + C_FIFO_WR_DEPTH-2) begin + //Add value on DIN port to FIFO + write_fifo; + next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH; + //Write successful, so issue acknowledge + // and no error + ideal_wr_ack <= #`TCQ 1; + //Still 2 from full + + ideal_wr_count <= #`TCQ num_write_words_sized_i; + + //If the FIFO is not close to being full + end else + if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD < + C_FIFO_WR_DEPTH-2) begin + //Add value on DIN port to FIFO + write_fifo; + next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH; + //Write successful, so issue acknowledge + // and no error + ideal_wr_ack <= #`TCQ 1; + //Not even close to full. + + ideal_wr_count <= num_write_words_sized_i; + + end + + end + + end else begin //(WR_EN == 1'b1) + + //If user did not attempt a write, then do not + // give ack or err + ideal_wr_ack <= #`TCQ 0; + ideal_wr_count <= #`TCQ num_write_words_sized_i; + end + num_wr_bits <= #`TCQ next_num_wr_bits; + rd_ptr_wrclk <= #`TCQ rd_ptr; + + end //wr_rst_i==0 + end // write always + + + /*************************************************************************** + * Programmable FULL flags + ***************************************************************************/ + + always @(posedge WR_CLK or posedge RST_FULL_FF) begin : gen_pf + + if (RST_FULL_FF == 1'b1) begin + diff_pntr <= 0; + ideal_prog_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + end else begin + if (ram_wr_en) + diff_pntr <= #`TCQ (wr_pntr - adj_rd_pntr_wr + 2'h1); + else if (!ram_wr_en) + diff_pntr <= #`TCQ (wr_pntr - adj_rd_pntr_wr); + + if (RST_FULL_GEN) + ideal_prog_full <= #`TCQ 0; + //Single Programmable Full Constant Threshold + else if (C_PROG_FULL_TYPE == 1) begin + if (FULL == 0) begin + if (diff_pntr >= C_PROG_FULL_THRESH_ASSERT_VAL) + ideal_prog_full <= #`TCQ 1; + else + ideal_prog_full <= #`TCQ 0; + end else + ideal_prog_full <= #`TCQ ideal_prog_full; + //Two Programmable Full Constant Thresholds + end else if (C_PROG_FULL_TYPE == 2) begin + if (FULL == 0) begin + if (diff_pntr >= C_PROG_FULL_THRESH_ASSERT_VAL) + ideal_prog_full <= #`TCQ 1; + else if (diff_pntr < C_PROG_FULL_THRESH_NEGATE_VAL) + ideal_prog_full <= #`TCQ 0; + else + ideal_prog_full <= #`TCQ ideal_prog_full; + end else + ideal_prog_full <= #`TCQ ideal_prog_full; + //Single Programmable Full Threshold Input + end else if (C_PROG_FULL_TYPE == 3) begin + if (FULL == 0) begin + if (diff_pntr >= PROG_FULL_THRESH) + ideal_prog_full <= #`TCQ 1; + else + ideal_prog_full <= #`TCQ 0; + end else + ideal_prog_full <= #`TCQ ideal_prog_full; + //Two Programmable Full Threshold Inputs + end else if (C_PROG_FULL_TYPE == 4) begin + if (FULL == 0) begin + if (diff_pntr >= PROG_FULL_THRESH_ASSERT) + ideal_prog_full <= #`TCQ 1; + else if (diff_pntr < PROG_FULL_THRESH_NEGATE) + ideal_prog_full <= #`TCQ 0; + else + ideal_prog_full <= #`TCQ ideal_prog_full; + end else + ideal_prog_full <= #`TCQ ideal_prog_full; + end // C_PROG_FULL_TYPE + + end //wr_rst_i==0 + end // + + + /************************************************************************** + * Read Domain Logic + **************************************************************************/ + + + /********************************************************* + * Programmable EMPTY flags + *********************************************************/ + //Determine the Assert and Negate thresholds for Programmable Empty + + reg [C_RD_PNTR_WIDTH-1:0] pe_thr_assert_val = 0; + reg [C_RD_PNTR_WIDTH-1:0] pe_thr_negate_val = 0; + reg [C_RD_PNTR_WIDTH-1:0] diff_pntr_rd = 0; + always @* begin + + if (C_PROG_EMPTY_TYPE == 3) begin + + // If empty input threshold is selected, then subtract 2 for FWFT to + // compensate the FWFT stage, otherwise assign the input value. + if (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) // FWFT + pe_thr_assert_val <= PROG_EMPTY_THRESH - 2'h2; + else + pe_thr_assert_val <= PROG_EMPTY_THRESH; + + end else if (C_PROG_EMPTY_TYPE == 4) begin + + // If empty input threshold is selected, then subtract 2 for FWFT to + // compensate the FWFT stage, otherwise assign the input value. + if (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) begin // FWFT + pe_thr_assert_val <= PROG_EMPTY_THRESH_ASSERT - 2'h2; + pe_thr_negate_val <= PROG_EMPTY_THRESH_NEGATE - 2'h2; + end else begin + pe_thr_assert_val <= PROG_EMPTY_THRESH_ASSERT; + pe_thr_negate_val <= PROG_EMPTY_THRESH_NEGATE; + end + end else begin + + if (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) begin // FWFT + pe_thr_assert_val <= C_PROG_EMPTY_THRESH_ASSERT_VAL - 2; + pe_thr_negate_val <= C_PROG_EMPTY_THRESH_NEGATE_VAL - 2; + end else begin + pe_thr_assert_val <= C_PROG_EMPTY_THRESH_ASSERT_VAL; + pe_thr_negate_val <= C_PROG_EMPTY_THRESH_NEGATE_VAL; + end + end + end // always @* + + always @(posedge RD_CLK or posedge rd_rst_i) begin : gen_pe + + if (rd_rst_i) begin + diff_pntr_rd <= #`TCQ 0; + ideal_prog_empty <= #`TCQ 1'b1; + end else begin + if (ram_rd_en) + diff_pntr_rd <= #`TCQ (adj_wr_pntr_rd - rd_pntr) - 1'h1; + else if (!ram_rd_en) + diff_pntr_rd <= #`TCQ (adj_wr_pntr_rd - rd_pntr); + else + diff_pntr_rd <= #`TCQ diff_pntr_rd; + + if (C_PROG_EMPTY_TYPE == 1) begin + if (EMPTY == 0) begin + if (diff_pntr_rd <= pe_thr_assert_val) + ideal_prog_empty <= #`TCQ 1; + else + ideal_prog_empty <= #`TCQ 0; + end else + ideal_prog_empty <= #`TCQ ideal_prog_empty; + end else if (C_PROG_EMPTY_TYPE == 2) begin + if (EMPTY == 0) begin + if (diff_pntr_rd <= pe_thr_assert_val) + ideal_prog_empty <= #`TCQ 1; + else if (diff_pntr_rd > pe_thr_negate_val) + ideal_prog_empty <= #`TCQ 0; + else + ideal_prog_empty <= #`TCQ ideal_prog_empty; + end else + ideal_prog_empty <= #`TCQ ideal_prog_empty; + end else if (C_PROG_EMPTY_TYPE == 3) begin + if (EMPTY == 0) begin + if (diff_pntr_rd <= pe_thr_assert_val) + ideal_prog_empty <= #`TCQ 1; + else + ideal_prog_empty <= #`TCQ 0; + end else + ideal_prog_empty <= #`TCQ ideal_prog_empty; + end else if (C_PROG_EMPTY_TYPE == 4) begin + if (EMPTY == 0) begin + if (diff_pntr_rd >= pe_thr_assert_val) + ideal_prog_empty <= #`TCQ 1; + else if (diff_pntr_rd > pe_thr_negate_val) + ideal_prog_empty <= #`TCQ 0; + else + ideal_prog_empty <= #`TCQ ideal_prog_empty; + end else + ideal_prog_empty <= #`TCQ ideal_prog_empty; + end //C_PROG_EMPTY_TYPE + end + end + + // block memory has a synchronous reset + always @(posedge RD_CLK) begin : gen_fifo_blkmemdout + // make it consistent with the core. + if (rd_rst_i) begin + // Reset err_type only if ECC is not selected + if (C_USE_ECC == 0 && C_MEMORY_TYPE < 2) + err_type <= #`TCQ 0; + + // BRAM resets synchronously + if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE < 2) begin + ideal_dout <= #`TCQ dout_reset_val; + ideal_dout_d1 <= #`TCQ dout_reset_val; + end + end + end //always + + always @(posedge RD_CLK or posedge rd_rst_i) begin : gen_fifo_r + + /****** Reset fifo (case 1)***************************************/ + if (rd_rst_i) begin + num_rd_bits <= #`TCQ 0; + next_num_rd_bits = #`TCQ 0; + rd_ptr <= #`TCQ C_RD_DEPTH -1; + rd_pntr <= #`TCQ 0; + rd_pntr_wr1 <= #`TCQ 0; + wr_pntr_rd2 <= #`TCQ 0; + wr_pntr_rd3 <= #`TCQ 0; + wr_pntr_rd <= #`TCQ 0; + wr_ptr_rdclk <= #`TCQ C_WR_DEPTH -1; + + // DRAM resets asynchronously + if (C_MEMORY_TYPE == 2 && C_USE_DOUT_RST == 1) + ideal_dout <= #`TCQ dout_reset_val; + + // Reset err_type only if ECC is not selected + if (C_USE_ECC == 0) + err_type <= #`TCQ 0; + ideal_valid <= #`TCQ 1'b0; + ideal_rd_count <= #`TCQ 0; + + end else begin //rd_rst_i==0 + + rd_pntr_wr1 <= #`TCQ rd_pntr; + + // Synchronize the wr_pntr in read domain + wr_pntr_rd2 <= #`TCQ wr_pntr_rd1; + wr_pntr_rd3 <= #`TCQ wr_pntr_rd2; + wr_pntr_rd <= #`TCQ wr_pntr_rd3; + + + + //Determine the current number of words in the FIFO + tmp_rd_listsize = (C_DEPTH_RATIO_WR > 1) ? num_rd_bits/C_DIN_WIDTH : + num_rd_bits/C_DOUT_WIDTH; + wr_ptr_rdclk_next = wr_ptr; + + if (wr_ptr_rdclk < wr_ptr_rdclk_next) begin + next_num_rd_bits = num_rd_bits + + C_DIN_WIDTH*(wr_ptr_rdclk +C_WR_DEPTH + - wr_ptr_rdclk_next); + end else begin + next_num_rd_bits = num_rd_bits + + C_DIN_WIDTH*(wr_ptr_rdclk - wr_ptr_rdclk_next); + end + + /*****************************************************************/ + // Read Operation - Read Latency 1 + /*****************************************************************/ + if (C_PRELOAD_LATENCY==1 || C_PRELOAD_LATENCY==2) begin + ideal_valid <= #`TCQ 1'b0; + + if (ram_rd_en == 1'b1) begin + + if (EMPTY == 1'b1) begin + + //If the FIFO is completely empty, and is reporting empty + if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Reminder that FIFO is still empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + end // if (tmp_rd_listsize <= 0) + + //If the FIFO is one from empty, but it is reporting empty + else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Note that FIFO is no longer empty, but is almost empty (has one word left) + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if (tmp_rd_listsize == 1) + + //If the FIFO is two from empty, and is reporting empty + else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Fifo has two words, so is neither empty or almost empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if (tmp_rd_listsize == 2) + + //If the FIFO is not close to empty, but is reporting that it is + // Treat the FIFO as empty this time, but unset EMPTY flags. + if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && (tmp_rd_listsize/C_DEPTH_RATIO_WR<C_FIFO_RD_DEPTH)) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Note that the FIFO is No Longer Empty or Almost Empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1)) + end // else: if(ideal_empty == 1'b1) + + else //if (ideal_empty == 1'b0) + begin + + //If the FIFO is completely full, and we are successfully reading from it + if (tmp_rd_listsize/C_DEPTH_RATIO_WR >= C_FIFO_RD_DEPTH) + begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= #`TCQ 1'b1; + //Not close to empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if (tmp_rd_listsize == C_FIFO_RD_DEPTH) + + //If the FIFO is not close to being empty + else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && (tmp_rd_listsize/C_DEPTH_RATIO_WR<=C_FIFO_RD_DEPTH)) + begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= #`TCQ 1'b1; + //Not close to empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1)) + + //If the FIFO is two from empty + else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) + begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= #`TCQ 1'b1; + //Fifo is not yet empty. It is going almost_empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if (tmp_rd_listsize == 2) + + //If the FIFO is one from empty + else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR == 1)) + begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= #`TCQ 1'b1; + //Note that FIFO is GOING empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if (tmp_rd_listsize == 1) + + + //If the FIFO is completely empty + else if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) + begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if (tmp_rd_listsize <= 0) + + end // if (ideal_empty == 1'b0) + + end //(RD_EN == 1'b1) + + else //if (RD_EN == 1'b0) + begin + //If user did not attempt a read, do not give an ack or err + ideal_valid <= #`TCQ 1'b0; + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // else: !if(RD_EN == 1'b1) + + /*****************************************************************/ + // Read Operation - Read Latency 0 + /*****************************************************************/ + end else if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + ideal_valid <= #`TCQ 1'b0; + if (ram_rd_en == 1'b1) begin + + if (EMPTY == 1'b1) begin + + //If the FIFO is completely empty, and is reporting empty + if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Reminder that FIFO is still empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + //If the FIFO is one from empty, but it is reporting empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Note that FIFO is no longer empty, but is almost empty (has one word left) + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + //If the FIFO is two from empty, and is reporting empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Fifo has two words, so is neither empty or almost empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + //If the FIFO is not close to empty, but is reporting that it is + // Treat the FIFO as empty this time, but unset EMPTY flags. + end else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && + (tmp_rd_listsize/C_DEPTH_RATIO_WR<C_FIFO_RD_DEPTH)) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Note that the FIFO is No Longer Empty or Almost Empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1)) + + end else begin + + //If the FIFO is completely full, and we are successfully reading from it + if (tmp_rd_listsize/C_DEPTH_RATIO_WR >= C_FIFO_RD_DEPTH) begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= #`TCQ 1'b1; + //Not close to empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + //If the FIFO is not close to being empty + end else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && + (tmp_rd_listsize/C_DEPTH_RATIO_WR<=C_FIFO_RD_DEPTH)) begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= #`TCQ 1'b1; + //Not close to empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + //If the FIFO is two from empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= #`TCQ 1'b1; + //Fifo is not yet empty. It is going almost_empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + //If the FIFO is one from empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1) begin + //Read the value from the FIFO + read_fifo; + next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH; + + //Acknowledge the read from the FIFO, no error + ideal_valid <= #`TCQ 1'b1; + //Note that FIFO is GOING empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + //If the FIFO is completely empty + end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) begin + //Do not change the contents of the FIFO + + //Do not acknowledge the read from empty FIFO + ideal_valid <= #`TCQ 1'b0; + //Reminder that FIFO is still empty + + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // if (tmp_rd_listsize <= 0) + + end // if (ideal_empty == 1'b0) + + end else begin//(RD_EN == 1'b0) + + + //If user did not attempt a read, do not give an ack or err + ideal_valid <= #`TCQ 1'b0; + ideal_rd_count <= #`TCQ num_read_words_sized_i; + + end // else: !if(RD_EN == 1'b1) + end //if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) + + num_rd_bits <= #`TCQ next_num_rd_bits; + wr_ptr_rdclk <= #`TCQ wr_ptr; + end //rd_rst_i==0 + end //always + +endmodule // fifo_generator_v6_1_bhv_ver_as + + +/******************************************************************************* + * Declaration of top-level module + ******************************************************************************/ +module fifo_generator_v6_1_bhv_ver_ss + + /************************************************************************** + * Declare user parameters and their defaults + *************************************************************************/ + #( + parameter C_DATA_COUNT_WIDTH = 2, + parameter C_DIN_WIDTH = 8, + parameter C_DOUT_RST_VAL = "", + parameter C_DOUT_WIDTH = 8, + parameter C_FULL_FLAGS_RST_VAL = 1, + parameter C_HAS_ALMOST_EMPTY = 0, + parameter C_HAS_ALMOST_FULL = 0, + parameter C_HAS_DATA_COUNT = 0, + parameter C_HAS_OVERFLOW = 0, + parameter C_HAS_RD_DATA_COUNT = 0, + parameter C_HAS_RST = 0, + parameter C_HAS_SRST = 0, + parameter C_HAS_UNDERFLOW = 0, + parameter C_HAS_VALID = 0, + parameter C_HAS_WR_ACK = 0, + parameter C_HAS_WR_DATA_COUNT = 0, + parameter C_IMPLEMENTATION_TYPE = 0, + parameter C_MEMORY_TYPE = 1, + parameter C_OVERFLOW_LOW = 0, + parameter C_PRELOAD_LATENCY = 1, + parameter C_PRELOAD_REGS = 0, + parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0, + parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0, + parameter C_PROG_EMPTY_TYPE = 0, + parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0, + parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0, + parameter C_PROG_FULL_TYPE = 0, + parameter C_RD_DATA_COUNT_WIDTH = 2, + parameter C_RD_DEPTH = 256, + parameter C_RD_PNTR_WIDTH = 8, + parameter C_UNDERFLOW_LOW = 0, + parameter C_USE_DOUT_RST = 0, + parameter C_USE_EMBEDDED_REG = 0, + parameter C_USE_FWFT_DATA_COUNT = 0, + parameter C_VALID_LOW = 0, + parameter C_WR_ACK_LOW = 0, + parameter C_WR_DATA_COUNT_WIDTH = 2, + parameter C_WR_DEPTH = 256, + parameter C_WR_PNTR_WIDTH = 8, + parameter C_USE_ECC = 0, + parameter C_ENABLE_RST_SYNC = 1, + parameter C_ERROR_INJECTION_TYPE = 0 + ) + + /************************************************************************** + * Declare Input and Output Ports + *************************************************************************/ + ( + //Inputs + input CLK, + input [C_DIN_WIDTH-1:0] DIN, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT, + input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT, + input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE, + input RD_EN, + input RST, + input RST_FULL_GEN, + input RST_FULL_FF, + input SRST, + input WR_EN, + input INJECTDBITERR, + input INJECTSBITERR, + + //Outputs + output ALMOST_EMPTY, + output ALMOST_FULL, + output reg [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT, + output [C_DOUT_WIDTH-1:0] DOUT, + output EMPTY, + output FULL, + output OVERFLOW, + output PROG_EMPTY, + output PROG_FULL, + output VALID, + output UNDERFLOW, + output WR_ACK, + output SBITERR, + output DBITERR + ); + + + /*************************************************************************** + * Parameters used as constants + **************************************************************************/ + //When RST is present, set FULL reset value to '1'. + //If core has no RST, make sure FULL powers-on as '0'. + //The reset value assignments for FULL, ALMOST_FULL, and PROG_FULL are not + //changed for v3.2(IP2_Im). When the core has Sync Reset, C_HAS_SRST=1 and C_HAS_RST=0. + // Therefore, during SRST, all the FULL flags reset to 0. + parameter C_HAS_FAST_FIFO = 0; + parameter C_FIFO_WR_DEPTH = C_WR_DEPTH; + parameter C_FIFO_RD_DEPTH = C_RD_DEPTH; + + /************************************************************************** + * FIFO Contents Tracking and Data Count Calculations + *************************************************************************/ + // Memory which will be used to simulate a FIFO + reg [C_DIN_WIDTH-1:0] memory[C_WR_DEPTH-1:0]; + // Local parameters used to determine whether to inject ECC error or not + localparam SYMMETRIC_PORT = (C_DIN_WIDTH == C_DOUT_WIDTH) ? 1 : 0; + localparam ERR_INJECTION = (C_ERROR_INJECTION_TYPE != 0) ? 1 : 0; + localparam ENABLE_ERR_INJECTION = C_USE_ECC && SYMMETRIC_PORT && ERR_INJECTION; + // Array that holds the error injection type (single/double bit error) on + // a specific write operation, which is returned on read to corrupt the + // output data. + reg [1:0] ecc_err[C_WR_DEPTH-1:0]; + + //The amount of data stored in the FIFO at any time is given + // by num_bits. + //num_bits is calculated by from the total words in the FIFO. + reg [31:0] num_bits; + + //The write pointer - tracks write operations + // (Works opposite to core: wr_ptr is a DOWN counter) + reg [31:0] wr_ptr; + + //The write pointer - tracks read operations + // (Works opposite to core: rd_ptr is a DOWN counter) + reg [31:0] rd_ptr; + + /************************** + * Data Count + *************************/ + //Amount of data stored in the FIFO scaled to read words + wire [31:0] num_read_words = num_bits/C_DOUT_WIDTH; + //num_read_words delayed 1 clock cycle + reg [31:0] num_read_words_q; + + //Amount of data stored in the FIFO scaled to write words + wire [31:0] num_write_words = num_bits/C_DIN_WIDTH; + //num_write_words delayed 1 clock cycle + reg [31:0] num_write_words_q; + + + /************************************************************************** + * Internal Registers and wires + *************************************************************************/ + + //Temporary signals used for calculating the model's outputs. These + //are only used in the assign statements immediately following wire, + //parameter, and function declarations. + wire underflow_i; + wire valid_i; + wire valid_out; + + //Ideal FIFO signals. These are the raw output of the behavioral model, + //which behaves like an ideal FIFO. + reg [1:0] err_type = 0; + reg [1:0] err_type_d1 = 0; + reg [C_DOUT_WIDTH-1:0] ideal_dout = 0; + reg [C_DOUT_WIDTH-1:0] ideal_dout_d1 = 0; + wire [C_DOUT_WIDTH-1:0] ideal_dout_out; + wire fwft_enabled; + reg ideal_wr_ack = 0; + reg ideal_valid = 0; + reg ideal_overflow = 0; + reg ideal_underflow = 0; + reg ideal_full = 0; + reg ideal_empty = 1; + reg ideal_almost_full = 0; + reg ideal_almost_empty = 1; + reg ideal_prog_full = 0; + reg ideal_prog_empty = 1; + + //Assorted reg values for delayed versions of signals + reg valid_d1 = 0; + reg prog_full_d = 0; + reg prog_empty_d = 1; + + wire rst_i; + wire srst_i; + + //Delayed version of RST + reg rst_q; + reg rst_qq; + + //user specified value for reseting the size of the fifo + reg [C_DOUT_WIDTH-1:0] dout_reset_val = 0; + + + /**************************************************************************** + * Function Declarations + ***************************************************************************/ + + /************************************************************************** + * write_fifo + * This task writes a word to the FIFO memory and updates the + * write pointer. + * FIFO size is relative to write domain. + ***************************************************************************/ + task write_fifo; + reg [1:0] corrupted_data; + begin + memory[wr_ptr] <= DIN; + // Store the type of error injection (double/single) on write + case (C_ERROR_INJECTION_TYPE) + 3: ecc_err[wr_ptr] <= {INJECTDBITERR,INJECTSBITERR}; + 2: ecc_err[wr_ptr] <= {INJECTDBITERR,1'b0}; + 1: ecc_err[wr_ptr] <= {1'b0,INJECTSBITERR}; + default: ecc_err[wr_ptr] <= 0; + endcase + if (wr_ptr == 0) begin + wr_ptr <= C_WR_DEPTH - 1; + end else begin + wr_ptr <= wr_ptr - 1; + end + end + endtask // write_fifo + + /************************************************************************** + * read_fifo + * This task reads a word from the FIFO memory and updates the read + * pointer. It's output is the ideal_dout bus. + * FIFO size is relative to write domain. + ***************************************************************************/ + task read_fifo; + reg [C_DOUT_WIDTH-1:0] tmp_dout; + reg [1:0] tmp_ecc_err; + begin + tmp_dout = memory[rd_ptr][C_DOUT_WIDTH-1:0]; + // Retreive the error injection type. Based on the error injection type + // corrupt the output data. + tmp_ecc_err = ecc_err[rd_ptr]; + if (ENABLE_ERR_INJECTION) begin + if (tmp_ecc_err[1]) begin // Corrupt the output data only for double bit error + if (C_DOUT_WIDTH == 1) + tmp_dout = tmp_dout[C_DOUT_WIDTH-1:0]; + else if (C_DOUT_WIDTH == 2) + tmp_dout = {~tmp_dout[C_DOUT_WIDTH-1],~tmp_dout[C_DOUT_WIDTH-2]}; + else + tmp_dout = {~tmp_dout[C_DOUT_WIDTH-1],~tmp_dout[C_DOUT_WIDTH-2],(tmp_dout << 2)}; + end else begin + tmp_dout = tmp_dout[C_DOUT_WIDTH-1:0]; + end + err_type <= {tmp_ecc_err[1], tmp_ecc_err[0] & !tmp_ecc_err[1]}; + end else begin + err_type <= 0; + end + ideal_dout <= tmp_dout; + + if (rd_ptr == 0) begin + rd_ptr <= C_RD_DEPTH - 1; + end else begin + rd_ptr <= rd_ptr - 1; + end + end + endtask + + /**************************************************************************** + * log2_val + * Returns the 'log2' value for the input value for the supported ratios + ***************************************************************************/ + function [31:0] log2_val; + input [31:0] binary_val; + + begin + if (binary_val == 8) begin + log2_val = 3; + end else if (binary_val == 4) begin + log2_val = 2; + end else begin + log2_val = 1; + end + end + endfunction + + /**************************************************************************** + * hexstr_conv + * Converts a string of type hex to a binary value (for C_DOUT_RST_VAL) + ***************************************************************************/ + function [C_DOUT_WIDTH-1:0] hexstr_conv; + input [(C_DOUT_WIDTH*8)-1:0] def_data; + + integer index,i,j; + reg [3:0] bin; + + begin + index = 0; + hexstr_conv = 'b0; + for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 ) + begin + case (def_data[7:0]) + 8'b00000000 : + begin + bin = 4'b0000; + i = -1; + end + 8'b00110000 : bin = 4'b0000; + 8'b00110001 : bin = 4'b0001; + 8'b00110010 : bin = 4'b0010; + 8'b00110011 : bin = 4'b0011; + 8'b00110100 : bin = 4'b0100; + 8'b00110101 : bin = 4'b0101; + 8'b00110110 : bin = 4'b0110; + 8'b00110111 : bin = 4'b0111; + 8'b00111000 : bin = 4'b1000; + 8'b00111001 : bin = 4'b1001; + 8'b01000001 : bin = 4'b1010; + 8'b01000010 : bin = 4'b1011; + 8'b01000011 : bin = 4'b1100; + 8'b01000100 : bin = 4'b1101; + 8'b01000101 : bin = 4'b1110; + 8'b01000110 : bin = 4'b1111; + 8'b01100001 : bin = 4'b1010; + 8'b01100010 : bin = 4'b1011; + 8'b01100011 : bin = 4'b1100; + 8'b01100100 : bin = 4'b1101; + 8'b01100101 : bin = 4'b1110; + 8'b01100110 : bin = 4'b1111; + default : + begin + bin = 4'bx; + end + endcase + for( j=0; j<4; j=j+1) + begin + if ((index*4)+j < C_DOUT_WIDTH) + begin + hexstr_conv[(index*4)+j] = bin[j]; + end + end + index = index + 1; + def_data = def_data >> 8; + end + end + endfunction + + + /************************************************************************* + * Initialize Signals for clean power-on simulation + *************************************************************************/ + initial begin + num_bits = 0; + num_read_words_q = 0; + num_write_words_q = 0; + rd_ptr = C_RD_DEPTH -1; + wr_ptr = C_WR_DEPTH -1; + dout_reset_val = hexstr_conv(C_DOUT_RST_VAL); + ideal_dout = dout_reset_val; + err_type = 0; + ideal_wr_ack = 1'b0; + ideal_valid = 1'b0; + valid_d1 = 1'b0; + ideal_overflow = 1'b0; + ideal_underflow = 1'b0; + ideal_full = 1'b0; + ideal_empty = 1'b1; + ideal_almost_full = 1'b0; + ideal_almost_empty = 1'b1; + ideal_prog_full = 1'b0; + ideal_prog_empty = 1'b1; + prog_full_d = 1'b0; + prog_empty_d = 1'b1; + rst_q = 1'b0; + rst_qq = 1'b0; + end + + + /************************************************************************* + * Connect the module inputs and outputs to the internal signals of the + * behavioral model. + *************************************************************************/ + //Inputs + /* + wire CLK; + wire [C_DIN_WIDTH-1:0] DIN; + wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH; + wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT; + wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE; + wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH; + wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT; + wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE; + wire RD_EN; + wire RST; + wire WR_EN; + */ + + //Outputs + generate + if (C_HAS_ALMOST_EMPTY==1) begin : blockAE10 + assign ALMOST_EMPTY = ideal_almost_empty; + end + endgenerate + + generate + if (C_HAS_ALMOST_FULL==1) begin : blockAF10 + assign ALMOST_FULL = ideal_almost_full; + end + endgenerate + + //Dout may change behavior based on latency + assign fwft_enabled = (C_PRELOAD_LATENCY == 0 && C_PRELOAD_REGS == 1)? + 1: 0; + assign ideal_dout_out= ((C_USE_EMBEDDED_REG==1 && (fwft_enabled == 0)) && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))? + ideal_dout_d1: ideal_dout; + assign DOUT = ideal_dout_out; + + // Assign SBITERR and DBITERR based on latency + assign SBITERR = (C_ERROR_INJECTION_TYPE == 1 || C_ERROR_INJECTION_TYPE == 3) && + ((C_USE_EMBEDDED_REG==1 && (fwft_enabled == 0)) && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1)) ? + err_type_d1[0]: err_type[0]; + assign DBITERR = (C_ERROR_INJECTION_TYPE == 2 || C_ERROR_INJECTION_TYPE == 3) && + ((C_USE_EMBEDDED_REG==1 && (fwft_enabled == 0)) && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1)) ? + err_type_d1[1]: err_type[1]; + + assign EMPTY = ideal_empty; + assign FULL = ideal_full; + + //Overflow may be active-low + generate + if (C_HAS_OVERFLOW==1) begin : blockOF10 + assign OVERFLOW = ideal_overflow ? !C_OVERFLOW_LOW : C_OVERFLOW_LOW; + end + endgenerate + + assign PROG_EMPTY = ideal_prog_empty; + assign PROG_FULL = ideal_prog_full; + + //Valid may change behavior based on latency or active-low + generate + if (C_HAS_VALID==1) begin : blockVL10 + assign valid_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & ~EMPTY) : ideal_valid; + assign valid_out = (C_PRELOAD_LATENCY==2 && + (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))? + valid_d1: valid_i; + assign VALID = valid_out ? !C_VALID_LOW : C_VALID_LOW; + end + endgenerate + + //Trim data count differently depending on set widths + generate + if ((C_HAS_DATA_COUNT == 1) && + (C_DATA_COUNT_WIDTH > C_RD_PNTR_WIDTH)) begin : blockDC1 + always @(num_read_words) + DATA_COUNT = num_read_words[C_RD_PNTR_WIDTH:0]; + end else if (C_HAS_DATA_COUNT == 1) begin : blockDC2 + always @(num_read_words) + DATA_COUNT = num_read_words[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_DATA_COUNT_WIDTH]; + end //if + endgenerate + + //Underflow may change behavior based on latency or active-low + generate + if (C_HAS_UNDERFLOW==1) begin : blockUF10 + assign underflow_i = ideal_underflow; + assign UNDERFLOW = underflow_i ? !C_UNDERFLOW_LOW : C_UNDERFLOW_LOW; + end + endgenerate + + + //Write acknowledge may be active low + generate + if (C_HAS_WR_ACK==1) begin : blockWK10 + assign WR_ACK = ideal_wr_ack ? !C_WR_ACK_LOW : C_WR_ACK_LOW; + end + endgenerate + + + /***************************************************************************** + * Internal reset logic + ****************************************************************************/ + assign srst_i = C_HAS_SRST ? SRST : 0; + assign rst_i = C_HAS_RST ? RST : 0; + + /************************************************************************** + * Assorted registers for delayed versions of signals + **************************************************************************/ + //Capture delayed version of valid + generate + if (C_HAS_VALID==1) begin : blockVL20 + always @(posedge CLK or posedge rst_i) begin + if (rst_i == 1'b1) begin + valid_d1 <= #`TCQ 1'b0; + end else begin + if (srst_i) begin + valid_d1 <= #`TCQ 1'b0; + end else begin + valid_d1 <= #`TCQ valid_i; + end + end + end // always @ (posedge CLK or posedge rst_i) + end + endgenerate + + + // block memory has a synchronous reset + always @(posedge CLK) begin : gen_fifo_blkmemdout_emb + // make it consistent with the core. + if (rst_i || srst_i) begin + // BRAM resets synchronously + if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE < 2) begin + ideal_dout_d1 <= #`TCQ dout_reset_val; + end + end + end //always + + reg ram_rd_en_d1 = 1'b0; + //Capture delayed version of dout + always @(posedge CLK or posedge rst_i) begin + if (rst_i == 1'b1) begin + // Reset err_type only if ECC is not selected + if (C_USE_ECC == 0) + err_type_d1 <= #`TCQ 0; + + // DRAM and SRAM reset asynchronously + if ((C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3) && C_USE_DOUT_RST == 1) + ideal_dout_d1 <= #`TCQ dout_reset_val; + + ram_rd_en_d1 <= #`TCQ 1'b0; + end else begin + ram_rd_en_d1 <= #`TCQ RD_EN & !EMPTY; + if (srst_i) begin + ram_rd_en_d1 <= #`TCQ 1'b0; + // Reset err_type only if ECC is not selected + if (C_USE_ECC == 0) + err_type_d1 <= #`TCQ 0; + // Reset DRAM and SRAM based FIFO, BRAM based FIFO is reset above + if ((C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3) && C_USE_DOUT_RST == 1) + ideal_dout_d1 <= #`TCQ dout_reset_val; + end else if (ram_rd_en_d1) begin + ideal_dout_d1 <= #`TCQ ideal_dout; + err_type_d1 <= #`TCQ err_type; + end + end + end + + /************************************************************************** + * Overflow and Underflow Flag calculation + * (handled separately because they don't support rst) + **************************************************************************/ + generate + if (C_HAS_OVERFLOW==1) begin : blockOF20 + always @(posedge CLK) begin + ideal_overflow <= #`TCQ WR_EN & ideal_full; + end + end + endgenerate + + generate + if (C_HAS_UNDERFLOW==1) begin : blockUF20 + always @(posedge CLK) begin + ideal_underflow <= #`TCQ ideal_empty & RD_EN; + end + end + endgenerate + + /************************************************************************* + * Write and Read Logic + ************************************************************************/ + always @(posedge CLK or posedge rst_i) + begin : gen_wr_ack_resp + + //Register reset + rst_q <= #`TCQ rst_i; + rst_qq <= #`TCQ rst_q; + + end // block: gen_wr_ack_resp + + // block memory has a synchronous reset + always @(posedge CLK) begin : gen_fifo_blkmemdout + //Changed the latency of during async reset to '1' instead of '2' to + // make it consistent with the core. + if (rst_i || rst_q || srst_i) begin + // Reset err_type only if ECC is not selected + if (C_USE_ECC == 0 && C_MEMORY_TYPE == 1) + err_type <= #`TCQ 0; + /******Initialize Read Domain Signals*********************************/ + if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE < 2) begin + ideal_dout <= #`TCQ dout_reset_val; + end + end + end //always + + // FULL_FLAG_RESET value given for SRST as well. + reg srst_i_d1 = 0; + reg srst_i_d2 = 0; + always @(posedge CLK or posedge RST_FULL_FF) begin : gen_fifo + + /****** Reset fifo - Asynchronous Reset**********************************/ + //Changed the latency of during async reset to '1' instead of '2' to + // make it consistent with the core. + if (RST_FULL_FF) begin //v3.2 + /******Initialize Generic FIFO constructs*****************************/ + num_bits <= #`TCQ 0; + wr_ptr <= #`TCQ C_WR_DEPTH - 1; + rd_ptr <= #`TCQ C_RD_DEPTH - 1; + num_read_words_q <= #`TCQ 0; + num_write_words_q <= #`TCQ 0; + // Reset err_type only if ECC is not selected + if (C_USE_ECC == 0 && C_MEMORY_TYPE != 1) + err_type <= #`TCQ 0; + + + /******Initialize Write Domain Signals********************************/ + ideal_wr_ack <= #`TCQ 0; + ideal_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + ideal_almost_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + + /******Initialize Read Domain Signals*********************************/ + // DRAM and SRAM reset asynchronously + if (C_USE_DOUT_RST == 1 && (C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3)) begin + ideal_dout <= #`TCQ dout_reset_val; + end + ideal_valid <= #`TCQ 1'b0; + ideal_empty <= #`TCQ 1'b1; + ideal_almost_empty <= #`TCQ 1'b1; + + end else begin + // Register SRST twice to be consistant with RST behavior + srst_i_d1 <= #`TCQ srst_i; + srst_i_d2 <= #`TCQ srst_i_d1; + if (srst_i) begin + // SRST is available only for Sync BRAM, DRAM and SRAM. + if (C_MEMORY_TYPE == 1 || C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3) begin + /******Initialize Generic FIFO constructs***********************/ + num_bits <= #`TCQ 0; + wr_ptr <= #`TCQ C_WR_DEPTH - 1; + rd_ptr <= #`TCQ C_RD_DEPTH - 1; + num_read_words_q <= #`TCQ 0; + num_write_words_q <= #`TCQ 0; + // Reset err_type only if ECC is not selected + if (C_USE_ECC == 0) + err_type <= #`TCQ 0; + + /******Initialize Write Domain Signals**************************/ + ideal_wr_ack <= #`TCQ 0; + ideal_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + ideal_almost_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + + /******Initialize Read Domain Signals***************************/ + //Reset DOUT of Sync DRAM/Shift RAM. Sync BRAM DOUT was reset in the + // above always block. + if (C_USE_DOUT_RST == 1 && (C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3)) begin + ideal_dout <= #`TCQ dout_reset_val; + end + ideal_valid <= #`TCQ 1'b0; + ideal_empty <= #`TCQ 1'b1; + ideal_almost_empty <= #`TCQ 1'b1; + end + + end else if ((srst_i_d1 || srst_i_d2) && (C_FULL_FLAGS_RST_VAL == 1)) begin //Hold full flag reset value set during RST/SRST + ideal_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + ideal_almost_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + end else begin //normal operating conditions + /********************************************************************/ + // Synchronous FIFO Condition #1 : Writing and not reading + /********************************************************************/ + ideal_valid <= #`TCQ 1'b0; + if (WR_EN & ~RD_EN) begin + + /*********************************/ + //If the FIFO is full, do NOT perform the write, + // update flags accordingly + /*********************************/ + if (num_write_words >= C_FIFO_WR_DEPTH) begin + ideal_wr_ack <= #`TCQ 0; + + //still full + ideal_full <= #`TCQ 1'b1; + ideal_almost_full <= #`TCQ 1'b1; + + //write unsuccessful - do not change contents + + // no read attempted + ideal_valid <= #`TCQ 1'b0; + + //Not near empty + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + + /*********************************/ + //If the FIFO is reporting FULL + // (Startup condition) + /*********************************/ + end else if ((num_write_words < C_FIFO_WR_DEPTH) && (ideal_full == 1'b1)) begin + ideal_wr_ack <= #`TCQ 0; + + //still full + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //write unsuccessful - do not change contents + + // no read attempted + ideal_valid <= #`TCQ 1'b0; + + //FIFO EMPTY in this state can not be determined + //ideal_empty <= 1'b0; + //ideal_almost_empty <= 1'b0; + + + /*********************************/ + //If the FIFO is one from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-1) begin + //good write + ideal_wr_ack <= #`TCQ 1; + + //FIFO is one from FULL and going FULL + ideal_full <= #`TCQ 1'b1; + ideal_almost_full <= #`TCQ 1'b1; + + //Add input data + write_fifo; + + // no read attempted + ideal_valid <= #`TCQ 1'b0; + + //Not near empty + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + num_bits <= num_bits + C_DIN_WIDTH; + + /*********************************/ + //If the FIFO is 2 from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-2) begin + //good write + ideal_wr_ack <= #`TCQ 1; + + //2 from full, and writing, so set almost_full + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b1; + + //Add input data + write_fifo; + + //no read attempted + ideal_valid <= #`TCQ 1'b0; + + //Not near empty + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + num_bits <= #`TCQ num_bits + C_DIN_WIDTH; + + /*********************************/ + //If the FIFO is ALMOST EMPTY + /*********************************/ + end else if (num_read_words == 1) begin + //good write + ideal_wr_ack <= #`TCQ 1; + + //Not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Add input data + write_fifo; + + // no read attempted + ideal_valid <= #`TCQ 1'b0; + + //Leaving ALMOST_EMPTY + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + num_bits <= #`TCQ num_bits + C_DIN_WIDTH; + + /*********************************/ + //If the FIFO is EMPTY + /*********************************/ + end else if (num_read_words == 0) begin + // good write + ideal_wr_ack <= #`TCQ 1; + + //Not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Add input data + write_fifo; + + // no read attempted + ideal_valid <= #`TCQ 1'b0; + + //Leaving EMPTY (still ALMOST_EMPTY) + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b1; + + num_bits <= #`TCQ num_bits + C_DIN_WIDTH; + + /*********************************/ + //If the FIFO is not near EMPTY or FULL + /*********************************/ + end else begin + // good write + ideal_wr_ack <= #`TCQ 1; + + //Not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Add input data + write_fifo; + + // no read attempted + ideal_valid <= #`TCQ 1'b0; + + //Not near EMPTY + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + num_bits <= #`TCQ num_bits + C_DIN_WIDTH; + + end // average case + + + /******************************************************************/ + // Synchronous FIFO Condition #2 : Reading and not writing + /******************************************************************/ + end else if (~WR_EN & RD_EN) begin + + /*********************************/ + //If the FIFO is EMPTY + /*********************************/ + if ((num_read_words == 0) || (ideal_empty == 1'b1)) begin + //no write attemped + ideal_wr_ack <= #`TCQ 0; + + //FIFO is not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Read will fail + ideal_valid <= #`TCQ 1'b0; + + //FIFO is still empty + ideal_empty <= #`TCQ 1'b1; + ideal_almost_empty <= #`TCQ 1'b1; + + //No read + + /*********************************/ + //If the FIFO is ALMOST EMPTY + /*********************************/ + end else if (num_read_words == 1) begin + //no write attempted + ideal_wr_ack <= #`TCQ 0; + + //FIFO is not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + //This read will make FIFO go empty + ideal_empty <= #`TCQ 1'b1; + ideal_almost_empty <= #`TCQ 1'b1; + + //Get the data from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits - C_DIN_WIDTH; + + + /*********************************/ + //If the FIFO is 2 from EMPTY + /*********************************/ + end else if (num_read_words == 2) begin + + //no write attempted + ideal_wr_ack <= #`TCQ 0; + + //FIFO is not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + //FIFO is going ALMOST_EMPTY + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b1; + + //Get the data from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits - C_DOUT_WIDTH; + + + + /*********************************/ + //If the FIFO is one from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-1) begin + + //no write attempted + ideal_wr_ack <= #`TCQ 0; + + //FIFO is leaving ALMOST FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + //Not near empty + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits - C_DOUT_WIDTH; + + + /*********************************/ + // FIFO is FULL + /*********************************/ + end else if (num_write_words >= C_FIFO_WR_DEPTH) + begin + //no write attempted + ideal_wr_ack <= #`TCQ 0; + + //FIFO is leaving FULL, but is still ALMOST_FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b1; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + //Not near empty + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits - C_DOUT_WIDTH; + + /*********************************/ + //If the FIFO is not near EMPTY or FULL + /*********************************/ + end else begin + //no write attemped + ideal_wr_ack <= #`TCQ 0; + + //Not near empty + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + //Not near empty + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits - C_DOUT_WIDTH; + + + end // average read + + + /******************************************************************/ + // Synchronous FIFO Condition #3 : Reading and writing + /******************************************************************/ + end else if (WR_EN & RD_EN) begin + + /*********************************/ + // FIFO is FULL + /*********************************/ + if (num_write_words >= C_FIFO_WR_DEPTH) begin + + ideal_wr_ack <= #`TCQ 0; + + //Read will be successful, so FIFO will leave FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b1; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + //Not near empty + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits - C_DOUT_WIDTH; + + + /*********************************/ + // FIFO is reporting FULL, but it is empty + // (This is a special case, when coming out of RST + /*********************************/ + end else if ((num_write_words == 0) && (ideal_full == 1'b1)) begin + + ideal_wr_ack <= #`TCQ 0; + + //Read will be successful, so FIFO will leave FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //Read unsuccessful + ideal_valid <= #`TCQ 1'b0; + + //Report empty condition + ideal_empty <= #`TCQ 1'b1; + ideal_almost_empty <= #`TCQ 1'b1; + + //Do not read from empty FIFO + // Read from the FIFO + + + /*********************************/ + //If the FIFO is one from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-1) begin + + //Write successful + ideal_wr_ack <= #`TCQ 1; + + //FIFO will remain ALMOST_FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b1; + + // put the data into the FIFO + write_fifo; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + //Not near empty + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits + C_DIN_WIDTH - C_DOUT_WIDTH; + + /*********************************/ + //If the FIFO is ALMOST EMPTY + /*********************************/ + end else if (num_read_words == 1) begin + + //Write successful + ideal_wr_ack <= #`TCQ 1; + + // Not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + // put the data into the FIFO + write_fifo; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + //FIFO will stay ALMOST_EMPTY + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b1; + + //Read from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits + C_DIN_WIDTH - C_DOUT_WIDTH; + + + /*********************************/ + //If the FIFO is EMPTY + /*********************************/ + end else if (num_read_words == 0) begin + + //Write successful + ideal_wr_ack <= #`TCQ 1; + + // Not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + // put the data into the FIFO + write_fifo; + + //Read will fail + ideal_valid <= #`TCQ 1'b0; + + //FIFO will leave EMPTY + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b1; + + // No read + num_bits <= #`TCQ num_bits + C_DIN_WIDTH; + + + /*********************************/ + //If the FIFO is not near EMPTY or FULL + /*********************************/ + end else begin + + //Write successful + ideal_wr_ack <= #`TCQ 1; + + // Not near FULL + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + // put the data into the FIFO + write_fifo; + + //Read successful + ideal_valid <= #`TCQ 1'b1; + + // Not near EMPTY + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //Read from the FIFO + read_fifo; + num_bits <= #`TCQ num_bits + C_DIN_WIDTH - C_DOUT_WIDTH; + + end // average case + + /******************************************************************/ + // Synchronous FIFO Condition #4 : Not reading or writing + /******************************************************************/ + end else begin + + /*********************************/ + // FIFO is FULL + /*********************************/ + if (num_write_words >= C_FIFO_WR_DEPTH) begin + + //No write + ideal_wr_ack <= #`TCQ 0; + ideal_full <= #`TCQ 1'b1; + ideal_almost_full <= #`TCQ 1'b1; + + //No read + ideal_valid <= #`TCQ 1'b0; + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //No change to memory + + /*********************************/ + //If the FIFO is one from full + /*********************************/ + end else if (num_write_words == C_FIFO_WR_DEPTH-1) begin + + //No write + ideal_wr_ack <= #`TCQ 0; + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b1; + + //No read + ideal_valid <= #`TCQ 1'b0; + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //No change to memory + + /*********************************/ + //If the FIFO is ALMOST EMPTY + /*********************************/ + end else if (num_read_words == 1) begin + //No write + ideal_wr_ack <= #`TCQ 0; + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //No read + ideal_valid <= #`TCQ 1'b0; + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b1; + + //No change to memory + + end // almost empty + + + /*********************************/ + //If the FIFO is EMPTY + /*********************************/ + else if (num_read_words == 0) + begin + //No write + ideal_wr_ack <= #`TCQ 0; + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //No read + ideal_valid <= #`TCQ 1'b0; + ideal_empty <= #`TCQ 1'b1; + ideal_almost_empty <= #`TCQ 1'b1; + + //No change to memory + + /*********************************/ + //If the FIFO is not near EMPTY or FULL + /*********************************/ + end else begin + + //No write + ideal_wr_ack <= #`TCQ 0; + ideal_full <= #`TCQ 1'b0; + ideal_almost_full <= #`TCQ 1'b0; + + //No read + ideal_valid <= #`TCQ 1'b0; + ideal_empty <= #`TCQ 1'b0; + ideal_almost_empty <= #`TCQ 1'b0; + + //No change to memory + + end // average case + + end // neither reading or writing + + num_read_words_q <= #`TCQ num_read_words; + num_write_words_q <= #`TCQ num_write_words; + + end //normal operating conditions + end + + end // block: gen_fifo + + + always @(posedge CLK or posedge RST_FULL_FF) begin : gen_fifo_p + + /****** Reset fifo - Async Reset****************************************/ + //The latency of de-assertion of the flags is reduced by 1 to be + // consistent with the core. + if (RST_FULL_FF) begin + ideal_prog_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + ideal_prog_empty <= #`TCQ 1'b1; + prog_full_d <= #`TCQ C_FULL_FLAGS_RST_VAL; + prog_empty_d <= #`TCQ 1'b1; + + end else begin + if (srst_i) begin + //SRST is available only for Sync BRAM and Sync DRAM. Not for SSHFT. + if (C_MEMORY_TYPE == 1 || C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3) begin + ideal_prog_empty <= #`TCQ 1'b1; + prog_empty_d <= #`TCQ 1'b1; + ideal_prog_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + prog_full_d <= #`TCQ C_FULL_FLAGS_RST_VAL; + end + end else if ((srst_i_d1 || srst_i_d2) && (C_FULL_FLAGS_RST_VAL == 1)) begin + ideal_prog_full <= #`TCQ C_FULL_FLAGS_RST_VAL; + prog_full_d <= #`TCQ C_FULL_FLAGS_RST_VAL; + end else begin + + /*************************************************************** + * Programmable FULL flags + ****************************************************************/ + //calculation for standard fifo and latency =2 + if (! (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) ) begin + //Single constant threshold + if (C_PROG_FULL_TYPE == 1) begin + if ((num_write_words >= C_PROG_FULL_THRESH_ASSERT_VAL-1) + && WR_EN && !RD_EN) begin + prog_full_d <= #`TCQ 1'b1; + end else if (((num_write_words == C_PROG_FULL_THRESH_ASSERT_VAL) + && RD_EN && !WR_EN) || (RST_FULL_GEN)) begin + prog_full_d <= #`TCQ 1'b0; + end + + //Dual constant thresholds + end else if (C_PROG_FULL_TYPE == 2) begin + if ((num_write_words == C_PROG_FULL_THRESH_ASSERT_VAL-1) + && WR_EN && !RD_EN) begin + prog_full_d <= #`TCQ 1'b1; + end else if ((num_write_words == C_PROG_FULL_THRESH_NEGATE_VAL) + && RD_EN && !WR_EN) begin + prog_full_d <= #`TCQ 1'b0; + end + + //Single input threshold + end else if (C_PROG_FULL_TYPE == 3) begin + if ((num_write_words == PROG_FULL_THRESH-1) + && WR_EN && !RD_EN) begin + prog_full_d <= #`TCQ 1'b1; + end else if ((num_write_words == PROG_FULL_THRESH) + && !WR_EN && RD_EN) begin + prog_full_d <= #`TCQ 1'b0; + end else if (num_write_words >= PROG_FULL_THRESH) begin + prog_full_d <= #`TCQ 1'b1; + end else if (num_write_words < PROG_FULL_THRESH) begin + prog_full_d <= #`TCQ 1'b0; + end + + //Dual input thresholds + end else begin + if ((num_write_words == PROG_FULL_THRESH_ASSERT-1) + && WR_EN && !RD_EN) begin + prog_full_d <= #`TCQ 1'b1; + end else if ((num_write_words == PROG_FULL_THRESH_NEGATE) + && !WR_EN && RD_EN)begin + prog_full_d <= #`TCQ 1'b0; + end else if (num_write_words >= PROG_FULL_THRESH_ASSERT) begin + prog_full_d <= #`TCQ 1'b1; + end else if (num_write_words < PROG_FULL_THRESH_NEGATE) begin + prog_full_d <= #`TCQ 1'b0; + end + end + end // (~ (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) ) + + + //calculation for FWFT fifo + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + if (C_PROG_FULL_TYPE == 1) begin + if ((num_write_words >= C_PROG_FULL_THRESH_ASSERT_VAL-1 - 2) + && WR_EN && !RD_EN) begin + prog_full_d <= #`TCQ 1'b1; + end else if (((num_write_words == C_PROG_FULL_THRESH_ASSERT_VAL - 2) + && RD_EN && !WR_EN) || (RST_FULL_GEN)) begin + prog_full_d <= #`TCQ 1'b0; + end + + //Dual constant thresholds + end else if (C_PROG_FULL_TYPE == 2) begin + if ((num_write_words == C_PROG_FULL_THRESH_ASSERT_VAL-1 - 2) + && WR_EN && !RD_EN) begin + prog_full_d <= #`TCQ 1'b1; + end else if ((num_write_words == C_PROG_FULL_THRESH_NEGATE_VAL - 2) + && RD_EN && !WR_EN) begin + prog_full_d <= #`TCQ 1'b0; + end + + //Single input threshold + end else if (C_PROG_FULL_TYPE == 3) begin + if ((num_write_words == PROG_FULL_THRESH-1 - 2) + && WR_EN && !RD_EN) begin + prog_full_d <= #`TCQ 1'b1; + end else if ((num_write_words == PROG_FULL_THRESH - 2) + && !WR_EN && RD_EN) begin + prog_full_d <= #`TCQ 1'b0; + end else if (num_write_words >= PROG_FULL_THRESH - 2) begin + prog_full_d <= #`TCQ 1'b1; + end else if (num_write_words < PROG_FULL_THRESH - 2) begin + prog_full_d <= #`TCQ 1'b0; + end + + //Dual input thresholds + end else begin + if ((num_write_words == PROG_FULL_THRESH_ASSERT-1 - 2) + && WR_EN && !RD_EN) begin + prog_full_d <= #`TCQ 1'b1; + end else if ((num_write_words == PROG_FULL_THRESH_NEGATE - 2) + && !WR_EN && RD_EN)begin + prog_full_d <= #`TCQ 1'b0; + end else if (num_write_words >= PROG_FULL_THRESH_ASSERT - 2) begin + prog_full_d <= #`TCQ 1'b1; + end else if (num_write_words < PROG_FULL_THRESH_NEGATE - 2) begin + prog_full_d <= #`TCQ 1'b0; + end + end + end // (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) + + /***************************************************************** + * Programmable EMPTY flags + ****************************************************************/ + //calculation for standard fifo and latency = 2 + if (! (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) ) begin + //Single constant threshold + if (C_PROG_EMPTY_TYPE == 1) begin + if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL+1) + && RD_EN && !WR_EN) begin + prog_empty_d <= #`TCQ 1'b1; + end else if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL) + && WR_EN && !RD_EN) begin + prog_empty_d <= #`TCQ 1'b0; + end + //Dual constant thresholds + end else if (C_PROG_EMPTY_TYPE == 2) begin + if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL+1) + && RD_EN && !WR_EN) begin + prog_empty_d <= #`TCQ 1'b1; + end else if ((num_read_words == C_PROG_EMPTY_THRESH_NEGATE_VAL) + && !RD_EN && WR_EN) begin + prog_empty_d <= #`TCQ 1'b0; + end + + //Single input threshold + end else if (C_PROG_EMPTY_TYPE == 3) begin + if ((num_read_words == PROG_EMPTY_THRESH+1) + && RD_EN && !WR_EN) begin + prog_empty_d <= #`TCQ 1'b1; + end else if ((num_read_words == PROG_EMPTY_THRESH) + && !RD_EN && WR_EN) begin + prog_empty_d <= #`TCQ 1'b0; + end else if (num_read_words <= PROG_EMPTY_THRESH) begin + prog_empty_d <= #`TCQ 1'b1; + end else if (num_read_words > PROG_EMPTY_THRESH)begin + prog_empty_d <= #`TCQ 1'b0; + end + + //Dual input thresholds + end else begin + if (num_read_words <= PROG_EMPTY_THRESH_ASSERT) begin + prog_empty_d <= #`TCQ 1'b1; + end else if ((num_read_words == PROG_EMPTY_THRESH_ASSERT+1) + && RD_EN && !WR_EN) begin + prog_empty_d <= #`TCQ 1'b1; + end else if (num_read_words > PROG_EMPTY_THRESH_NEGATE)begin + prog_empty_d <= #`TCQ 1'b0; + end else if ((num_read_words == PROG_EMPTY_THRESH_NEGATE) + && !RD_EN && WR_EN) begin + prog_empty_d <= #`TCQ 1'b0; + end + end + end // (~ (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) ) + + //calculation for FWFT fifo + if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin + //Single constant threshold + if (C_PROG_EMPTY_TYPE == 1) begin + if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL+1 - 2) + && RD_EN && !WR_EN) begin + prog_empty_d <= #`TCQ 1'b1; + end else if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL - 2) + && WR_EN && !RD_EN) begin + prog_empty_d <= #`TCQ 1'b0; + end + //Dual constant thresholds + end else if (C_PROG_EMPTY_TYPE == 2) begin + if ((num_read_words == C_PROG_EMPTY_THRESH_ASSERT_VAL+1 - 2) + && RD_EN && !WR_EN) begin + prog_empty_d <= #`TCQ 1'b1; + end else if ((num_read_words == C_PROG_EMPTY_THRESH_NEGATE_VAL - 2) + && !RD_EN && WR_EN) begin + prog_empty_d <= #`TCQ 1'b0; + end + + //Single input threshold + end else if (C_PROG_EMPTY_TYPE == 3) begin + if ((num_read_words == PROG_EMPTY_THRESH+1 - 2) + && RD_EN && !WR_EN) begin + prog_empty_d <= #`TCQ 1'b1; + end else if ((num_read_words == PROG_EMPTY_THRESH - 2) + && !RD_EN && WR_EN) begin + prog_empty_d <= #`TCQ 1'b0; + end else if (num_read_words <= PROG_EMPTY_THRESH - 2) begin + prog_empty_d <= #`TCQ 1'b1; + end else if (num_read_words > PROG_EMPTY_THRESH - 2)begin + prog_empty_d <= #`TCQ 1'b0; + end + + //Dual input thresholds + end else begin + if (num_read_words <= PROG_EMPTY_THRESH_ASSERT - 2) begin + prog_empty_d <= #`TCQ 1'b1; + end else if ((num_read_words == PROG_EMPTY_THRESH_ASSERT+1 - 2) + && RD_EN && !WR_EN) begin + prog_empty_d <= #`TCQ 1'b1; + end else if (num_read_words > PROG_EMPTY_THRESH_NEGATE - 2)begin + prog_empty_d <= #`TCQ 1'b0; + end else if ((num_read_words == PROG_EMPTY_THRESH_NEGATE - 2) + && !RD_EN && WR_EN) begin + prog_empty_d <= #`TCQ 1'b0; + end + end + end // (~ (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) ) + + ideal_prog_empty <= prog_empty_d; + if (RST_FULL_GEN) begin + ideal_prog_full <= #`TCQ 1'b0; + prog_full_d <= #`TCQ 1'b0; + end else begin + ideal_prog_full <= #`TCQ prog_full_d; + end + + end //if (srst_i) begin + end //if (rst_i) begin + end //always @(posedge CLK or posedge rst_i) begin : gen_fifo_p +endmodule // fifo_generator_v6_1_bhv_ver_ss + + + +/************************************************************************** + * First-Word Fall-Through module (preload 0) + **************************************************************************/ +module fifo_generator_v6_1_bhv_ver_preload0 + ( + RD_CLK, + RD_RST, + SRST, + RD_EN, + FIFOEMPTY, + FIFODATA, + FIFOSBITERR, + FIFODBITERR, + USERDATA, + USERVALID, + USERUNDERFLOW, + USEREMPTY, + USERALMOSTEMPTY, + RAMVALID, + FIFORDEN, + USERSBITERR, + USERDBITERR + ); + + parameter C_DOUT_RST_VAL = ""; + parameter C_DOUT_WIDTH = 8; + parameter C_HAS_RST = 0; + parameter C_ENABLE_RST_SYNC = 0; + parameter C_HAS_SRST = 0; + parameter C_USE_DOUT_RST = 0; + parameter C_USE_ECC = 0; + parameter C_USERVALID_LOW = 0; + parameter C_USERUNDERFLOW_LOW = 0; + parameter C_MEMORY_TYPE = 0; + + //Inputs + input RD_CLK; + input RD_RST; + input SRST; + input RD_EN; + input FIFOEMPTY; + input [C_DOUT_WIDTH-1:0] FIFODATA; + input FIFOSBITERR; + input FIFODBITERR; + + //Outputs + output [C_DOUT_WIDTH-1:0] USERDATA; + output USERVALID; + output USERUNDERFLOW; + output USEREMPTY; + output USERALMOSTEMPTY; + output RAMVALID; + output FIFORDEN; + output USERSBITERR; + output USERDBITERR; + + //Inputs + wire RD_CLK; + wire RD_RST; + wire RD_EN; + wire FIFOEMPTY; + wire [C_DOUT_WIDTH-1:0] FIFODATA; + wire FIFOSBITERR; + wire FIFODBITERR; + + //Outputs + reg [C_DOUT_WIDTH-1:0] USERDATA; + wire USERVALID; + wire USERUNDERFLOW; + wire USEREMPTY; + wire USERALMOSTEMPTY; + wire RAMVALID; + wire FIFORDEN; + reg USERSBITERR; + reg USERDBITERR; + + //Internal signals + wire preloadstage1; + wire preloadstage2; + reg ram_valid_i; + reg read_data_valid_i; + wire ram_regout_en; + wire ram_rd_en; + reg empty_i = 1'b1; + reg empty_q = 1'b1; + reg rd_en_q = 1'b0; + reg almost_empty_i = 1'b1; + reg almost_empty_q = 1'b1; + wire rd_rst_i; + wire srst_i; + + +/************************************************************************* +* FUNCTIONS +*************************************************************************/ + + /************************************************************************* + * hexstr_conv + * Converts a string of type hex to a binary value (for C_DOUT_RST_VAL) + ***********************************************************************/ + function [C_DOUT_WIDTH-1:0] hexstr_conv; + input [(C_DOUT_WIDTH*8)-1:0] def_data; + + integer index,i,j; + reg [3:0] bin; + + begin + index = 0; + hexstr_conv = 'b0; + for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 ) + begin + case (def_data[7:0]) + 8'b00000000 : + begin + bin = 4'b0000; + i = -1; + end + 8'b00110000 : bin = 4'b0000; + 8'b00110001 : bin = 4'b0001; + 8'b00110010 : bin = 4'b0010; + 8'b00110011 : bin = 4'b0011; + 8'b00110100 : bin = 4'b0100; + 8'b00110101 : bin = 4'b0101; + 8'b00110110 : bin = 4'b0110; + 8'b00110111 : bin = 4'b0111; + 8'b00111000 : bin = 4'b1000; + 8'b00111001 : bin = 4'b1001; + 8'b01000001 : bin = 4'b1010; + 8'b01000010 : bin = 4'b1011; + 8'b01000011 : bin = 4'b1100; + 8'b01000100 : bin = 4'b1101; + 8'b01000101 : bin = 4'b1110; + 8'b01000110 : bin = 4'b1111; + 8'b01100001 : bin = 4'b1010; + 8'b01100010 : bin = 4'b1011; + 8'b01100011 : bin = 4'b1100; + 8'b01100100 : bin = 4'b1101; + 8'b01100101 : bin = 4'b1110; + 8'b01100110 : bin = 4'b1111; + default : + begin + bin = 4'bx; + end + endcase + for( j=0; j<4; j=j+1) + begin + if ((index*4)+j < C_DOUT_WIDTH) + begin + hexstr_conv[(index*4)+j] = bin[j]; + end + end + index = index + 1; + def_data = def_data >> 8; + end + end + endfunction + + + //************************************************************************* + // Set power-on states for regs + //************************************************************************* + initial begin + ram_valid_i = 1'b0; + read_data_valid_i = 1'b0; + USERDATA = hexstr_conv(C_DOUT_RST_VAL); + USERSBITERR = 1'b0; + USERDBITERR = 1'b0; + end //initial + + //*************************************************************************** + // connect up optional reset + //*************************************************************************** + assign rd_rst_i = (C_HAS_RST == 1 || C_ENABLE_RST_SYNC == 0) ? RD_RST : 0; + assign srst_i = C_HAS_SRST ? SRST : 0; + + + //*************************************************************************** + // preloadstage2 indicates that stage2 needs to be updated. This is true + // whenever read_data_valid is false, and RAM_valid is true. + //*************************************************************************** + assign preloadstage2 = ram_valid_i & (~read_data_valid_i | RD_EN); + + //*************************************************************************** + // preloadstage1 indicates that stage1 needs to be updated. This is true + // whenever the RAM has data (RAM_EMPTY is false), and either RAM_Valid is + // false (indicating that Stage1 needs updating), or preloadstage2 is active + // (indicating that Stage2 is going to update, so Stage1, therefore, must + // also be updated to keep it valid. + //*************************************************************************** + assign preloadstage1 = ((~ram_valid_i | preloadstage2) & ~FIFOEMPTY); + + //*************************************************************************** + // Calculate RAM_REGOUT_EN + // The output registers are controlled by the ram_regout_en signal. + // These registers should be updated either when the output in Stage2 is + // invalid (preloadstage2), OR when the user is reading, in which case the + // Stage2 value will go invalid unless it is replenished. + //*************************************************************************** + assign ram_regout_en = preloadstage2; + + //*************************************************************************** + // Calculate RAM_RD_EN + // RAM_RD_EN will be asserted whenever the RAM needs to be read in order to + // update the value in Stage1. + // One case when this happens is when preloadstage1=true, which indicates + // that the data in Stage1 or Stage2 is invalid, and needs to automatically + // be updated. + // The other case is when the user is reading from the FIFO, which + // guarantees that Stage1 or Stage2 will be invalid on the next clock + // cycle, unless it is replinished by data from the memory. So, as long + // as the RAM has data in it, a read of the RAM should occur. + //*************************************************************************** + assign ram_rd_en = (RD_EN & ~FIFOEMPTY) | preloadstage1; + + //*************************************************************************** + // Calculate RAMVALID_P0_OUT + // RAMVALID_P0_OUT indicates that the data in Stage1 is valid. + // + // If the RAM is being read from on this clock cycle (ram_rd_en=1), then + // RAMVALID_P0_OUT is certainly going to be true. + // If the RAM is not being read from, but the output registers are being + // updated to fill Stage2 (ram_regout_en=1), then Stage1 will be emptying, + // therefore causing RAMVALID_P0_OUT to be false. + // Otherwise, RAMVALID_P0_OUT will remain unchanged. + //*************************************************************************** + // PROCESS regout_valid + always @ (posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i) begin + // asynchronous reset (active high) + ram_valid_i <= #`TCQ 1'b0; + end else begin + if (srst_i) begin + // synchronous reset (active high) + ram_valid_i <= #`TCQ 1'b0; + end else begin + if (ram_rd_en == 1'b1) begin + ram_valid_i <= #`TCQ 1'b1; + end else begin + if (ram_regout_en == 1'b1) + ram_valid_i <= #`TCQ 1'b0; + else + ram_valid_i <= #`TCQ ram_valid_i; + end + end //srst_i + end //rd_rst_i + end //always + + //*************************************************************************** + // Calculate READ_DATA_VALID + // READ_DATA_VALID indicates whether the value in Stage2 is valid or not. + // Stage2 has valid data whenever Stage1 had valid data and + // ram_regout_en_i=1, such that the data in Stage1 is propogated + // into Stage2. + //*************************************************************************** + always @ (posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i) + read_data_valid_i <= #`TCQ 1'b0; + else if (srst_i) + read_data_valid_i <= #`TCQ 1'b0; + else + read_data_valid_i <= #`TCQ ram_valid_i | (read_data_valid_i & ~RD_EN); + end //always + + + //************************************************************************** + // Calculate EMPTY + // Defined as the inverse of READ_DATA_VALID + // + // Description: + // + // If read_data_valid_i indicates that the output is not valid, + // and there is no valid data on the output of the ram to preload it + // with, then we will report empty. + // + // If there is no valid data on the output of the ram and we are + // reading, then the FIFO will go empty. + // + //************************************************************************** + always @ (posedge RD_CLK or posedge rd_rst_i) begin + if (rd_rst_i) begin + // asynchronous reset (active high) + empty_i <= #`TCQ 1'b1; + end else begin + if (srst_i) begin + // synchronous reset (active high) + empty_i <= #`TCQ 1'b1; + end else begin + // rising clock edge + empty_i <= #`TCQ (~ram_valid_i & ~read_data_valid_i) | (~ram_valid_i & RD_EN); + end + end + end //always + + // Register RD_EN from user to calculate USERUNDERFLOW. + // Register empty_i to calculate USERUNDERFLOW. + always @ (posedge RD_CLK) begin + rd_en_q <= #`TCQ RD_EN; + empty_q <= #`TCQ empty_i; + end //always + + + //*************************************************************************** + // Calculate user_almost_empty + // user_almost_empty is defined such that, unless more words are written + // to the FIFO, the next read will cause the FIFO to go EMPTY. + // + // In most cases, whenever the output registers are updated (due to a user + // read or a preload condition), then user_almost_empty will update to + // whatever RAM_EMPTY is. + // + // The exception is when the output is valid, the user is not reading, and + // Stage1 is not empty. In this condition, Stage1 will be preloaded from the + // memory, so we need to make sure user_almost_empty deasserts properly under + // this condition. + //*************************************************************************** + always @ (posedge RD_CLK or posedge rd_rst_i) + begin + if (rd_rst_i) begin // asynchronous reset (active high) + almost_empty_i <= #`TCQ 1'b1; + almost_empty_q <= #`TCQ 1'b1; + end else begin // rising clock edge + if (srst_i) begin // synchronous reset (active high) + almost_empty_i <= #`TCQ 1'b1; + almost_empty_q <= #`TCQ 1'b1; + end else begin + if ((ram_regout_en) | (~FIFOEMPTY & read_data_valid_i & ~RD_EN)) begin + almost_empty_i <= #`TCQ FIFOEMPTY; + end + almost_empty_q <= #`TCQ empty_i; + end + end + end //always + + + assign USEREMPTY = empty_i; + assign USERALMOSTEMPTY = almost_empty_i; + assign FIFORDEN = ram_rd_en; + assign RAMVALID = ram_valid_i; + assign USERVALID = C_USERVALID_LOW ? ~read_data_valid_i : read_data_valid_i; + assign USERUNDERFLOW = C_USERUNDERFLOW_LOW ? ~(empty_q & rd_en_q) : empty_q & rd_en_q; + + // BRAM resets synchronously + always @ (posedge RD_CLK) + begin + if (rd_rst_i || srst_i) begin + if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE < 2) + USERDATA <= #`TCQ hexstr_conv(C_DOUT_RST_VAL); + end + end //always + + + always @ (posedge RD_CLK or posedge rd_rst_i) + begin + if (rd_rst_i) begin //asynchronous reset (active high) + if (C_USE_ECC == 0) begin // Reset S/DBITERR only if ECC is OFF + USERSBITERR <= #`TCQ 0; + USERDBITERR <= #`TCQ 0; + end + // DRAM resets asynchronously + if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE == 2) //asynchronous reset (active high) + USERDATA <= #`TCQ hexstr_conv(C_DOUT_RST_VAL); + end else begin // rising clock edge + if (srst_i) begin + if (C_USE_ECC == 0) begin // Reset S/DBITERR only if ECC is OFF + USERSBITERR <= #`TCQ 0; + USERDBITERR <= #`TCQ 0; + end + if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE == 2) + USERDATA <= #`TCQ hexstr_conv(C_DOUT_RST_VAL); + end else begin + if (ram_regout_en) begin + USERDATA <= #`TCQ FIFODATA; + USERSBITERR <= #`TCQ FIFOSBITERR; + USERDBITERR <= #`TCQ FIFODBITERR; + end + end + end + end //always + +endmodule + diff --git a/fpga/usrp2/models/IOBUF.v b/fpga/usrp2/models/IOBUF.v new file mode 100644 index 000000000..1195dfb17 --- /dev/null +++ b/fpga/usrp2/models/IOBUF.v @@ -0,0 +1,83 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/IOBUF.v,v 1.9 2007/05/23 21:43:39 patrickp Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2004 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 10.1 +// \ \ Description : Xilinx Functional Simulation Library Component +// / / Bi-Directional Buffer +// /___/ /\ Filename : IOBUF.v +// \ \ / \ Timestamp : Thu Mar 25 16:42:37 PST 2004 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// 02/22/06 - CR#226003 - Added integer, real parameter type +// 05/23/07 - Changed timescale to 1 ps / 1 ps. +// 05/23/07 - Added wire declaration for internal signals. + +`timescale 1 ps / 1 ps + + +module IOBUF (O, IO, I, T); + + parameter CAPACITANCE = "DONT_CARE"; + parameter integer DRIVE = 12; + parameter IBUF_DELAY_VALUE = "0"; + parameter IFD_DELAY_VALUE = "AUTO"; + parameter IOSTANDARD = "DEFAULT"; + parameter SLEW = "SLOW"; + + output O; + inout IO; + input I, T; + + wire ts; + + //tri0 GTS = glbl.GTS; + + or O1 (ts, GTS, T); + bufif0 T1 (IO, I, ts); + + buf B1 (O, IO); + + initial begin + + case (CAPACITANCE) + + "LOW", "NORMAL", "DONT_CARE" : ; + default : begin + $display("Attribute Syntax Error : The attribute CAPACITANCE on IOBUF instance %m is set to %s. Legal values for this attribute are DONT_CARE, LOW or NORMAL.", CAPACITANCE); + $finish; + end + + endcase + + case (IBUF_DELAY_VALUE) + + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" : ; + default : begin + $display("Attribute Syntax Error : The attribute IBUF_DELAY_VALUE on IOBUF instance %m is set to %s. Legal values for this attribute are 0, 1, 2, ... or 16.", IBUF_DELAY_VALUE); + $finish; + end + + endcase + + + case (IFD_DELAY_VALUE) + + "AUTO", "0", "1", "2", "3", "4", "5", "6", "7", "8" : ; + default : begin + $display("Attribute Syntax Error : The attribute IFD_DELAY_VALUE on IOBUF instance %m is set to %s. Legal values for this attribute are AUTO, 0, 1, 2, ... or 8.", IFD_DELAY_VALUE); + $finish; + end + + endcase + + end // initial begin + +endmodule + diff --git a/fpga/usrp2/models/M24LC024B.v b/fpga/usrp2/models/M24LC024B.v new file mode 100644 index 000000000..5531f80fc --- /dev/null +++ b/fpga/usrp2/models/M24LC024B.v @@ -0,0 +1,476 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +// Modified 11/14/07 to simulate the 24lc024, which responds to the address pins + +// ******************************************************************************************************* +// ** ** +// ** M24LC024B.v - 24LC02B 2K-BIT I2C SERIAL EEPROM (VCC = +2.5V TO +5.5V) ** +// ** ** +// ******************************************************************************************************* +// ** ** +// ** COPYRIGHT (c) 2003 YOUNG ENGINEERING ** +// ** ALL RIGHTS RESERVED ** +// ** ** +// ** THIS PROGRAM IS CONFIDENTIAL AND A TRADE SECRET OF YOUNG ENGINEERING. THE RECEIPT OR ** +// ** POSSESSION OF THIS PROGRAM DOES NOT CONVEY ANY RIGHTS TO REPRODUCE OR DISCLOSE ITS ** +// ** CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN ** +// ** PART, WITHOUT THE SPECIFIC WRITTEN CONSENT OF YOUNG ENGINEERING. ** +// ** ** +// ******************************************************************************************************* +// ** Revision : 1.1 ** +// ** Modified Date : 07/19/2004 ** +// ** Revision History: ** +// ** ** +// ** 02/01/2003: Initial design ** +// ** 07/19/2004: Fixed the timing checks and the open-drain modeling for SDA. ** +// ** ** +// ******************************************************************************************************* +// ** TABLE OF CONTENTS ** +// ******************************************************************************************************* +// **---------------------------------------------------------------------------------------------------** +// ** DECLARATIONS ** +// **---------------------------------------------------------------------------------------------------** +// **---------------------------------------------------------------------------------------------------** +// ** INITIALIZATION ** +// **---------------------------------------------------------------------------------------------------** +// **---------------------------------------------------------------------------------------------------** +// ** CORE LOGIC ** +// **---------------------------------------------------------------------------------------------------** +// ** 1.01: START Bit Detection ** +// ** 1.02: STOP Bit Detection ** +// ** 1.03: Input Shift Register ** +// ** 1.04: Input Bit Counter ** +// ** 1.05: Control Byte Register ** +// ** 1.06: Byte Address Register ** +// ** 1.07: Write Data Buffer ** +// ** 1.08: Acknowledge Generator ** +// ** 1.09: Acknowledge Detect ** +// ** 1.10: Write Cycle Timer ** +// ** 1.11: Write Cycle Processor ** +// ** 1.12: Read Data Multiplexor ** +// ** 1.13: Read Data Processor ** +// ** 1.14: SDA Data I/O Buffer ** +// ** ** +// **---------------------------------------------------------------------------------------------------** +// ** DEBUG LOGIC ** +// **---------------------------------------------------------------------------------------------------** +// ** 2.01: Memory Data Bytes ** +// ** 2.02: Write Data Buffer ** +// ** ** +// **---------------------------------------------------------------------------------------------------** +// ** TIMING CHECKS ** +// **---------------------------------------------------------------------------------------------------** +// ** ** +// ******************************************************************************************************* + + +`timescale 1ns/10ps + +module M24LC024B (A0, A1, A2, WP, SDA, SCL, RESET); + + input A0; // unconnected pin + input A1; // unconnected pin + input A2; // unconnected pin + + input WP; // write protect pin + + inout SDA; // serial data I/O + input SCL; // serial data clock + + input RESET; // system reset + + +// ******************************************************************************************************* +// ** DECLARATIONS ** +// ******************************************************************************************************* + + reg SDA_DO; // serial data - output + reg SDA_OE; // serial data - output enable + + wire SDA_DriveEnable; // serial data output enable + reg SDA_DriveEnableDlyd; // serial data output enable - delayed + + reg [03:00] BitCounter; // serial bit counter + + reg START_Rcvd; // START bit received flag + reg STOP_Rcvd; // STOP bit received flag + reg CTRL_Rcvd; // control byte received flag + reg ADDR_Rcvd; // byte address received flag + reg MACK_Rcvd; // master acknowledge received flag + + reg WrCycle; // memory write cycle + reg RdCycle; // memory read cycle + + reg [07:00] ShiftRegister; // input data shift register + + reg [07:00] ControlByte; // control byte register + wire RdWrBit; // read/write control bit + + reg [07:00] StartAddress; // memory access starting address + reg [02:00] PageAddress; // memory page address + + reg [07:00] WrDataByte [0:7]; // memory write data buffer + wire [07:00] RdDataByte; // memory read data + + reg [15:00] WrCounter; // write buffer counter + + reg [02:00] WrPointer; // write buffer pointer + reg [07:00] RdPointer; // read address pointer + + reg WriteActive; // memory write cycle active + + reg [07:00] MemoryBlock [0:255]; // EEPROM data memory array + + integer LoopIndex; // iterative loop index + + integer tAA; // timing parameter + integer tWC; // timing parameter + + +// ******************************************************************************************************* +// ** INITIALIZATION ** +// ******************************************************************************************************* + + initial tAA = 900; // SCL to SDA output delay + initial tWC = 5000000; // memory write cycle time + //initial tWC = 50000; // shortened memory write cycle time to speed up sims + + initial begin + SDA_DO = 0; + SDA_OE = 0; + end + + initial begin + START_Rcvd = 0; + STOP_Rcvd = 0; + CTRL_Rcvd = 0; + ADDR_Rcvd = 0; + MACK_Rcvd = 0; + end + + initial begin + BitCounter = 0; + ControlByte = 0; + end + + initial begin + WrCycle = 0; + RdCycle = 0; + + WriteActive = 0; + end + + +// ******************************************************************************************************* +// ** CORE LOGIC ** +// ******************************************************************************************************* +// ------------------------------------------------------------------------------------------------------- +// 1.01: START Bit Detection +// ------------------------------------------------------------------------------------------------------- + + always @(negedge SDA) begin + if (SCL == 1) begin + START_Rcvd <= 1; + STOP_Rcvd <= 0; + CTRL_Rcvd <= 0; + ADDR_Rcvd <= 0; + MACK_Rcvd <= 0; + + WrCycle <= #1 0; + RdCycle <= #1 0; + + BitCounter <= 0; + end + end + +// ------------------------------------------------------------------------------------------------------- +// 1.02: STOP Bit Detection +// ------------------------------------------------------------------------------------------------------- + + always @(posedge SDA) begin + if (SCL == 1) begin + START_Rcvd <= 0; + STOP_Rcvd <= 1; + CTRL_Rcvd <= 0; + ADDR_Rcvd <= 0; + MACK_Rcvd <= 0; + + WrCycle <= #1 0; + RdCycle <= #1 0; + + BitCounter <= 10; + end + end + +// ------------------------------------------------------------------------------------------------------- +// 1.03: Input Shift Register +// ------------------------------------------------------------------------------------------------------- + + always @(posedge SCL) begin + ShiftRegister[00] <= SDA; + ShiftRegister[01] <= ShiftRegister[00]; + ShiftRegister[02] <= ShiftRegister[01]; + ShiftRegister[03] <= ShiftRegister[02]; + ShiftRegister[04] <= ShiftRegister[03]; + ShiftRegister[05] <= ShiftRegister[04]; + ShiftRegister[06] <= ShiftRegister[05]; + ShiftRegister[07] <= ShiftRegister[06]; + end + +// ------------------------------------------------------------------------------------------------------- +// 1.04: Input Bit Counter +// ------------------------------------------------------------------------------------------------------- + + always @(posedge SCL) begin + if (BitCounter < 10) BitCounter <= BitCounter + 1; + end + +// ------------------------------------------------------------------------------------------------------- +// 1.05: Control Byte Register +// ------------------------------------------------------------------------------------------------------- + + always @(negedge SCL) begin + if (START_Rcvd & (BitCounter == 8)) begin + if (!WriteActive & (ShiftRegister[07:04] == 4'b1010) + & (ShiftRegister[3:1] == {A2,A1,A0})) begin + if (ShiftRegister[00] == 0) WrCycle <= 1; + if (ShiftRegister[00] == 1) RdCycle <= 1; + + ControlByte <= ShiftRegister[07:00]; + + CTRL_Rcvd <= 1; + end + + START_Rcvd <= 0; + end + end + + assign RdWrBit = ControlByte[00]; + +// ------------------------------------------------------------------------------------------------------- +// 1.06: Byte Address Register +// ------------------------------------------------------------------------------------------------------- + + always @(negedge SCL) begin + if (CTRL_Rcvd & (BitCounter == 8)) begin + if (RdWrBit == 0) begin + StartAddress <= ShiftRegister[07:00]; + RdPointer <= ShiftRegister[07:00]; + + ADDR_Rcvd <= 1; + end + + WrCounter <= 0; + WrPointer <= 0; + + CTRL_Rcvd <= 0; + end + end + +// ------------------------------------------------------------------------------------------------------- +// 1.07: Write Data Buffer +// ------------------------------------------------------------------------------------------------------- + + always @(negedge SCL) begin + if (ADDR_Rcvd & (BitCounter == 8)) begin + if ((WP == 0) & (RdWrBit == 0)) begin + WrDataByte[WrPointer] <= ShiftRegister[07:00]; + + WrCounter <= WrCounter + 1; + WrPointer <= WrPointer + 1; + end + end + end + +// ------------------------------------------------------------------------------------------------------- +// 1.08: Acknowledge Generator +// ------------------------------------------------------------------------------------------------------- + + always @(negedge SCL) begin + if (!WriteActive) begin + if (BitCounter == 8) begin + if (WrCycle | (START_Rcvd & (ShiftRegister[07:04] == 4'b1010))) begin + SDA_DO <= 0; + SDA_OE <= 1; + end + end + if (BitCounter == 9) begin + BitCounter <= 0; + + if (!RdCycle) begin + SDA_DO <= 0; + SDA_OE <= 0; + end + end + end + end + +// ------------------------------------------------------------------------------------------------------- +// 1.09: Acknowledge Detect +// ------------------------------------------------------------------------------------------------------- + + always @(posedge SCL) begin + if (RdCycle & (BitCounter == 8)) begin + if ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1; + end + end + + always @(negedge SCL) MACK_Rcvd <= 0; + +// ------------------------------------------------------------------------------------------------------- +// 1.10: Write Cycle Timer +// ------------------------------------------------------------------------------------------------------- + + always @(posedge STOP_Rcvd) begin + if (WrCycle & (WP == 0) & (WrCounter > 0)) begin + WriteActive = 1; + #(tWC); + WriteActive = 0; + end + end + + always @(posedge STOP_Rcvd) begin + #(1.0); + STOP_Rcvd = 0; + end + +// ------------------------------------------------------------------------------------------------------- +// 1.11: Write Cycle Processor +// ------------------------------------------------------------------------------------------------------- + + always @(posedge WriteActive) begin + for (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) begin + PageAddress = StartAddress[02:00] + LoopIndex; + + MemoryBlock[{StartAddress[07:03],PageAddress[02:00]}] = WrDataByte[LoopIndex[02:00]]; + end + end + +// ------------------------------------------------------------------------------------------------------- +// 1.12: Read Data Multiplexor +// ------------------------------------------------------------------------------------------------------- + + always @(negedge SCL) begin + if (BitCounter == 8) begin + if (WrCycle & ADDR_Rcvd) begin + RdPointer <= StartAddress + WrPointer + 1; + end + if (RdCycle) begin + RdPointer <= RdPointer + 1; + end + end + end + + assign RdDataByte = MemoryBlock[RdPointer[07:00]]; + +// ------------------------------------------------------------------------------------------------------- +// 1.13: Read Data Processor +// ------------------------------------------------------------------------------------------------------- + + always @(negedge SCL) begin + if (RdCycle) begin + if (BitCounter == 8) begin + SDA_DO <= 0; + SDA_OE <= 0; + end + else if (BitCounter == 9) begin + SDA_DO <= RdDataByte[07]; + + if (MACK_Rcvd) SDA_OE <= 1; + end + else begin + SDA_DO <= RdDataByte[7-BitCounter]; + end + end + end + +// ------------------------------------------------------------------------------------------------------- +// 1.14: SDA Data I/O Buffer +// ------------------------------------------------------------------------------------------------------- + + bufif1 (SDA, 1'b0, SDA_DriveEnableDlyd); + + assign SDA_DriveEnable = !SDA_DO & SDA_OE; + always @(SDA_DriveEnable) SDA_DriveEnableDlyd <= #(tAA) SDA_DriveEnable; + + +// ******************************************************************************************************* +// ** DEBUG LOGIC ** +// ******************************************************************************************************* +// ------------------------------------------------------------------------------------------------------- +// 2.01: Memory Data Bytes +// ------------------------------------------------------------------------------------------------------- + + wire [07:00] MemoryByte00 = MemoryBlock[00]; + wire [07:00] MemoryByte01 = MemoryBlock[01]; + wire [07:00] MemoryByte02 = MemoryBlock[02]; + wire [07:00] MemoryByte03 = MemoryBlock[03]; + wire [07:00] MemoryByte04 = MemoryBlock[04]; + wire [07:00] MemoryByte05 = MemoryBlock[05]; + wire [07:00] MemoryByte06 = MemoryBlock[06]; + wire [07:00] MemoryByte07 = MemoryBlock[07]; + + wire [07:00] MemoryByte08 = MemoryBlock[08]; + wire [07:00] MemoryByte09 = MemoryBlock[09]; + wire [07:00] MemoryByte0A = MemoryBlock[10]; + wire [07:00] MemoryByte0B = MemoryBlock[11]; + wire [07:00] MemoryByte0C = MemoryBlock[12]; + wire [07:00] MemoryByte0D = MemoryBlock[13]; + wire [07:00] MemoryByte0E = MemoryBlock[14]; + wire [07:00] MemoryByte0F = MemoryBlock[15]; + +// ------------------------------------------------------------------------------------------------------- +// 2.02: Write Data Buffer +// ------------------------------------------------------------------------------------------------------- + + wire [07:00] WriteData_0 = WrDataByte[00]; + wire [07:00] WriteData_1 = WrDataByte[01]; + wire [07:00] WriteData_2 = WrDataByte[02]; + wire [07:00] WriteData_3 = WrDataByte[03]; + wire [07:00] WriteData_4 = WrDataByte[04]; + wire [07:00] WriteData_5 = WrDataByte[05]; + wire [07:00] WriteData_6 = WrDataByte[06]; + wire [07:00] WriteData_7 = WrDataByte[07]; + + +// ******************************************************************************************************* +// ** TIMING CHECKS ** +// ******************************************************************************************************* + + wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0); + + specify + specparam + tHI = 600, // SCL pulse width - high + tLO = 1300, // SCL pulse width - low + tSU_STA = 600, // SCL to SDA setup time + tHD_STA = 600, // SCL to SDA hold time + tSU_DAT = 100, // SDA to SCL setup time + tSU_STO = 600; // SCL to SDA setup time + + $width (posedge SCL, tHI); + $width (negedge SCL, tLO); + + $setup (SCL, negedge SDA &&& TimingCheckEnable, tSU_STA); + $setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT); + $setup (SCL, posedge SDA &&& TimingCheckEnable, tSU_STO); + + $hold (negedge SDA &&& TimingCheckEnable, SCL, tHD_STA); + endspecify + +endmodule diff --git a/fpga/usrp2/models/M24LC02B.v b/fpga/usrp2/models/M24LC02B.v new file mode 100644 index 000000000..00ed6f44a --- /dev/null +++ b/fpga/usrp2/models/M24LC02B.v @@ -0,0 +1,472 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +// *******************************************************************************************************
+// ** **
+// ** M24LC02B.v - 24LC02B 2K-BIT I2C SERIAL EEPROM (VCC = +2.5V TO +5.5V) **
+// ** **
+// *******************************************************************************************************
+// ** **
+// ** COPYRIGHT (c) 2003 YOUNG ENGINEERING **
+// ** ALL RIGHTS RESERVED **
+// ** **
+// ** THIS PROGRAM IS CONFIDENTIAL AND A TRADE SECRET OF YOUNG ENGINEERING. THE RECEIPT OR **
+// ** POSSESSION OF THIS PROGRAM DOES NOT CONVEY ANY RIGHTS TO REPRODUCE OR DISCLOSE ITS **
+// ** CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN **
+// ** PART, WITHOUT THE SPECIFIC WRITTEN CONSENT OF YOUNG ENGINEERING. **
+// ** **
+// *******************************************************************************************************
+// ** Revision : 1.1 **
+// ** Modified Date : 07/19/2004 **
+// ** Revision History: **
+// ** **
+// ** 02/01/2003: Initial design **
+// ** 07/19/2004: Fixed the timing checks and the open-drain modeling for SDA. **
+// ** **
+// *******************************************************************************************************
+// ** TABLE OF CONTENTS **
+// *******************************************************************************************************
+// **---------------------------------------------------------------------------------------------------**
+// ** DECLARATIONS **
+// **---------------------------------------------------------------------------------------------------**
+// **---------------------------------------------------------------------------------------------------**
+// ** INITIALIZATION **
+// **---------------------------------------------------------------------------------------------------**
+// **---------------------------------------------------------------------------------------------------**
+// ** CORE LOGIC **
+// **---------------------------------------------------------------------------------------------------**
+// ** 1.01: START Bit Detection **
+// ** 1.02: STOP Bit Detection **
+// ** 1.03: Input Shift Register **
+// ** 1.04: Input Bit Counter **
+// ** 1.05: Control Byte Register **
+// ** 1.06: Byte Address Register **
+// ** 1.07: Write Data Buffer **
+// ** 1.08: Acknowledge Generator **
+// ** 1.09: Acknowledge Detect **
+// ** 1.10: Write Cycle Timer **
+// ** 1.11: Write Cycle Processor **
+// ** 1.12: Read Data Multiplexor **
+// ** 1.13: Read Data Processor **
+// ** 1.14: SDA Data I/O Buffer **
+// ** **
+// **---------------------------------------------------------------------------------------------------**
+// ** DEBUG LOGIC **
+// **---------------------------------------------------------------------------------------------------**
+// ** 2.01: Memory Data Bytes **
+// ** 2.02: Write Data Buffer **
+// ** **
+// **---------------------------------------------------------------------------------------------------**
+// ** TIMING CHECKS **
+// **---------------------------------------------------------------------------------------------------**
+// ** **
+// *******************************************************************************************************
+
+
+`timescale 1ns/10ps
+
+module M24LC02B (A0, A1, A2, WP, SDA, SCL, RESET);
+
+ input A0; // unconnected pin
+ input A1; // unconnected pin
+ input A2; // unconnected pin
+
+ input WP; // write protect pin
+
+ inout SDA; // serial data I/O
+ input SCL; // serial data clock
+
+ input RESET; // system reset
+
+
+// *******************************************************************************************************
+// ** DECLARATIONS **
+// *******************************************************************************************************
+
+ reg SDA_DO; // serial data - output
+ reg SDA_OE; // serial data - output enable
+
+ wire SDA_DriveEnable; // serial data output enable
+ reg SDA_DriveEnableDlyd; // serial data output enable - delayed
+
+ reg [03:00] BitCounter; // serial bit counter
+
+ reg START_Rcvd; // START bit received flag
+ reg STOP_Rcvd; // STOP bit received flag
+ reg CTRL_Rcvd; // control byte received flag
+ reg ADDR_Rcvd; // byte address received flag
+ reg MACK_Rcvd; // master acknowledge received flag
+
+ reg WrCycle; // memory write cycle
+ reg RdCycle; // memory read cycle
+
+ reg [07:00] ShiftRegister; // input data shift register
+
+ reg [07:00] ControlByte; // control byte register
+ wire RdWrBit; // read/write control bit
+
+ reg [07:00] StartAddress; // memory access starting address
+ reg [02:00] PageAddress; // memory page address
+
+ reg [07:00] WrDataByte [0:7]; // memory write data buffer
+ wire [07:00] RdDataByte; // memory read data
+
+ reg [15:00] WrCounter; // write buffer counter
+
+ reg [02:00] WrPointer; // write buffer pointer
+ reg [07:00] RdPointer; // read address pointer
+
+ reg WriteActive; // memory write cycle active
+
+ reg [07:00] MemoryBlock [0:255]; // EEPROM data memory array
+
+ integer LoopIndex; // iterative loop index
+
+ integer tAA; // timing parameter
+ integer tWC; // timing parameter
+
+
+// *******************************************************************************************************
+// ** INITIALIZATION **
+// *******************************************************************************************************
+
+ initial tAA = 900; // SCL to SDA output delay
+ initial tWC = 5000000; // memory write cycle time
+
+ initial begin
+ SDA_DO = 0;
+ SDA_OE = 0;
+ end
+
+ initial begin
+ START_Rcvd = 0;
+ STOP_Rcvd = 0;
+ CTRL_Rcvd = 0;
+ ADDR_Rcvd = 0;
+ MACK_Rcvd = 0;
+ end
+
+ initial begin
+ BitCounter = 0;
+ ControlByte = 0;
+ end
+
+ initial begin
+ WrCycle = 0;
+ RdCycle = 0;
+
+ WriteActive = 0;
+ end
+
+
+// *******************************************************************************************************
+// ** CORE LOGIC **
+// *******************************************************************************************************
+// -------------------------------------------------------------------------------------------------------
+// 1.01: START Bit Detection
+// -------------------------------------------------------------------------------------------------------
+
+ always @(negedge SDA) begin
+ if (SCL == 1) begin
+ START_Rcvd <= 1;
+ STOP_Rcvd <= 0;
+ CTRL_Rcvd <= 0;
+ ADDR_Rcvd <= 0;
+ MACK_Rcvd <= 0;
+
+ WrCycle <= #1 0;
+ RdCycle <= #1 0;
+
+ BitCounter <= 0;
+ end
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.02: STOP Bit Detection
+// -------------------------------------------------------------------------------------------------------
+
+ always @(posedge SDA) begin
+ if (SCL == 1) begin
+ START_Rcvd <= 0;
+ STOP_Rcvd <= 1;
+ CTRL_Rcvd <= 0;
+ ADDR_Rcvd <= 0;
+ MACK_Rcvd <= 0;
+
+ WrCycle <= #1 0;
+ RdCycle <= #1 0;
+
+ BitCounter <= 10;
+ end
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.03: Input Shift Register
+// -------------------------------------------------------------------------------------------------------
+
+ always @(posedge SCL) begin
+ ShiftRegister[00] <= SDA;
+ ShiftRegister[01] <= ShiftRegister[00];
+ ShiftRegister[02] <= ShiftRegister[01];
+ ShiftRegister[03] <= ShiftRegister[02];
+ ShiftRegister[04] <= ShiftRegister[03];
+ ShiftRegister[05] <= ShiftRegister[04];
+ ShiftRegister[06] <= ShiftRegister[05];
+ ShiftRegister[07] <= ShiftRegister[06];
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.04: Input Bit Counter
+// -------------------------------------------------------------------------------------------------------
+
+ always @(posedge SCL) begin
+ if (BitCounter < 10) BitCounter <= BitCounter + 1;
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.05: Control Byte Register
+// -------------------------------------------------------------------------------------------------------
+
+ always @(negedge SCL) begin
+ if (START_Rcvd & (BitCounter == 8)) begin
+ if (!WriteActive & (ShiftRegister[07:04] == 4'b1010)) begin
+ if (ShiftRegister[00] == 0) WrCycle <= 1;
+ if (ShiftRegister[00] == 1) RdCycle <= 1;
+
+ ControlByte <= ShiftRegister[07:00];
+
+ CTRL_Rcvd <= 1;
+ end
+
+ START_Rcvd <= 0;
+ end
+ end
+
+ assign RdWrBit = ControlByte[00];
+
+// -------------------------------------------------------------------------------------------------------
+// 1.06: Byte Address Register
+// -------------------------------------------------------------------------------------------------------
+
+ always @(negedge SCL) begin
+ if (CTRL_Rcvd & (BitCounter == 8)) begin
+ if (RdWrBit == 0) begin
+ StartAddress <= ShiftRegister[07:00];
+ RdPointer <= ShiftRegister[07:00];
+
+ ADDR_Rcvd <= 1;
+ end
+
+ WrCounter <= 0;
+ WrPointer <= 0;
+
+ CTRL_Rcvd <= 0;
+ end
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.07: Write Data Buffer
+// -------------------------------------------------------------------------------------------------------
+
+ always @(negedge SCL) begin
+ if (ADDR_Rcvd & (BitCounter == 8)) begin
+ if ((WP == 0) & (RdWrBit == 0)) begin
+ WrDataByte[WrPointer] <= ShiftRegister[07:00];
+
+ WrCounter <= WrCounter + 1;
+ WrPointer <= WrPointer + 1;
+ end
+ end
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.08: Acknowledge Generator
+// -------------------------------------------------------------------------------------------------------
+
+ always @(negedge SCL) begin
+ if (!WriteActive) begin
+ if (BitCounter == 8) begin
+ if (WrCycle | (START_Rcvd & (ShiftRegister[07:04] == 4'b1010))) begin
+ SDA_DO <= 0;
+ SDA_OE <= 1;
+ end
+ end
+ if (BitCounter == 9) begin
+ BitCounter <= 0;
+
+ if (!RdCycle) begin
+ SDA_DO <= 0;
+ SDA_OE <= 0;
+ end
+ end
+ end
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.09: Acknowledge Detect
+// -------------------------------------------------------------------------------------------------------
+
+ always @(posedge SCL) begin
+ if (RdCycle & (BitCounter == 8)) begin
+ if ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1;
+ end
+ end
+
+ always @(negedge SCL) MACK_Rcvd <= 0;
+
+// -------------------------------------------------------------------------------------------------------
+// 1.10: Write Cycle Timer
+// -------------------------------------------------------------------------------------------------------
+
+ always @(posedge STOP_Rcvd) begin
+ if (WrCycle & (WP == 0) & (WrCounter > 0)) begin
+ WriteActive = 1;
+ #(tWC);
+ WriteActive = 0;
+ end
+ end
+
+ always @(posedge STOP_Rcvd) begin
+ #(1.0);
+ STOP_Rcvd = 0;
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.11: Write Cycle Processor
+// -------------------------------------------------------------------------------------------------------
+
+ always @(posedge WriteActive) begin
+ for (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) begin
+ PageAddress = StartAddress[02:00] + LoopIndex;
+
+ MemoryBlock[{StartAddress[07:03],PageAddress[02:00]}] = WrDataByte[LoopIndex[02:00]];
+ end
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.12: Read Data Multiplexor
+// -------------------------------------------------------------------------------------------------------
+
+ always @(negedge SCL) begin
+ if (BitCounter == 8) begin
+ if (WrCycle & ADDR_Rcvd) begin
+ RdPointer <= StartAddress + WrPointer + 1;
+ end
+ if (RdCycle) begin
+ RdPointer <= RdPointer + 1;
+ end
+ end
+ end
+
+ assign RdDataByte = MemoryBlock[RdPointer[07:00]];
+
+// -------------------------------------------------------------------------------------------------------
+// 1.13: Read Data Processor
+// -------------------------------------------------------------------------------------------------------
+
+ always @(negedge SCL) begin
+ if (RdCycle) begin
+ if (BitCounter == 8) begin
+ SDA_DO <= 0;
+ SDA_OE <= 0;
+ end
+ else if (BitCounter == 9) begin
+ SDA_DO <= RdDataByte[07];
+
+ if (MACK_Rcvd) SDA_OE <= 1;
+ end
+ else begin
+ SDA_DO <= RdDataByte[7-BitCounter];
+ end
+ end
+ end
+
+// -------------------------------------------------------------------------------------------------------
+// 1.14: SDA Data I/O Buffer
+// -------------------------------------------------------------------------------------------------------
+
+ bufif1 (SDA, 1'b0, SDA_DriveEnableDlyd);
+
+ assign SDA_DriveEnable = !SDA_DO & SDA_OE;
+ always @(SDA_DriveEnable) SDA_DriveEnableDlyd <= #(tAA) SDA_DriveEnable;
+
+
+// *******************************************************************************************************
+// ** DEBUG LOGIC **
+// *******************************************************************************************************
+// -------------------------------------------------------------------------------------------------------
+// 2.01: Memory Data Bytes
+// -------------------------------------------------------------------------------------------------------
+
+ wire [07:00] MemoryByte00 = MemoryBlock[00];
+ wire [07:00] MemoryByte01 = MemoryBlock[01];
+ wire [07:00] MemoryByte02 = MemoryBlock[02];
+ wire [07:00] MemoryByte03 = MemoryBlock[03];
+ wire [07:00] MemoryByte04 = MemoryBlock[04];
+ wire [07:00] MemoryByte05 = MemoryBlock[05];
+ wire [07:00] MemoryByte06 = MemoryBlock[06];
+ wire [07:00] MemoryByte07 = MemoryBlock[07];
+
+ wire [07:00] MemoryByte08 = MemoryBlock[08];
+ wire [07:00] MemoryByte09 = MemoryBlock[09];
+ wire [07:00] MemoryByte0A = MemoryBlock[10];
+ wire [07:00] MemoryByte0B = MemoryBlock[11];
+ wire [07:00] MemoryByte0C = MemoryBlock[12];
+ wire [07:00] MemoryByte0D = MemoryBlock[13];
+ wire [07:00] MemoryByte0E = MemoryBlock[14];
+ wire [07:00] MemoryByte0F = MemoryBlock[15];
+
+// -------------------------------------------------------------------------------------------------------
+// 2.02: Write Data Buffer
+// -------------------------------------------------------------------------------------------------------
+
+ wire [07:00] WriteData_0 = WrDataByte[00];
+ wire [07:00] WriteData_1 = WrDataByte[01];
+ wire [07:00] WriteData_2 = WrDataByte[02];
+ wire [07:00] WriteData_3 = WrDataByte[03];
+ wire [07:00] WriteData_4 = WrDataByte[04];
+ wire [07:00] WriteData_5 = WrDataByte[05];
+ wire [07:00] WriteData_6 = WrDataByte[06];
+ wire [07:00] WriteData_7 = WrDataByte[07];
+
+
+// *******************************************************************************************************
+// ** TIMING CHECKS **
+// *******************************************************************************************************
+
+ wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0);
+
+ specify
+ specparam
+ tHI = 600, // SCL pulse width - high
+ tLO = 1300, // SCL pulse width - low
+ tSU_STA = 600, // SCL to SDA setup time
+ tHD_STA = 600, // SCL to SDA hold time
+ tSU_DAT = 100, // SDA to SCL setup time
+ tSU_STO = 600; // SCL to SDA setup time
+
+ $width (posedge SCL, tHI);
+ $width (negedge SCL, tLO);
+
+ $setup (SCL, negedge SDA &&& TimingCheckEnable, tSU_STA);
+ $setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT);
+ $setup (SCL, posedge SDA &&& TimingCheckEnable, tSU_STO);
+
+ $hold (negedge SDA &&& TimingCheckEnable, SCL, tHD_STA);
+ endspecify
+
+endmodule
diff --git a/fpga/usrp2/models/MULT18X18S.v b/fpga/usrp2/models/MULT18X18S.v new file mode 100644 index 000000000..3ce2a267a --- /dev/null +++ b/fpga/usrp2/models/MULT18X18S.v @@ -0,0 +1,37 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + +// Model of the Xilinx mult18x18s for signed 18x18 bit multiplies, +// As in the Spartan 3 series + +module MULT18X18S + (output reg signed [35:0] P, + input signed [17:0] A, + input signed [17:0] B, + input C, // Clock + input CE, // Clock Enable + input R // Synchronous Reset + ); + + always @(posedge C) + if(R) + P <= 36'sd0; + else if(CE) + P <= A * B; + +endmodule // MULT18X18S diff --git a/fpga/usrp2/models/RAMB16_S36_S36.v b/fpga/usrp2/models/RAMB16_S36_S36.v new file mode 100644 index 000000000..f1a92c7ce --- /dev/null +++ b/fpga/usrp2/models/RAMB16_S36_S36.v @@ -0,0 +1,2194 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/RAMB16_S36_S36.v,v 1.10 2007/02/22 01:58:06 wloo Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2005 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 10.1 +// \ \ Description : Xilinx Functional Simulation Library Component +// / / 16K-Bit Data and 2K-Bit Parity Dual Port Block RAM +// /___/ /\ Filename : RAMB16_S36_S36.v +// \ \ / \ Timestamp : Thu Mar 10 16:43:36 PST 2005 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// End Revision + +`ifdef legacy_model + +`timescale 1 ps / 1 ps + +module RAMB16_S36_S36 (DOA, DOB, DOPA, DOPB, ADDRA, ADDRB, CLKA, CLKB, DIA, DIB, DIPA, DIPB, ENA, ENB, SSRA, SSRB, WEA, WEB); + + parameter INIT_A = 36'h0; + parameter INIT_B = 36'h0; + parameter SRVAL_A = 36'h0; + parameter SRVAL_B = 36'h0; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + parameter SIM_COLLISION_CHECK = "ALL"; + localparam SETUP_ALL = 1000; + localparam SETUP_READ_FIRST = 3000; + + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + output [31:0] DOA; + output [3:0] DOPA; + reg [31:0] doa_out; + reg [3:0] dopa_out; + wire doa_out0, doa_out1, doa_out2, doa_out3, doa_out4, doa_out5, doa_out6, doa_out7, doa_out8, doa_out9, doa_out10, doa_out11, doa_out12, doa_out13, doa_out14, doa_out15, doa_out16, doa_out17, doa_out18, doa_out19, doa_out20, doa_out21, doa_out22, doa_out23, doa_out24, doa_out25, doa_out26, doa_out27, doa_out28, doa_out29, doa_out30, doa_out31; + wire dopa0_out, dopa1_out, dopa2_out, dopa3_out; + + input [8:0] ADDRA; + input [31:0] DIA; + input [3:0] DIPA; + input ENA, CLKA, WEA, SSRA; + + output [31:0] DOB; + output [3:0] DOPB; + reg [31:0] dob_out; + reg [3:0] dopb_out; + wire dob_out0, dob_out1, dob_out2, dob_out3, dob_out4, dob_out5, dob_out6, dob_out7, dob_out8, dob_out9, dob_out10, dob_out11, dob_out12, dob_out13, dob_out14, dob_out15, dob_out16, dob_out17, dob_out18, dob_out19, dob_out20, dob_out21, dob_out22, dob_out23, dob_out24, dob_out25, dob_out26, dob_out27, dob_out28, dob_out29, dob_out30, dob_out31; + wire dopb0_out, dopb1_out, dopb2_out, dopb3_out; + + input [8:0] ADDRB; + input [31:0] DIB; + input [3:0] DIPB; + input ENB, CLKB, WEB, SSRB; + + reg [18431:0] mem; + reg [8:0] count; + reg [1:0] wr_mode_a, wr_mode_b; + + reg [5:0] dmi, dbi; + reg [5:0] pmi, pbi; + + wire [8:0] addra_int; + reg [8:0] addra_reg; + wire [31:0] dia_int; + wire [3:0] dipa_int; + wire ena_int, clka_int, wea_int, ssra_int; + reg ena_reg, wea_reg, ssra_reg; + wire [8:0] addrb_int; + reg [8:0] addrb_reg; + wire [31:0] dib_int; + wire [3:0] dipb_int; + wire enb_int, clkb_int, web_int, ssrb_int; + reg display_flag; + reg enb_reg, web_reg, ssrb_reg; + + time time_clka, time_clkb; + time time_clka_clkb; + time time_clkb_clka; + + reg setup_all_a_b; + reg setup_all_b_a; + reg setup_zero; + reg setup_rf_a_b; + reg setup_rf_b_a; + reg [1:0] data_collision, data_collision_a_b, data_collision_b_a; + reg memory_collision, memory_collision_a_b, memory_collision_b_a; + reg address_collision, address_collision_a_b, address_collision_b_a; + reg change_clka; + reg change_clkb; + + wire [14:0] data_addra_int; + wire [14:0] data_addra_reg; + wire [14:0] data_addrb_int; + wire [14:0] data_addrb_reg; + wire [15:0] parity_addra_int; + wire [15:0] parity_addra_reg; + wire [15:0] parity_addrb_int; + wire [15:0] parity_addrb_reg; + + tri0 GSR = glbl.GSR; + + always @(GSR) + if (GSR) begin + assign doa_out = INIT_A[31:0]; + assign dopa_out = INIT_A[35:32]; + assign dob_out = INIT_B[31:0]; + assign dopb_out = INIT_B[35:32]; + end + else begin + deassign doa_out; + deassign dopa_out; + deassign dob_out; + deassign dopb_out; + end + + buf b_doa_out0 (doa_out0, doa_out[0]); + buf b_doa_out1 (doa_out1, doa_out[1]); + buf b_doa_out2 (doa_out2, doa_out[2]); + buf b_doa_out3 (doa_out3, doa_out[3]); + buf b_doa_out4 (doa_out4, doa_out[4]); + buf b_doa_out5 (doa_out5, doa_out[5]); + buf b_doa_out6 (doa_out6, doa_out[6]); + buf b_doa_out7 (doa_out7, doa_out[7]); + buf b_doa_out8 (doa_out8, doa_out[8]); + buf b_doa_out9 (doa_out9, doa_out[9]); + buf b_doa_out10 (doa_out10, doa_out[10]); + buf b_doa_out11 (doa_out11, doa_out[11]); + buf b_doa_out12 (doa_out12, doa_out[12]); + buf b_doa_out13 (doa_out13, doa_out[13]); + buf b_doa_out14 (doa_out14, doa_out[14]); + buf b_doa_out15 (doa_out15, doa_out[15]); + buf b_doa_out16 (doa_out16, doa_out[16]); + buf b_doa_out17 (doa_out17, doa_out[17]); + buf b_doa_out18 (doa_out18, doa_out[18]); + buf b_doa_out19 (doa_out19, doa_out[19]); + buf b_doa_out20 (doa_out20, doa_out[20]); + buf b_doa_out21 (doa_out21, doa_out[21]); + buf b_doa_out22 (doa_out22, doa_out[22]); + buf b_doa_out23 (doa_out23, doa_out[23]); + buf b_doa_out24 (doa_out24, doa_out[24]); + buf b_doa_out25 (doa_out25, doa_out[25]); + buf b_doa_out26 (doa_out26, doa_out[26]); + buf b_doa_out27 (doa_out27, doa_out[27]); + buf b_doa_out28 (doa_out28, doa_out[28]); + buf b_doa_out29 (doa_out29, doa_out[29]); + buf b_doa_out30 (doa_out30, doa_out[30]); + buf b_doa_out31 (doa_out31, doa_out[31]); + buf b_dopa_out0 (dopa_out0, dopa_out[0]); + buf b_dopa_out1 (dopa_out1, dopa_out[1]); + buf b_dopa_out2 (dopa_out2, dopa_out[2]); + buf b_dopa_out3 (dopa_out3, dopa_out[3]); + buf b_dob_out0 (dob_out0, dob_out[0]); + buf b_dob_out1 (dob_out1, dob_out[1]); + buf b_dob_out2 (dob_out2, dob_out[2]); + buf b_dob_out3 (dob_out3, dob_out[3]); + buf b_dob_out4 (dob_out4, dob_out[4]); + buf b_dob_out5 (dob_out5, dob_out[5]); + buf b_dob_out6 (dob_out6, dob_out[6]); + buf b_dob_out7 (dob_out7, dob_out[7]); + buf b_dob_out8 (dob_out8, dob_out[8]); + buf b_dob_out9 (dob_out9, dob_out[9]); + buf b_dob_out10 (dob_out10, dob_out[10]); + buf b_dob_out11 (dob_out11, dob_out[11]); + buf b_dob_out12 (dob_out12, dob_out[12]); + buf b_dob_out13 (dob_out13, dob_out[13]); + buf b_dob_out14 (dob_out14, dob_out[14]); + buf b_dob_out15 (dob_out15, dob_out[15]); + buf b_dob_out16 (dob_out16, dob_out[16]); + buf b_dob_out17 (dob_out17, dob_out[17]); + buf b_dob_out18 (dob_out18, dob_out[18]); + buf b_dob_out19 (dob_out19, dob_out[19]); + buf b_dob_out20 (dob_out20, dob_out[20]); + buf b_dob_out21 (dob_out21, dob_out[21]); + buf b_dob_out22 (dob_out22, dob_out[22]); + buf b_dob_out23 (dob_out23, dob_out[23]); + buf b_dob_out24 (dob_out24, dob_out[24]); + buf b_dob_out25 (dob_out25, dob_out[25]); + buf b_dob_out26 (dob_out26, dob_out[26]); + buf b_dob_out27 (dob_out27, dob_out[27]); + buf b_dob_out28 (dob_out28, dob_out[28]); + buf b_dob_out29 (dob_out29, dob_out[29]); + buf b_dob_out30 (dob_out30, dob_out[30]); + buf b_dob_out31 (dob_out31, dob_out[31]); + buf b_dopb_out0 (dopb_out0, dopb_out[0]); + buf b_dopb_out1 (dopb_out1, dopb_out[1]); + buf b_dopb_out2 (dopb_out2, dopb_out[2]); + buf b_dopb_out3 (dopb_out3, dopb_out[3]); + + buf b_doa0 (DOA[0], doa_out0); + buf b_doa1 (DOA[1], doa_out1); + buf b_doa2 (DOA[2], doa_out2); + buf b_doa3 (DOA[3], doa_out3); + buf b_doa4 (DOA[4], doa_out4); + buf b_doa5 (DOA[5], doa_out5); + buf b_doa6 (DOA[6], doa_out6); + buf b_doa7 (DOA[7], doa_out7); + buf b_doa8 (DOA[8], doa_out8); + buf b_doa9 (DOA[9], doa_out9); + buf b_doa10 (DOA[10], doa_out10); + buf b_doa11 (DOA[11], doa_out11); + buf b_doa12 (DOA[12], doa_out12); + buf b_doa13 (DOA[13], doa_out13); + buf b_doa14 (DOA[14], doa_out14); + buf b_doa15 (DOA[15], doa_out15); + buf b_doa16 (DOA[16], doa_out16); + buf b_doa17 (DOA[17], doa_out17); + buf b_doa18 (DOA[18], doa_out18); + buf b_doa19 (DOA[19], doa_out19); + buf b_doa20 (DOA[20], doa_out20); + buf b_doa21 (DOA[21], doa_out21); + buf b_doa22 (DOA[22], doa_out22); + buf b_doa23 (DOA[23], doa_out23); + buf b_doa24 (DOA[24], doa_out24); + buf b_doa25 (DOA[25], doa_out25); + buf b_doa26 (DOA[26], doa_out26); + buf b_doa27 (DOA[27], doa_out27); + buf b_doa28 (DOA[28], doa_out28); + buf b_doa29 (DOA[29], doa_out29); + buf b_doa30 (DOA[30], doa_out30); + buf b_doa31 (DOA[31], doa_out31); + buf b_dopa0 (DOPA[0], dopa_out0); + buf b_dopa1 (DOPA[1], dopa_out1); + buf b_dopa2 (DOPA[2], dopa_out2); + buf b_dopa3 (DOPA[3], dopa_out3); + buf b_dob0 (DOB[0], dob_out0); + buf b_dob1 (DOB[1], dob_out1); + buf b_dob2 (DOB[2], dob_out2); + buf b_dob3 (DOB[3], dob_out3); + buf b_dob4 (DOB[4], dob_out4); + buf b_dob5 (DOB[5], dob_out5); + buf b_dob6 (DOB[6], dob_out6); + buf b_dob7 (DOB[7], dob_out7); + buf b_dob8 (DOB[8], dob_out8); + buf b_dob9 (DOB[9], dob_out9); + buf b_dob10 (DOB[10], dob_out10); + buf b_dob11 (DOB[11], dob_out11); + buf b_dob12 (DOB[12], dob_out12); + buf b_dob13 (DOB[13], dob_out13); + buf b_dob14 (DOB[14], dob_out14); + buf b_dob15 (DOB[15], dob_out15); + buf b_dob16 (DOB[16], dob_out16); + buf b_dob17 (DOB[17], dob_out17); + buf b_dob18 (DOB[18], dob_out18); + buf b_dob19 (DOB[19], dob_out19); + buf b_dob20 (DOB[20], dob_out20); + buf b_dob21 (DOB[21], dob_out21); + buf b_dob22 (DOB[22], dob_out22); + buf b_dob23 (DOB[23], dob_out23); + buf b_dob24 (DOB[24], dob_out24); + buf b_dob25 (DOB[25], dob_out25); + buf b_dob26 (DOB[26], dob_out26); + buf b_dob27 (DOB[27], dob_out27); + buf b_dob28 (DOB[28], dob_out28); + buf b_dob29 (DOB[29], dob_out29); + buf b_dob30 (DOB[30], dob_out30); + buf b_dob31 (DOB[31], dob_out31); + buf b_dopb0 (DOPB[0], dopb_out0); + buf b_dopb1 (DOPB[1], dopb_out1); + buf b_dopb2 (DOPB[2], dopb_out2); + buf b_dopb3 (DOPB[3], dopb_out3); + + buf b_addra_0 (addra_int[0], ADDRA[0]); + buf b_addra_1 (addra_int[1], ADDRA[1]); + buf b_addra_2 (addra_int[2], ADDRA[2]); + buf b_addra_3 (addra_int[3], ADDRA[3]); + buf b_addra_4 (addra_int[4], ADDRA[4]); + buf b_addra_5 (addra_int[5], ADDRA[5]); + buf b_addra_6 (addra_int[6], ADDRA[6]); + buf b_addra_7 (addra_int[7], ADDRA[7]); + buf b_addra_8 (addra_int[8], ADDRA[8]); + buf b_dia_0 (dia_int[0], DIA[0]); + buf b_dia_1 (dia_int[1], DIA[1]); + buf b_dia_2 (dia_int[2], DIA[2]); + buf b_dia_3 (dia_int[3], DIA[3]); + buf b_dia_4 (dia_int[4], DIA[4]); + buf b_dia_5 (dia_int[5], DIA[5]); + buf b_dia_6 (dia_int[6], DIA[6]); + buf b_dia_7 (dia_int[7], DIA[7]); + buf b_dia_8 (dia_int[8], DIA[8]); + buf b_dia_9 (dia_int[9], DIA[9]); + buf b_dia_10 (dia_int[10], DIA[10]); + buf b_dia_11 (dia_int[11], DIA[11]); + buf b_dia_12 (dia_int[12], DIA[12]); + buf b_dia_13 (dia_int[13], DIA[13]); + buf b_dia_14 (dia_int[14], DIA[14]); + buf b_dia_15 (dia_int[15], DIA[15]); + buf b_dia_16 (dia_int[16], DIA[16]); + buf b_dia_17 (dia_int[17], DIA[17]); + buf b_dia_18 (dia_int[18], DIA[18]); + buf b_dia_19 (dia_int[19], DIA[19]); + buf b_dia_20 (dia_int[20], DIA[20]); + buf b_dia_21 (dia_int[21], DIA[21]); + buf b_dia_22 (dia_int[22], DIA[22]); + buf b_dia_23 (dia_int[23], DIA[23]); + buf b_dia_24 (dia_int[24], DIA[24]); + buf b_dia_25 (dia_int[25], DIA[25]); + buf b_dia_26 (dia_int[26], DIA[26]); + buf b_dia_27 (dia_int[27], DIA[27]); + buf b_dia_28 (dia_int[28], DIA[28]); + buf b_dia_29 (dia_int[29], DIA[29]); + buf b_dia_30 (dia_int[30], DIA[30]); + buf b_dia_31 (dia_int[31], DIA[31]); + buf b_dipa_0 (dipa_int[0], DIPA[0]); + buf b_dipa_1 (dipa_int[1], DIPA[1]); + buf b_dipa_2 (dipa_int[2], DIPA[2]); + buf b_dipa_3 (dipa_int[3], DIPA[3]); + buf b_ena (ena_int, ENA); + buf b_clka (clka_int, CLKA); + buf b_ssra (ssra_int, SSRA); + buf b_wea (wea_int, WEA); + buf b_addrb_0 (addrb_int[0], ADDRB[0]); + buf b_addrb_1 (addrb_int[1], ADDRB[1]); + buf b_addrb_2 (addrb_int[2], ADDRB[2]); + buf b_addrb_3 (addrb_int[3], ADDRB[3]); + buf b_addrb_4 (addrb_int[4], ADDRB[4]); + buf b_addrb_5 (addrb_int[5], ADDRB[5]); + buf b_addrb_6 (addrb_int[6], ADDRB[6]); + buf b_addrb_7 (addrb_int[7], ADDRB[7]); + buf b_addrb_8 (addrb_int[8], ADDRB[8]); + buf b_dib_0 (dib_int[0], DIB[0]); + buf b_dib_1 (dib_int[1], DIB[1]); + buf b_dib_2 (dib_int[2], DIB[2]); + buf b_dib_3 (dib_int[3], DIB[3]); + buf b_dib_4 (dib_int[4], DIB[4]); + buf b_dib_5 (dib_int[5], DIB[5]); + buf b_dib_6 (dib_int[6], DIB[6]); + buf b_dib_7 (dib_int[7], DIB[7]); + buf b_dib_8 (dib_int[8], DIB[8]); + buf b_dib_9 (dib_int[9], DIB[9]); + buf b_dib_10 (dib_int[10], DIB[10]); + buf b_dib_11 (dib_int[11], DIB[11]); + buf b_dib_12 (dib_int[12], DIB[12]); + buf b_dib_13 (dib_int[13], DIB[13]); + buf b_dib_14 (dib_int[14], DIB[14]); + buf b_dib_15 (dib_int[15], DIB[15]); + buf b_dib_16 (dib_int[16], DIB[16]); + buf b_dib_17 (dib_int[17], DIB[17]); + buf b_dib_18 (dib_int[18], DIB[18]); + buf b_dib_19 (dib_int[19], DIB[19]); + buf b_dib_20 (dib_int[20], DIB[20]); + buf b_dib_21 (dib_int[21], DIB[21]); + buf b_dib_22 (dib_int[22], DIB[22]); + buf b_dib_23 (dib_int[23], DIB[23]); + buf b_dib_24 (dib_int[24], DIB[24]); + buf b_dib_25 (dib_int[25], DIB[25]); + buf b_dib_26 (dib_int[26], DIB[26]); + buf b_dib_27 (dib_int[27], DIB[27]); + buf b_dib_28 (dib_int[28], DIB[28]); + buf b_dib_29 (dib_int[29], DIB[29]); + buf b_dib_30 (dib_int[30], DIB[30]); + buf b_dib_31 (dib_int[31], DIB[31]); + buf b_dipb_0 (dipb_int[0], DIPB[0]); + buf b_dipb_1 (dipb_int[1], DIPB[1]); + buf b_dipb_2 (dipb_int[2], DIPB[2]); + buf b_dipb_3 (dipb_int[3], DIPB[3]); + buf b_enb (enb_int, ENB); + buf b_clkb (clkb_int, CLKB); + buf b_ssrb (ssrb_int, SSRB); + buf b_web (web_int, WEB); + + initial begin + for (count = 0; count < 256; count = count + 1) begin + mem[count] <= INIT_00[count]; + mem[256 * 1 + count] <= INIT_01[count]; + mem[256 * 2 + count] <= INIT_02[count]; + mem[256 * 3 + count] <= INIT_03[count]; + mem[256 * 4 + count] <= INIT_04[count]; + mem[256 * 5 + count] <= INIT_05[count]; + mem[256 * 6 + count] <= INIT_06[count]; + mem[256 * 7 + count] <= INIT_07[count]; + mem[256 * 8 + count] <= INIT_08[count]; + mem[256 * 9 + count] <= INIT_09[count]; + mem[256 * 10 + count] <= INIT_0A[count]; + mem[256 * 11 + count] <= INIT_0B[count]; + mem[256 * 12 + count] <= INIT_0C[count]; + mem[256 * 13 + count] <= INIT_0D[count]; + mem[256 * 14 + count] <= INIT_0E[count]; + mem[256 * 15 + count] <= INIT_0F[count]; + mem[256 * 16 + count] <= INIT_10[count]; + mem[256 * 17 + count] <= INIT_11[count]; + mem[256 * 18 + count] <= INIT_12[count]; + mem[256 * 19 + count] <= INIT_13[count]; + mem[256 * 20 + count] <= INIT_14[count]; + mem[256 * 21 + count] <= INIT_15[count]; + mem[256 * 22 + count] <= INIT_16[count]; + mem[256 * 23 + count] <= INIT_17[count]; + mem[256 * 24 + count] <= INIT_18[count]; + mem[256 * 25 + count] <= INIT_19[count]; + mem[256 * 26 + count] <= INIT_1A[count]; + mem[256 * 27 + count] <= INIT_1B[count]; + mem[256 * 28 + count] <= INIT_1C[count]; + mem[256 * 29 + count] <= INIT_1D[count]; + mem[256 * 30 + count] <= INIT_1E[count]; + mem[256 * 31 + count] <= INIT_1F[count]; + mem[256 * 32 + count] <= INIT_20[count]; + mem[256 * 33 + count] <= INIT_21[count]; + mem[256 * 34 + count] <= INIT_22[count]; + mem[256 * 35 + count] <= INIT_23[count]; + mem[256 * 36 + count] <= INIT_24[count]; + mem[256 * 37 + count] <= INIT_25[count]; + mem[256 * 38 + count] <= INIT_26[count]; + mem[256 * 39 + count] <= INIT_27[count]; + mem[256 * 40 + count] <= INIT_28[count]; + mem[256 * 41 + count] <= INIT_29[count]; + mem[256 * 42 + count] <= INIT_2A[count]; + mem[256 * 43 + count] <= INIT_2B[count]; + mem[256 * 44 + count] <= INIT_2C[count]; + mem[256 * 45 + count] <= INIT_2D[count]; + mem[256 * 46 + count] <= INIT_2E[count]; + mem[256 * 47 + count] <= INIT_2F[count]; + mem[256 * 48 + count] <= INIT_30[count]; + mem[256 * 49 + count] <= INIT_31[count]; + mem[256 * 50 + count] <= INIT_32[count]; + mem[256 * 51 + count] <= INIT_33[count]; + mem[256 * 52 + count] <= INIT_34[count]; + mem[256 * 53 + count] <= INIT_35[count]; + mem[256 * 54 + count] <= INIT_36[count]; + mem[256 * 55 + count] <= INIT_37[count]; + mem[256 * 56 + count] <= INIT_38[count]; + mem[256 * 57 + count] <= INIT_39[count]; + mem[256 * 58 + count] <= INIT_3A[count]; + mem[256 * 59 + count] <= INIT_3B[count]; + mem[256 * 60 + count] <= INIT_3C[count]; + mem[256 * 61 + count] <= INIT_3D[count]; + mem[256 * 62 + count] <= INIT_3E[count]; + mem[256 * 63 + count] <= INIT_3F[count]; + mem[256 * 64 + count] <= INITP_00[count]; + mem[256 * 65 + count] <= INITP_01[count]; + mem[256 * 66 + count] <= INITP_02[count]; + mem[256 * 67 + count] <= INITP_03[count]; + mem[256 * 68 + count] <= INITP_04[count]; + mem[256 * 69 + count] <= INITP_05[count]; + mem[256 * 70 + count] <= INITP_06[count]; + mem[256 * 71 + count] <= INITP_07[count]; + end + address_collision <= 0; + address_collision_a_b <= 0; + address_collision_b_a <= 0; + change_clka <= 0; + change_clkb <= 0; + data_collision <= 0; + data_collision_a_b <= 0; + data_collision_b_a <= 0; + memory_collision <= 0; + memory_collision_a_b <= 0; + memory_collision_b_a <= 0; + setup_all_a_b <= 0; + setup_all_b_a <= 0; + setup_zero <= 0; + setup_rf_a_b <= 0; + setup_rf_b_a <= 0; + end + + assign data_addra_int = addra_int * 32; + assign data_addra_reg = addra_reg * 32; + assign data_addrb_int = addrb_int * 32; + assign data_addrb_reg = addrb_reg * 32; + assign parity_addra_int = 16384 + addra_int * 4; + assign parity_addra_reg = 16384 + addra_reg * 4; + assign parity_addrb_int = 16384 + addrb_int * 4; + assign parity_addrb_reg = 16384 + addrb_reg * 4; + + + initial begin + + display_flag = 1; + + case (SIM_COLLISION_CHECK) + + "NONE" : begin + assign setup_all_a_b = 1'b0; + assign setup_all_b_a = 1'b0; + assign setup_zero = 1'b0; + assign setup_rf_a_b = 1'b0; + assign setup_rf_b_a = 1'b0; + assign display_flag = 0; + end + "WARNING_ONLY" : begin + assign data_collision = 2'b00; + assign data_collision_a_b = 2'b00; + assign data_collision_b_a = 2'b00; + assign memory_collision = 1'b0; + assign memory_collision_a_b = 1'b0; + assign memory_collision_b_a = 1'b0; + end + "GENERATE_X_ONLY" : begin + assign display_flag = 0; + end + "ALL" : ; + default : begin + $display("Attribute Syntax Error : The Attribute SIM_COLLISION_CHECK on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are ALL, NONE, WARNING_ONLY or GENERATE_X_ONLY.", SIM_COLLISION_CHECK); + $finish; + end + + endcase // case(SIM_COLLISION_CHECK) + + end // initial begin + + + always @(posedge clka_int) begin + time_clka = $time; + #0 time_clkb_clka = time_clka - time_clkb; + change_clka = ~change_clka; + end + + always @(posedge clkb_int) begin + time_clkb = $time; + #0 time_clka_clkb = time_clkb - time_clka; + change_clkb = ~change_clkb; + end + + always @(change_clkb) begin + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_ALL)) + setup_all_a_b = 1; + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_READ_FIRST)) + setup_rf_a_b = 1; + end + + always @(change_clka) begin + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_ALL)) + setup_all_b_a = 1; + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_READ_FIRST)) + setup_rf_b_a = 1; + end + + always @(change_clkb or change_clka) begin + if ((time_clkb_clka == 0) && (time_clka_clkb == 0)) + setup_zero = 1; + end + + always @(posedge setup_zero) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_int[14:5] == data_addrb_int[14:5])) + memory_collision <= 1; + end + + always @(posedge setup_all_a_b or posedge setup_rf_a_b) begin + if ((ena_reg == 1) && (wea_reg == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_reg[14:5] == data_addrb_int[14:5])) + memory_collision_a_b <= 1; + end + + always @(posedge setup_all_b_a or posedge setup_rf_b_a) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_reg == 1) && (web_reg == 1) && + (data_addra_int[14:5] == data_addrb_reg[14:5])) + memory_collision_b_a <= 1; + end + + always @(posedge setup_all_a_b) begin + if (data_addra_reg[14:5] == data_addrb_int[14:5]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) + 6'b000011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b010011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b010111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b011011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b100011 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_a_b <= 0; + end + + + always @(posedge setup_all_b_a) begin + if (data_addra_int[14:5] == data_addrb_reg[14:5]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) + 6'b000011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b000111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b001011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b010111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b011011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b001001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b011001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b101001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_b_a <= 0; + end + + + always @(posedge setup_zero) begin + if (data_addra_int[14:5] == data_addrb_int[14:5]) begin + if ((ena_int == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_int}) + 6'b000011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision <= 2'b01; display_wa_rb; end + endcase + end + end + setup_zero <= 0; + end + + task display_ra_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port A while a write was requested to the same address on Port B. The write will be successful however the read value on Port A is unknown until the next CLKA cycle.", $time/1000.0, addra_int); + end + endtask + + task display_wa_rb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port B while a write was requested to the same address on Port A. The write will be successful however the read value on Port B is unknown until the next CLKB cycle.", $time/1000.0, addrb_int); + end + endtask + + task display_wa_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA write was requested to the same address simultaneously at both Port A and Port B of the RAM. The contents written to the RAM at address location %h (hex) of Port A and address location %h (hex) of Port B are unknown.", $time/1000.0, addra_int, addrb_int); + end + endtask + + + always @(posedge setup_rf_a_b) begin + if (data_addra_reg[14:5] == data_addrb_int[14:5]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) +// 6'b000011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b001011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b010011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b100011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b100111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b101011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b001001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b011001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b101001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b010010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b010110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b011010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b100010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_a_b <= 0; + end + + + always @(posedge setup_rf_b_a) begin + if (data_addra_int[14:5] == data_addrb_reg[14:5]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) +// 6'b000011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b000111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b001011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b010011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b010111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b011011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b100011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end +// 6'b101011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b001001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b011001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b101001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_b_a <= 0; + end + + + always @(posedge clka_int) begin + addra_reg <= addra_int; + ena_reg <= ena_int; + ssra_reg <= ssra_int; + wea_reg <= wea_int; + end + + always @(posedge clkb_int) begin + addrb_reg <= addrb_int; + enb_reg <= enb_int; + ssrb_reg <= ssrb_int; + web_reg <= web_int; + end + + // Data + always @(posedge memory_collision) begin + for (dmi = 0; dmi < 32; dmi = dmi + 1) begin + mem[data_addra_int + dmi] <= 1'bX; + end + memory_collision <= 0; + end + + always @(posedge memory_collision_a_b) begin + for (dmi = 0; dmi < 32; dmi = dmi + 1) begin + mem[data_addra_reg + dmi] <= 1'bX; + end + memory_collision_a_b <= 0; + end + + always @(posedge memory_collision_b_a) begin + for (dmi = 0; dmi < 32; dmi = dmi + 1) begin + mem[data_addra_int + dmi] <= 1'bX; + end + memory_collision_b_a <= 0; + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0) begin + doa_out <= 32'bX; + end + data_collision[1] <= 0; + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0) begin + dob_out <= 32'bX; + end + data_collision[0] <= 0; + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0) begin + doa_out <= 32'bX; + end + data_collision_a_b[1] <= 0; + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0) begin + dob_out <= 32'bX; + end + data_collision_a_b[0] <= 0; + end + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0) begin + doa_out <= 32'bX; + end + data_collision_b_a[1] <= 0; + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0) begin + dob_out <= 32'bX; + end + data_collision_b_a[0] <= 0; + end + + + // Parity + always @(posedge memory_collision) begin + for (pmi = 0; pmi < 4; pmi = pmi + 1) begin + mem[parity_addra_int + pmi] <= 1'bX; + end + end + + always @(posedge memory_collision_a_b) begin + for (pmi = 0; pmi < 4; pmi = pmi + 1) begin + mem[parity_addra_reg + pmi] <= 1'bX; + end + end + + always @(posedge memory_collision_b_a) begin + for (pmi = 0; pmi < 4; pmi = pmi + 1) begin + mem[parity_addra_int + pmi] <= 1'bX; + end + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0) begin + dopa_out <= 4'bX; + end + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0) begin + dopb_out <= 4'bX; + end + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0) begin + dopa_out <= 4'bX; + end + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0) begin + dopb_out <= 4'bX; + end + end + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0) begin + dopa_out <= 4'bX; + end + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0) begin + dopb_out <= 4'bX; + end + end + + + initial begin + case (WRITE_MODE_A) + "WRITE_FIRST" : wr_mode_a <= 2'b00; + "READ_FIRST" : wr_mode_a <= 2'b01; + "NO_CHANGE" : wr_mode_a <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_A on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_A); + $finish; + end + endcase + end + + initial begin + case (WRITE_MODE_B) + "WRITE_FIRST" : wr_mode_b <= 2'b00; + "READ_FIRST" : wr_mode_b <= 2'b01; + "NO_CHANGE" : wr_mode_b <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_B on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_B); + $finish; + end + endcase + end + + // Port A + always @(posedge clka_int) begin + if (ena_int == 1'b1) begin + if (ssra_int == 1'b1) begin + doa_out[0] <= SRVAL_A[0]; + doa_out[1] <= SRVAL_A[1]; + doa_out[2] <= SRVAL_A[2]; + doa_out[3] <= SRVAL_A[3]; + doa_out[4] <= SRVAL_A[4]; + doa_out[5] <= SRVAL_A[5]; + doa_out[6] <= SRVAL_A[6]; + doa_out[7] <= SRVAL_A[7]; + doa_out[8] <= SRVAL_A[8]; + doa_out[9] <= SRVAL_A[9]; + doa_out[10] <= SRVAL_A[10]; + doa_out[11] <= SRVAL_A[11]; + doa_out[12] <= SRVAL_A[12]; + doa_out[13] <= SRVAL_A[13]; + doa_out[14] <= SRVAL_A[14]; + doa_out[15] <= SRVAL_A[15]; + doa_out[16] <= SRVAL_A[16]; + doa_out[17] <= SRVAL_A[17]; + doa_out[18] <= SRVAL_A[18]; + doa_out[19] <= SRVAL_A[19]; + doa_out[20] <= SRVAL_A[20]; + doa_out[21] <= SRVAL_A[21]; + doa_out[22] <= SRVAL_A[22]; + doa_out[23] <= SRVAL_A[23]; + doa_out[24] <= SRVAL_A[24]; + doa_out[25] <= SRVAL_A[25]; + doa_out[26] <= SRVAL_A[26]; + doa_out[27] <= SRVAL_A[27]; + doa_out[28] <= SRVAL_A[28]; + doa_out[29] <= SRVAL_A[29]; + doa_out[30] <= SRVAL_A[30]; + doa_out[31] <= SRVAL_A[31]; + dopa_out[0] <= SRVAL_A[32]; + dopa_out[1] <= SRVAL_A[33]; + dopa_out[2] <= SRVAL_A[34]; + dopa_out[3] <= SRVAL_A[35]; + end + else begin + if (wea_int == 1'b1) begin + if (wr_mode_a == 2'b00) begin + doa_out <= dia_int; + dopa_out <= dipa_int; + end + else if (wr_mode_a == 2'b01) begin + doa_out[0] <= mem[data_addra_int + 0]; + doa_out[1] <= mem[data_addra_int + 1]; + doa_out[2] <= mem[data_addra_int + 2]; + doa_out[3] <= mem[data_addra_int + 3]; + doa_out[4] <= mem[data_addra_int + 4]; + doa_out[5] <= mem[data_addra_int + 5]; + doa_out[6] <= mem[data_addra_int + 6]; + doa_out[7] <= mem[data_addra_int + 7]; + doa_out[8] <= mem[data_addra_int + 8]; + doa_out[9] <= mem[data_addra_int + 9]; + doa_out[10] <= mem[data_addra_int + 10]; + doa_out[11] <= mem[data_addra_int + 11]; + doa_out[12] <= mem[data_addra_int + 12]; + doa_out[13] <= mem[data_addra_int + 13]; + doa_out[14] <= mem[data_addra_int + 14]; + doa_out[15] <= mem[data_addra_int + 15]; + doa_out[16] <= mem[data_addra_int + 16]; + doa_out[17] <= mem[data_addra_int + 17]; + doa_out[18] <= mem[data_addra_int + 18]; + doa_out[19] <= mem[data_addra_int + 19]; + doa_out[20] <= mem[data_addra_int + 20]; + doa_out[21] <= mem[data_addra_int + 21]; + doa_out[22] <= mem[data_addra_int + 22]; + doa_out[23] <= mem[data_addra_int + 23]; + doa_out[24] <= mem[data_addra_int + 24]; + doa_out[25] <= mem[data_addra_int + 25]; + doa_out[26] <= mem[data_addra_int + 26]; + doa_out[27] <= mem[data_addra_int + 27]; + doa_out[28] <= mem[data_addra_int + 28]; + doa_out[29] <= mem[data_addra_int + 29]; + doa_out[30] <= mem[data_addra_int + 30]; + doa_out[31] <= mem[data_addra_int + 31]; + dopa_out[0] <= mem[parity_addra_int + 0]; + dopa_out[1] <= mem[parity_addra_int + 1]; + dopa_out[2] <= mem[parity_addra_int + 2]; + dopa_out[3] <= mem[parity_addra_int + 3]; + end + end + else begin + doa_out[0] <= mem[data_addra_int + 0]; + doa_out[1] <= mem[data_addra_int + 1]; + doa_out[2] <= mem[data_addra_int + 2]; + doa_out[3] <= mem[data_addra_int + 3]; + doa_out[4] <= mem[data_addra_int + 4]; + doa_out[5] <= mem[data_addra_int + 5]; + doa_out[6] <= mem[data_addra_int + 6]; + doa_out[7] <= mem[data_addra_int + 7]; + doa_out[8] <= mem[data_addra_int + 8]; + doa_out[9] <= mem[data_addra_int + 9]; + doa_out[10] <= mem[data_addra_int + 10]; + doa_out[11] <= mem[data_addra_int + 11]; + doa_out[12] <= mem[data_addra_int + 12]; + doa_out[13] <= mem[data_addra_int + 13]; + doa_out[14] <= mem[data_addra_int + 14]; + doa_out[15] <= mem[data_addra_int + 15]; + doa_out[16] <= mem[data_addra_int + 16]; + doa_out[17] <= mem[data_addra_int + 17]; + doa_out[18] <= mem[data_addra_int + 18]; + doa_out[19] <= mem[data_addra_int + 19]; + doa_out[20] <= mem[data_addra_int + 20]; + doa_out[21] <= mem[data_addra_int + 21]; + doa_out[22] <= mem[data_addra_int + 22]; + doa_out[23] <= mem[data_addra_int + 23]; + doa_out[24] <= mem[data_addra_int + 24]; + doa_out[25] <= mem[data_addra_int + 25]; + doa_out[26] <= mem[data_addra_int + 26]; + doa_out[27] <= mem[data_addra_int + 27]; + doa_out[28] <= mem[data_addra_int + 28]; + doa_out[29] <= mem[data_addra_int + 29]; + doa_out[30] <= mem[data_addra_int + 30]; + doa_out[31] <= mem[data_addra_int + 31]; + dopa_out[0] <= mem[parity_addra_int + 0]; + dopa_out[1] <= mem[parity_addra_int + 1]; + dopa_out[2] <= mem[parity_addra_int + 2]; + dopa_out[3] <= mem[parity_addra_int + 3]; + end + end + end + end + + always @(posedge clka_int) begin + if (ena_int == 1'b1 && wea_int == 1'b1) begin + mem[data_addra_int + 0] <= dia_int[0]; + mem[data_addra_int + 1] <= dia_int[1]; + mem[data_addra_int + 2] <= dia_int[2]; + mem[data_addra_int + 3] <= dia_int[3]; + mem[data_addra_int + 4] <= dia_int[4]; + mem[data_addra_int + 5] <= dia_int[5]; + mem[data_addra_int + 6] <= dia_int[6]; + mem[data_addra_int + 7] <= dia_int[7]; + mem[data_addra_int + 8] <= dia_int[8]; + mem[data_addra_int + 9] <= dia_int[9]; + mem[data_addra_int + 10] <= dia_int[10]; + mem[data_addra_int + 11] <= dia_int[11]; + mem[data_addra_int + 12] <= dia_int[12]; + mem[data_addra_int + 13] <= dia_int[13]; + mem[data_addra_int + 14] <= dia_int[14]; + mem[data_addra_int + 15] <= dia_int[15]; + mem[data_addra_int + 16] <= dia_int[16]; + mem[data_addra_int + 17] <= dia_int[17]; + mem[data_addra_int + 18] <= dia_int[18]; + mem[data_addra_int + 19] <= dia_int[19]; + mem[data_addra_int + 20] <= dia_int[20]; + mem[data_addra_int + 21] <= dia_int[21]; + mem[data_addra_int + 22] <= dia_int[22]; + mem[data_addra_int + 23] <= dia_int[23]; + mem[data_addra_int + 24] <= dia_int[24]; + mem[data_addra_int + 25] <= dia_int[25]; + mem[data_addra_int + 26] <= dia_int[26]; + mem[data_addra_int + 27] <= dia_int[27]; + mem[data_addra_int + 28] <= dia_int[28]; + mem[data_addra_int + 29] <= dia_int[29]; + mem[data_addra_int + 30] <= dia_int[30]; + mem[data_addra_int + 31] <= dia_int[31]; + mem[parity_addra_int + 0] <= dipa_int[0]; + mem[parity_addra_int + 1] <= dipa_int[1]; + mem[parity_addra_int + 2] <= dipa_int[2]; + mem[parity_addra_int + 3] <= dipa_int[3]; + end + end + + // Port B + always @(posedge clkb_int) begin + if (enb_int == 1'b1) begin + if (ssrb_int == 1'b1) begin + dob_out[0] <= SRVAL_B[0]; + dob_out[1] <= SRVAL_B[1]; + dob_out[2] <= SRVAL_B[2]; + dob_out[3] <= SRVAL_B[3]; + dob_out[4] <= SRVAL_B[4]; + dob_out[5] <= SRVAL_B[5]; + dob_out[6] <= SRVAL_B[6]; + dob_out[7] <= SRVAL_B[7]; + dob_out[8] <= SRVAL_B[8]; + dob_out[9] <= SRVAL_B[9]; + dob_out[10] <= SRVAL_B[10]; + dob_out[11] <= SRVAL_B[11]; + dob_out[12] <= SRVAL_B[12]; + dob_out[13] <= SRVAL_B[13]; + dob_out[14] <= SRVAL_B[14]; + dob_out[15] <= SRVAL_B[15]; + dob_out[16] <= SRVAL_B[16]; + dob_out[17] <= SRVAL_B[17]; + dob_out[18] <= SRVAL_B[18]; + dob_out[19] <= SRVAL_B[19]; + dob_out[20] <= SRVAL_B[20]; + dob_out[21] <= SRVAL_B[21]; + dob_out[22] <= SRVAL_B[22]; + dob_out[23] <= SRVAL_B[23]; + dob_out[24] <= SRVAL_B[24]; + dob_out[25] <= SRVAL_B[25]; + dob_out[26] <= SRVAL_B[26]; + dob_out[27] <= SRVAL_B[27]; + dob_out[28] <= SRVAL_B[28]; + dob_out[29] <= SRVAL_B[29]; + dob_out[30] <= SRVAL_B[30]; + dob_out[31] <= SRVAL_B[31]; + dopb_out[0] <= SRVAL_B[32]; + dopb_out[1] <= SRVAL_B[33]; + dopb_out[2] <= SRVAL_B[34]; + dopb_out[3] <= SRVAL_B[35]; + end + else begin + if (web_int == 1'b1) begin + if (wr_mode_b == 2'b00) begin + dob_out <= dib_int; + dopb_out <= dipb_int; + end + else if (wr_mode_b == 2'b01) begin + dob_out[0] <= mem[data_addrb_int + 0]; + dob_out[1] <= mem[data_addrb_int + 1]; + dob_out[2] <= mem[data_addrb_int + 2]; + dob_out[3] <= mem[data_addrb_int + 3]; + dob_out[4] <= mem[data_addrb_int + 4]; + dob_out[5] <= mem[data_addrb_int + 5]; + dob_out[6] <= mem[data_addrb_int + 6]; + dob_out[7] <= mem[data_addrb_int + 7]; + dob_out[8] <= mem[data_addrb_int + 8]; + dob_out[9] <= mem[data_addrb_int + 9]; + dob_out[10] <= mem[data_addrb_int + 10]; + dob_out[11] <= mem[data_addrb_int + 11]; + dob_out[12] <= mem[data_addrb_int + 12]; + dob_out[13] <= mem[data_addrb_int + 13]; + dob_out[14] <= mem[data_addrb_int + 14]; + dob_out[15] <= mem[data_addrb_int + 15]; + dob_out[16] <= mem[data_addrb_int + 16]; + dob_out[17] <= mem[data_addrb_int + 17]; + dob_out[18] <= mem[data_addrb_int + 18]; + dob_out[19] <= mem[data_addrb_int + 19]; + dob_out[20] <= mem[data_addrb_int + 20]; + dob_out[21] <= mem[data_addrb_int + 21]; + dob_out[22] <= mem[data_addrb_int + 22]; + dob_out[23] <= mem[data_addrb_int + 23]; + dob_out[24] <= mem[data_addrb_int + 24]; + dob_out[25] <= mem[data_addrb_int + 25]; + dob_out[26] <= mem[data_addrb_int + 26]; + dob_out[27] <= mem[data_addrb_int + 27]; + dob_out[28] <= mem[data_addrb_int + 28]; + dob_out[29] <= mem[data_addrb_int + 29]; + dob_out[30] <= mem[data_addrb_int + 30]; + dob_out[31] <= mem[data_addrb_int + 31]; + dopb_out[0] <= mem[parity_addrb_int + 0]; + dopb_out[1] <= mem[parity_addrb_int + 1]; + dopb_out[2] <= mem[parity_addrb_int + 2]; + dopb_out[3] <= mem[parity_addrb_int + 3]; + end + end + else begin + dob_out[0] <= mem[data_addrb_int + 0]; + dob_out[1] <= mem[data_addrb_int + 1]; + dob_out[2] <= mem[data_addrb_int + 2]; + dob_out[3] <= mem[data_addrb_int + 3]; + dob_out[4] <= mem[data_addrb_int + 4]; + dob_out[5] <= mem[data_addrb_int + 5]; + dob_out[6] <= mem[data_addrb_int + 6]; + dob_out[7] <= mem[data_addrb_int + 7]; + dob_out[8] <= mem[data_addrb_int + 8]; + dob_out[9] <= mem[data_addrb_int + 9]; + dob_out[10] <= mem[data_addrb_int + 10]; + dob_out[11] <= mem[data_addrb_int + 11]; + dob_out[12] <= mem[data_addrb_int + 12]; + dob_out[13] <= mem[data_addrb_int + 13]; + dob_out[14] <= mem[data_addrb_int + 14]; + dob_out[15] <= mem[data_addrb_int + 15]; + dob_out[16] <= mem[data_addrb_int + 16]; + dob_out[17] <= mem[data_addrb_int + 17]; + dob_out[18] <= mem[data_addrb_int + 18]; + dob_out[19] <= mem[data_addrb_int + 19]; + dob_out[20] <= mem[data_addrb_int + 20]; + dob_out[21] <= mem[data_addrb_int + 21]; + dob_out[22] <= mem[data_addrb_int + 22]; + dob_out[23] <= mem[data_addrb_int + 23]; + dob_out[24] <= mem[data_addrb_int + 24]; + dob_out[25] <= mem[data_addrb_int + 25]; + dob_out[26] <= mem[data_addrb_int + 26]; + dob_out[27] <= mem[data_addrb_int + 27]; + dob_out[28] <= mem[data_addrb_int + 28]; + dob_out[29] <= mem[data_addrb_int + 29]; + dob_out[30] <= mem[data_addrb_int + 30]; + dob_out[31] <= mem[data_addrb_int + 31]; + dopb_out[0] <= mem[parity_addrb_int + 0]; + dopb_out[1] <= mem[parity_addrb_int + 1]; + dopb_out[2] <= mem[parity_addrb_int + 2]; + dopb_out[3] <= mem[parity_addrb_int + 3]; + end + end + end + end + + always @(posedge clkb_int) begin + if (enb_int == 1'b1 && web_int == 1'b1) begin + mem[data_addrb_int + 0] <= dib_int[0]; + mem[data_addrb_int + 1] <= dib_int[1]; + mem[data_addrb_int + 2] <= dib_int[2]; + mem[data_addrb_int + 3] <= dib_int[3]; + mem[data_addrb_int + 4] <= dib_int[4]; + mem[data_addrb_int + 5] <= dib_int[5]; + mem[data_addrb_int + 6] <= dib_int[6]; + mem[data_addrb_int + 7] <= dib_int[7]; + mem[data_addrb_int + 8] <= dib_int[8]; + mem[data_addrb_int + 9] <= dib_int[9]; + mem[data_addrb_int + 10] <= dib_int[10]; + mem[data_addrb_int + 11] <= dib_int[11]; + mem[data_addrb_int + 12] <= dib_int[12]; + mem[data_addrb_int + 13] <= dib_int[13]; + mem[data_addrb_int + 14] <= dib_int[14]; + mem[data_addrb_int + 15] <= dib_int[15]; + mem[data_addrb_int + 16] <= dib_int[16]; + mem[data_addrb_int + 17] <= dib_int[17]; + mem[data_addrb_int + 18] <= dib_int[18]; + mem[data_addrb_int + 19] <= dib_int[19]; + mem[data_addrb_int + 20] <= dib_int[20]; + mem[data_addrb_int + 21] <= dib_int[21]; + mem[data_addrb_int + 22] <= dib_int[22]; + mem[data_addrb_int + 23] <= dib_int[23]; + mem[data_addrb_int + 24] <= dib_int[24]; + mem[data_addrb_int + 25] <= dib_int[25]; + mem[data_addrb_int + 26] <= dib_int[26]; + mem[data_addrb_int + 27] <= dib_int[27]; + mem[data_addrb_int + 28] <= dib_int[28]; + mem[data_addrb_int + 29] <= dib_int[29]; + mem[data_addrb_int + 30] <= dib_int[30]; + mem[data_addrb_int + 31] <= dib_int[31]; + mem[parity_addrb_int + 0] <= dipb_int[0]; + mem[parity_addrb_int + 1] <= dipb_int[1]; + mem[parity_addrb_int + 2] <= dipb_int[2]; + mem[parity_addrb_int + 3] <= dipb_int[3]; + end + end + + specify + (CLKA *> DOA) = (100, 100); + (CLKA *> DOPA) = (100, 100); + (CLKB *> DOB) = (100, 100); + (CLKB *> DOPB) = (100, 100); + endspecify + +endmodule + +`else + +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/RAMB16_S36_S36.v,v 1.10 2007/02/22 01:58:06 wloo Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2005 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 10.1 +// \ \ Description : Xilinx Timing Simulation Library Component +// / / 16K-Bit Data and 2K-Bit Parity Dual Port Block RAM +// /___/ /\ Filename : RAMB16_S36_S36.v +// \ \ / \ Timestamp : Thu Mar 10 16:44:01 PST 2005 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// 03/10/05 - Initialized outputs. +// 02/21/07 - Fixed parameter SIM_COLLISION_CHECK (CR 433281). +// End Revision + +`timescale 1 ps/1 ps + +module RAMB16_S36_S36 (DOA, DOB, DOPA, DOPB, ADDRA, ADDRB, CLKA, CLKB, DIA, DIB, DIPA, DIPB, ENA, ENB, SSRA, SSRB, WEA, WEB); + + parameter INIT_A = 36'h0; + parameter INIT_B = 36'h0; + parameter SRVAL_A = 36'h0; + parameter SRVAL_B = 36'h0; + parameter WRITE_MODE_A = "WRITE_FIRST"; + parameter WRITE_MODE_B = "WRITE_FIRST"; + parameter SIM_COLLISION_CHECK = "ALL"; + localparam SETUP_ALL = 1000; + localparam SETUP_READ_FIRST = 3000; + + parameter INIT_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_08 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_09 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_0F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_10 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_11 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_12 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_13 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_14 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_15 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_16 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_17 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_18 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_19 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_1F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_20 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_21 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_22 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_23 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_24 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_25 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_26 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_27 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_28 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_29 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_2F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_30 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_31 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_32 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_33 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_34 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_35 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_36 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_37 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_38 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_39 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3A = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3B = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3C = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3D = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3E = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INIT_3F = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_03 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_04 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_05 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_06 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + parameter INITP_07 = 256'h0000000000000000000000000000000000000000000000000000000000000000; + + output [31:0] DOA; + output [3:0] DOPA; + output [31:0] DOB; + output [3:0] DOPB; + + input [8:0] ADDRA; + input [31:0] DIA; + input [3:0] DIPA; + input ENA, CLKA, WEA, SSRA; + input [8:0] ADDRB; + input [31:0] DIB; + input [3:0] DIPB; + input ENB, CLKB, WEB, SSRB; + + reg [31:0] doa_out = INIT_A[31:0]; + reg [3:0] dopa_out = INIT_A[35:32]; + reg [31:0] dob_out = INIT_B[31:0]; + reg [3:0] dopb_out = INIT_B[35:32]; + + reg [31:0] mem [511:0]; + reg [3:0] memp [511:0]; + + reg [8:0] count, countp; + reg [1:0] wr_mode_a, wr_mode_b; + + reg [5:0] dmi, dbi; + reg [5:0] pmi, pbi; + + wire [8:0] addra_int; + reg [8:0] addra_reg; + wire [31:0] dia_int; + wire [3:0] dipa_int; + wire ena_int, clka_int, wea_int, ssra_int; + reg ena_reg, wea_reg, ssra_reg; + wire [8:0] addrb_int; + reg [8:0] addrb_reg; + wire [31:0] dib_int; + wire [3:0] dipb_int; + wire enb_int, clkb_int, web_int, ssrb_int; + reg display_flag, output_flag; + reg enb_reg, web_reg, ssrb_reg; + + time time_clka, time_clkb; + time time_clka_clkb; + time time_clkb_clka; + + reg setup_all_a_b; + reg setup_all_b_a; + reg setup_zero; + reg setup_rf_a_b; + reg setup_rf_b_a; + reg [1:0] data_collision, data_collision_a_b, data_collision_b_a; + reg memory_collision, memory_collision_a_b, memory_collision_b_a; + reg change_clka; + reg change_clkb; + + wire [14:0] data_addra_int; + wire [14:0] data_addra_reg; + wire [14:0] data_addrb_int; + wire [14:0] data_addrb_reg; + + wire dia_enable = ena_int && wea_int; + wire dib_enable = enb_int && web_int; + + tri0 GSR = glbl.GSR; + wire gsr_int; + + buf b_gsr (gsr_int, GSR); + + buf b_doa [31:0] (DOA, doa_out); + buf b_dopa [3:0] (DOPA, dopa_out); + buf b_addra [8:0] (addra_int, ADDRA); + buf b_dia [31:0] (dia_int, DIA); + buf b_dipa [3:0] (dipa_int, DIPA); + buf b_ena (ena_int, ENA); + buf b_clka (clka_int, CLKA); + buf b_ssra (ssra_int, SSRA); + buf b_wea (wea_int, WEA); + + buf b_dob [31:0] (DOB, dob_out); + buf b_dopb [3:0] (DOPB, dopb_out); + buf b_addrb [8:0] (addrb_int, ADDRB); + buf b_dib [31:0] (dib_int, DIB); + buf b_dipb [3:0] (dipb_int, DIPB); + buf b_enb (enb_int, ENB); + buf b_clkb (clkb_int, CLKB); + buf b_ssrb (ssrb_int, SSRB); + buf b_web (web_int, WEB); + + + always @(gsr_int) + if (gsr_int) begin + assign {dopa_out, doa_out} = INIT_A; + assign {dopb_out, dob_out} = INIT_B; + end + else begin + deassign doa_out; + deassign dopa_out; + deassign dob_out; + deassign dopb_out; + end + + + initial begin + + for (count = 0; count < 8; count = count + 1) begin + mem[count] = INIT_00[(count * 32) +: 32]; + mem[8 * 1 + count] = INIT_01[(count * 32) +: 32]; + mem[8 * 2 + count] = INIT_02[(count * 32) +: 32]; + mem[8 * 3 + count] = INIT_03[(count * 32) +: 32]; + mem[8 * 4 + count] = INIT_04[(count * 32) +: 32]; + mem[8 * 5 + count] = INIT_05[(count * 32) +: 32]; + mem[8 * 6 + count] = INIT_06[(count * 32) +: 32]; + mem[8 * 7 + count] = INIT_07[(count * 32) +: 32]; + mem[8 * 8 + count] = INIT_08[(count * 32) +: 32]; + mem[8 * 9 + count] = INIT_09[(count * 32) +: 32]; + mem[8 * 10 + count] = INIT_0A[(count * 32) +: 32]; + mem[8 * 11 + count] = INIT_0B[(count * 32) +: 32]; + mem[8 * 12 + count] = INIT_0C[(count * 32) +: 32]; + mem[8 * 13 + count] = INIT_0D[(count * 32) +: 32]; + mem[8 * 14 + count] = INIT_0E[(count * 32) +: 32]; + mem[8 * 15 + count] = INIT_0F[(count * 32) +: 32]; + mem[8 * 16 + count] = INIT_10[(count * 32) +: 32]; + mem[8 * 17 + count] = INIT_11[(count * 32) +: 32]; + mem[8 * 18 + count] = INIT_12[(count * 32) +: 32]; + mem[8 * 19 + count] = INIT_13[(count * 32) +: 32]; + mem[8 * 20 + count] = INIT_14[(count * 32) +: 32]; + mem[8 * 21 + count] = INIT_15[(count * 32) +: 32]; + mem[8 * 22 + count] = INIT_16[(count * 32) +: 32]; + mem[8 * 23 + count] = INIT_17[(count * 32) +: 32]; + mem[8 * 24 + count] = INIT_18[(count * 32) +: 32]; + mem[8 * 25 + count] = INIT_19[(count * 32) +: 32]; + mem[8 * 26 + count] = INIT_1A[(count * 32) +: 32]; + mem[8 * 27 + count] = INIT_1B[(count * 32) +: 32]; + mem[8 * 28 + count] = INIT_1C[(count * 32) +: 32]; + mem[8 * 29 + count] = INIT_1D[(count * 32) +: 32]; + mem[8 * 30 + count] = INIT_1E[(count * 32) +: 32]; + mem[8 * 31 + count] = INIT_1F[(count * 32) +: 32]; + mem[8 * 32 + count] = INIT_20[(count * 32) +: 32]; + mem[8 * 33 + count] = INIT_21[(count * 32) +: 32]; + mem[8 * 34 + count] = INIT_22[(count * 32) +: 32]; + mem[8 * 35 + count] = INIT_23[(count * 32) +: 32]; + mem[8 * 36 + count] = INIT_24[(count * 32) +: 32]; + mem[8 * 37 + count] = INIT_25[(count * 32) +: 32]; + mem[8 * 38 + count] = INIT_26[(count * 32) +: 32]; + mem[8 * 39 + count] = INIT_27[(count * 32) +: 32]; + mem[8 * 40 + count] = INIT_28[(count * 32) +: 32]; + mem[8 * 41 + count] = INIT_29[(count * 32) +: 32]; + mem[8 * 42 + count] = INIT_2A[(count * 32) +: 32]; + mem[8 * 43 + count] = INIT_2B[(count * 32) +: 32]; + mem[8 * 44 + count] = INIT_2C[(count * 32) +: 32]; + mem[8 * 45 + count] = INIT_2D[(count * 32) +: 32]; + mem[8 * 46 + count] = INIT_2E[(count * 32) +: 32]; + mem[8 * 47 + count] = INIT_2F[(count * 32) +: 32]; + mem[8 * 48 + count] = INIT_30[(count * 32) +: 32]; + mem[8 * 49 + count] = INIT_31[(count * 32) +: 32]; + mem[8 * 50 + count] = INIT_32[(count * 32) +: 32]; + mem[8 * 51 + count] = INIT_33[(count * 32) +: 32]; + mem[8 * 52 + count] = INIT_34[(count * 32) +: 32]; + mem[8 * 53 + count] = INIT_35[(count * 32) +: 32]; + mem[8 * 54 + count] = INIT_36[(count * 32) +: 32]; + mem[8 * 55 + count] = INIT_37[(count * 32) +: 32]; + mem[8 * 56 + count] = INIT_38[(count * 32) +: 32]; + mem[8 * 57 + count] = INIT_39[(count * 32) +: 32]; + mem[8 * 58 + count] = INIT_3A[(count * 32) +: 32]; + mem[8 * 59 + count] = INIT_3B[(count * 32) +: 32]; + mem[8 * 60 + count] = INIT_3C[(count * 32) +: 32]; + mem[8 * 61 + count] = INIT_3D[(count * 32) +: 32]; + mem[8 * 62 + count] = INIT_3E[(count * 32) +: 32]; + mem[8 * 63 + count] = INIT_3F[(count * 32) +: 32]; + end + +// initiate parity start + for (countp = 0; countp < 64; countp = countp + 1) begin + memp[countp] = INITP_00[(countp * 4) +: 4]; + memp[64 * 1 + countp] = INITP_01[(countp * 4) +: 4]; + memp[64 * 2 + countp] = INITP_02[(countp * 4) +: 4]; + memp[64 * 3 + countp] = INITP_03[(countp * 4) +: 4]; + memp[64 * 4 + countp] = INITP_04[(countp * 4) +: 4]; + memp[64 * 5 + countp] = INITP_05[(countp * 4) +: 4]; + memp[64 * 6 + countp] = INITP_06[(countp * 4) +: 4]; + memp[64 * 7 + countp] = INITP_07[(countp * 4) +: 4]; + end +// initiate parity end + + change_clka <= 0; + change_clkb <= 0; + data_collision <= 0; + data_collision_a_b <= 0; + data_collision_b_a <= 0; + memory_collision <= 0; + memory_collision_a_b <= 0; + memory_collision_b_a <= 0; + setup_all_a_b <= 0; + setup_all_b_a <= 0; + setup_zero <= 0; + setup_rf_a_b <= 0; + setup_rf_b_a <= 0; + end + + assign data_addra_int = addra_int * 32; + assign data_addra_reg = addra_reg * 32; + assign data_addrb_int = addrb_int * 32; + assign data_addrb_reg = addrb_reg * 32; + + + initial begin + + display_flag = 1; + output_flag = 1; + + case (SIM_COLLISION_CHECK) + + "NONE" : begin + output_flag = 0; + display_flag = 0; + end + "WARNING_ONLY" : output_flag = 0; + "GENERATE_X_ONLY" : display_flag = 0; + "ALL" : ; + + default : begin + $display("Attribute Syntax Error : The Attribute SIM_COLLISION_CHECK on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are ALL, NONE, WARNING_ONLY or GENERATE_X_ONLY.", SIM_COLLISION_CHECK); + $finish; + end + + endcase // case(SIM_COLLISION_CHECK) + + end // initial begin + + + always @(posedge clka_int) begin + if ((output_flag || display_flag)) begin + time_clka = $time; + #0 time_clkb_clka = time_clka - time_clkb; + change_clka = ~change_clka; + end + end + + always @(posedge clkb_int) begin + if ((output_flag || display_flag)) begin + time_clkb = $time; + #0 time_clka_clkb = time_clkb - time_clka; + change_clkb = ~change_clkb; + end + end + + always @(change_clkb) begin + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_ALL)) + setup_all_a_b = 1; + if ((0 < time_clka_clkb) && (time_clka_clkb < SETUP_READ_FIRST)) + setup_rf_a_b = 1; + end + + always @(change_clka) begin + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_ALL)) + setup_all_b_a = 1; + if ((0 < time_clkb_clka) && (time_clkb_clka < SETUP_READ_FIRST)) + setup_rf_b_a = 1; + end + + always @(change_clkb or change_clka) begin + if ((time_clkb_clka == 0) && (time_clka_clkb == 0)) + setup_zero = 1; + end + + always @(posedge setup_zero) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_int[14:5] == data_addrb_int[14:5])) + memory_collision <= 1; + end + + always @(posedge setup_all_a_b or posedge setup_rf_a_b) begin + if ((ena_reg == 1) && (wea_reg == 1) && + (enb_int == 1) && (web_int == 1) && + (data_addra_reg[14:5] == data_addrb_int[14:5])) + memory_collision_a_b <= 1; + end + + always @(posedge setup_all_b_a or posedge setup_rf_b_a) begin + if ((ena_int == 1) && (wea_int == 1) && + (enb_reg == 1) && (web_reg == 1) && + (data_addra_int[14:5] == data_addrb_reg[14:5])) + memory_collision_b_a <= 1; + end + + always @(posedge setup_all_a_b) begin + if (data_addra_reg[14:5] == data_addrb_int[14:5]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) + 6'b000011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b010011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b010111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b011011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b100011 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_a_b <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision_a_b <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_a_b <= 0; + end + + + always @(posedge setup_all_b_a) begin + if (data_addra_int[14:5] == data_addrb_reg[14:5]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) + 6'b000011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b000111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b001011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b010111 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b011011 : begin data_collision_b_a <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b001001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b011001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b101001 : begin data_collision_b_a <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision_b_a <= 2'b01; display_wa_rb; end + endcase + end + end + setup_all_b_a <= 0; + end + + + always @(posedge setup_zero) begin + if (data_addra_int[14:5] == data_addrb_int[14:5]) begin + if ((ena_int == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_int}) + 6'b000011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b000111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b001011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b010011 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision <= 2'b10; display_wa_wb; end + 6'b100011 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b100111 : begin data_collision <= 2'b01; display_wa_wb; end + 6'b101011 : begin display_wa_wb; end + 6'b000001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b000101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b001001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b010001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b010101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b011001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b100001 : begin data_collision <= 2'b10; display_ra_wb; end +// 6'b100101 : begin data_collision <= 2'b00; display_ra_wb; end + 6'b101001 : begin data_collision <= 2'b10; display_ra_wb; end + 6'b000010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b000110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b001010 : begin data_collision <= 2'b01; display_wa_rb; end +// 6'b010010 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision <= 2'b00; display_wa_rb; end + 6'b100010 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b100110 : begin data_collision <= 2'b01; display_wa_rb; end + 6'b101010 : begin data_collision <= 2'b01; display_wa_rb; end + endcase + end + end + setup_zero <= 0; + end + + task display_ra_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port A while a write was requested to the same address on Port B. The write will be successful however the read value on Port A is unknown until the next CLKA cycle.", $time/1000.0, addra_int); + end + endtask + + task display_wa_rb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA read was performed on address %h (hex) of Port B while a write was requested to the same address on Port A. The write will be successful however the read value on Port B is unknown until the next CLKB cycle.", $time/1000.0, addrb_int); + end + endtask + + task display_wa_wb; + begin + if (display_flag) + $display("Memory Collision Error on RAMB16_S36_S36:%m at simulation time %.3f ns\nA write was requested to the same address simultaneously at both Port A and Port B of the RAM. The contents written to the RAM at address location %h (hex) of Port A and address location %h (hex) of Port B are unknown.", $time/1000.0, addra_int, addrb_int); + end + endtask + + + always @(posedge setup_rf_a_b) begin + if (data_addra_reg[14:5] == data_addrb_int[14:5]) begin + if ((ena_reg == 1) && (enb_int == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_reg, web_int}) +// 6'b000011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b001011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end + 6'b010011 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b010111 : begin data_collision_a_b <= 2'b11; display_wa_wb; end + 6'b011011 : begin data_collision_a_b <= 2'b10; display_wa_wb; end +// 6'b100011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b100111 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b101011 : begin data_collision_a_b <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b001001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b010101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b011001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b100101 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b101001 : begin data_collision_a_b <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + 6'b010010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b010110 : begin data_collision_a_b <= 2'b01; display_wa_rb; end + 6'b011010 : begin data_collision_a_b <= 2'b01; display_wa_rb; end +// 6'b100010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_a_b <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_a_b <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_a_b <= 0; + end + + + always @(posedge setup_rf_b_a) begin + if (data_addra_int[14:5] == data_addrb_reg[14:5]) begin + if ((ena_int == 1) && (enb_reg == 1)) begin + case ({wr_mode_a, wr_mode_b, wea_int, web_reg}) +// 6'b000011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b000111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b001011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b010011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b010111 : begin data_collision_b_a <= 2'b11; display_wa_wb; end +// 6'b011011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b100011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end + 6'b100111 : begin data_collision_b_a <= 2'b01; display_wa_wb; end +// 6'b101011 : begin data_collision_b_a <= 2'b00; display_wa_wb; end +// 6'b000001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b000101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b001001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b010001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b010101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b011001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b100001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end + 6'b100101 : begin data_collision_b_a <= 2'b10; display_ra_wb; end +// 6'b101001 : begin data_collision_b_a <= 2'b00; display_ra_wb; end +// 6'b000010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b000110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b001010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b010110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b011010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b100110 : begin data_collision_b_a <= 2'b00; display_wa_rb; end +// 6'b101010 : begin data_collision_b_a <= 2'b00; display_wa_rb; end + endcase + end + end + setup_rf_b_a <= 0; + end + + + always @(posedge clka_int) begin + if ((output_flag || display_flag)) begin + addra_reg <= addra_int; + ena_reg <= ena_int; + ssra_reg <= ssra_int; + wea_reg <= wea_int; + end + end + + always @(posedge clkb_int) begin + if ((output_flag || display_flag)) begin + addrb_reg <= addrb_int; + enb_reg <= enb_int; + ssrb_reg <= ssrb_int; + web_reg <= web_int; + end + end + + + // Data + always @(posedge memory_collision) begin + if ((output_flag || display_flag)) begin + mem[addra_int] <= 32'bx; + memory_collision <= 0; + end + + end + + always @(posedge memory_collision_a_b) begin + if ((output_flag || display_flag)) begin + mem[addra_reg] <= 32'bx; + memory_collision_a_b <= 0; + end + end + + always @(posedge memory_collision_b_a) begin + if ((output_flag || display_flag)) begin + mem[addra_int] <= 32'bx; + memory_collision_b_a <= 0; + end + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0 && output_flag) begin + doa_out <= #100 32'bX; + end + data_collision[1] <= 0; + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0 && output_flag) begin + dob_out <= #100 32'bX; + end + data_collision[0] <= 0; + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0 && output_flag) begin + doa_out <= #100 32'bX; + end + data_collision_a_b[1] <= 0; + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0 && output_flag) begin + dob_out <= #100 32'bX; + end + data_collision_a_b[0] <= 0; + end + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0 && output_flag) begin + doa_out <= #100 32'bX; + end + data_collision_b_a[1] <= 0; + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0 && output_flag) begin + dob_out <= #100 32'bX; + end + data_collision_b_a[0] <= 0; + end + +// x parity start + always @(posedge memory_collision) begin + if ((output_flag || display_flag)) + memp[addra_int] <= 4'bx; + end + + always @(posedge memory_collision_a_b) begin + if ((output_flag || display_flag)) + memp[addra_reg] <= 4'bx; + end + + always @(posedge memory_collision_b_a) begin + if ((output_flag || display_flag)) + memp[addra_int] <= 4'bx; + end + + always @(posedge data_collision[1]) begin + if (ssra_int == 0 && output_flag) begin + dopa_out <= #100 4'bX; + end + end + + always @(posedge data_collision_a_b[1]) begin + if (ssra_reg == 0 && output_flag) begin + dopa_out <= #100 4'bX; + end + end + + + always @(posedge data_collision_b_a[1]) begin + if (ssra_int == 0 && output_flag) begin + dopa_out <= #100 4'bX; + end + end + + always @(posedge data_collision[0]) begin + if (ssrb_int == 0 && output_flag) begin + dopb_out <= #100 4'bx; + end + end + + always @(posedge data_collision_a_b[0]) begin + if (ssrb_int == 0 && output_flag) begin + dopb_out <= #100 4'bx; + end + end + + always @(posedge data_collision_b_a[0]) begin + if (ssrb_reg == 0 && output_flag) begin + dopb_out <= #100 4'bx; + end + end +// x parity end + + initial begin + case (WRITE_MODE_A) + "WRITE_FIRST" : wr_mode_a <= 2'b00; + "READ_FIRST" : wr_mode_a <= 2'b01; + "NO_CHANGE" : wr_mode_a <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_A on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_A); + $finish; + end + endcase + end + + initial begin + case (WRITE_MODE_B) + "WRITE_FIRST" : wr_mode_b <= 2'b00; + "READ_FIRST" : wr_mode_b <= 2'b01; + "NO_CHANGE" : wr_mode_b <= 2'b10; + default : begin + $display("Attribute Syntax Error : The Attribute WRITE_MODE_B on RAMB16_S36_S36 instance %m is set to %s. Legal values for this attribute are WRITE_FIRST, READ_FIRST or NO_CHANGE.", WRITE_MODE_B); + $finish; + end + endcase + end + + + // Port A + always @(posedge clka_int) begin + + if (ena_int == 1'b1) begin + + if (ssra_int == 1'b1) begin + {dopa_out, doa_out} <= #100 SRVAL_A; + end + else begin + if (wea_int == 1'b1) begin + if (wr_mode_a == 2'b00) begin + doa_out <= #100 dia_int; + dopa_out <= #100 dipa_int; + end + else if (wr_mode_a == 2'b01) begin + + doa_out <= #100 mem[addra_int]; + dopa_out <= #100 memp[addra_int]; + + end + end + else begin + + doa_out <= #100 mem[addra_int]; + dopa_out <= #100 memp[addra_int]; + + end + end + + // memory + if (wea_int == 1'b1) begin + mem[addra_int] <= dia_int; + memp[addra_int] <= dipa_int; + end + + end + end + + + // Port B + always @(posedge clkb_int) begin + + if (enb_int == 1'b1) begin + + if (ssrb_int == 1'b1) begin + {dopb_out, dob_out} <= #100 SRVAL_B; + end + else begin + if (web_int == 1'b1) begin + if (wr_mode_b == 2'b00) begin + dob_out <= #100 dib_int; + dopb_out <= #100 dipb_int; + end + else if (wr_mode_b == 2'b01) begin + dob_out <= #100 mem[addrb_int]; + dopb_out <= #100 memp[addrb_int]; + end + end + else begin + dob_out <= #100 mem[addrb_int]; + dopb_out <= #100 memp[addrb_int]; + end + end + + // memory + if (web_int == 1'b1) begin + mem[addrb_int] <= dib_int; + memp[addrb_int] <= dipb_int; + end + + end + end + + +endmodule + +`endif diff --git a/fpga/usrp2/models/SRL16E.v b/fpga/usrp2/models/SRL16E.v new file mode 100644 index 000000000..e71a419ac --- /dev/null +++ b/fpga/usrp2/models/SRL16E.v @@ -0,0 +1,53 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/SRL16E.v,v 1.7 2005/03/14 22:32:58 yanx Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2004 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 8.1i (I.13) +// \ \ Description : Xilinx Functional Simulation Library Component +// / / 16-Bit Shift Register Look-Up-Table with Clock Enable +// /___/ /\ Filename : SRL16E.v +// \ \ / \ Timestamp : Thu Mar 25 16:43:40 PST 2004 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// End Revision + +`timescale 1 ps / 1 ps + + +module SRL16E (Q, A0, A1, A2, A3, CE, CLK, D); + + parameter INIT = 16'h0000; + + output Q; + + input A0, A1, A2, A3, CE, CLK, D; + + reg [15:0] data; + + + assign Q = data[{A3, A2, A1, A0}]; + + initial + begin + assign data = INIT; + while (CLK === 1'b1 || CLK===1'bX) + #10; + deassign data; + end + + always @(posedge CLK) + begin + if (CE == 1'b1) begin + {data[15:0]} <= #100 {data[14:0], D}; + end + end + + +endmodule + diff --git a/fpga/usrp2/models/SRLC16E.v b/fpga/usrp2/models/SRLC16E.v new file mode 100644 index 000000000..a68bbe9e9 --- /dev/null +++ b/fpga/usrp2/models/SRLC16E.v @@ -0,0 +1,61 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/unisims/SRLC16E.v,v 1.6.158.1 2007/03/09 18:13:20 patrickp Exp $ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1995/2004 Xilinx, Inc. +// All Right Reserved. +/////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor : Xilinx +// \ \ \/ Version : 8.1i (I.13) +// \ \ Description : Xilinx Functional Simulation Library Component +// / / 16-Bit Shift Register Look-Up-Table with Carry and Clock Enable +// /___/ /\ Filename : SRLC16E.v +// \ \ / \ Timestamp : Thu Mar 25 16:43:40 PST 2004 +// \___\/\___\ +// +// Revision: +// 03/23/04 - Initial version. +// End Revision + +`timescale 1 ps / 1 ps + + +module SRLC16E (Q, Q15, A0, A1, A2, A3, CE, CLK, D); + + parameter INIT = 16'h0000; + + output Q, Q15; + + input A0, A1, A2, A3, CE, CLK, D; + + reg [15:0] data; + wire [3:0] addr; + wire q_int; + + buf b_a3 (addr[3], A3); + buf b_a2 (addr[2], A2); + buf b_a1 (addr[1], A1); + buf b_a0 (addr[0], A0); + + buf b_q_int (q_int, data[addr]); + buf b_q (Q, q_int); + buf b_q15_int (q15_int, data[15]); + buf b_q15 (Q15, q15_int); + + initial + begin + assign data = INIT; + while (CLK === 1'b1 || CLK===1'bX) + #10; + deassign data; + end + + always @(posedge CLK) begin + if (CE == 1'b1) begin + {data[15:0]} <= #100 {data[14:0], D}; + end + end + + +endmodule + diff --git a/fpga/usrp2/models/adc_model.v b/fpga/usrp2/models/adc_model.v new file mode 100644 index 000000000..1d1f1c929 --- /dev/null +++ b/fpga/usrp2/models/adc_model.v @@ -0,0 +1,65 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + +module adc_model + (input clk, input rst, + output [13:0] adc_a, + output adc_ovf_a, + input adc_on_a, + input adc_oe_a, + output [13:0] adc_b, + output adc_ovf_b, + input adc_on_b, + input adc_oe_b + ); + + math_real math ( ) ; + + reg [13:0] adc_a_int = 0; + reg [13:0] adc_b_int = 0; + + assign adc_a = adc_oe_a ? adc_a_int : 14'bz; + assign adc_ovf_a = adc_oe_a ? 1'b0 : 1'bz; + assign adc_b = adc_oe_b ? adc_b_int : 14'bz; + assign adc_ovf_b = adc_oe_b ? 1'b0 : 1'bz; + + real phase = 0; + real freq = 330000/100000000; + + real scale = 8190; // math.pow(2,13)-2; + always @(posedge clk) + if(rst) + begin + adc_a_int <= 0; + adc_b_int <= 0; + end + else + begin + if(adc_on_a) + //adc_a_int <= $rtoi(math.round(math.sin(phase*math.MATH_2_PI)*scale)) ; + adc_a_int <= adc_a_int + 3; + if(adc_on_b) + adc_b_int <= adc_b_int - 7; + //adc_b_int <= $rtoi(math.round(math.cos(phase*math.MATH_2_PI)*scale)) ; + if(phase > 1) + phase <= phase + freq - 1; + else + phase <= phase + freq; + end + +endmodule // adc_model diff --git a/fpga/usrp2/models/cpld_model.v b/fpga/usrp2/models/cpld_model.v new file mode 100644 index 000000000..900577852 --- /dev/null +++ b/fpga/usrp2/models/cpld_model.v @@ -0,0 +1,113 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + +module cpld_model + (input aux_clk, input start, input mode, input done, + output dout, output reg sclk, output detached); + + reg [7:0] rom[0:65535]; + + reg [15:0] addr; + reg [7:0] data; + assign dout = data[7]; + + reg [2:0] state, bitcnt; + + localparam IDLE = 3'd0; + localparam READ = 3'd1; + localparam BIT1 = 3'd2; + localparam BIT2 = 3'd3; + localparam DONE = 3'd4; + localparam DETACHED = 3'd5; + localparam ERROR = 3'd7; + + integer i; + reg [1023:0] ROMFile; + + initial begin + for (i=0;i<65536;i=i+1) begin + rom[i] <= 32'h0; + end + if ( !$value$plusargs( "rom=%s", ROMFile ) ) + begin + $display( "Using default ROM file, 'flash.rom'" ); + ROMFile = "flash.rom"; + end + else + $display( "Using %s as ROM file.", ROMFile); + + #1 $readmemh( ROMFile,rom ); + end + + initial addr = 16'd0; + initial data = 8'd0; + initial state = IDLE; + initial bitcnt = 3'd0; + initial sclk = 1'b0; + + always @(posedge aux_clk) + case(state) + IDLE : + if(start) + if(~mode) + state <= READ; + else + state <= ERROR; + READ : + if(done) + state <= DONE; + else + begin + data <= rom[addr]; + addr <= addr + 1; + bitcnt <= 3'd0; + if(addr==16'hFFFF) + state <= ERROR; + else + state <= BIT1; + end // else: !if(start) + BIT1 : + begin + sclk <= 1'b1; + state <= BIT2; + end + BIT2 : + begin + sclk <= 1'b0; + data <= {data[6:0],1'b0}; + bitcnt <= bitcnt + 1; + if(bitcnt==7) + state <= READ; + else + state <=BIT1; + end + DONE : + begin + if(start) + state <= ERROR; + else + state <= DETACHED; + end + DETACHED : + if(start) + state <= ERROR; + endcase // case(state) + + assign detached = (state == DETACHED) || (state == IDLE); + +endmodule // cpld_model diff --git a/fpga/usrp2/models/gpmc_model_async.v b/fpga/usrp2/models/gpmc_model_async.v new file mode 100644 index 000000000..22b3cdf9f --- /dev/null +++ b/fpga/usrp2/models/gpmc_model_async.v @@ -0,0 +1,147 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +`timescale 1ps/1ps + +module gpmc_model_async + (output EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE, + output reg EM_WAIT0, output reg EM_NCS4, output reg EM_NCS6, + output reg EM_NWE, output reg EM_NOE ); + + assign EM_CLK = 0; + reg [15:0] EM_D_int; + assign EM_D = EM_D_int; + + initial + begin + EM_A <= 10'bz; + EM_NBE <= 2'b11; + EM_NWE <= 1; + EM_NOE <= 1; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + EM_D_int <= 16'bz; + EM_WAIT0 <= 0; // FIXME this is actually an input + end + + task GPMC_Write; + input ctrl; + input [10:0] addr; + input [15:0] data; + begin + #23000; + EM_A <= addr[10:1]; + EM_D_int <= data; + #20100; + if(ctrl) + EM_NCS6 <= 0; + else + EM_NCS4 <= 0; + #14000; + EM_NWE <= 0; + #77500; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + //#1.5; + EM_NWE <= 1; + #60000; + EM_A <= 10'bz; + EM_D_int <= 16'bz; + end + endtask // GPMC_Write + + task GPMC_Read; + input ctrl; + input [10:0] addr; + begin + #13000; + EM_A <= addr[10:1]; + #3000; + if(ctrl) + EM_NCS6 <= 0; + else + EM_NCS4 <= 0; + #14000; + EM_NOE <= 0; + #77500; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + //#1.5; + $display("Data Read from GPMC: %X",EM_D); + EM_NOE <= 1; + #254000; + EM_A <= 10'bz; + end + endtask // GPMC_Read + + initial + begin + #1000000; + GPMC_Write(1,36,16'hF00D); + #1000000; + GPMC_Read(1,36); + #1000000; + GPMC_Write(0,0,16'h1234); + GPMC_Write(0,0,16'h5678); + GPMC_Write(0,0,16'h9abc); + GPMC_Write(0,0,16'hF00D); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + #1000000; + GPMC_Write(0,0,16'h1234); + GPMC_Write(0,0,16'h5678); + GPMC_Write(0,0,16'h9abc); + GPMC_Write(0,0,16'hF00D); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'hDEAD); + GPMC_Write(0,0,16'h9876); + #1000000; + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + #1000000; + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + GPMC_Read(0,0); + #1000000; + GPMC_Read(0,0); + #100000000; + $finish; + end + +endmodule // gpmc_model_async diff --git a/fpga/usrp2/models/gpmc_model_sync.v b/fpga/usrp2/models/gpmc_model_sync.v new file mode 100644 index 000000000..0f66961e7 --- /dev/null +++ b/fpga/usrp2/models/gpmc_model_sync.v @@ -0,0 +1,114 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + + +module gpmc_model_sync + (output reg EM_CLK, inout [15:0] EM_D, output reg [10:1] EM_A, output reg [1:0] EM_NBE, + output reg EM_WAIT0, output reg EM_NCS4, output reg EM_NCS6, + output reg EM_NWE, output reg EM_NOE ); + + reg [15:0] EM_D_int; + assign EM_D = EM_D_int; + + initial + begin + EM_CLK <= 0; + EM_A <= 10'bz; + EM_NBE <= 2'b11; + EM_NWE <= 1; + EM_NOE <= 1; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + EM_D_int <= 16'bz; + EM_WAIT0 <= 0; // FIXME this is actually an input + end + + task GPMC_Write; + input ctrl; + input [10:0] addr; + input [15:0] data; + begin + EM_CLK <= 1; + #10; + EM_CLK <= 0; + EM_NWE <= 0; + if(ctrl) + EM_NCS6 <= 0; + else + EM_NCS4 <= 0; + EM_A <= addr[10:1]; + EM_D_int <= data; + #10; + EM_CLK <= 1; + #10; + EM_CLK <= 0; + EM_NWE <= 1; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + EM_A <= 10'bz; + EM_D_int <= 16'bz; + #100; + end + endtask // GPMC_Write + + task GPMC_Read; + input ctrl; + input [10:0] addr; + begin + #1.3; + EM_A <= addr[10:1]; + #3; + if(ctrl) + EM_NCS6 <= 0; + else + EM_NCS4 <= 0; + #14; + EM_NOE <= 0; + #77.5; + EM_NCS4 <= 1; + EM_NCS6 <= 1; + //#1.5; + $display("Data Read from GPMC: %X",EM_D); + EM_NOE <= 1; + #254; + EM_A <= 10'bz; + end + endtask // GPMC_Read + + initial + begin + #1000; + GPMC_Write(1,36,16'hF00D); + #1000; + GPMC_Read(1,36); + #1000; + GPMC_Write(0,36,16'h1234); + GPMC_Write(0,38,16'h5678); + GPMC_Write(0,40,16'h9abc); + GPMC_Write(0,11'h2F4,16'hF00D); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + GPMC_Write(0,11'h7FE,16'hDEAD); + #100000; + $finish; + end + +endmodule // gpmc_model diff --git a/fpga/usrp2/models/idt71v65603s150.v b/fpga/usrp2/models/idt71v65603s150.v new file mode 100755 index 000000000..457dfa6dd --- /dev/null +++ b/fpga/usrp2/models/idt71v65603s150.v @@ -0,0 +1,301 @@ +/******************************************************************************* + * + * File Name : idt71v65603s150.v + * Product : IDT71V65603 + * Function : 256K x 36 pipeline ZBT Static RAM + * Simulation Tool/Version : Verilog-XL 2.5 + * Date : 07/19/00 + * + * Copyright 1999 Integrated Device Technology, Inc. + * + * Revision Notes: 07/19/00 Rev00 + * + ******************************************************************************/ +/******************************************************************************* + * Module Name: idt71v65603s150 + * + * Notes : This model is believed to be functionally + * accurate. Please direct any inquiries to + * IDT SRAM Applications at: sramhelp@idt.com + * + *******************************************************************************/ + + /*************************************************************** + * + * Integrated Device Technology, Inc. ("IDT") hereby grants the + * user of this Verilog/VCS model a non-exclusive, nontransferable + * license to use this Verilog/VCS model under the following terms. + * The user is granted this license only to use the Verilog/VCS + * model and is not granted rights to sell, copy (except as needed + * to run the IBIS model), rent, lease or sub-license the Verilog/VCS + * model in whole or in part, or in modified form to anyone. The User + * may modify the Verilog/VCS model to suit its specific applications, + * but rights to derivative works and such modifications shall belong + * to IDT. + * + * This Verilog/VCS model is provided on an "AS IS" basis and + * IDT makes absolutely no warranty with respect to the information + * contained herein. IDT DISCLAIMS AND CUSTOMER WAIVES ALL + * WARRANTIES, EXPRESS AND IMPLIED, INCLUDING WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * ENTIRE RISK AS TO QUALITY AND PERFORMANCE IS WITH THE + * USER ACCORDINGLY, IN NO EVENT SHALL IDT BE LIABLE + * FOR ANY DIRECT OR INDIRECT DAMAGES, WHETHER IN CONTRACT OR + * TORT, INCLUDING ANY LOST PROFITS OR OTHER INCIDENTAL, + * CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES ARISING OUT OF + * THE USE OR APPLICATION OF THE VERILOG/VCS model. Further, + * IDT reserves the right to make changes without notice to any + * product herein to improve reliability, function, or design. + * IDT does not convey any license under patent rights or + * any other intellectual property rights, including those of + * third parties. IDT is not obligated to provide maintenance + * or support for the licensed Verilog/VCS model. + * + ***************************************************************/ + + `timescale 1ns/100ps + +module idt71v65603s150 (A, + adv_ld_, // advance (high) / load (low) + bw1_, bw2_, bw3_, bw4_, // byte write enables (low) + ce1_, ce2, ce2_, // chip enables + cen_, // clock enable (low) + clk, // clock + IO, IOP, // data bus + lbo_, // linear burst order (low) + oe_, // output enable (low) + r_w_); // read (high) / write (low) + +initial +begin + $write("\n********************************************************\n"); + $write(" idt71v65603s150, 256K x 36 Pipelined burst ZBT SRAM \n"); + $write(" Rev: 00 July 2000 \n"); + $write(" copyright 1997,1998,1999,2000 by IDT, Inc. \n"); + $write("********************************************************\n\n"); +end + +input [17:0] A; +inout [31:0] IO; +inout [4:1] IOP; +input adv_ld_, bw1_, bw2_, bw3_, bw4_, ce1_, ce2, ce2_, + cen_, clk, lbo_, oe_, r_w_; + + +//internal registers for data, address, etc +reg [8:0] mem1[0:262143]; //memory array +reg [8:0] mem2[0:262143]; //memory array +reg [8:0] mem3[0:262143]; //memory array +reg [8:0] mem4[0:262143]; //memory array + +reg [35:0] dout; +reg [17:0] addr_a, + addr_b; +reg wren_a, wren_b; +reg cs_a, cs_b; +reg bw_a1, bw_b1; +reg bw_a2, bw_b2; +reg bw_a3, bw_b3; +reg bw_a4, bw_b4; +reg [1:0] brst_cnt; + +wire[35:0] data_out; +wire doe; +wire cs = (~ce1_ & ce2 & ~ce2_); +wire baddr0, baddr1; + + +parameter regdelay = 0.2; +parameter outdly = 0.2; + +specify +specparam +//Clock Parameters + tCYC = 6.7, //clock cycle time + tCH = 2.0, //clock high time + tCL = 2.0, //clock low time + +//Output Parameters + tCD = 3.8, //clk to data valid + tCLZ = 1.5, //clk to output Low-Z + tCHZ = 3.0, //clk to data Hi-Z + tOE = 3.8, //OE to output valid + tOLZ = 0.0, //OE to output Hi-Z + tOHZ = 3.8, //OE to output Hi-Z + +//Set up times + tSE = 1.5, //clock enable set-up + tSA = 1.5, //address set-up + tSD = 1.5, //data set-up + tSW = 1.5, //Read/Write set-up + tSADV = 1.5, //Advance/Load set-up + tSC = 1.5, //Chip enable set-up + tSB = 1.5, //Byte write enable set-up + +//Hold times + tHE = 0.5, //clock enable hold + tHA = 0.5, //address hold + tHD = 0.5, //data hold + tHW = 0.5, //Read/Write hold + tHADV = 0.5, //Advance/Load hold + tHC = 0.5, //Chip enable hold + tHB = 0.5; //Byte write enable hold + + + (oe_ *> IO) = (tOE,tOE,tOHZ,tOLZ,tOHZ,tOLZ); //(01,10,0z,z1,1z,z0) + (clk *> IO) = (tCD,tCD,tCHZ,tCLZ,tCHZ,tCLZ); //(01,10,0z,z1,1z,z0) + + (oe_ *> IOP) = (tOE,tOE,tOHZ,tOLZ,tOHZ,tOLZ); //(01,10,0z,z1,1z,z0) + (clk *> IOP) = (tCD,tCD,tCHZ,tCLZ,tCHZ,tCLZ); //(01,10,0z,z1,1z,z0) + +//timing checks + + $period(posedge clk, tCYC ); + $width (posedge clk, tCH ); + $width (negedge clk, tCL ); + + + $setuphold(posedge clk, A, tSA, tHA); + $setuphold(posedge clk, IO, tSD, tHD); + $setuphold(posedge clk, IOP, tSD, tHD); + $setuphold(posedge clk, adv_ld_, tSADV, tHADV); + $setuphold(posedge clk, bw1_, tSB, tHB); + $setuphold(posedge clk, bw2_, tSB, tHB); + $setuphold(posedge clk, bw3_, tSB, tHB); + $setuphold(posedge clk, bw4_, tSB, tHB); + $setuphold(posedge clk, ce1_, tSC, tHC); + $setuphold(posedge clk, ce2, tSC, tHC); + $setuphold(posedge clk, ce2_, tSC, tHC); + $setuphold(posedge clk, cen_, tSE, tHE); + $setuphold(posedge clk, r_w_, tSW, tHW); + +endspecify + +initial begin + cs_a = 0; + cs_b = 0; +end + + +///////////////////////////////////////////////////////////////////////// +//input registers +//-------------------- +always @(posedge clk) +begin + if ( ~cen_ & ~adv_ld_ ) cs_a <= #regdelay cs; + if ( ~cen_ ) cs_b <= #regdelay cs_a; + + if ( ~cen_ & ~adv_ld_ ) wren_a <= #regdelay (cs & ~r_w_); + if ( ~cen_ ) wren_b <= #regdelay wren_a; + + if ( ~cen_ ) bw_a1 <= #regdelay ~bw1_; + if ( ~cen_ ) bw_a2 <= #regdelay ~bw2_; + if ( ~cen_ ) bw_a3 <= #regdelay ~bw3_; + if ( ~cen_ ) bw_a4 <= #regdelay ~bw4_; + + if ( ~cen_ ) bw_b1 <= #regdelay bw_a1; + if ( ~cen_ ) bw_b2 <= #regdelay bw_a2; + if ( ~cen_ ) bw_b3 <= #regdelay bw_a3; + if ( ~cen_ ) bw_b4 <= #regdelay bw_a4; + + if ( ~cen_ & ~adv_ld_ ) addr_a[17:0] <= #regdelay A[17:0]; + if ( ~cen_ ) addr_b[17:0] <= #regdelay {addr_a[17:2], baddr1, baddr0}; +end + + +///////////////////////////////////////////////////////////////////////// +//burst counter +//-------------------- +always @(posedge clk) +begin + if ( lbo_ & ~cen_ & ~adv_ld_) brst_cnt <= #regdelay 0; + else if (~lbo_ & ~cen_ & ~adv_ld_) brst_cnt <= #regdelay A[1:0]; + else if ( ~cen_ & adv_ld_) brst_cnt <= #regdelay brst_cnt + 1; +end + + +///////////////////////////////////////////////////////////////////////// +//address logic +//-------------------- +assign baddr1 = lbo_ ? (brst_cnt[1] ^ addr_a[1]) : brst_cnt[1]; +assign baddr0 = lbo_ ? (brst_cnt[0] ^ addr_a[0]) : brst_cnt[0]; + + +///////////////////////////////////////////////////////////////////////// +//data output register +//-------------------- +always @(posedge clk) +begin + #regdelay; + #regdelay; + dout[8:0] = mem1[addr_b]; + dout[17:9] = mem2[addr_b]; + dout[26:18] = mem3[addr_b]; + dout[35:27] = mem4[addr_b]; +end + +assign data_out = dout; + + +///////////////////////////////////////////////////////////////////////// +//Output buffers: using a bufif1 has the same effect as... +// +// assign D = doe ? data_out : 36'hz; +// +//It was coded this way to support SPECIFY delays in the specparam section. +//-------------------- +bufif1 #outdly (IO[0],data_out[0],doe); +bufif1 #outdly (IO[1],data_out[1],doe); +bufif1 #outdly (IO[2],data_out[2],doe); +bufif1 #outdly (IO[3],data_out[3],doe); +bufif1 #outdly (IO[4],data_out[4],doe); +bufif1 #outdly (IO[5],data_out[5],doe); +bufif1 #outdly (IO[6],data_out[6],doe); +bufif1 #outdly (IO[7],data_out[7],doe); +bufif1 #outdly (IOP[1],data_out[8],doe); + +bufif1 #outdly (IO[8],data_out[9],doe); +bufif1 #outdly (IO[9],data_out[10],doe); +bufif1 #outdly (IO[10],data_out[11],doe); +bufif1 #outdly (IO[11],data_out[12],doe); +bufif1 #outdly (IO[12],data_out[13],doe); +bufif1 #outdly (IO[13],data_out[14],doe); +bufif1 #outdly (IO[14],data_out[15],doe); +bufif1 #outdly (IO[15],data_out[16],doe); +bufif1 #outdly (IOP[2],data_out[17],doe); + +bufif1 #outdly (IO[16],data_out[18],doe); +bufif1 #outdly (IO[17],data_out[19],doe); +bufif1 #outdly (IO[18],data_out[20],doe); +bufif1 #outdly (IO[19],data_out[21],doe); +bufif1 #outdly (IO[20],data_out[22],doe); +bufif1 #outdly (IO[21],data_out[23],doe); +bufif1 #outdly (IO[22],data_out[24],doe); +bufif1 #outdly (IO[23],data_out[25],doe); +bufif1 #outdly (IOP[3],data_out[26],doe); + +bufif1 #outdly (IO[24],data_out[27],doe); +bufif1 #outdly (IO[25],data_out[28],doe); +bufif1 #outdly (IO[26],data_out[29],doe); +bufif1 #outdly (IO[27],data_out[30],doe); +bufif1 #outdly (IO[28],data_out[31],doe); +bufif1 #outdly (IO[29],data_out[32],doe); +bufif1 #outdly (IO[30],data_out[33],doe); +bufif1 #outdly (IO[31],data_out[34],doe); +bufif1 #outdly (IOP[4],data_out[35],doe); + +assign doe = cs_b & ~wren_b & ~oe_ ; + + +///////////////////////////////////////////////////////////////////////// +// write to ram +//------------- +always @(posedge clk) +begin + if (wren_b & bw_b1 & ~cen_) mem1[addr_b] = {IOP[1], IO[7:0]}; + if (wren_b & bw_b2 & ~cen_) mem2[addr_b] = {IOP[2], IO[15:8]}; + if (wren_b & bw_b3 & ~cen_) mem3[addr_b] = {IOP[3], IO[23:16]}; + if (wren_b & bw_b4 & ~cen_) mem4[addr_b] = {IOP[4], IO[31:24]}; +end + +endmodule diff --git a/fpga/usrp2/models/math_real.v b/fpga/usrp2/models/math_real.v new file mode 100644 index 000000000..d88f72669 --- /dev/null +++ b/fpga/usrp2/models/math_real.v @@ -0,0 +1,512 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +/*
+ * This is a general recreation of the VHDL ieee.math_real package.
+ */
+
+module math_real ;
+ // Constants for use below and for general reference
+ // TODO: Bring it out to 12 (or more???) places beyond the decimal?
+ localparam MATH_E = 2.7182818284;
+ localparam MATH_1_OVER_E = 0.3678794411;
+ localparam MATH_PI = 3.1415926536;
+ localparam MATH_2_PI = 6.2831853071;
+ localparam MATH_1_OVER_PI = 0.3183098861;
+ localparam MATH_PI_OVER_2 = 1.5707963267;
+ localparam MATH_PI_OVER_3 = 1.0471975511;
+ localparam MATH_PI_OVER_4 = 0.7853981633;
+ localparam MATH_3_PI_OVER_2 = 4.7123889803;
+ localparam MATH_LOG_OF_2 = 0.6931471805;
+ localparam MATH_LOG_OF_10 = 2.3025850929;
+ localparam MATH_LOG2_OF_E = 1.4426950408;
+ localparam MATH_LOG10_OF_E = 0.4342944819;
+ localparam MATH_SQRT_2 = 1.4142135623;
+ localparam MATH_1_OVER_SQRT_2= 0.7071067811;
+ localparam MATH_SQRT_PI = 1.7724538509;
+ localparam MATH_DEG_TO_RAD = 0.0174532925;
+ localparam MATH_RAD_TO_DEG = 57.2957795130;
+
+ // The number of iterations to do for the Taylor series approximations
+ localparam EXPLOG_ITERATIONS = 19;
+ localparam COS_ITERATIONS = 8;
+
+ /* Conversion Routines */
+
+ // Return the sign of a particular number.
+ function real sign ;
+ input real x ;
+ begin
+ sign = x < 0.0 ? 1.0 : 0.0 ;
+ end
+ endfunction
+
+ // Return the trunc function of a number
+ function real trunc ;
+ input real x ;
+ begin
+ trunc = x - mod(x,1.0) ;
+ end
+ endfunction
+
+ // Return the ceiling function of a number.
+ function real ceil ;
+ input real x ;
+ real retval ;
+ begin
+ retval = mod(x,1.0) ;
+ if( retval != 0.0 && x > 0.0 ) retval = x+1.0 ;
+ else retval = x ;
+ ceil = trunc(retval) ;
+ end
+ endfunction
+
+ // Return the floor function of a number
+ function real floor ;
+ input real x ;
+ real retval ;
+ begin
+ retval = mod(x,1.0) ;
+ if( retval != 0.0 && x < 0.0 ) retval = x - 1.0 ;
+ else retval = x ;
+ floor = trunc(retval) ;
+ end
+ endfunction
+
+ // Return the round function of a number
+ function real round ;
+ input real x ;
+ real retval ;
+ begin
+ retval = x > 0.0 ? x + 0.5 : x - 0.5 ;
+ round = trunc(retval) ;
+ end
+ endfunction
+
+ // Return the fractional remainder of (x mod m)
+ function real mod ;
+ input real x ;
+ input real m ;
+ real retval ;
+ begin
+ retval = x ;
+ if( retval > m ) begin
+ while( retval > m ) begin
+ retval = retval - m ;
+ end
+ end
+ else begin
+ while( retval < -m ) begin
+ retval = retval + m ;
+ end
+ end
+ mod = retval ;
+ end
+ endfunction
+
+ // Return the max between two real numbers
+ function real realmax ;
+ input real x ;
+ input real y ;
+ begin
+ realmax = x > y ? x : y ;
+ end
+ endfunction
+
+ // Return the min between two real numbers
+ function real realmin ;
+ input real x ;
+ input real y ;
+ begin
+ realmin = x > y ? y : x ;
+ end
+ endfunction
+
+ /* Random Numbers */
+
+ // Generate Gaussian distributed variables
+ function real gaussian ;
+ input real mean ;
+ input real var ;
+ real u1, u2, v1, v2, s ;
+ begin
+ s = 1.0 ;
+ while( s >= 1.0 ) begin
+ // Two random numbers between 0 and 1
+ u1 = $random/4294967296.0 + 0.5 ;
+ u2 = $random/4294967296.0 + 0.5 ;
+ // Adjust to be between -1,1
+ v1 = 2*u1-1.0 ;
+ v2 = 2*u2-1.0 ;
+ // Polar mag squared
+ s = (v1*v1 + v2*v2) ;
+ end
+ gaussian = mean + sqrt((-2.0*log(s))/s) * v1 * sqrt(var) ;
+ // gaussian2 = mean + sqrt(-2*log(s)/s)*v2 * sqrt(var) ;
+ end
+ endfunction
+
+ /* Roots and Log Functions */
+
+ // Return the square root of a number
+ function real sqrt ;
+ input real x ;
+ real retval ;
+ begin
+ sqrt = (x == 0.0) ? 0.0 : powr(x,0.5) ;
+ end
+ endfunction
+
+ // Return the cube root of a number
+ function real cbrt ;
+ input real x ;
+ real retval ;
+ begin
+ cbrt = (x == 0.0) ? 0.0 : powr(x,1.0/3.0) ;
+ end
+ endfunction
+
+ // Return the absolute value of a real value
+ function real abs ;
+ input real x ;
+ begin
+ abs = (x > 0.0) ? x : -x ;
+ end
+ endfunction
+
+ // Return a real value raised to an integer power
+ function real pow ;
+ input real b ;
+ input integer x ;
+ integer absx ;
+ real retval ;
+ begin
+ retval = 1.0 ;
+ absx = abs(x) ;
+ repeat(absx) begin
+ retval = b*retval ;
+ end
+ pow = x < 0 ? (1.0/retval) : retval ;
+ end
+ endfunction
+
+ // Return a real value raised to a real power
+ function real powr ;
+ input real b ;
+ input real x ;
+ begin
+ powr = exp(x*log(b)) ;
+ end
+ endfunction
+
+ // Return the evaluation of e^x where e is the natural logarithm base
+ // NOTE: This is the Taylor series expansion of e^x
+ function real exp ;
+ input real x ;
+ real retval ;
+ integer i ;
+ real nm1_fact ;
+ real powm1 ;
+ begin
+ nm1_fact = 1.0 ;
+ powm1 = 1.0 ;
+ retval = 1.0 ;
+ for( i = 1 ; i < EXPLOG_ITERATIONS ; i = i + 1 ) begin
+ powm1 = x*powm1 ;
+ nm1_fact = nm1_fact * i ;
+ retval = retval + powm1/nm1_fact ;
+ end
+ exp = retval ;
+ end
+ endfunction
+
+ // Return the evaluation log(x)
+ function real log ;
+ input real x ;
+ integer i ;
+ real whole ;
+ real xm1oxp1 ;
+ real retval ;
+ real newx ;
+ begin
+ retval = 0.0 ;
+ whole = 0.0 ;
+ newx = x ;
+ while( newx > MATH_E ) begin
+ whole = whole + 1.0 ;
+ newx = newx / MATH_E ;
+ end
+ xm1oxp1 = (newx-1.0)/(newx+1.0) ;
+ for( i = 0 ; i < EXPLOG_ITERATIONS ; i = i + 1 ) begin
+ retval = retval + pow(xm1oxp1,2*i+1)/(2.0*i+1.0) ;
+ end
+ log = whole+2.0*retval ;
+ end
+ endfunction
+
+ // Return the evaluation ln(x) (same as log(x))
+ function real ln ;
+ input real x ;
+ begin
+ ln = log(x) ;
+ end
+ endfunction
+
+ // Return the evaluation log_2(x)
+ function real log2 ;
+ input real x ;
+ begin
+ log2 = log(x)/MATH_LOG_OF_2 ;
+ end
+ endfunction
+
+ function real log10 ;
+ input real x ;
+ begin
+ log10 = log(x)/MATH_LOG_OF_10 ;
+ end
+ endfunction
+
+ function real log_base ;
+ input real x ;
+ input real b ;
+ begin
+ log_base = log(x)/log(b) ;
+ end
+ endfunction
+
+ /* Trigonometric Functions */
+
+ // Internal function to reduce a value to be between [-pi:pi]
+ function real reduce ;
+ input real x ;
+ real retval ;
+ begin
+ retval = x ;
+ while( abs(retval) > MATH_PI ) begin
+ retval = retval > MATH_PI ?
+ (retval - MATH_2_PI) :
+ (retval + MATH_2_PI) ;
+ end
+ reduce = retval ;
+ end
+ endfunction
+
+ // Return the cos of a number in radians
+ function real cos ;
+ input real x ;
+ integer i ;
+ integer sign ;
+ real newx ;
+ real retval ;
+ real xsqnm1 ;
+ real twonm1fact ;
+ begin
+ newx = reduce(x) ;
+ xsqnm1 = 1.0 ;
+ twonm1fact = 1.0 ;
+ retval = 1.0 ;
+ for( i = 1 ; i < COS_ITERATIONS ; i = i + 1 ) begin
+ sign = -2*(i % 2)+1 ;
+ xsqnm1 = xsqnm1*newx*newx ;
+ twonm1fact = twonm1fact * (2.0*i) * (2.0*i-1.0) ;
+ retval = retval + sign*(xsqnm1/twonm1fact) ;
+ end
+ cos = retval ;
+ end
+ endfunction
+
+ // Return the sin of a number in radians
+ function real sin ;
+ input real x ;
+ begin
+ sin = cos(x - MATH_PI_OVER_2) ;
+ end
+ endfunction
+
+ // Return the tan of a number in radians
+ function real tan ;
+ input real x ;
+ begin
+ tan = sin(x) / cos(x) ;
+ end
+ endfunction
+
+ // Return the arcsin in radians of a number
+ function real arcsin ;
+ input real x ;
+ begin
+ arcsin = 2.0*arctan(x/(1.0+sqrt(1.0-x*x))) ;
+ end
+ endfunction
+
+ // Return the arccos in radians of a number
+ function real arccos ;
+ input real x ;
+ begin
+ arccos = MATH_PI_OVER_2-arcsin(x) ;
+ end
+ endfunction
+
+ // Return the arctan in radians of a number
+ // TODO: Make sure this REALLY does work as it is supposed to!
+ function real arctan ;
+ input real x ;
+ real retval ;
+ real y ;
+ real newx ;
+ real twoiotwoip1 ;
+ integer i ;
+ integer mult ;
+ begin
+ retval = 1.0 ;
+ twoiotwoip1 = 1.0 ;
+ mult = 1 ;
+ newx = abs(x) ;
+ while( newx > 1.0 ) begin
+ mult = mult*2 ;
+ newx = newx/(1.0+sqrt(1.0+newx*newx)) ;
+ end
+ y = 1.0 ;
+ for( i = 1 ; i < 2*COS_ITERATIONS ; i = i + 1 ) begin
+ y = y*((newx*newx)/(1+newx*newx)) ;
+ twoiotwoip1 = twoiotwoip1 * (2.0*i)/(2.0*i+1.0) ;
+ retval = retval + twoiotwoip1*y ;
+ end
+ retval = retval * (newx/(1+newx*newx)) ;
+ retval = retval * mult ;
+
+ arctan = (x > 0.0) ? retval : -retval ;
+ end
+ endfunction
+
+ // Return the arctan in radians of a ratio x/y
+ // TODO: Test to make sure this works as it is supposed to!
+ function real arctan_xy ;
+ input real x ;
+ input real y ;
+ real retval ;
+ begin
+ retval = 0.0 ;
+ if( x < 0.0 ) retval = MATH_PI - arctan(-abs(y)/x) ;
+ else if( x > 0.0 ) retval = arctan(abs(y)/x) ;
+ else if( x == 0.0 ) retval = MATH_PI_OVER_2 ;
+ arctan_xy = (y < 0.0) ? -retval : retval ;
+ end
+ endfunction
+
+ /* Hyperbolic Functions */
+
+ // Return the sinh of a number
+ function real sinh ;
+ input real x ;
+ begin
+ sinh = (exp(x) - exp(-x))/2.0 ;
+ end
+ endfunction
+
+ // Return the cosh of a number
+ function real cosh ;
+ input real x ;
+ begin
+ cosh = (exp(x) + exp(-x))/2.0 ;
+ end
+ endfunction
+
+ // Return the tanh of a number
+ function real tanh ;
+ input real x ;
+ real e2x ;
+ begin
+ e2x = exp(2.0*x) ;
+ tanh = (e2x+1.0)/(e2x-1.0) ;
+ end
+ endfunction
+
+ // Return the arcsinh of a number
+ function real arcsinh ;
+ input real x ;
+ begin
+ arcsinh = log(x+sqrt(x*x+1.0)) ;
+ end
+ endfunction
+
+ // Return the arccosh of a number
+ function real arccosh ;
+ input real x ;
+ begin
+ arccosh = ln(x+sqrt(x*x-1.0)) ;
+ end
+ endfunction
+
+ // Return the arctanh of a number
+ function real arctanh ;
+ input real x ;
+ begin
+ arctanh = 0.5*ln((1.0+x)/(1.0-x)) ;
+ end
+ endfunction
+ /*
+ initial begin
+ $display( "cos(MATH_PI_OVER_3): %f", cos(MATH_PI_OVER_3) ) ;
+ $display( "sin(MATH_PI_OVER_3): %f", sin(MATH_PI_OVER_3) ) ;
+ $display( "sign(-10): %f", sign(-10) ) ;
+ $display( "realmax(MATH_PI,MATH_E): %f", realmax(MATH_PI,MATH_E) ) ;
+ $display( "realmin(MATH_PI,MATH_E): %f", realmin(MATH_PI,MATH_E) ) ;
+ $display( "mod(MATH_PI,MATH_E): %f", mod(MATH_PI,MATH_E) ) ;
+ $display( "ceil(-MATH_PI): %f", ceil(-MATH_PI) ) ;
+ $display( "ceil(4.0): %f", ceil(4.0) ) ;
+ $display( "ceil(3.99999999999999): %f", ceil(3.99999999999999) ) ;
+ $display( "pow(MATH_PI,2): %f", pow(MATH_PI,2) ) ;
+ $display( "gaussian(1.0,1.0): %f", gaussian(1.0,1.0) ) ;
+ $display( "round(MATH_PI): %f", round(MATH_PI) ) ;
+ $display( "trunc(-MATH_PI): %f", trunc(-MATH_PI) ) ;
+ $display( "ceil(-MATH_PI): %f", ceil(-MATH_PI) ) ;
+ $display( "floor(MATH_PI): %f", floor(MATH_PI) ) ;
+ $display( "round(e): %f", round(MATH_E)) ;
+ $display( "ceil(-e): %f", ceil(-MATH_E)) ;
+ $display( "exp(MATH_PI): %f", exp(MATH_PI) ) ;
+ $display( "log2(MATH_PI): %f", log2(MATH_PI) ) ;
+ $display( "log_base(pow(2,32),2): %f", log_base(pow(2,32),2) ) ;
+ $display( "ln(0.1): %f", log(0.1) ) ;
+ $display( "cbrt(7): %f", cbrt(7) ) ;
+ $display( "cos(MATH_2_PI): %f", cos(20*MATH_2_PI) ) ;
+ $display( "sin(-MATH_2_PI): %f", sin(-50*MATH_2_PI) ) ;
+ $display( "sinh(MATH_E): %f", sinh(MATH_E) ) ;
+ $display( "cosh(MATH_2_PI): %f", cosh(MATH_2_PI) ) ;
+ $display( "arctan_xy(-4,3): %f", arctan_xy(-4,3) ) ;
+ $display( "arctan(MATH_PI): %f", arctan(MATH_PI) ) ;
+ $display( "arctan(-MATH_E/2): %f", arctan(-MATH_E/2) ) ;
+ $display( "arctan(MATH_PI_OVER_2): %f", arctan(MATH_PI_OVER_2) ) ;
+ $display( "arctan(1/7) = %f", arctan(1.0/7.0) ) ;
+ $display( "arctan(3/79) = %f", arctan(3.0/79.0) ) ;
+ $display( "pi/4 ?= %f", 5*arctan(1.0/7.0)+2*arctan(3.0/79.0) ) ;
+ $display( "arcsin(1.0): %f", arcsin(1.0) ) ;
+ $display( "cos(pi/2): %f", cos(MATH_PI_OVER_2)) ;
+ $display( "arccos(cos(pi/2)): %f", arccos(cos(MATH_PI_OVER_2)) ) ;
+ $display( "cos(0): %f", cos(0) ) ;
+ $display( "cos(MATH_PI_OVER_4): %f", cos(MATH_PI_OVER_4) ) ;
+ $display( "cos(MATH_PI_OVER_2): %f", cos(MATH_PI_OVER_2) ) ;
+ $display( "cos(3*MATH_PI_OVER_4): %f", cos(3*MATH_PI_OVER_4) ) ;
+ $display( "cos(MATH_PI): %f", cos(MATH_PI) ) ;
+ $display( "cos(5*MATH_PI_OVER_4): %f", cos(5*MATH_PI_OVER_4) ) ;
+ $display( "cos(6*MATH_PI_OVER_4): %f", cos(6*MATH_PI_OVER_4) ) ;
+ $display( "cos(7*MATH_PI_OVER_4): %f", cos(7*MATH_PI_OVER_4) ) ;
+ $display( "cos(8*MATH_PI_OVER_4): %f", cos(8*MATH_PI_OVER_4) ) ;
+ end*/
+
+endmodule
diff --git a/fpga/usrp2/models/miim_model.v b/fpga/usrp2/models/miim_model.v new file mode 100644 index 000000000..8eb8e571d --- /dev/null +++ b/fpga/usrp2/models/miim_model.v @@ -0,0 +1,31 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + +// Skeleton PHY interface simulator + +module miim_model(input mdc_i, + inout mdio, + input phy_resetn_i, + input phy_clk_i, + output phy_intn_o, + output [2:0] speed_o); + + assign phy_intn_o = 1; // No interrupts + assign speed_o = 3'b100; // 1G mode + +endmodule // miim_model diff --git a/fpga/usrp2/models/phy_sim.v b/fpga/usrp2/models/phy_sim.v new file mode 100644 index 000000000..b3de19b04 --- /dev/null +++ b/fpga/usrp2/models/phy_sim.v @@ -0,0 +1,113 @@ +//////////////////////////////////////////////////////////////////////
+//// ////
+//// Phy_sim.v ////
+//// ////
+//// This file is part of the Ethernet IP core project ////
+//// http://www.opencores.org/projects.cgi/web/ethernet_tri_mode/////
+//// ////
+//// Author(s): ////
+//// - Jon Gao (gaojon@yahoo.com) ////
+//// ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2001 Authors ////
+//// ////
+//// 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: Phy_sim.v,v $
+// Revision 1.3 2006/11/17 17:53:07 maverickist
+// no message
+//
+// Revision 1.2 2006/01/19 14:07:50 maverickist
+// verification is complete.
+//
+// Revision 1.1.1.1 2005/12/13 01:51:44 Administrator
+// no message
+//
+
+`timescale 1ns/100ps
+
+module phy_sim(
+ input Gtx_clk, // Used only in GMII mode
+ output Rx_clk,
+ output Tx_clk, // Used only in MII mode
+ input Tx_er,
+ input Tx_en,
+ input [7:0] Txd,
+ output Rx_er,
+ output Rx_dv,
+ output [7:0] Rxd,
+ output Crs,
+ output Col,
+ input [2:0] Speed,
+ input Done
+);
+
+//////////////////////////////////////////////////////////////////////
+// this file used to simulate Phy.
+// generate clk and loop the Tx data to Rx data
+// full duplex mode can be verified on loop mode.
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+// internal signals
+//////////////////////////////////////////////////////////////////////
+reg Clk_25m; // Used for 100 Mbps mode
+reg Clk_2_5m; // Used for 10 Mbps mode
+
+//wire Rx_clk;
+//wire Tx_clk; // Used only in MII mode
+
+ initial
+ begin
+ #10;
+ while ( !Done )
+ begin
+ #20 Clk_25m = 0;
+ #20 Clk_25m = 1;
+ end
+ end
+
+ initial
+ begin
+ #10;
+ while ( !Done )
+ begin
+ #200 Clk_2_5m = 0;
+ #200 Clk_2_5m = 1;
+ end
+ end
+
+ assign Rx_clk = Speed[2] ? Gtx_clk : Speed[1] ? Clk_25m : Speed[0] ? Clk_2_5m : 0;
+ assign Tx_clk = Speed[2] ? Gtx_clk : Speed[1] ? Clk_25m : Speed[0] ? Clk_2_5m : 0;
+
+ assign Rx_dv = Tx_en;
+ assign Rxd = Txd;
+ assign Rx_er = Tx_er;
+ assign Crs = Tx_en;
+ assign Col = 0;
+
+endmodule
diff --git a/fpga/usrp2/models/serdes_model.v b/fpga/usrp2/models/serdes_model.v new file mode 100644 index 000000000..5e1602163 --- /dev/null +++ b/fpga/usrp2/models/serdes_model.v @@ -0,0 +1,51 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + +module serdes_model + (input ser_tx_clk, + input ser_tkmsb, + input ser_tklsb, + input [15:0] ser_t, + + output ser_rx_clk, + output ser_rkmsb, + output ser_rklsb, + output [15:0] ser_r, + + input even, + input error); + + wire [15:0] ser_r_odd; + wire ser_rklsb_odd, ser_rkmsb_odd; + + reg [7:0] hold_dat; + reg hold_k; + + always @(posedge ser_tx_clk) hold_k <= ser_tklsb; + always @(posedge ser_tx_clk) hold_dat <= ser_t[15:8]; + assign ser_rklsb_odd = hold_k; + assign ser_rkmsb_odd = ser_tklsb; + assign ser_r_odd = {ser_t[7:0], hold_dat}; + + // Set outputs + assign ser_rx_clk = ser_tx_clk; + assign ser_rkmsb = even ? ser_tkmsb : ser_rkmsb_odd; + assign ser_rklsb = even ? ser_tklsb : ser_rklsb_odd; + assign ser_r = error ^ (even ? ser_t : ser_r_odd); + +endmodule // serdes_model diff --git a/fpga/usrp2/models/uart_rx.v b/fpga/usrp2/models/uart_rx.v new file mode 100644 index 000000000..738ffb45b --- /dev/null +++ b/fpga/usrp2/models/uart_rx.v @@ -0,0 +1,65 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + + + +// Simple printout of characters from the UART +// Only does 8N1, requires the baud clock + +module uart_rx (input baudclk, input rxd); + reg [8:0] sr = 9'b0; + reg [3:0] baud_ctr = 4'b0; + + /* + wire byteclk = baud_ctr[3]; + reg rxd_d1 = 0; + always @(posedge baudclk) + rxd_d1 <= rxd; + + always @(posedge baudclk) + if(rxd_d1 != rxd) + baud_ctr <= 0; + else + baud_ctr <= baud_ctr + 1; +*/ + + wire byteclk = baudclk; + + always @(posedge byteclk) + sr <= { rxd, sr[8:1] }; + + reg [3:0] state = 0; + always @(posedge byteclk) + case(state) + 0 : + if(~sr[8] & sr[7]) // found start bit + state <= 1; + 1, 2, 3, 4, 5, 6, 7, 8 : + state <= state + 1; + 9 : + begin + state <= 0; + $write("%c",sr[7:0]); + if(~sr[8]) + $display("Error, no stop bit\n"); + end + default : + state <= 0; + endcase // case(state) + +endmodule // uart_rx + diff --git a/fpga/usrp2/models/xlnx_glbl.v b/fpga/usrp2/models/xlnx_glbl.v new file mode 100644 index 000000000..62e29fef4 --- /dev/null +++ b/fpga/usrp2/models/xlnx_glbl.v @@ -0,0 +1,46 @@ +// +// Copyright 2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +module xlnx_glbl
+(
+ GSR,
+ GTS
+);
+
+ //--------------------------------------------------------------------------
+ // Parameters
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // IO declarations
+ //--------------------------------------------------------------------------
+
+ output GSR;
+ output GTS;
+
+ //--------------------------------------------------------------------------
+ // Local declarations
+ //--------------------------------------------------------------------------
+
+ //--------------------------------------------------------------------------
+ // Internal declarations
+ //--------------------------------------------------------------------------
+
+ assign GSR = 0;
+ assign GTS = 0;
+
+endmodule
|