diff --git a/docs/xue-bom.ods b/docs/xue-bom.ods deleted file mode 100644 index 1cd59c0..0000000 Binary files a/docs/xue-bom.ods and /dev/null differ diff --git a/kicad/library/PSU.lib b/kicad/components/PSU.lib similarity index 100% rename from kicad/library/PSU.lib rename to kicad/components/PSU.lib diff --git a/kicad/library/a7130.lib b/kicad/components/a7130.lib similarity index 100% rename from kicad/library/a7130.lib rename to kicad/components/a7130.lib diff --git a/kicad/library/attiny.lib b/kicad/components/attiny.lib similarity index 100% rename from kicad/library/attiny.lib rename to kicad/components/attiny.lib diff --git a/kicad/library/ft2232c.dcm b/kicad/components/ft2232c.dcm similarity index 100% rename from kicad/library/ft2232c.dcm rename to kicad/components/ft2232c.dcm diff --git a/kicad/library/ft2232c.lib b/kicad/components/ft2232c.lib similarity index 100% rename from kicad/library/ft2232c.lib rename to kicad/components/ft2232c.lib diff --git a/kicad/library/fxo-hc536r.lib b/kicad/components/fxo-hc536r.lib similarity index 100% rename from kicad/library/fxo-hc536r.lib rename to kicad/components/fxo-hc536r.lib diff --git a/kicad/library/k8001.lib b/kicad/components/k8001.lib similarity index 100% rename from kicad/library/k8001.lib rename to kicad/components/k8001.lib diff --git a/kicad/library/m12-tu400a.lib b/kicad/components/m12-tu400a.lib similarity index 100% rename from kicad/library/m12-tu400a.lib rename to kicad/components/m12-tu400a.lib diff --git a/kicad/library/mic2550.lib b/kicad/components/mic2550.lib similarity index 100% rename from kicad/library/mic2550.lib rename to kicad/components/mic2550.lib diff --git a/kicad/library/mic2550ayts.dcm b/kicad/components/mic2550ayts.dcm similarity index 100% rename from kicad/library/mic2550ayts.dcm rename to kicad/components/mic2550ayts.dcm diff --git a/kicad/library/mic2550ayts.lib b/kicad/components/mic2550ayts.lib similarity index 100% rename from kicad/library/mic2550ayts.lib rename to kicad/components/mic2550ayts.lib diff --git a/kicad/library/micron_ddr_512Mb.lib b/kicad/components/micron_ddr_512Mb.lib similarity index 100% rename from kicad/library/micron_ddr_512Mb.lib rename to kicad/components/micron_ddr_512Mb.lib diff --git a/kicad/library/micron_mobile_ddr.lib b/kicad/components/micron_mobile_ddr.lib similarity index 100% rename from kicad/library/micron_mobile_ddr.lib rename to kicad/components/micron_mobile_ddr.lib diff --git a/kicad/library/microsmd075f.dcm b/kicad/components/microsmd075f.dcm similarity index 100% rename from kicad/library/microsmd075f.dcm rename to kicad/components/microsmd075f.dcm diff --git a/kicad/library/microsmd075f.lib b/kicad/components/microsmd075f.lib similarity index 100% rename from kicad/library/microsmd075f.lib rename to kicad/components/microsmd075f.lib diff --git a/kicad/library/mt9m033.lib b/kicad/components/mt9m033.lib similarity index 100% rename from kicad/library/mt9m033.lib rename to kicad/components/mt9m033.lib diff --git a/kicad/library/pasives-connectors.lib b/kicad/components/pasives-connectors.lib similarity index 100% rename from kicad/library/pasives-connectors.lib rename to kicad/components/pasives-connectors.lib diff --git a/kicad/library/r_pack2.dcm b/kicad/components/r_pack2.dcm similarity index 100% rename from kicad/library/r_pack2.dcm rename to kicad/components/r_pack2.dcm diff --git a/kicad/library/r_pack2.lib b/kicad/components/r_pack2.lib similarity index 100% rename from kicad/library/r_pack2.lib rename to kicad/components/r_pack2.lib diff --git a/kicad/library/reg102.lib b/kicad/components/reg102.lib similarity index 100% rename from kicad/library/reg102.lib rename to kicad/components/reg102.lib diff --git a/kicad/library/rj45-48025.dcm b/kicad/components/rj45-48025.dcm similarity index 100% rename from kicad/library/rj45-48025.dcm rename to kicad/components/rj45-48025.dcm diff --git a/kicad/library/rj45-48025.lib b/kicad/components/rj45-48025.lib similarity index 100% rename from kicad/library/rj45-48025.lib rename to kicad/components/rj45-48025.lib diff --git a/kicad/library/tps793xx.lib b/kicad/components/tps793xx.lib similarity index 100% rename from kicad/library/tps793xx.lib rename to kicad/components/tps793xx.lib diff --git a/kicad/library/usb-48204-0001.dcm b/kicad/components/usb-48204-0001.dcm similarity index 100% rename from kicad/library/usb-48204-0001.dcm rename to kicad/components/usb-48204-0001.dcm diff --git a/kicad/library/usb-48204-0001.lib b/kicad/components/usb-48204-0001.lib similarity index 100% rename from kicad/library/usb-48204-0001.lib rename to kicad/components/usb-48204-0001.lib diff --git a/kicad/library/v0402mhs03.dcm b/kicad/components/v0402mhs03.dcm similarity index 100% rename from kicad/library/v0402mhs03.dcm rename to kicad/components/v0402mhs03.dcm diff --git a/kicad/library/v0402mhs03.lib b/kicad/components/v0402mhs03.lib similarity index 100% rename from kicad/library/v0402mhs03.lib rename to kicad/components/v0402mhs03.lib diff --git a/kicad/library/x25x64mb.lib b/kicad/components/x25x64mb.lib similarity index 100% rename from kicad/library/x25x64mb.lib rename to kicad/components/x25x64mb.lib diff --git a/kicad/library/xc6slx45fgg484.lib b/kicad/components/xc6slx45fgg484.lib similarity index 100% rename from kicad/library/xc6slx45fgg484.lib rename to kicad/components/xc6slx45fgg484.lib diff --git a/kicad/library/xc6slx75fgg484.lib b/kicad/components/xc6slx75fgg484.lib similarity index 100% rename from kicad/library/xc6slx75fgg484.lib rename to kicad/components/xc6slx75fgg484.lib diff --git a/kicad/library/xue-nv.lib b/kicad/components/xue-nv.lib similarity index 100% rename from kicad/library/xue-nv.lib rename to kicad/components/xue-nv.lib diff --git a/kicad/library/zx62d-b-5p8.lib b/kicad/components/zx62d-b-5p8.lib similarity index 100% rename from kicad/library/zx62d-b-5p8.lib rename to kicad/components/zx62d-b-5p8.lib diff --git a/kicad/xue-rnc/xue-rnc.pro b/kicad/xue-rnc/xue-rnc.pro index 7201cf9..58263f5 100644 --- a/kicad/xue-rnc/xue-rnc.pro +++ b/kicad/xue-rnc/xue-rnc.pro @@ -38,18 +38,18 @@ PrintMonochrome=1 ShowSheetReferenceAndTitleBlock=1 [eeschema/libraries] LibName1=power -LibName2=../library/r_pack2 -LibName3=../library/v0402mhs03 -LibName4=../library/usb-48204-0001 -LibName5=../library/microsmd075f -LibName6=../library/mic2550 -LibName7=../library/rj45-48025 -LibName8=../library/xue-nv -LibName9=../library/xc6slx75fgg484 -LibName10=../library/xc6slx45fgg484 -LibName11=../library/micron_mobile_ddr -LibName12=../library/micron_ddr_512Mb -LibName13=../library/k8001 +LibName2=../components/r_pack2 +LibName3=../components/v0402mhs03 +LibName4=../components/usb-48204-0001 +LibName5=../components/microsmd075f +LibName6=../components/mic2550 +LibName7=../components/rj45-48025 +LibName8=../components/xue-nv +LibName9=../components/xc6slx75fgg484 +LibName10=../components/xc6slx45fgg484 +LibName11=../components/micron_mobile_ddr +LibName12=../components/micron_ddr_512Mb +LibName13=../components/k8001 LibName14=device LibName15=transistors LibName16=conn @@ -79,18 +79,18 @@ LibName39=opto LibName40=atmel LibName41=contrib LibName42=valves -LibName43=../library/pasives-connectors -LibName44=../library/x25x64mb -LibName45=../library/attiny -LibName46=../library/PSU -LibName47=../library/tps793xx -LibName48=../library/reg102 -LibName49=../library/mt9m033 -LibName50=../library/m12-tu400a -LibName51=../library/ft2232c -LibName52=../library/fxo-hc536r -LibName53=../library/zx62d-b-5p8 -LibName54=../library/a7130 +LibName43=../components/pasives-connectors +LibName44=../components/x25x64mb +LibName45=../components/attiny +LibName46=../components/PSU +LibName47=../components/tps793xx +LibName48=../components/reg102 +LibName49=../components/mt9m033 +LibName50=../components/m12-tu400a +LibName51=../components/ft2232c +LibName52=../components/fxo-hc536r +LibName53=../components/zx62d-b-5p8 +LibName54=../components/a7130 [cvpcb] version=1 NetIExt=net diff --git a/sim/verilog/micron/2048Mb_ddr2.zip b/sim/verilog/micron/2048Mb_ddr2.zip deleted file mode 100644 index 783db03..0000000 Binary files a/sim/verilog/micron/2048Mb_ddr2.zip and /dev/null differ diff --git a/sim/verilog/micron/mobile_ddr.zip b/sim/verilog/micron/mobile_ddr.zip deleted file mode 100644 index d994d31..0000000 Binary files a/sim/verilog/micron/mobile_ddr.zip and /dev/null differ diff --git a/sim/verilog/micron_2048Mb_ddr2/ddr2.v b/sim/verilog/micron_2048Mb_ddr2/ddr2.v new file mode 100644 index 0000000..481fadc --- /dev/null +++ b/sim/verilog/micron_2048Mb_ddr2/ddr2.v @@ -0,0 +1,2031 @@ +/**************************************************************************************** +* +* File Name: ddr2.v +* Version: 5.83 +* Model: BUS Functional +* +* Dependencies: ddr2_parameters.vh +* +* Description: Micron SDRAM DDR2 (Double Data Rate 2) +* +* Limitation: - doesn't check for average refresh timings +* - positive ck and ck_n edges are used to form internal clock +* - positive dqs and dqs_n edges are used to latch data +* - test mode is not modeled +* +* Note: - Set simulator resolution to "ps" accuracy +* - Set Debug = 0 to disable $display messages +* +* Disclaimer This software code and all associated documentation, comments or other +* of Warranty: information (collectively "Software") is provided "AS IS" without +* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY +* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES +* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT +* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE +* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. +* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR +* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE +* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, +* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, +* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, +* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, +* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE +* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGES. Because some jurisdictions prohibit the exclusion or +* limitation of liability for consequential or incidental damages, the +* above limitation may not apply to you. +* +* Copyright 2003 Micron Technology, Inc. All rights reserved. +* +* Rev Author Date Changes +* --------------------------------------------------------------------------------------- +* 1.00 JMK 07/29/03 Initial Release +* 1.10 JMK 08/09/03 Timing Parameter updates to tIS, tIH, tDS, tDH +* 2.20 JMK 08/07/03 General cleanup +* 2.30 JMK 11/26/03 Added CL_MIN, CL_MAX, wl_min and wl_max parameters. +* Added AL_MIN and AL_MAX parameters. +* Removed support for OCD. +* 2.40 JMK 01/15/04 Removed verilog 2001 constructs. +* 2.50 JMK 01/29/04 Removed tRP checks during Precharge command. +* 2.60 JMK 04/20/04 Fixed tWTR check. +* 2.70 JMK 04/30/04 Added tRFC maximum check. +* Combined Self Refresh and Power Down always blocks. +* Added Reset Function (CKE LOW Anytime). +* 2.80 JMK 08/19/04 Precharge is treated as NOP when bank is not active. +* Added checks for tRAS, tWR, tRTP to any bank during Pre-All. +* tRFC maximum violation will only display one time. +* 2.90 JMK 11/05/04 Fixed DQS checking during write. +* Fixed false tRFC max assertion during power up and self ref. +* Added warning for 200us CKE low time during initialization. +* Added -3, -3E, and -37V speed grades to ddr2_parameters.v +* 3.00 JMK 04/22/05 Removed ODT off requirement during power down. +* Added tAOND, tAOFD, tANPD, tAXPD, tAONPD, and tAOFPD parameters. +* Added ODT status messages. +* Updated the initialization sequence. +* Disable ODT and CLK pins during self refresh. +* Disable cmd and addr pins during power down and self refresh. +* 3.10 JMK 06/07/05 Disable trpa checking if the part does not have 8 banks. +* Changed tAXPD message from error to a warning. +* Added tDSS checking. +* Removed tDQSL checking during tWPRE and tWPST. +* Fixed a burst order error during writes. +* Renamed parameters file with .vh extension. +* 3.20 JMK 07/18/05 Removed 14 tCK requirement from LMR to READ. +* 3.30 JMK 08/03/05 Added check for interrupting a burst with auto precharge. +* 4.00 JMK 11/21/05 Parameter names all UPPERCASE, signal names all lowercase. +* Clock jitter can be tolerated within specification range. +* Clock frequency is sampled from the CK pin. +* Scaleable up to 64 DQ and 16 DQS bits. +* Read data can be randomly skewed using RANDOM_OUT_DELAY. +* Parameterized read and write DQS, and read DQ. +* Initialization can be bypassed using initialize task. +* 4.10 JMK 11/30/05 Fixed compile errors when `MAX_MEM was defined. +* 4.20 JMK 12/09/05 Fixed memory addressing error when `MAX_MEM was defined. +* 4.30 JMK 02/15/06 Added dummy write to initialization sequence. +* Removed tWPST maximum checking. +* Rising dqs_n edge latches data when enabled in EMR. +* Fixed a sign error in the tJIT(cc) calculation. +* 4.40 JMK 02/16/06 Fixed dummy write when`MAX_MEM was defined. +* 4.50 JMK 02/27/06 Fixed extra tDQSS assertions. +* Fixed tRCD and tWTR checking. +* Errors entering Power Down or Self Refresh will cause reset. +* Ignore dqs_n when disabled in EMR. +* 5.00 JMK 04/24/06 Test stimulus now included from external file (subtest.vh) +* Fixed tRFC max assertion during self refresh. +* Fixed tANPD checking during Power Down. +* Removed dummy write from initialization sequence. +* 5.01 JMK 04/28/06 Fixed Auto Precharge to Load Mode, Refresh and Self Refresh. +* Removed Auto Precharge error message during Power Down Enter. +* 5.10 JMK 07/26/06 Created internal clock using ck and ck_n. +* RDQS can only be enabled in EMR for x8 configurations. +* CAS latency is checked vs frequency when DLL locks. +* tMOD changed from tCK units to ns units. +* Added 50 Ohm setting for Rtt in EMR. +* Improved checking of DQS during writes. +* 5.20 JMK 10/02/06 Fixed DQS checking for interrupting write to write and x16. +* 5.30 JMK 05/25/07 Fixed checking for 0-Z transition on write postamble. +* 5.50 JMK 05/30/08 Renamed ddr2_dimm.v to ddr2_module.v and added SODIMM support. +* Added a register delay to ddr2_module.v when RDIMM is defined. +* Added multi-chip package model support in ddr2_mcp.v +* Added High Temp Self Refresh rate setting in EMRS2[7] +* 5.70 JMK 04/23/09 Updated tRPA definition +* Increased internal width to 72 bit DQ bus +* 5.80 SPH 08/12/09 Fixed tRAS maximum violation (only check if bank still open) +* 5.81 SPH 12/08/09 Only check tIH for cmd_addr if CS# LOW +* 5.82 SPH 04/08/10 Correct debug message for SRT in EMR2 +* 5.83 SPH 04/29/10 Correct tDQSS check on valid DQS group +****************************************************************************************/ + +// DO NOT CHANGE THE TIMESCALE +// MAKE SURE YOUR SIMULATOR USES "PS" RESOLUTION +`timescale 1ps / 1ps + +module ddr2 ( + ck, + ck_n, + cke, + cs_n, + ras_n, + cas_n, + we_n, + dm_rdqs, + ba, + addr, + dq, + dqs, + dqs_n, + rdqs_n, + odt +); + + `include "ddr2_parameters.vh" + + // text macros + `define DQ_PER_DQS DQ_BITS/DQS_BITS + `define BANKS (1<= 2. \nBL_MAX = %d", BL_MAX); + if ((1< BL_MAX) + $display("%m ERROR: 2^BO_BITS cannot be greater than BL_MAX parameter."); + $timeformat (-12, 1, " ps", 1); + reset_task; + seed = RANDOM_SEED; + ck_cntr = 0; + end + + // calculate the absolute value of a real number + function real abs_value; + input arg; + real arg; + begin + if (arg < 0.0) + abs_value = -1.0 * arg; + else + abs_value = arg; + end + endfunction + +`ifdef MAX_MEM +`else + function get_index; + input [`MAX_BITS-1:0] addr; + begin : index + get_index = 0; + for (memory_index=0; memory_index TRAS_MAX) && (active_bank[bank] === 1'b1)) $display ("%m: at time %t ERROR: tRAS maximum violation during %s to bank %d", $time, cmd_string[cmd], bank); + if ($time - tm_bank_activate[bank] < TRAS_MIN) $display ("%m: at time %t ERROR: tRAS minimum violation during %s to bank %d", $time, cmd_string[cmd], bank);end + {1'b0, ACTIVATE , ACTIVATE } : begin if ($time - tm_activate < TRRD) $display ("%m: at time %t ERROR: tRRD violation during %s to bank %d", $time, cmd_string[cmd], bank); end + {1'b1, ACTIVATE , ACTIVATE } : begin if ($time - tm_bank_activate[bank] < TRC) $display ("%m: at time %t ERROR: tRC violation during %s to bank %d", $time, cmd_string[cmd], bank); end + {1'b1, ACTIVATE , 4'b010x } : ; // tRCD is checked outside this task + {1'b1, ACTIVATE , PWR_DOWN } : ; // 1 tCK + {1'b1, WRITE , PRECHARGE} : begin if ((ck_cntr - ck_bank_write[bank] <= write_latency + burst_length/2) || ($time - tm_bank_write_end[bank] < TWR)) $display ("%m: at time %t ERROR: tWR violation during %s to bank %d", $time, cmd_string[cmd], bank); end + {1'b0, WRITE , WRITE } : begin if (ck_cntr - ck_write < TCCD) $display ("%m: at time %t ERROR: tCCD violation during %s to bank %d", $time, cmd_string[cmd], bank); end + {1'b0, WRITE , READ } : begin if ((ck_load_mode < ck_write) && (ck_cntr - ck_write < write_latency + burst_length/2 + 2 - additive_latency)) $display ("%m: at time %t ERROR: tWTR violation during %s to bank %d", $time, cmd_string[cmd], bank); end + {1'b0, WRITE , PWR_DOWN } : begin if ((ck_load_mode < ck_write) && ( + |write_precharge_bank + || (ck_cntr - ck_write_ap < 1) + || (ck_cntr - ck_write < write_latency + burst_length/2 + 2) + || ($time - tm_write_end < TWTR))) begin $display ("%m: at time %t INFO: Write to Reset condition", $time); init_done = 0; end end + {1'b1, READ , PRECHARGE} : begin if ((ck_cntr - ck_bank_read[bank] < additive_latency + burst_length/2) || ($time - tm_bank_read_end[bank] < TRTP)) $display ("%m: at time %t ERROR: tRTP violation during %s to bank %d", $time, cmd_string[cmd], bank); end + {1'b0, READ , WRITE } : begin if ((ck_load_mode < ck_read) && (ck_cntr - ck_read < read_latency + burst_length/2 + 1 - write_latency)) $display ("%m: at time %t ERROR: tRTW violation during %s to bank %d", $time, cmd_string[cmd], bank); end + {1'b0, READ , READ } : begin if (ck_cntr - ck_read < TCCD) $display ("%m: at time %t ERROR: tCCD violation during %s to bank %d", $time, cmd_string[cmd], bank); end + {1'b0, READ , PWR_DOWN } : begin if ((ck_load_mode < ck_read) && (ck_cntr - ck_read < read_latency + burst_length/2 + 1)) begin $display ("%m: at time %t INFO: Read to Reset condition", $time); init_done = 0; end end + {1'b0, PWR_DOWN , 4'b00xx } : begin if (ck_cntr - ck_power_down < TXP) $display ("%m: at time %t ERROR: tXP violation during %s", $time, cmd_string[cmd]); end + {1'b0, PWR_DOWN , WRITE } : begin if (ck_cntr - ck_power_down < TXP) $display ("%m: at time %t ERROR: tXP violation during %s", $time, cmd_string[cmd]); end + {1'b0, PWR_DOWN , READ } : begin if (ck_cntr - ck_slow_exit_pd < TXARDS - additive_latency) $display ("%m: at time %t ERROR: tXARDS violation during %s", $time, cmd_string[cmd]); + else if (ck_cntr - ck_power_down < TXARD) $display ("%m: at time %t ERROR: tXARD violation during %s", $time, cmd_string[cmd]); end + {1'b0, SELF_REF , 4'b00xx } : begin if ($time - tm_self_refresh < TXSNR) $display ("%m: at time %t ERROR: tXSNR violation during %s", $time, cmd_string[cmd]); end + {1'b0, SELF_REF , WRITE } : begin if ($time - tm_self_refresh < TXSNR) $display ("%m: at time %t ERROR: tXSNR violation during %s", $time, cmd_string[cmd]); end + {1'b0, SELF_REF , READ } : begin if (ck_cntr - ck_self_refresh < TXSRD) $display ("%m: at time %t ERROR: tXSRD violation during %s", $time, cmd_string[cmd]); end + {1'b0, 4'b100x , 4'b100x } : begin if (ck_cntr - ck_cke < TCKE) begin $display ("%m: at time %t ERROR: tCKE violation on CKE", $time); init_done = 0; end end + endcase + end + endtask + + task cmd_task; + input cke; + input [2:0] cmd; + input [BA_BITS-1:0] bank; + input [ADDR_BITS-1:0] addr; + reg [`BANKS:0] i; + integer j; + reg [`BANKS:0] tfaw_cntr; + reg [COL_BITS-1:0] col; + begin + + // tRFC max check + if (!er_trfc_max && !in_self_refresh) begin + if ($time - tm_refresh > TRFC_MAX) begin + $display ("%m: at time %t ERROR: tRFC maximum violation during %s", $time, cmd_string[cmd]); + er_trfc_max = 1; + end + end + if (cke) begin + if ((cmd < NOP) && ((cmd != PRECHARGE) || !addr[AP])) begin + for (j=0; j= BL_MIN) && (burst_length <= BL_MAX)) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Length = %d", $time, cmd_string[cmd], bank, burst_length); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal Burst Length = %d", $time, cmd_string[cmd], bank, burst_length); + end + // Burst Order + burst_order = addr[3]; + if (!burst_order) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Order = Sequential", $time, cmd_string[cmd], bank); + end else if (burst_order) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Order = Interleaved", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal Burst Order = %d", $time, cmd_string[cmd], bank, burst_order); + end + // CAS Latency + cas_latency = addr[6:4]; + read_latency = cas_latency + additive_latency; + write_latency = read_latency - 1; + if ((cas_latency >= CL_MIN) && (cas_latency <= CL_MAX)) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d CAS Latency = %d", $time, cmd_string[cmd], bank, cas_latency); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal CAS Latency = %d", $time, cmd_string[cmd], bank, cas_latency); + end + // Test Mode + if (!addr[7]) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Test Mode = Normal", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal Test Mode = %d", $time, cmd_string[cmd], bank, addr[7]); + end + // DLL Reset + dll_reset = addr[8]; + if (!dll_reset) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Reset = Normal", $time, cmd_string[cmd], bank); + end else if (dll_reset) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Reset = Reset DLL", $time, cmd_string[cmd], bank); + dll_locked = 0; + ck_dll_reset <= ck_cntr; + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal DLL Reset = %d", $time, cmd_string[cmd], bank, dll_reset); + end + // Write Recovery + write_recovery = addr[11:9] + 1; + if ((write_recovery >= WR_MIN) && (write_recovery <= WR_MAX)) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Write Recovery = %d", $time, cmd_string[cmd], bank, write_recovery); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal Write Recovery = %d", $time, cmd_string[cmd], bank, write_recovery); + end + // Power Down Mode + low_power = addr[12]; + if (!low_power) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Power Down Mode = Fast Exit", $time, cmd_string[cmd], bank); + end else if (low_power) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Power Down Mode = Slow Exit", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal Power Down Mode = %d", $time, cmd_string[cmd], bank, low_power); + end + end + 1 : begin + // DLL Enable + dll_en = !addr[0]; + if (!dll_en) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Enable = Disabled", $time, cmd_string[cmd], bank); + end else if (dll_en) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Enable = Enabled", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal DLL Enable = %d", $time, cmd_string[cmd], bank, dll_en); + end + // Output Drive Strength + if (!addr[1]) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Drive Strength = Full", $time, cmd_string[cmd], bank); + end else if (addr[1]) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Drive Strength = Reduced", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal Output Drive Strength = %d", $time, cmd_string[cmd], bank, addr[1]); + end + // ODT Rtt + odt_rtt = {addr[6], addr[2]}; + if (odt_rtt == 2'b00) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = Disabled", $time, cmd_string[cmd], bank); + odt_en = 0; + end else if (odt_rtt == 2'b01) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 75 Ohm", $time, cmd_string[cmd], bank); + odt_en = 1; + tm_odt_en <= $time; + end else if (odt_rtt == 2'b10) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 150 Ohm", $time, cmd_string[cmd], bank); + odt_en = 1; + tm_odt_en <= $time; + end else if (odt_rtt == 2'b11) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 50 Ohm", $time, cmd_string[cmd], bank); + odt_en = 1; + tm_odt_en <= $time; + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal ODT Rtt = %d", $time, cmd_string[cmd], bank, odt_rtt); + odt_en = 0; + end + // Additive Latency + additive_latency = addr[5:3]; + read_latency = cas_latency + additive_latency; + write_latency = read_latency - 1; + if ((additive_latency >= AL_MIN) && (additive_latency <= AL_MAX)) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Additive Latency = %d", $time, cmd_string[cmd], bank, additive_latency); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal Additive Latency = %d", $time, cmd_string[cmd], bank, additive_latency); + end + // OCD Program + ocd = addr[9:7]; + if (ocd == 3'b000) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d OCD Program = OCD Exit", $time, cmd_string[cmd], bank); + end else if (ocd == 3'b111) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d OCD Program = OCD Default", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal OCD Program = %b", $time, cmd_string[cmd], bank, ocd); + end + + // DQS_N Enable + dqs_n_en = !addr[10]; + if (!dqs_n_en) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d DQS_N Enable = Disabled", $time, cmd_string[cmd], bank); + end else if (dqs_n_en) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d DQS_N Enable = Enabled", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal DQS_N Enable = %d", $time, cmd_string[cmd], bank, dqs_n_en); + end + // RDQS Enable + rdqs_en = addr[11]; + if (!rdqs_en) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d RDQS Enable = Disabled", $time, cmd_string[cmd], bank); + end else if (rdqs_en) begin +`ifdef x8 + if (DEBUG) $display ("%m: at time %t INFO: %s %d RDQS Enable = Enabled", $time, cmd_string[cmd], bank); +`else + $display ("%m: at time %t WARNING: %s %d Illegal RDQS Enable. RDQS only exists on a x8 part", $time, cmd_string[cmd], bank); + rdqs_en = 0; +`endif + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal RDQS Enable = %d", $time, cmd_string[cmd], bank, rdqs_en); + end + // Output Enable + out_en = !addr[12]; + if (!out_en) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Enable = Disabled", $time, cmd_string[cmd], bank); + end else if (out_en) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Enable = Enabled", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal Output Enable = %d", $time, cmd_string[cmd], bank, out_en); + end + end + 2 : begin + // High Temperature Self Refresh rate + if (!addr[7]) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d High Temperature Self Refresh rate = 1X (0C-85C)", $time, cmd_string[cmd], bank); + end else if (addr[7]) begin + if (DEBUG) $display ("%m: at time %t INFO: %s %d High Temperature Self Refresh rate = 2X (>85C)", $time, cmd_string[cmd], bank); + end else begin + $display ("%m: at time %t ERROR: %s %d Illegal High Temperature Self Refresh rate = %d", $time, cmd_string[cmd], bank, addr[7]); + end + if ((addr & ~(1<<7)) !== 0) begin + $display ("%m: at time %t ERROR: %s %d Illegal value. Reserved bits must be programmed to zero", $time, cmd_string[cmd], bank); + end + end + 3 : begin + if (addr !== 0) begin + $display ("%m: at time %t ERROR: %s %d Illegal value. Reserved bits must be programmed to zero", $time, cmd_string[cmd], bank); + end + end + endcase + init_mode_reg[bank] = 1; + ck_load_mode <= ck_cntr; + end + end + REFRESH : begin + if (|active_bank) begin + $display ("%m: at time %t ERROR: %s Failure. All banks must be Precharged.", $time, cmd_string[cmd]); + if (STOP_ON_ERROR) $stop(0); + end else begin + if (DEBUG) $display ("%m: at time %t INFO: %s", $time, cmd_string[cmd]); + er_trfc_max = 0; + ref_cntr = ref_cntr + 1; + tm_refresh <= $time; + end + end + PRECHARGE : begin + if (addr[AP]) begin + // tRPA timing applies when the PRECHARGE (ALL) command is issued, regardless of + // the number of banks already open or closed. + for (i=0; i<`BANKS; i=i+1) begin + for (j=0; j 3) begin + $display ("%m: at time %t ERROR: tFAW violation during %s to bank %d", $time, cmd_string[cmd], bank); + end + end + + if (!init_done) begin + $display ("%m: at time %t ERROR: %s Failure. Initialization sequence is not complete.", $time, cmd_string[cmd]); + if (STOP_ON_ERROR) $stop(0); + end else if (active_bank[bank]) begin + $display ("%m: at time %t ERROR: %s Failure. Bank %d must be Precharged.", $time, cmd_string[cmd], bank); + if (STOP_ON_ERROR) $stop(0); + end else begin + if (addr >= 1<>1) & -1*(1<= 1<>1) & -1*(1<= 1< $time) +// $display("%m: at time %t WARNING: NOP or DESELECT is required for 200 us before CKE is brought high", $time); + init_step = init_step + 1; + end + 1 : if (dll_en) init_step = init_step + 1; + 2 : begin + if (&init_mode_reg && dll_reset) begin + active_bank = {`BANKS{1'b1}}; // require Precharge All or bank Precharges + ref_cntr = 0; // require refresh + init_step = init_step + 1; + end + end + 3 : if (ref_cntr == 2) begin + init_step = init_step + 1; + end + 4 : if (!dll_reset) init_step = init_step + 1; + 5 : if (ocd == 3'b111) init_step = init_step + 1; + 6 : begin + if (ocd == 3'b000) begin + if (DEBUG) $display ("%m: at time %t INFO: Initialization Sequence is complete", $time); + init_done = 1; + end + end + endcase + end + end else if (prev_cke) begin + if ((!init_done) && (init_step > 1)) begin + $display ("%m: at time %t ERROR: CKE must remain active until the initialization sequence is complete.", $time); + if (STOP_ON_ERROR) $stop(0); + end + case (cmd) + REFRESH : begin + for (j=0; j TDQSS*tck_avg)) + $display ("%m: at time %t ERROR: tDQSS violation on %s bit %d", $time, dqs_string[i/18], i%18); + end + if (check_write_dqs_low[i]) + $display ("%m: at time %t ERROR: %s bit %d latching edge required during the preceding clock period", $time, dqs_string[i/18], i%18); + end + check_write_preamble <= 0; + check_write_postamble <= 0; + check_write_dqs_low <= 0; + end + + if (wr_pipeline[0] || rd_pipeline[0]) begin + bank = ba_pipeline[0]; + row = row_pipeline[0]; + col = col_pipeline[0]; + burst_cntr = 0; + memory_read(bank, row, col, memory_data); + end + + // burst counter + if (burst_cntr < burst_length) begin + burst_position = col ^ burst_cntr; + if (!burst_order) begin + burst_position[BO_BITS-1:0] = col + burst_cntr; + end + burst_cntr = burst_cntr + 1; + end + + // write dqs counter + if (wr_pipeline[WDQS_PRE + 1]) begin + wdqs_cntr = WDQS_PRE + burst_length + WDQS_PST - 1; + end + // write dqs + if ((wdqs_cntr == burst_length + WDQS_PST) && (wdq_cntr == 0)) begin //write preamble + check_write_preamble <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}}; + end + if (wdqs_cntr > 1) begin // write data + if ((wdqs_cntr - WDQS_PST)%2) begin + check_write_dqs_high <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}}; + end else begin + check_write_dqs_low <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}}; + end + end + if (wdqs_cntr == WDQS_PST) begin // write postamble + check_write_postamble <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}}; + end + if (wdqs_cntr > 0) begin + wdqs_cntr = wdqs_cntr - 1; + end + + // write dq + if (dq_in_valid) begin // write data + bit_mask = 0; + if (diff_ck) begin + for (i=0; i>(burst_position*DQ_BITS); + if (DEBUG) $display ("%m: at time %t INFO: WRITE @ DQS= bank = %h row = %h col = %h data = %h",$time, bank, row, (-1*BL_MAX & col) + burst_position, dq_temp); + if (burst_cntr%BL_MIN == 0) begin + memory_write(bank, row, col, memory_data); + end + end + if (wr_pipeline[1]) begin + wdq_cntr = burst_length; + end + if (wdq_cntr > 0) begin + wdq_cntr = wdq_cntr - 1; + dq_in_valid = 1'b1; + end else begin + dq_in_valid = 1'b0; + dqs_in_valid <= 1'b0; + for (i=0; i<36; i=i+1) begin + wdqs_pos_cntr[i] <= 0; + end + end + if (wr_pipeline[0]) begin + b2b_write <= 1'b0; + end + if (wr_pipeline[2]) begin + if (dqs_in_valid) begin + b2b_write <= 1'b1; + end + dqs_in_valid <= 1'b1; + end + // read dqs enable counter + if (rd_pipeline[RDQSEN_PRE]) begin + rdqsen_cntr = RDQSEN_PRE + burst_length + RDQSEN_PST - 1; + end + if (rdqsen_cntr > 0) begin + rdqsen_cntr = rdqsen_cntr - 1; + dqs_out_en = 1'b1; + end else begin + dqs_out_en = 1'b0; + end + + // read dqs counter + if (rd_pipeline[RDQS_PRE]) begin + rdqs_cntr = RDQS_PRE + burst_length + RDQS_PST - 1; + end + // read dqs + if ((rdqs_cntr >= burst_length + RDQS_PST) && (rdq_cntr == 0)) begin //read preamble + dqs_out = 1'b0; + end else if (rdqs_cntr > RDQS_PST) begin // read data + dqs_out = rdqs_cntr - RDQS_PST; + end else if (rdqs_cntr > 0) begin // read postamble + dqs_out = 1'b0; + end else begin + dqs_out = 1'b1; + end + if (rdqs_cntr > 0) begin + rdqs_cntr = rdqs_cntr - 1; + end + + // read dq enable counter + if (rd_pipeline[RDQEN_PRE]) begin + rdqen_cntr = RDQEN_PRE + burst_length + RDQEN_PST; + end + if (rdqen_cntr > 0) begin + rdqen_cntr = rdqen_cntr - 1; + dq_out_en = 1'b1; + end else begin + dq_out_en = 1'b0; + end + // read dq + if (rd_pipeline[0]) begin + rdq_cntr = burst_length; + end + if (rdq_cntr > 0) begin // read data + dq_temp = memory_data>>(burst_position*DQ_BITS); + dq_out = dq_temp; + if (DEBUG) $display ("%m: at time %t INFO: READ @ DQS= bank = %h row = %h col = %h data = %h",$time, bank, row, (-1*BL_MAX & col) + burst_position, dq_temp); + rdq_cntr = rdq_cntr - 1; + end else begin + dq_out = {DQ_BITS{1'b1}}; + end + + // delay signals prior to output + if (RANDOM_OUT_DELAY && (dqs_out_en || |dqs_out_en_dly || dq_out_en || |dq_out_en_dly)) begin + for (i=0; i dqsck[i] + TQHS + TDQSQ) begin + dqsck_max = dqsck[i] + TQHS + TDQSQ; + end + dqsck_min = -1*TDQSCK; + if (dqsck_min < dqsck[i] - TQHS - TDQSQ) begin + dqsck_min = dqsck[i] - TQHS - TDQSQ; + end + + // DQSQ requirements + // 1.) less than tAC - DQSCK + // 2.) less than tDQSQ + // 3.) greater than -tAC + // 4.) greater than tQH from previous DQS edge + dqsq_min = -1*TAC; + if (dqsq_min < dqsck[i] - TQHS) begin + dqsq_min = dqsck[i] - TQHS; + end + if (dqsck_min == dqsck_max) begin + dqsck[i] = dqsck_min; + end else begin + dqsck[i] = $dist_uniform(seed, dqsck_min, dqsck_max); + end + dqsq_max = TAC; + if (dqsq_max > TDQSQ + dqsck[i]) begin + dqsq_max = TDQSQ + dqsck[i]; + end + + dqs_out_en_dly[i] <= #(tck_avg/2.0 + ($random % TAC)) dqs_out_en; + dqs_out_dly[i] <= #(tck_avg/2.0 + dqsck[i]) dqs_out; + for (j=0; j<`DQ_PER_DQS; j=j+1) begin + if (dq_out_en) begin // tLZ2 + dq_out_en_dly[i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + $dist_uniform(seed, -2*TAC, dqsq_max)) dq_out_en; + end else begin // tHZ + dq_out_en_dly[i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + ($random % TAC)) dq_out_en; + end + if (dqsq_min == dqsq_max) begin + dq_out_dly [i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + dqsq_min) dq_out[i*`DQ_PER_DQS + j]; + end else begin + dq_out_dly [i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + $dist_uniform(seed, dqsq_min, dqsq_max)) dq_out[i*`DQ_PER_DQS + j]; + end + end + end + end else begin + out_delay = tck_avg/2.0; + dqs_out_en_dly <= #(out_delay) {DQS_BITS{dqs_out_en}}; + dqs_out_dly <= #(out_delay) {DQS_BITS{dqs_out }}; + dq_out_en_dly <= #(out_delay) {DQ_BITS {dq_out_en }}; + dq_out_dly <= #(out_delay) {DQ_BITS {dq_out }}; + end + end + endtask + + always @(diff_ck) begin : main + integer i; + + if (!in_self_refresh && (diff_ck !== 1'b0) && (diff_ck !== 1'b1)) + $display ("%m: at time %t ERROR: CK and CK_N are not allowed to go to an unknown state.", $time); + data_task; + if (diff_ck) begin + // check setup of command signals + if ($time > TIS) begin + if ($time - tm_cke < TIS) + $display ("%m: at time %t ERROR: tIS violation on CKE by %t", $time, tm_cke + TIS - $time); + if (cke_in) begin + for (i=0; i<22; i=i+1) begin + if ($time - tm_cmd_addr[i] < TIS) + $display ("%m: at time %t ERROR: tIS violation on %s by %t", $time, cmd_addr_string[i], tm_cmd_addr[i] + TIS - $time); + end + end + end + + // update current state + if (!dll_locked && !in_self_refresh && (ck_cntr - ck_dll_reset == TDLLK)) begin + // check CL value against the clock frequency + if (cas_latency*tck_avg < CL_TIME) + $display ("%m: at time %t ERROR: CAS Latency = %d is illegal @tCK(avg) = %f", $time, cas_latency, tck_avg); + // check WR value against the clock frequency + if (write_recovery*tck_avg < TWR) + $display ("%m: at time %t ERROR: Write Recovery = %d is illegal @tCK(avg) = %f", $time, write_recovery, tck_avg); + dll_locked = 1; + end + if (|auto_precharge_bank) begin + for (i=0; i<`BANKS; i=i+1) begin + // Write with Auto Precharge Calculation + // 1. Meet minimum tRAS requirement + // 2. Write Latency PLUS BL/2 cycles PLUS WR after Write command + if (write_precharge_bank[i] + && ($time - tm_bank_activate[i] >= TRAS_MIN) + && (ck_cntr - ck_bank_write[i] >= write_latency + burst_length/2 + write_recovery)) begin + + if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", $time, i); + write_precharge_bank[i] = 0; + active_bank[i] = 0; + auto_precharge_bank[i] = 0; + ck_write_ap = ck_cntr; + tm_bank_precharge[i] = $time; + tm_precharge = $time; + end + // Read with Auto Precharge Calculation + // 1. Meet minimum tRAS requirement + // 2. Additive Latency plus BL/2 cycles after Read command + // 3. tRTP after the last 4-bit prefetch + if (read_precharge_bank[i] + && ($time - tm_bank_activate[i] >= TRAS_MIN) + && (ck_cntr - ck_bank_read[i] >= additive_latency + burst_length/2)) begin + + read_precharge_bank[i] = 0; + // In case the internal precharge is pushed out by tRTP, tRP starts at the point where + // the internal precharge happens (not at the next rising clock edge after this event). + if ($time - tm_bank_read_end[i] < TRTP) begin + if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", tm_bank_read_end[i] + TRTP, i); + active_bank[i] <= #(tm_bank_read_end[i] + TRTP - $time) 0; + auto_precharge_bank[i] <= #(tm_bank_read_end[i] + TRTP - $time) 0; + tm_bank_precharge[i] <= #(tm_bank_read_end[i] + TRTP - $time) tm_bank_read_end[i] + TRTP; + tm_precharge <= #(tm_bank_read_end[i] + TRTP - $time) tm_bank_read_end[i] + TRTP; + end else begin + if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", $time, i); + active_bank[i] = 0; + auto_precharge_bank[i] = 0; + tm_bank_precharge[i] = $time; + tm_precharge = $time; + end + end + end + end + + // respond to incoming command + if (cke_in ^ prev_cke) begin + ck_cke <= ck_cntr; + end + + cmd_task(cke_in, cmd_n_in, ba_in, addr_in); + if ((cmd_n_in == WRITE) || (cmd_n_in == READ)) begin + al_pipeline[2*additive_latency] = 1'b1; + end + if (al_pipeline[0]) begin + // check tRCD after additive latency + if ($time - tm_bank_activate[ba_pipeline[2*cas_latency - 1]] < TRCD) begin + if (rd_pipeline[2*cas_latency - 1]) begin + $display ("%m: at time %t ERROR: tRCD violation during %s", $time, cmd_string[READ]); + end else begin + $display ("%m: at time %t ERROR: tRCD violation during %s", $time, cmd_string[WRITE]); + end + end + // check tWTR after additive latency + if (rd_pipeline[2*cas_latency - 1]) begin + if ($time - tm_write_end < TWTR) + $display ("%m: at time %t ERROR: tWTR violation during %s", $time, cmd_string[READ]); + end + end + if (rd_pipeline[2*(cas_latency - burst_length/2 + 2) - 1]) begin + tm_bank_read_end[ba_pipeline[2*(cas_latency - burst_length/2 + 2) - 1]] <= $time; + end + for (i=0; i<`BANKS; i=i+1) begin + if ((ck_cntr - ck_bank_write[i] > write_latency) && (ck_cntr - ck_bank_write[i] <= write_latency + burst_length/2)) begin + tm_bank_write_end[i] <= $time; + tm_write_end <= $time; + end + end + + // clk pin is disabled during self refresh + if (!in_self_refresh) begin + tjit_cc_time = $time - tm_ck_pos - tck_i; + tck_i = $time - tm_ck_pos; + tck_avg = tck_avg - tck_sample[ck_cntr%TDLLK]/$itor(TDLLK); + tck_avg = tck_avg + tck_i/$itor(TDLLK); + tck_sample[ck_cntr%TDLLK] = tck_i; + tjit_per_rtime = tck_i - tck_avg; + + if (dll_locked) begin + // check accumulated error + terr_nper_rtime = 0; + for (i=0; i<50; i=i+1) begin + terr_nper_rtime = terr_nper_rtime + tck_sample[i] - tck_avg; + terr_nper_rtime = abs_value(terr_nper_rtime); + case (i) + 0 :; + 1 : if (terr_nper_rtime - TERR_2PER >= 1.0) $display ("%m: at time %t ERROR: tERR(2per) violation by %f ps.", $time, terr_nper_rtime - TERR_2PER); + 2 : if (terr_nper_rtime - TERR_3PER >= 1.0) $display ("%m: at time %t ERROR: tERR(3per) violation by %f ps.", $time, terr_nper_rtime - TERR_3PER); + 3 : if (terr_nper_rtime - TERR_4PER >= 1.0) $display ("%m: at time %t ERROR: tERR(4per) violation by %f ps.", $time, terr_nper_rtime - TERR_4PER); + 4 : if (terr_nper_rtime - TERR_5PER >= 1.0) $display ("%m: at time %t ERROR: tERR(5per) violation by %f ps.", $time, terr_nper_rtime - TERR_5PER); + 5,6,7,8,9 : if (terr_nper_rtime - TERR_N1PER >= 1.0) $display ("%m: at time %t ERROR: tERR(n1per) violation by %f ps.", $time, terr_nper_rtime - TERR_N1PER); + default : if (terr_nper_rtime - TERR_N2PER >= 1.0) $display ("%m: at time %t ERROR: tERR(n2per) violation by %f ps.", $time, terr_nper_rtime - TERR_N2PER); + endcase + end + + // check tCK min/max/jitter + if (abs_value(tjit_per_rtime) - TJIT_PER >= 1.0) + $display ("%m: at time %t ERROR: tJIT(per) violation by %f ps.", $time, abs_value(tjit_per_rtime) - TJIT_PER); + if (abs_value(tjit_cc_time) - TJIT_CC >= 1.0) + $display ("%m: at time %t ERROR: tJIT(cc) violation by %f ps.", $time, abs_value(tjit_cc_time) - TJIT_CC); + if (TCK_MIN - tck_avg >= 1.0) + $display ("%m: at time %t ERROR: tCK(avg) minimum violation by %f ps.", $time, TCK_MIN - tck_avg); + if (tck_avg - TCK_MAX >= 1.0) + $display ("%m: at time %t ERROR: tCK(avg) maximum violation by %f ps.", $time, tck_avg - TCK_MAX); + if (tm_ck_pos + TCK_MIN - TJIT_PER > $time) + $display ("%m: at time %t ERROR: tCK(abs) minimum violation by %t", $time, tm_ck_pos + TCK_MIN - TJIT_PER - $time); + if (tm_ck_pos + TCK_MAX + TJIT_PER < $time) + $display ("%m: at time %t ERROR: tCK(abs) maximum violation by %t", $time, $time - tm_ck_pos - TCK_MAX - TJIT_PER); + + // check tCL + if (tm_ck_neg + TCL_MIN*tck_avg - TJIT_DUTY > $time) + $display ("%m: at time %t ERROR: tCL(abs) minimum violation on CLK by %t", $time, tm_ck_neg + TCL_MIN*tck_avg - TJIT_DUTY - $time); + if (tm_ck_neg + TCL_MAX*tck_avg + TJIT_DUTY < $time) + $display ("%m: at time %t ERROR: tCL(abs) maximum violation on CLK by %t", $time, $time - tm_ck_neg - TCL_MAX*tck_avg - TJIT_DUTY); + if (tcl_avg < TCL_MIN*tck_avg) + $display ("%m: at time %t ERROR: tCL(avg) minimum violation on CLK by %t", $time, TCL_MIN*tck_avg - tcl_avg); + if (tcl_avg > TCL_MAX*tck_avg) + $display ("%m: at time %t ERROR: tCL(avg) maximum violation on CLK by %t", $time, tcl_avg - TCL_MAX*tck_avg); + end + + // calculate the tch avg jitter + tch_avg = tch_avg - tch_sample[ck_cntr%TDLLK]/$itor(TDLLK); + tch_avg = tch_avg + tch_i/$itor(TDLLK); + tch_sample[ck_cntr%TDLLK] = tch_i; + + // update timers/counters + tcl_i <= $time - tm_ck_neg; + end + + prev_odt <= odt_in; + // update timers/counters + ck_cntr <= ck_cntr + 1; + tm_ck_pos <= $time; + end else begin + // clk pin is disabled during self refresh + if (!in_self_refresh) begin + if (dll_locked) begin + if (tm_ck_pos + TCH_MIN*tck_avg - TJIT_DUTY > $time) + $display ("%m: at time %t ERROR: tCH(abs) minimum violation on CLK by %t", $time, tm_ck_pos + TCH_MIN*tck_avg - TJIT_DUTY + $time); + if (tm_ck_pos + TCH_MAX*tck_avg + TJIT_DUTY < $time) + $display ("%m: at time %t ERROR: tCH(abs) maximum violation on CLK by %t", $time, $time - tm_ck_pos - TCH_MAX*tck_avg - TJIT_DUTY); + if (tch_avg < TCH_MIN*tck_avg) + $display ("%m: at time %t ERROR: tCH(avg) minimum violation on CLK by %t", $time, TCH_MIN*tck_avg - tch_avg); + if (tch_avg > TCH_MAX*tck_avg) + $display ("%m: at time %t ERROR: tCH(avg) maximum violation on CLK by %t", $time, tch_avg - TCH_MAX*tck_avg); + end + + // calculate the tcl avg jitter + tcl_avg = tcl_avg - tcl_sample[ck_cntr%TDLLK]/$itor(TDLLK); + tcl_avg = tcl_avg + tcl_i/$itor(TDLLK); + tcl_sample[ck_cntr%TDLLK] = tcl_i; + + // update timers/counters + tch_i <= $time - tm_ck_pos; + end + tm_ck_neg <= $time; + end + + // on die termination + if (odt_en) begin + // clk pin is disabled during self refresh + if (!in_self_refresh && diff_ck) begin + if ($time - tm_odt < TIS) begin + $display ("%m: at time %t ERROR: tIS violation on ODT by %t", $time, tm_odt + TIS - $time); + end + if (prev_odt ^ odt_in) begin + if (!dll_locked) + $display ("%m: at time %t WARNING: tDLLK violation during ODT transition.", $time); + if (odt_in && ($time - tm_odt_en < TMOD)) + $display ("%m: at time %t ERROR: tMOD violation during ODT transition", $time); + if ($time - tm_self_refresh < TXSNR) + $display ("%m: at time %t ERROR: tXSNR violation during ODT transition", $time); + if (in_self_refresh) + $display ("%m: at time %t ERROR: Illegal ODT transition during Self Refresh.", $time); + + // async ODT mode applies: + // 1.) during active power down with slow exit + // 2.) during precharge power down + // 3.) if tANPD has not been satisfied + // 4.) until tAXPD has been satisfied + if ((in_power_down && (low_power || (active_bank == 0))) || (ck_cntr - ck_slow_exit_pd < TAXPD)) begin + if (ck_cntr - ck_slow_exit_pd < TAXPD) + $display ("%m: at time %t WARNING: tAXPD violation during ODT transition. Synchronous or asynchronous change in termination resistance is possible.", $time); + if (odt_in) begin + if (DEBUG) $display ("%m: at time %t INFO: Async On Die Termination = %d", $time + TAONPD, 1'b1); + odt_state <= #(TAONPD) 1'b1; + end else begin + if (DEBUG) $display ("%m: at time %t INFO: Async On Die Termination = %d", $time + TAOFPD, 1'b0); + odt_state <= #(TAOFPD) 1'b0; + end + // sync ODT mode applies: + // 1.) during normal operation + // 2.) during active power down with fast exit + end else begin + if (odt_in) begin + i = TAOND*2; + odt_pipeline[i] = 1'b1; + end else begin + i = TAOFD*2; + odt_pipeline[i] = 1'b1; + end + end + ck_odt <= ck_cntr; + end + end + if (odt_pipeline[0]) begin + odt_state = ~odt_state; + if (DEBUG) $display ("%m: at time %t INFO: Sync On Die Termination = %d", $time, odt_state); + end + end + + // shift pipelines + if (|wr_pipeline || |rd_pipeline || |al_pipeline) begin + al_pipeline = al_pipeline>>1; + wr_pipeline = wr_pipeline>>1; + rd_pipeline = rd_pipeline>>1; + for (i=0; i<`MAX_PIPE; i=i+1) begin + ba_pipeline[i] = ba_pipeline[i+1]; + row_pipeline[i] = row_pipeline[i+1]; + col_pipeline[i] = col_pipeline[i+1]; + end + end + if (|odt_pipeline) begin + odt_pipeline = odt_pipeline>>1; + end + end + + // receiver(s) + task dqs_even_receiver; + input [4:0] i; + reg [71:0] bit_mask; + begin + bit_mask = {`DQ_PER_DQS{1'b1}}<<(i*`DQ_PER_DQS); + if (dqs_even[i]) begin + if (rdqs_en) begin // rdqs disables dm + dm_in_pos[i] = 1'b0; + end else begin + dm_in_pos[i] = dm_in[i]; + end + dq_in_pos = (dq_in & bit_mask) | (dq_in_pos & ~bit_mask); + end + end + endtask + + always @(posedge dqs_even[ 0]) dqs_even_receiver( 0); + always @(posedge dqs_even[ 1]) dqs_even_receiver( 1); + always @(posedge dqs_even[ 2]) dqs_even_receiver( 2); + always @(posedge dqs_even[ 3]) dqs_even_receiver( 3); + always @(posedge dqs_even[ 4]) dqs_even_receiver( 4); + always @(posedge dqs_even[ 5]) dqs_even_receiver( 5); + always @(posedge dqs_even[ 6]) dqs_even_receiver( 6); + always @(posedge dqs_even[ 7]) dqs_even_receiver( 7); + always @(posedge dqs_even[ 8]) dqs_even_receiver( 8); + always @(posedge dqs_even[ 9]) dqs_even_receiver( 9); + always @(posedge dqs_even[10]) dqs_even_receiver(10); + always @(posedge dqs_even[11]) dqs_even_receiver(11); + always @(posedge dqs_even[12]) dqs_even_receiver(12); + always @(posedge dqs_even[13]) dqs_even_receiver(13); + always @(posedge dqs_even[14]) dqs_even_receiver(14); + always @(posedge dqs_even[15]) dqs_even_receiver(15); + always @(posedge dqs_even[16]) dqs_even_receiver(16); + always @(posedge dqs_even[17]) dqs_even_receiver(17); + + task dqs_odd_receiver; + input [4:0] i; + reg [71:0] bit_mask; + begin + bit_mask = {`DQ_PER_DQS{1'b1}}<<(i*`DQ_PER_DQS); + if (dqs_odd[i]) begin + if (rdqs_en) begin // rdqs disables dm + dm_in_neg[i] = 1'b0; + end else begin + dm_in_neg[i] = dm_in[i]; + end + dq_in_neg = (dq_in & bit_mask) | (dq_in_neg & ~bit_mask); + end + end + endtask + + always @(posedge dqs_odd[ 0]) dqs_odd_receiver( 0); + always @(posedge dqs_odd[ 1]) dqs_odd_receiver( 1); + always @(posedge dqs_odd[ 2]) dqs_odd_receiver( 2); + always @(posedge dqs_odd[ 3]) dqs_odd_receiver( 3); + always @(posedge dqs_odd[ 4]) dqs_odd_receiver( 4); + always @(posedge dqs_odd[ 5]) dqs_odd_receiver( 5); + always @(posedge dqs_odd[ 6]) dqs_odd_receiver( 6); + always @(posedge dqs_odd[ 7]) dqs_odd_receiver( 7); + always @(posedge dqs_odd[ 8]) dqs_odd_receiver( 8); + always @(posedge dqs_odd[ 9]) dqs_odd_receiver( 9); + always @(posedge dqs_odd[10]) dqs_odd_receiver(10); + always @(posedge dqs_odd[11]) dqs_odd_receiver(11); + always @(posedge dqs_odd[12]) dqs_odd_receiver(12); + always @(posedge dqs_odd[13]) dqs_odd_receiver(13); + always @(posedge dqs_odd[14]) dqs_odd_receiver(14); + always @(posedge dqs_odd[15]) dqs_odd_receiver(15); + always @(posedge dqs_odd[16]) dqs_odd_receiver(16); + always @(posedge dqs_odd[17]) dqs_odd_receiver(17); + + // Processes to check hold and pulse width of control signals + always @(cke_in) begin + if ($time > TIH) begin + if ($time - tm_ck_pos < TIH) + $display ("%m: at time %t ERROR: tIH violation on CKE by %t", $time, tm_ck_pos + TIH - $time); + end + if (dll_locked && ($time - tm_cke < $rtoi(TIPW*tck_avg))) + $display ("%m: at time %t ERROR: tIPW violation on CKE by %t", $time, tm_cke + TIPW*tck_avg - $time); + tm_cke = $time; + end + always @(odt_in) begin + if (odt_en && !in_self_refresh) begin + if ($time - tm_ck_pos < TIH) + $display ("%m: at time %t ERROR: tIH violation on ODT by %t", $time, tm_ck_pos + TIH - $time); + if (dll_locked && ($time - tm_odt < $rtoi(TIPW*tck_avg))) + $display ("%m: at time %t ERROR: tIPW violation on ODT by %t", $time, tm_odt + TIPW*tck_avg - $time); + end + tm_odt = $time; + end + + task cmd_addr_timing_check; + input i; + reg [4:0] i; + begin + if (prev_cke) begin + if ((i == 0) && ($time - tm_ck_pos < TIH)) // Always check tIH for CS# + $display ("%m: at time %t ERROR: tIH violation on %s by %t", $time, cmd_addr_string[i], tm_ck_pos + TIH - $time); + if ((i > 0) && (cs_n_in == 1'b0) && ($time - tm_ck_pos < TIH)) // Only check tIH for cmd_addr if CS# low + $display ("%m: at time %t ERROR: tIH violation on %s by %t", $time, cmd_addr_string[i], tm_ck_pos + TIH - $time); + if (dll_locked && ($time - tm_cmd_addr[i] < $rtoi(TIPW*tck_avg))) + $display ("%m: at time %t ERROR: tIPW violation on %s by %t", $time, cmd_addr_string[i], tm_cmd_addr[i] + TIPW*tck_avg - $time); + end + tm_cmd_addr[i] = $time; + end + endtask + + always @(cs_n_in ) cmd_addr_timing_check( 0); + always @(ras_n_in ) cmd_addr_timing_check( 1); + always @(cas_n_in ) cmd_addr_timing_check( 2); + always @(we_n_in ) cmd_addr_timing_check( 3); + always @(ba_in [ 0]) cmd_addr_timing_check( 4); + always @(ba_in [ 1]) cmd_addr_timing_check( 5); + always @(ba_in [ 2]) cmd_addr_timing_check( 6); + always @(addr_in[ 0]) cmd_addr_timing_check( 7); + always @(addr_in[ 1]) cmd_addr_timing_check( 8); + always @(addr_in[ 2]) cmd_addr_timing_check( 9); + always @(addr_in[ 3]) cmd_addr_timing_check(10); + always @(addr_in[ 4]) cmd_addr_timing_check(11); + always @(addr_in[ 5]) cmd_addr_timing_check(12); + always @(addr_in[ 6]) cmd_addr_timing_check(13); + always @(addr_in[ 7]) cmd_addr_timing_check(14); + always @(addr_in[ 8]) cmd_addr_timing_check(15); + always @(addr_in[ 9]) cmd_addr_timing_check(16); + always @(addr_in[10]) cmd_addr_timing_check(17); + always @(addr_in[11]) cmd_addr_timing_check(18); + always @(addr_in[12]) cmd_addr_timing_check(19); + always @(addr_in[13]) cmd_addr_timing_check(20); + always @(addr_in[14]) cmd_addr_timing_check(21); + always @(addr_in[15]) cmd_addr_timing_check(22); + + // Processes to check setup and hold of data signals + task dm_timing_check; + input i; + reg [4:0] i; + begin + if (dqs_in_valid) begin + if ($time - tm_dqs[i] < TDH) + $display ("%m: at time %t ERROR: tDH violation on DM bit %d by %t", $time, i, tm_dqs[i] + TDH - $time); + if (check_dm_tdipw[i]) begin + if (dll_locked && ($time - tm_dm[i] < $rtoi(TDIPW*tck_avg))) + $display ("%m: at time %t ERROR: tDIPW violation on DM bit %d by %t", $time, i, tm_dm[i] + TDIPW*tck_avg - $time); + end + end + check_dm_tdipw[i] <= 1'b0; + tm_dm[i] = $time; + end + endtask + + always @(dm_in[ 0]) dm_timing_check( 0); + always @(dm_in[ 1]) dm_timing_check( 1); + always @(dm_in[ 2]) dm_timing_check( 2); + always @(dm_in[ 3]) dm_timing_check( 3); + always @(dm_in[ 4]) dm_timing_check( 4); + always @(dm_in[ 5]) dm_timing_check( 5); + always @(dm_in[ 6]) dm_timing_check( 6); + always @(dm_in[ 7]) dm_timing_check( 7); + always @(dm_in[ 8]) dm_timing_check( 8); + always @(dm_in[ 9]) dm_timing_check( 9); + always @(dm_in[10]) dm_timing_check(10); + always @(dm_in[11]) dm_timing_check(11); + always @(dm_in[12]) dm_timing_check(12); + always @(dm_in[13]) dm_timing_check(13); + always @(dm_in[14]) dm_timing_check(14); + always @(dm_in[15]) dm_timing_check(15); + always @(dm_in[16]) dm_timing_check(16); + always @(dm_in[17]) dm_timing_check(17); + + task dq_timing_check; + input i; + reg [6:0] i; + begin + if (dqs_in_valid) begin + if ($time - tm_dqs[i/`DQ_PER_DQS] < TDH) + $display ("%m: at time %t ERROR: tDH violation on DQ bit %d by %t", $time, i, tm_dqs[i/`DQ_PER_DQS] + TDH - $time); + if (check_dq_tdipw[i]) begin + if (dll_locked && ($time - tm_dq[i] < $rtoi(TDIPW*tck_avg))) + $display ("%m: at time %t ERROR: tDIPW violation on DQ bit %d by %t", $time, i, tm_dq[i] + TDIPW*tck_avg - $time); + end + end + check_dq_tdipw[i] <= 1'b0; + tm_dq[i] = $time; + end + endtask + + always @(dq_in[ 0]) dq_timing_check( 0); + always @(dq_in[ 1]) dq_timing_check( 1); + always @(dq_in[ 2]) dq_timing_check( 2); + always @(dq_in[ 3]) dq_timing_check( 3); + always @(dq_in[ 4]) dq_timing_check( 4); + always @(dq_in[ 5]) dq_timing_check( 5); + always @(dq_in[ 6]) dq_timing_check( 6); + always @(dq_in[ 7]) dq_timing_check( 7); + always @(dq_in[ 8]) dq_timing_check( 8); + always @(dq_in[ 9]) dq_timing_check( 9); + always @(dq_in[10]) dq_timing_check(10); + always @(dq_in[11]) dq_timing_check(11); + always @(dq_in[12]) dq_timing_check(12); + always @(dq_in[13]) dq_timing_check(13); + always @(dq_in[14]) dq_timing_check(14); + always @(dq_in[15]) dq_timing_check(15); + always @(dq_in[16]) dq_timing_check(16); + always @(dq_in[17]) dq_timing_check(17); + always @(dq_in[18]) dq_timing_check(18); + always @(dq_in[19]) dq_timing_check(19); + always @(dq_in[20]) dq_timing_check(20); + always @(dq_in[21]) dq_timing_check(21); + always @(dq_in[22]) dq_timing_check(22); + always @(dq_in[23]) dq_timing_check(23); + always @(dq_in[24]) dq_timing_check(24); + always @(dq_in[25]) dq_timing_check(25); + always @(dq_in[26]) dq_timing_check(26); + always @(dq_in[27]) dq_timing_check(27); + always @(dq_in[28]) dq_timing_check(28); + always @(dq_in[29]) dq_timing_check(29); + always @(dq_in[30]) dq_timing_check(30); + always @(dq_in[31]) dq_timing_check(31); + always @(dq_in[32]) dq_timing_check(32); + always @(dq_in[33]) dq_timing_check(33); + always @(dq_in[34]) dq_timing_check(34); + always @(dq_in[35]) dq_timing_check(35); + always @(dq_in[36]) dq_timing_check(36); + always @(dq_in[37]) dq_timing_check(37); + always @(dq_in[38]) dq_timing_check(38); + always @(dq_in[39]) dq_timing_check(39); + always @(dq_in[40]) dq_timing_check(40); + always @(dq_in[41]) dq_timing_check(41); + always @(dq_in[42]) dq_timing_check(42); + always @(dq_in[43]) dq_timing_check(43); + always @(dq_in[44]) dq_timing_check(44); + always @(dq_in[45]) dq_timing_check(45); + always @(dq_in[46]) dq_timing_check(46); + always @(dq_in[47]) dq_timing_check(47); + always @(dq_in[48]) dq_timing_check(48); + always @(dq_in[49]) dq_timing_check(49); + always @(dq_in[50]) dq_timing_check(50); + always @(dq_in[51]) dq_timing_check(51); + always @(dq_in[52]) dq_timing_check(52); + always @(dq_in[53]) dq_timing_check(53); + always @(dq_in[54]) dq_timing_check(54); + always @(dq_in[55]) dq_timing_check(55); + always @(dq_in[56]) dq_timing_check(56); + always @(dq_in[57]) dq_timing_check(57); + always @(dq_in[58]) dq_timing_check(58); + always @(dq_in[59]) dq_timing_check(59); + always @(dq_in[60]) dq_timing_check(60); + always @(dq_in[61]) dq_timing_check(61); + always @(dq_in[62]) dq_timing_check(62); + always @(dq_in[63]) dq_timing_check(63); + always @(dq_in[64]) dq_timing_check(64); + always @(dq_in[65]) dq_timing_check(65); + always @(dq_in[66]) dq_timing_check(66); + always @(dq_in[67]) dq_timing_check(67); + always @(dq_in[68]) dq_timing_check(68); + always @(dq_in[69]) dq_timing_check(69); + always @(dq_in[70]) dq_timing_check(70); + always @(dq_in[71]) dq_timing_check(71); + + task dqs_pos_timing_check; + input i; + reg [5:0] i; + reg [3:0] j; + begin + if (dqs_in_valid && ((wdqs_pos_cntr[i] < burst_length/2) || b2b_write) && (dqs_n_en || i<18)) begin + if (dqs_in[i] ^ prev_dqs_in[i]) begin + if (dll_locked) begin + if (check_write_preamble[i]) begin + if ($time - tm_dqs_neg[i] < $rtoi(TWPRE*tck_avg)) + $display ("%m: at time %t ERROR: tWPRE violation on &s bit %d", $time, dqs_string[i/18], i%18); + end else if (check_write_postamble[i]) begin + if ($time - tm_dqs_neg[i] < $rtoi(TWPST*tck_avg)) + $display ("%m: at time %t ERROR: tWPST violation on %s bit %d", $time, dqs_string[i/18], i%18); + end else begin + if ($time - tm_dqs_neg[i] < $rtoi(TDQSL*tck_avg)) + $display ("%m: at time %t ERROR: tDQSL violation on %s bit %d", $time, dqs_string[i/18], i%18); + end + end + if ($time - tm_dm[i%18] < TDS) + $display ("%m: at time %t ERROR: tDS violation on DM bit %d by %t", $time, i, tm_dm[i%18] + TDS - $time); + if (!dq_out_en) begin + for (j=0; j<`DQ_PER_DQS; j=j+1) begin + if ($time - tm_dq[i*`DQ_PER_DQS+j] < TDS) + $display ("%m: at time %t ERROR: tDS violation on DQ bit %d by %t", $time, i*`DQ_PER_DQS+j, tm_dq[i*`DQ_PER_DQS+j] + TDS - $time); + check_dq_tdipw[i*`DQ_PER_DQS+j] <= 1'b1; + end + end + if ((wdqs_pos_cntr[i] < burst_length/2) && !b2b_write) begin + wdqs_pos_cntr[i] <= wdqs_pos_cntr[i] + 1; + end else begin + wdqs_pos_cntr[i] <= 1; + end + check_dm_tdipw[i%18] <= 1'b1; + check_write_preamble[i] <= 1'b0; + check_write_postamble[i] <= 1'b0; + check_write_dqs_low[i] <= 1'b0; + tm_dqs[i%18] <= $time; + end else begin + $display ("%m: at time %t ERROR: Invalid latching edge on %s bit %d", $time, dqs_string[i/18], i%18); + end + end + tm_dqss_pos[i] <= $time; + tm_dqs_pos[i] = $time; + prev_dqs_in[i] <= dqs_in[i]; + end + endtask + + always @(posedge dqs_in[ 0]) dqs_pos_timing_check( 0); + always @(posedge dqs_in[ 1]) dqs_pos_timing_check( 1); + always @(posedge dqs_in[ 2]) dqs_pos_timing_check( 2); + always @(posedge dqs_in[ 3]) dqs_pos_timing_check( 3); + always @(posedge dqs_in[ 4]) dqs_pos_timing_check( 4); + always @(posedge dqs_in[ 5]) dqs_pos_timing_check( 5); + always @(posedge dqs_in[ 6]) dqs_pos_timing_check( 6); + always @(posedge dqs_in[ 7]) dqs_pos_timing_check( 7); + always @(posedge dqs_in[ 8]) dqs_pos_timing_check( 8); + always @(posedge dqs_in[ 9]) dqs_pos_timing_check( 9); + always @(posedge dqs_in[10]) dqs_pos_timing_check(10); + always @(posedge dqs_in[11]) dqs_pos_timing_check(11); + always @(posedge dqs_in[12]) dqs_pos_timing_check(12); + always @(posedge dqs_in[13]) dqs_pos_timing_check(13); + always @(posedge dqs_in[14]) dqs_pos_timing_check(14); + always @(posedge dqs_in[15]) dqs_pos_timing_check(15); + always @(posedge dqs_in[16]) dqs_pos_timing_check(16); + always @(posedge dqs_in[17]) dqs_pos_timing_check(17); + always @(negedge dqs_in[18]) dqs_pos_timing_check(18); + always @(negedge dqs_in[19]) dqs_pos_timing_check(19); + always @(negedge dqs_in[20]) dqs_pos_timing_check(20); + always @(negedge dqs_in[21]) dqs_pos_timing_check(21); + always @(negedge dqs_in[22]) dqs_pos_timing_check(22); + always @(negedge dqs_in[23]) dqs_pos_timing_check(23); + always @(negedge dqs_in[24]) dqs_pos_timing_check(24); + always @(negedge dqs_in[25]) dqs_pos_timing_check(25); + always @(negedge dqs_in[26]) dqs_pos_timing_check(26); + always @(negedge dqs_in[27]) dqs_pos_timing_check(27); + always @(negedge dqs_in[28]) dqs_pos_timing_check(28); + always @(negedge dqs_in[29]) dqs_pos_timing_check(29); + always @(negedge dqs_in[30]) dqs_pos_timing_check(30); + always @(negedge dqs_in[31]) dqs_pos_timing_check(31); + always @(negedge dqs_in[32]) dqs_neg_timing_check(32); + always @(negedge dqs_in[33]) dqs_neg_timing_check(33); + always @(negedge dqs_in[34]) dqs_neg_timing_check(34); + always @(negedge dqs_in[35]) dqs_neg_timing_check(35); + + task dqs_neg_timing_check; + input i; + reg [5:0] i; + reg [3:0] j; + begin + if (dqs_in_valid && (wdqs_pos_cntr[i] > 0) && check_write_dqs_high[i] && (dqs_n_en || i < 18)) begin + if (dqs_in[i] ^ prev_dqs_in[i]) begin + if (dll_locked) begin + if ($time - tm_dqs_pos[i] < $rtoi(TDQSH*tck_avg)) + $display ("%m: at time %t ERROR: tDQSH violation on %s bit %d", $time, dqs_string[i/18], i%18); + if ($time - tm_ck_pos < $rtoi(TDSH*tck_avg)) + $display ("%m: at time %t ERROR: tDSH violation on %s bit %d", $time, dqs_string[i/18], i%18); + end + if ($time - tm_dm[i%18] < TDS) + $display ("%m: at time %t ERROR: tDS violation on DM bit %d by %t", $time, i, tm_dm[i%18] + TDS - $time); + if (!dq_out_en) begin + for (j=0; j<`DQ_PER_DQS; j=j+1) begin + if ($time - tm_dq[i*`DQ_PER_DQS+j] < TDS) + $display ("%m: at time %t ERROR: tDS violation on DQ bit %d by %t", $time, i*`DQ_PER_DQS+j, tm_dq[i*`DQ_PER_DQS+j] + TDS - $time); + check_dq_tdipw[i*`DQ_PER_DQS+j] <= 1'b1; + end + end + check_dm_tdipw[i%18] <= 1'b1; + check_write_dqs_high[i] <= 1'b0; + tm_dqs[i%18] <= $time; + end else begin + $display ("%m: at time %t ERROR: Invalid latching edge on %s bit %d", $time, dqs_string[i/18], i%18); + end + end + tm_dqs_neg[i] = $time; + prev_dqs_in[i] <= dqs_in[i]; + end + endtask + + always @(negedge dqs_in[ 0]) dqs_neg_timing_check( 0); + always @(negedge dqs_in[ 1]) dqs_neg_timing_check( 1); + always @(negedge dqs_in[ 2]) dqs_neg_timing_check( 2); + always @(negedge dqs_in[ 3]) dqs_neg_timing_check( 3); + always @(negedge dqs_in[ 4]) dqs_neg_timing_check( 4); + always @(negedge dqs_in[ 5]) dqs_neg_timing_check( 5); + always @(negedge dqs_in[ 6]) dqs_neg_timing_check( 6); + always @(negedge dqs_in[ 7]) dqs_neg_timing_check( 7); + always @(negedge dqs_in[ 8]) dqs_neg_timing_check( 8); + always @(negedge dqs_in[ 9]) dqs_neg_timing_check( 9); + always @(negedge dqs_in[10]) dqs_neg_timing_check(10); + always @(negedge dqs_in[11]) dqs_neg_timing_check(11); + always @(negedge dqs_in[12]) dqs_neg_timing_check(12); + always @(negedge dqs_in[13]) dqs_neg_timing_check(13); + always @(negedge dqs_in[14]) dqs_neg_timing_check(14); + always @(negedge dqs_in[15]) dqs_neg_timing_check(15); + always @(negedge dqs_in[16]) dqs_neg_timing_check(16); + always @(negedge dqs_in[17]) dqs_neg_timing_check(17); + always @(posedge dqs_in[18]) dqs_neg_timing_check(18); + always @(posedge dqs_in[19]) dqs_neg_timing_check(19); + always @(posedge dqs_in[20]) dqs_neg_timing_check(20); + always @(posedge dqs_in[21]) dqs_neg_timing_check(21); + always @(posedge dqs_in[22]) dqs_neg_timing_check(22); + always @(posedge dqs_in[23]) dqs_neg_timing_check(23); + always @(posedge dqs_in[24]) dqs_neg_timing_check(24); + always @(posedge dqs_in[25]) dqs_neg_timing_check(25); + always @(posedge dqs_in[26]) dqs_neg_timing_check(26); + always @(posedge dqs_in[27]) dqs_neg_timing_check(27); + always @(posedge dqs_in[28]) dqs_neg_timing_check(28); + always @(posedge dqs_in[29]) dqs_neg_timing_check(29); + always @(posedge dqs_in[30]) dqs_neg_timing_check(30); + always @(posedge dqs_in[31]) dqs_neg_timing_check(31); + always @(posedge dqs_in[32]) dqs_neg_timing_check(32); + always @(posedge dqs_in[33]) dqs_neg_timing_check(33); + always @(posedge dqs_in[34]) dqs_neg_timing_check(34); + always @(posedge dqs_in[35]) dqs_neg_timing_check(35); + +endmodule diff --git a/sim/verilog/micron_2048Mb_ddr2/ddr2_mcp.v b/sim/verilog/micron_2048Mb_ddr2/ddr2_mcp.v new file mode 100644 index 0000000..38e04bb --- /dev/null +++ b/sim/verilog/micron_2048Mb_ddr2/ddr2_mcp.v @@ -0,0 +1,94 @@ +/**************************************************************************************** +* +* File Name: ddr2_mcp.v +* +* Dependencies: ddr2.v, ddr2_parameters.vh +* +* Description: Micron SDRAM DDR2 (Double Data Rate 2) multi-chip package model +* +* Disclaimer This software code and all associated documentation, comments or other +* of Warranty: information (collectively "Software") is provided "AS IS" without +* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY +* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES +* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT +* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE +* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. +* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR +* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE +* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, +* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, +* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, +* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, +* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE +* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGES. Because some jurisdictions prohibit the exclusion or +* limitation of liability for consequential or incidental damages, the +* above limitation may not apply to you. +* +* Copyright 2003 Micron Technology, Inc. All rights reserved. +* +****************************************************************************************/ + `timescale 1ps / 1ps + +module ddr2_mcp ( + ck, + ck_n, + cke, + cs_n, + ras_n, + cas_n, + we_n, + dm_rdqs, + ba, + addr, + dq, + dqs, + dqs_n, + rdqs_n, + odt +); + + `include "ddr2_parameters.vh" + + // Declare Ports + input ck; + input ck_n; + input [CS_BITS-1:0] cke; + input [CS_BITS-1:0] cs_n; + input ras_n; + input cas_n; + input we_n; + inout [DM_BITS-1:0] dm_rdqs; + input [BA_BITS-1:0] ba; + input [ADDR_BITS-1:0] addr; + inout [DQ_BITS-1:0] dq; + inout [DQS_BITS-1:0] dqs; + inout [DQS_BITS-1:0] dqs_n; + output [DQS_BITS-1:0] rdqs_n; + input [CS_BITS-1:0] odt; + + wire [RANKS-1:0] cke_mcp = cke; + wire [RANKS-1:0] cs_n_mcp = cs_n; + wire [RANKS-1:0] odt_mcp = odt; + + ddr2 rank [RANKS-1:0] ( + ck, + ck_n, + cke_mcp, + cs_n_mcp, + ras_n, + cas_n, + we_n, + dm_rdqs, + ba, + addr, + dq, + dqs, + dqs_n, + rdqs_n, + odt_mcp + ); + +endmodule diff --git a/sim/verilog/micron_2048Mb_ddr2/ddr2_module.v b/sim/verilog/micron_2048Mb_ddr2/ddr2_module.v new file mode 100644 index 0000000..2fd45be --- /dev/null +++ b/sim/verilog/micron_2048Mb_ddr2/ddr2_module.v @@ -0,0 +1,377 @@ +/**************************************************************************************** +* +* File Name: ddr2_module.v +* +* Dependencies: ddr2.v, ddr2.v, ddr2_parameters.vh +* +* Description: Micron SDRAM DDR2 (Double Data Rate 2) module model +* +* Limitation: - SPD (Serial Presence-Detect) is not modeled +* +* Disclaimer This software code and all associated documentation, comments or other +* of Warranty: information (collectively "Software") is provided "AS IS" without +* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY +* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES +* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT +* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE +* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. +* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR +* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE +* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, +* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, +* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, +* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, +* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE +* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGES. Because some jurisdictions prohibit the exclusion or +* limitation of liability for consequential or incidental damages, the +* above limitation may not apply to you. +* +* Copyright 2003 Micron Technology, Inc. All rights reserved. +* +* Rev Author Date Changes +* --------------------------------------------------------------------------------------- +* 1.00 SPH 09/18/09 Fixed cb connection in ECC mode +* Added invalid ECC mode error message in x16 configuration +****************************************************************************************/ + `timescale 1ps / 1ps + +module ddr2_module ( +`ifdef SODIMM +`else + reset_n, + cb , +`endif + ck , + ck_n , + cke , + s_n , + ras_n , + cas_n , + we_n , + ba , + addr , + odt , + dqs , + dqs_n , + dq , + scl , + sa , + sda +); + +`include "ddr2_parameters.vh" + + input [1:0] cke ; + input ras_n ; + input cas_n ; + input we_n ; + input [2:0] ba ; + input [15:0] addr ; + input [1:0] odt ; + inout [17:0] dqs ; + inout [17:0] dqs_n ; + inout [63:0] dq ; + input scl ; // no connect + inout sda ; // no connect + +`ifdef QUAD_RANK + initial if (DEBUG) $display("%m: Quad Rank"); +`else `ifdef DUAL_RANK + initial if (DEBUG) $display("%m: Dual Rank"); +`else + initial if (DEBUG) $display("%m: Single Rank"); +`endif `endif + +`ifdef ECC + initial if (DEBUG) $display("%m: ECC"); + `ifdef SODIMM + initial begin + $display("%m ERROR: ECC is not available on SODIMM configurations"); + if (STOP_ON_ERROR) $stop(0); + end + `endif + `ifdef x16 + initial begin + $display("%m ERROR: ECC is not available on x16 configurations"); + if (STOP_ON_ERROR) $stop(0); + end + `endif +`else + initial if (DEBUG) $display("%m: non ECC"); +`endif + +`ifdef RDIMM + initial if (DEBUG) $display("%m: RDIMM"); + input reset_n; + input ck ; + input ck_n ; + input [3:0] s_n ; + inout [7:0] cb ; + input [2:0] sa ; // no connect + + wire [5:0] rck = {6{ck}}; + wire [5:0] rck_n = {6{ck_n}}; + reg [3:0] rs_n ; + reg rras_n ; + reg rcas_n ; + reg rwe_n ; + reg [2:0] rba ; + reg [15:0] raddr ; + reg [3:0] rcke ; + reg [3:0] rodt ; + + always @(negedge reset_n or posedge ck) begin + if (!reset_n) begin + rs_n <= #(500) 0; + rras_n <= #(500) 0; + rcas_n <= #(500) 0; + rwe_n <= #(500) 0; + rba <= #(500) 0; + raddr <= #(500) 0; + rcke <= #(500) 0; + rodt <= #(500) 0; + end else begin + rs_n <= #(500) s_n ; + rras_n <= #(500) ras_n; + rcas_n <= #(500) cas_n; + rwe_n <= #(500) we_n ; + rba <= #(500) ba ; + raddr <= #(500) addr ; + `ifdef QUAD_RANK + rcke <= #(500) {{2{cke[1]}}, {2{cke[0]}}}; + rodt <= #(500) {{2{odt[1]}}, {2{odt[0]}}}; + `else + rcke <= #(500) {2'b00, cke}; + rodt <= #(500) {2'b00, odt}; + `endif + + end + end +`else + `ifdef SODIMM + initial if (DEBUG) $display("%m: SODIMM"); + input [1:0] ck ; + input [1:0] ck_n ; + input [1:0] s_n ; + input [1:0] sa ; // no connect + + wire [7:0] cb; + wire [5:0] rck = {{3{ck[1]}}, {3{ck[0]}}}; + wire [5:0] rck_n = {{3{ck_n[1]}}, {3{ck_n[0]}}}; + `else + initial if (DEBUG) $display("%m: UDIMM"); + input reset_n; + input [2:0] ck ; + input [2:0] ck_n ; + input [1:0] s_n ; + inout [7:0] cb ; + input [2:0] sa ; // no connect + + wire [5:0] rck = {2{ck}}; + wire [5:0] rck_n = {2{ck_n}}; + `endif + + wire [2:0] rba = ba ; + wire [15:0] raddr = addr ; + wire rras_n = ras_n; + wire rcas_n = cas_n; + wire rwe_n = we_n ; + `ifdef QUAD_RANK + wire [3:0] rs_n = {{2{s_n[1]}}, {2{s_n[0]}}}; + wire [3:0] rcke = {{2{cke[1]}}, {2{cke[0]}}}; + wire [3:0] rodt = {{2{odt[1]}}, {2{odt[0]}}}; + `else + wire [3:0] rs_n = {2'b00, s_n}; + wire [3:0] rcke = {2'b00, cke}; + wire [3:0] rodt = {2'b00, odt}; + `endif +`endif + wire [15:0] rcb = {8'b0, cb}; + wire zero = 1'b0; + wire one = 1'b1; + + //ddr2 (ck , ck_n , cke , cs_n , ras_n , cas_n , we_n , dm_rdqs , ba , addr , dq , dqs , dqs_n , rdqs_n , odt ); +`ifdef x4 + initial if (DEBUG) $display("%m: Component Width = x4"); + ddr2 U1R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [ 3: 0], dqs[ 0] , dqs_n[ 0], , rodt[0]); + ddr2 U2R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [11: 8], dqs[ 1] , dqs_n[ 1], , rodt[0]); + ddr2 U3R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [19:16], dqs[ 2] , dqs_n[ 2], , rodt[0]); + ddr2 U4R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [27:24], dqs[ 3] , dqs_n[ 3], , rodt[0]); + ddr2 U6R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [35:32], dqs[ 4] , dqs_n[ 4], , rodt[0]); + ddr2 U7R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [43:40], dqs[ 5] , dqs_n[ 5], , rodt[0]); + ddr2 U8R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [51:48], dqs[ 6] , dqs_n[ 6], , rodt[0]); + ddr2 U9R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [59:56], dqs[ 7] , dqs_n[ 7], , rodt[0]); + `ifdef ECC + ddr2 U5R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], cb [ 3: 0], dqs[ 8] , dqs_n[ 8], , rodt[0]); + `endif + ddr2 U18R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [ 7: 4], dqs[ 9] , dqs_n[ 9], , rodt[0]); + ddr2 U17R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [15:12], dqs[ 10] , dqs_n[ 10], , rodt[0]); + ddr2 U16R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [23:20], dqs[ 11] , dqs_n[ 11], , rodt[0]); + ddr2 U15R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [31:28], dqs[ 12] , dqs_n[ 12], , rodt[0]); + ddr2 U13R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [39:36], dqs[ 13] , dqs_n[ 13], , rodt[0]); + ddr2 U12R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [47:44], dqs[ 14] , dqs_n[ 14], , rodt[0]); + ddr2 U11R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [55:52], dqs[ 15] , dqs_n[ 15], , rodt[0]); + ddr2 U10R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [63:60], dqs[ 16] , dqs_n[ 16], , rodt[0]); + `ifdef ECC + ddr2 U14R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], cb [ 7: 4], dqs[ 17] , dqs_n[ 17], , rodt[0]); + `endif + `ifdef DUAL_RANK + ddr2 U1R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [ 3: 0], dqs[ 0] , dqs_n[ 0], , rodt[1]); + ddr2 U2R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [11: 8], dqs[ 1] , dqs_n[ 1], , rodt[1]); + ddr2 U3R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [19:16], dqs[ 2] , dqs_n[ 2], , rodt[1]); + ddr2 U4R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [27:24], dqs[ 3] , dqs_n[ 3], , rodt[1]); + ddr2 U6R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [35:32], dqs[ 4] , dqs_n[ 4], , rodt[1]); + ddr2 U7R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [43:40], dqs[ 5] , dqs_n[ 5], , rodt[1]); + ddr2 U8R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [51:48], dqs[ 6] , dqs_n[ 6], , rodt[1]); + ddr2 U9R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [59:56], dqs[ 7] , dqs_n[ 7], , rodt[1]); + `ifdef ECC + ddr2 U5R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], cb [ 3: 0], dqs[ 8] , dqs_n[ 8], , rodt[1]); + `endif + ddr2 U18R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [ 7: 4], dqs[ 9] , dqs_n[ 9], , rodt[1]); + ddr2 U17R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [15:12], dqs[ 10] , dqs_n[ 10], , rodt[1]); + ddr2 U16R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [23:20], dqs[ 11] , dqs_n[ 11], , rodt[1]); + ddr2 U15R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [31:28], dqs[ 12] , dqs_n[ 12], , rodt[1]); + ddr2 U13R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [39:36], dqs[ 13] , dqs_n[ 13], , rodt[1]); + ddr2 U12R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [47:44], dqs[ 14] , dqs_n[ 14], , rodt[1]); + ddr2 U11R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [55:52], dqs[ 15] , dqs_n[ 15], , rodt[1]); + ddr2 U10R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [63:60], dqs[ 16] , dqs_n[ 16], , rodt[1]); + `ifdef ECC + ddr2 U14R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], cb [ 7: 4], dqs[ 17] , dqs_n[ 17], , rodt[1]); + `endif + `endif + `ifdef QUAD_RANK + ddr2 U1R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [ 3: 0], dqs[ 0] , dqs_n[ 0], , rodt[2]); + ddr2 U2R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [11: 8], dqs[ 1] , dqs_n[ 1], , rodt[2]); + ddr2 U3R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [19:16], dqs[ 2] , dqs_n[ 2], , rodt[2]); + ddr2 U4R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [27:24], dqs[ 3] , dqs_n[ 3], , rodt[2]); + ddr2 U6R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [35:32], dqs[ 4] , dqs_n[ 4], , rodt[2]); + ddr2 U7R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [43:40], dqs[ 5] , dqs_n[ 5], , rodt[2]); + ddr2 U8R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [51:48], dqs[ 6] , dqs_n[ 6], , rodt[2]); + ddr2 U9R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [59:56], dqs[ 7] , dqs_n[ 7], , rodt[2]); + `ifdef ECC + ddr2 U5R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], cb [ 3: 0], dqs[ 8] , dqs_n[ 8], , rodt[2]); + `endif + ddr2 U18R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [ 7: 4], dqs[ 9] , dqs_n[ 9], , rodt[2]); + ddr2 U17R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [15:12], dqs[ 10] , dqs_n[ 10], , rodt[2]); + ddr2 U16R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [23:20], dqs[ 11] , dqs_n[ 11], , rodt[2]); + ddr2 U15R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [31:28], dqs[ 12] , dqs_n[ 12], , rodt[2]); + ddr2 U13R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [39:36], dqs[ 13] , dqs_n[ 13], , rodt[2]); + ddr2 U12R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [47:44], dqs[ 14] , dqs_n[ 14], , rodt[2]); + ddr2 U11R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [55:52], dqs[ 15] , dqs_n[ 15], , rodt[2]); + ddr2 U10R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [63:60], dqs[ 16] , dqs_n[ 16], , rodt[2]); + `ifdef ECC + ddr2 U14R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], cb [ 7: 4], dqs[ 17] , dqs_n[ 17], , rodt[2]); + `endif + ddr2 U1R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [ 3: 0], dqs[ 0] , dqs_n[ 0], , rodt[3]); + ddr2 U2R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [11: 8], dqs[ 1] , dqs_n[ 1], , rodt[3]); + ddr2 U3R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [19:16], dqs[ 2] , dqs_n[ 2], , rodt[3]); + ddr2 U4R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [27:24], dqs[ 3] , dqs_n[ 3], , rodt[3]); + ddr2 U6R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [35:32], dqs[ 4] , dqs_n[ 4], , rodt[3]); + ddr2 U7R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [43:40], dqs[ 5] , dqs_n[ 5], , rodt[3]); + ddr2 U8R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [51:48], dqs[ 6] , dqs_n[ 6], , rodt[3]); + ddr2 U9R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [59:56], dqs[ 7] , dqs_n[ 7], , rodt[3]); + `ifdef ECC + ddr2 U5R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], cb [ 3: 0], dqs[ 8] , dqs_n[ 8], , rodt[3]); + `endif + ddr2 U18R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [ 7: 4], dqs[ 9] , dqs_n[ 9], , rodt[3]); + ddr2 U17R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [15:12], dqs[ 10] , dqs_n[ 10], , rodt[3]); + ddr2 U16R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [23:20], dqs[ 11] , dqs_n[ 11], , rodt[3]); + ddr2 U15R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [31:28], dqs[ 12] , dqs_n[ 12], , rodt[3]); + ddr2 U13R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [39:36], dqs[ 13] , dqs_n[ 13], , rodt[3]); + ddr2 U12R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [47:44], dqs[ 14] , dqs_n[ 14], , rodt[3]); + ddr2 U11R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [55:52], dqs[ 15] , dqs_n[ 15], , rodt[3]); + ddr2 U10R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], dq [63:60], dqs[ 16] , dqs_n[ 16], , rodt[3]); + `ifdef ECC + ddr2 U14R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, zero , rba, raddr[ADDR_BITS-1:0], cb [ 7: 4], dqs[ 17] , dqs_n[ 17], , rodt[3]); + `endif + `endif +`else `ifdef x8 + initial if (DEBUG) $display("%m: Component Width = x8"); + ddr2 U1R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[ 9] , rba, raddr[ADDR_BITS-1:0], dq [ 7: 0], dqs[ 0] , dqs_n[ 0], dqs_n[ 9], rodt[0]); + ddr2 U2R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[10] , rba, raddr[ADDR_BITS-1:0], dq [15: 8], dqs[ 1] , dqs_n[ 1], dqs_n[10], rodt[0]); + ddr2 U3R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[11] , rba, raddr[ADDR_BITS-1:0], dq [23:16], dqs[ 2] , dqs_n[ 2], dqs_n[11], rodt[0]); + ddr2 U4R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[12] , rba, raddr[ADDR_BITS-1:0], dq [31:24], dqs[ 3] , dqs_n[ 3], dqs_n[12], rodt[0]); + ddr2 U6R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[13] , rba, raddr[ADDR_BITS-1:0], dq [39:32], dqs[ 4] , dqs_n[ 4], dqs_n[13], rodt[0]); + ddr2 U7R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[14] , rba, raddr[ADDR_BITS-1:0], dq [47:40], dqs[ 5] , dqs_n[ 5], dqs_n[14], rodt[0]); + ddr2 U8R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[15] , rba, raddr[ADDR_BITS-1:0], dq [55:48], dqs[ 6] , dqs_n[ 6], dqs_n[15], rodt[0]); + ddr2 U9R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[16] , rba, raddr[ADDR_BITS-1:0], dq [63:56], dqs[ 7] , dqs_n[ 7], dqs_n[16], rodt[0]); + `ifdef ECC + ddr2 U5R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[17] , rba, raddr[ADDR_BITS-1:0], cb [ 7: 0], dqs[ 8] , dqs_n[ 8], dqs_n[17], rodt[0]); + `endif + `ifdef DUAL_RANK + ddr2 U1R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[ 9] , rba, raddr[ADDR_BITS-1:0], dq [ 7: 0], dqs[ 0] , dqs_n[ 0], dqs_n[ 9], rodt[1]); + ddr2 U2R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[10] , rba, raddr[ADDR_BITS-1:0], dq [15: 8], dqs[ 1] , dqs_n[ 1], dqs_n[10], rodt[1]); + ddr2 U3R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[11] , rba, raddr[ADDR_BITS-1:0], dq [23:16], dqs[ 2] , dqs_n[ 2], dqs_n[11], rodt[1]); + ddr2 U4R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[12] , rba, raddr[ADDR_BITS-1:0], dq [31:24], dqs[ 3] , dqs_n[ 3], dqs_n[12], rodt[1]); + ddr2 U6R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[13] , rba, raddr[ADDR_BITS-1:0], dq [39:32], dqs[ 4] , dqs_n[ 4], dqs_n[13], rodt[1]); + ddr2 U7R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[14] , rba, raddr[ADDR_BITS-1:0], dq [47:40], dqs[ 5] , dqs_n[ 5], dqs_n[14], rodt[1]); + ddr2 U8R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[15] , rba, raddr[ADDR_BITS-1:0], dq [55:48], dqs[ 6] , dqs_n[ 6], dqs_n[15], rodt[1]); + ddr2 U9R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[16] , rba, raddr[ADDR_BITS-1:0], dq [63:56], dqs[ 7] , dqs_n[ 7], dqs_n[16], rodt[1]); + `ifdef ECC + ddr2 U5R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[17] , rba, raddr[ADDR_BITS-1:0], cb [ 7: 0], dqs[ 8] , dqs_n[ 8], dqs_n[17], rodt[1]); + `endif + `endif + `ifdef QUAD_RANK + ddr2 U1R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[ 9] , rba, raddr[ADDR_BITS-1:0], dq [ 7: 0], dqs[ 0] , dqs_n[ 0], dqs_n[ 9], rodt[2]); + ddr2 U2R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[10] , rba, raddr[ADDR_BITS-1:0], dq [15: 8], dqs[ 1] , dqs_n[ 1], dqs_n[10], rodt[2]); + ddr2 U3R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[11] , rba, raddr[ADDR_BITS-1:0], dq [23:16], dqs[ 2] , dqs_n[ 2], dqs_n[11], rodt[2]); + ddr2 U4R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[12] , rba, raddr[ADDR_BITS-1:0], dq [31:24], dqs[ 3] , dqs_n[ 3], dqs_n[12], rodt[2]); + ddr2 U6R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[13] , rba, raddr[ADDR_BITS-1:0], dq [39:32], dqs[ 4] , dqs_n[ 4], dqs_n[13], rodt[2]); + ddr2 U7R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[14] , rba, raddr[ADDR_BITS-1:0], dq [47:40], dqs[ 5] , dqs_n[ 5], dqs_n[14], rodt[2]); + ddr2 U8R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[15] , rba, raddr[ADDR_BITS-1:0], dq [55:48], dqs[ 6] , dqs_n[ 6], dqs_n[15], rodt[2]); + ddr2 U9R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[16] , rba, raddr[ADDR_BITS-1:0], dq [63:56], dqs[ 7] , dqs_n[ 7], dqs_n[16], rodt[2]); + `ifdef ECC + ddr2 U5R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[17] , rba, raddr[ADDR_BITS-1:0], cb [ 7: 0], dqs[ 8] , dqs_n[ 8], dqs_n[17], rodt[2]); + `endif + ddr2 U1R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[ 9] , rba, raddr[ADDR_BITS-1:0], dq [ 7: 0], dqs[ 0] , dqs_n[ 0], dqs_n[ 9], rodt[3]); + ddr2 U2R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[10] , rba, raddr[ADDR_BITS-1:0], dq [15: 8], dqs[ 1] , dqs_n[ 1], dqs_n[10], rodt[3]); + ddr2 U3R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[11] , rba, raddr[ADDR_BITS-1:0], dq [23:16], dqs[ 2] , dqs_n[ 2], dqs_n[11], rodt[3]); + ddr2 U4R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[12] , rba, raddr[ADDR_BITS-1:0], dq [31:24], dqs[ 3] , dqs_n[ 3], dqs_n[12], rodt[3]); + ddr2 U6R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[13] , rba, raddr[ADDR_BITS-1:0], dq [39:32], dqs[ 4] , dqs_n[ 4], dqs_n[13], rodt[3]); + ddr2 U7R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[14] , rba, raddr[ADDR_BITS-1:0], dq [47:40], dqs[ 5] , dqs_n[ 5], dqs_n[14], rodt[3]); + ddr2 U8R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[15] , rba, raddr[ADDR_BITS-1:0], dq [55:48], dqs[ 6] , dqs_n[ 6], dqs_n[15], rodt[3]); + ddr2 U9R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[16] , rba, raddr[ADDR_BITS-1:0], dq [63:56], dqs[ 7] , dqs_n[ 7], dqs_n[16], rodt[3]); + `ifdef ECC + ddr2 U5R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[17] , rba, raddr[ADDR_BITS-1:0], cb [ 7: 0], dqs[ 8] , dqs_n[ 8], dqs_n[17], rodt[3]); + `endif + `endif +`else `ifdef x16 + initial if (DEBUG) $display("%m: Component Width = x16"); + ddr2 U1R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[10: 9] , rba, raddr[ADDR_BITS-1:0], dq [15: 0], dqs[1:0] , dqs_n[1:0], , rodt[0]); + ddr2 U2R0 (rck[1], rck_n[1], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[12:11] , rba, raddr[ADDR_BITS-1:0], dq [31:16], dqs[3:2] , dqs_n[3:2], , rodt[0]); + ddr2 U4R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[14:13] , rba, raddr[ADDR_BITS-1:0], dq [47:32], dqs[5:4] , dqs_n[5:4], , rodt[0]); + ddr2 U5R0 (rck[2], rck_n[2], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, dqs[16:15] , rba, raddr[ADDR_BITS-1:0], dq [63:48], dqs[7:6] , dqs_n[7:6], , rodt[0]); + `ifdef ECC + ddr2 U3R0 (rck[0], rck_n[0], rcke[0], rs_n[0], rras_n, rcas_n, rwe_n, {one, dqs[17]}, rba, raddr[ADDR_BITS-1:0], rcb[15: 0], {zero, dqs[8]}, {one, dqs_n[8]}, , rodt[0]); + `endif + `ifdef DUAL_RANK + ddr2 U1R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[10: 9] , rba, raddr[ADDR_BITS-1:0], dq [15: 0], dqs[1:0] , dqs_n[1:0], , rodt[1]); + ddr2 U2R1 (rck[4], rck_n[4], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[12:11] , rba, raddr[ADDR_BITS-1:0], dq [31:16], dqs[3:2] , dqs_n[3:2], , rodt[1]); + ddr2 U4R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[14:13] , rba, raddr[ADDR_BITS-1:0], dq [47:32], dqs[5:4] , dqs_n[5:4], , rodt[1]); + ddr2 U5R1 (rck[5], rck_n[5], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, dqs[16:15] , rba, raddr[ADDR_BITS-1:0], dq [63:48], dqs[7:6] , dqs_n[7:6], , rodt[1]); + `ifdef ECC + ddr2 U3R1 (rck[3], rck_n[3], rcke[1], rs_n[1], rras_n, rcas_n, rwe_n, {one, dqs[17]}, rba, raddr[ADDR_BITS-1:0], rcb[15: 0], {zero, dqs[8]}, {one, dqs_n[8]}, , rodt[1]); + `endif + `endif + `ifdef QUAD_RANK + ddr2 U1R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[10: 9] , rba, raddr[ADDR_BITS-1:0], dq [15: 0], dqs[1:0] , dqs_n[1:0], , rodt[2]); + ddr2 U2R2 (rck[1], rck_n[1], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[12:11] , rba, raddr[ADDR_BITS-1:0], dq [31:16], dqs[3:2] , dqs_n[3:2], , rodt[2]); + ddr2 U4R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[14:13] , rba, raddr[ADDR_BITS-1:0], dq [47:32], dqs[5:4] , dqs_n[5:4], , rodt[2]); + ddr2 U5R2 (rck[2], rck_n[2], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, dqs[16:15] , rba, raddr[ADDR_BITS-1:0], dq [63:48], dqs[7:6] , dqs_n[7:6], , rodt[2]); + `ifdef ECC + ddr2 U3R2 (rck[0], rck_n[0], rcke[2], rs_n[2], rras_n, rcas_n, rwe_n, {one, dqs[17]}, rba, raddr[ADDR_BITS-1:0], rcb[15: 0], {zero, dqs[8]}, {one, dqs_n[8]}, , rodt[2]); + `endif + ddr2 U1R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[10: 9] , rba, raddr[ADDR_BITS-1:0], dq [15: 0], dqs[1:0] , dqs_n[1:0], , rodt[3]); + ddr2 U2R3 (rck[4], rck_n[4], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[12:11] , rba, raddr[ADDR_BITS-1:0], dq [31:16], dqs[3:2] , dqs_n[3:2], , rodt[3]); + ddr2 U4R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[14:13] , rba, raddr[ADDR_BITS-1:0], dq [47:32], dqs[5:4] , dqs_n[5:4], , rodt[3]); + ddr2 U5R3 (rck[5], rck_n[5], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, dqs[16:15] , rba, raddr[ADDR_BITS-1:0], dq [63:48], dqs[7:6] , dqs_n[7:6], , rodt[3]); + `ifdef ECC + ddr2 U3R3 (rck[3], rck_n[3], rcke[3], rs_n[3], rras_n, rcas_n, rwe_n, {one, dqs[17]}, rba, raddr[ADDR_BITS-1:0], rcb[15: 0], {zero, dqs[8]}, {one, dqs_n[8]}, , rodt[3]); + `endif + `endif +`endif `endif `endif + +endmodule diff --git a/sim/verilog/micron_2048Mb_ddr2/ddr2_parameters.vh b/sim/verilog/micron_2048Mb_ddr2/ddr2_parameters.vh new file mode 100644 index 0000000..4e4d866 --- /dev/null +++ b/sim/verilog/micron_2048Mb_ddr2/ddr2_parameters.vh @@ -0,0 +1,383 @@ +/**************************************************************************************** +* +* Disclaimer This software code and all associated documentation, comments or other +* of Warranty: information (collectively "Software") is provided "AS IS" without +* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY +* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES +* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT +* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE +* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. +* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR +* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE +* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, +* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, +* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, +* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, +* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE +* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGES. Because some jurisdictions prohibit the exclusion or +* limitation of liability for consequential or incidental damages, the +* above limitation may not apply to you. +* +* Copyright 2003 Micron Technology, Inc. All rights reserved. +* +****************************************************************************************/ + + // Parameters current with 2Gb datasheet rev B + + // Timing parameters based on Speed Grade + + // SYMBOL UNITS DESCRIPTION + // ------ ----- ----------- +`ifdef sg187E + parameter TCK_MIN = 1875; // tCK ps Minimum Clock Cycle Time + parameter TJIT_PER = 90; // tJIT(per) ps Period JItter + parameter TJIT_DUTY = 75; // tJIT(duty) ps Half Period Jitter + parameter TJIT_CC = 180; // tJIT(cc) ps Cycle to Cycle jitter + parameter TERR_2PER = 132; // tERR(nper) ps Accumulated Error (2-cycle) + parameter TERR_3PER = 157; // tERR(nper) ps Accumulated Error (3-cycle) + parameter TERR_4PER = 175; // tERR(nper) ps Accumulated Error (4-cycle) + parameter TERR_5PER = 188; // tERR(nper) ps Accumulated Error (5-cycle) + parameter TERR_N1PER = 250; // tERR(nper) ps Accumulated Error (6-10-cycle) + parameter TERR_N2PER = 425; // tERR(nper) ps Accumulated Error (11-50-cycle) + parameter TQHS = 250; // tQHS ps Data hold skew factor + parameter TAC = 350; // tAC ps DQ output access time from CK/CK# + parameter TDS = 0; // tDS ps DQ and DM input setup time relative to DQS + parameter TDH = 75; // tDH ps DQ and DM input hold time relative to DQS + parameter TDQSCK = 300; // tDQSCK ps DQS output access time from CK/CK# + parameter TDQSQ = 175; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access + parameter TIS = 125; // tIS ps Input Setup Time + parameter TIH = 200; // tIH ps Input Hold Time + parameter TRC = 54000; // tRC ps Active to Active/Auto Refresh command time + parameter TRCD = 13125; // tRCD ps Active to Read/Write command time + parameter TWTR = 7500; // tWTR ps Write to Read command delay + parameter TRP = 13125; // tRP ps Precharge command period + parameter TRPA = 15000; // tRPA ps Precharge All period + parameter TXARDS = 10; // tXARDS tCK Exit low power active power down to a read command + parameter TXARD = 3; // tXARD tCK Exit active power down to a read command + parameter TXP = 3; // tXP tCK Exit power down to a non-read command + parameter TANPD = 4; // tANPD tCK ODT to power-down entry latency + parameter TAXPD = 11; // tAXPD tCK ODT power-down exit latency + parameter CL_TIME = 13125; // CL ps Minimum CAS Latency +`else `ifdef sg25E + parameter TCK_MIN = 2500; // tCK ps Minimum Clock Cycle Time + parameter TJIT_PER = 100; // tJIT(per) ps Period JItter + parameter TJIT_DUTY = 100; // tJIT(duty) ps Half Period Jitter + parameter TJIT_CC = 200; // tJIT(cc) ps Cycle to Cycle jitter + parameter TERR_2PER = 150; // tERR(nper) ps Accumulated Error (2-cycle) + parameter TERR_3PER = 175; // tERR(nper) ps Accumulated Error (3-cycle) + parameter TERR_4PER = 200; // tERR(nper) ps Accumulated Error (4-cycle) + parameter TERR_5PER = 200; // tERR(nper) ps Accumulated Error (5-cycle) + parameter TERR_N1PER = 300; // tERR(nper) ps Accumulated Error (6-10-cycle) + parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) + parameter TQHS = 300; // tQHS ps Data hold skew factor + parameter TAC = 400; // tAC ps DQ output access time from CK/CK# + parameter TDS = 50; // tDS ps DQ and DM input setup time relative to DQS + parameter TDH = 125; // tDH ps DQ and DM input hold time relative to DQS + parameter TDQSCK = 350; // tDQSCK ps DQS output access time from CK/CK# + parameter TDQSQ = 200; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access + parameter TIS = 175; // tIS ps Input Setup Time + parameter TIH = 250; // tIH ps Input Hold Time + parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time + parameter TRCD = 12500; // tRCD ps Active to Read/Write command time + parameter TWTR = 7500; // tWTR ps Write to Read command delay + parameter TRP = 12500; // tRP ps Precharge command period + parameter TRPA = 15000; // tRPA ps Precharge All period + parameter TXARDS = 8; // tXARDS tCK Exit low power active power down to a read command + parameter TXARD = 2; // tXARD tCK Exit active power down to a read command + parameter TXP = 2; // tXP tCK Exit power down to a non-read command + parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency + parameter TAXPD = 10; // tAXPD tCK ODT power-down exit latency + parameter CL_TIME = 12500; // CL ps Minimum CAS Latency +`else `ifdef sg25 + parameter TCK_MIN = 2500; // tCK ps Minimum Clock Cycle Time + parameter TJIT_PER = 100; // tJIT(per) ps Period JItter + parameter TJIT_DUTY = 100; // tJIT(duty) ps Half Period Jitter + parameter TJIT_CC = 200; // tJIT(cc) ps Cycle to Cycle jitter + parameter TERR_2PER = 150; // tERR(nper) ps Accumulated Error (2-cycle) + parameter TERR_3PER = 175; // tERR(nper) ps Accumulated Error (3-cycle) + parameter TERR_4PER = 200; // tERR(nper) ps Accumulated Error (4-cycle) + parameter TERR_5PER = 200; // tERR(nper) ps Accumulated Error (5-cycle) + parameter TERR_N1PER = 300; // tERR(nper) ps Accumulated Error (6-10-cycle) + parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) + parameter TQHS = 300; // tQHS ps Data hold skew factor + parameter TAC = 400; // tAC ps DQ output access time from CK/CK# + parameter TDS = 50; // tDS ps DQ and DM input setup time relative to DQS + parameter TDH = 125; // tDH ps DQ and DM input hold time relative to DQS + parameter TDQSCK = 350; // tDQSCK ps DQS output access time from CK/CK# + parameter TDQSQ = 200; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access + parameter TIS = 175; // tIS ps Input Setup Time + parameter TIH = 250; // tIH ps Input Hold Time + parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time + parameter TRCD = 15000; // tRCD ps Active to Read/Write command time + parameter TWTR = 7500; // tWTR ps Write to Read command delay + parameter TRP = 15000; // tRP ps Precharge command period + parameter TRPA = 17500; // tRPA ps Precharge All period + parameter TXARDS = 8; // tXARDS tCK Exit low power active power down to a read command + parameter TXARD = 2; // tXARD tCK Exit active power down to a read command + parameter TXP = 2; // tXP tCK Exit power down to a non-read command + parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency + parameter TAXPD = 10; // tAXPD tCK ODT power-down exit latency + parameter CL_TIME = 15000; // CL ps Minimum CAS Latency +`else `ifdef sg3E + parameter TCK_MIN = 3000; // tCK ps Minimum Clock Cycle Time + parameter TJIT_PER = 125; // tJIT(per) ps Period JItter + parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter + parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter + parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle) + parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle) + parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle) + parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle) + parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle) + parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) + parameter TQHS = 340; // tQHS ps Data hold skew factor + parameter TAC = 450; // tAC ps DQ output access time from CK/CK# + parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS + parameter TDH = 175; // tDH ps DQ and DM input hold time relative to DQS + parameter TDQSCK = 400; // tDQSCK ps DQS output access time from CK/CK# + parameter TDQSQ = 240; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access + parameter TIS = 200; // tIS ps Input Setup Time + parameter TIH = 275; // tIH ps Input Hold Time + parameter TRC = 54000; // tRC ps Active to Active/Auto Refresh command time + parameter TRCD = 12000; // tRCD ps Active to Read/Write command time + parameter TWTR = 7500; // tWTR ps Write to Read command delay + parameter TRP = 12000; // tRP ps Precharge command period + parameter TRPA = 15000; // tRPA ps Precharge All period + parameter TXARDS = 7; // tXARDS tCK Exit low power active power down to a read command + parameter TXARD = 2; // tXARD tCK Exit active power down to a read command + parameter TXP = 2; // tXP tCK Exit power down to a non-read command + parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency + parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency + parameter CL_TIME = 12000; // CL ps Minimum CAS Latency +`else `ifdef sg3 + parameter TCK_MIN = 3000; // tCK ps Minimum Clock Cycle Time + parameter TJIT_PER = 125; // tJIT(per) ps Period JItter + parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter + parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter + parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle) + parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle) + parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle) + parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle) + parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle) + parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) + parameter TQHS = 340; // tQHS ps Data hold skew factor + parameter TAC = 450; // tAC ps DQ output access time from CK/CK# + parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS + parameter TDH = 175; // tDH ps DQ and DM input hold time relative to DQS + parameter TDQSCK = 400; // tDQSCK ps DQS output access time from CK/CK# + parameter TDQSQ = 240; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access + parameter TIS = 200; // tIS ps Input Setup Time + parameter TIH = 275; // tIH ps Input Hold Time + parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time + parameter TRCD = 15000; // tRCD ps Active to Read/Write command time + parameter TWTR = 7500; // tWTR ps Write to Read command delay + parameter TRP = 15000; // tRP ps Precharge command period + parameter TRPA = 18000; // tRPA ps Precharge All period + parameter TXARDS = 7; // tXARDS tCK Exit low power active power down to a read command + parameter TXARD = 2; // tXARD tCK Exit active power down to a read command + parameter TXP = 2; // tXP tCK Exit power down to a non-read command + parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency + parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency + parameter CL_TIME = 15000; // CL ps Minimum CAS Latency +`else `ifdef sg37E + parameter TCK_MIN = 3750; // tCK ps Minimum Clock Cycle Time + parameter TJIT_PER = 125; // tJIT(per) ps Period JItter + parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter + parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter + parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle) + parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle) + parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle) + parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle) + parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle) + parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) + parameter TQHS = 400; // tQHS ps Data hold skew factor + parameter TAC = 500; // tAC ps DQ output access time from CK/CK# + parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS + parameter TDH = 225; // tDH ps DQ and DM input hold time relative to DQS + parameter TDQSCK = 450; // tDQSCK ps DQS output access time from CK/CK# + parameter TDQSQ = 300; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access + parameter TIS = 250; // tIS ps Input Setup Time + parameter TIH = 375; // tIH ps Input Hold Time + parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time + parameter TRCD = 15000; // tRCD ps Active to Read/Write command time + parameter TWTR = 7500; // tWTR ps Write to Read command delay + parameter TRP = 15000; // tRP ps Precharge command period + parameter TRPA = 18750; // tRPA ps Precharge All period + parameter TXARDS = 6; // tXARDS tCK Exit low power active power down to a read command + parameter TXARD = 2; // tXARD tCK Exit active power down to a read command + parameter TXP = 2; // tXP tCK Exit power down to a non-read command + parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency + parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency + parameter CL_TIME = 15000; // CL ps Minimum CAS Latency +`else `define sg5E + parameter TCK_MIN = 5000; // tCK ps Minimum Clock Cycle Time + parameter TJIT_PER = 125; // tJIT(per) ps Period JItter + parameter TJIT_DUTY = 150; // tJIT(duty) ps Half Period Jitter + parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter + parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle) + parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle) + parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle) + parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle) + parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle) + parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) + parameter TQHS = 450; // tQHS ps Data hold skew factor + parameter TAC = 600; // tAC ps DQ output access time from CK/CK# + parameter TDS = 150; // tDS ps DQ and DM input setup time relative to DQS + parameter TDH = 275; // tDH ps DQ and DM input hold time relative to DQS + parameter TDQSCK = 500; // tDQSCK ps DQS output access time from CK/CK# + parameter TDQSQ = 350; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access + parameter TIS = 350; // tIS ps Input Setup Time + parameter TIH = 475; // tIH ps Input Hold Time + parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time + parameter TRCD = 15000; // tRCD ps Active to Read/Write command time + parameter TWTR = 10000; // tWTR ps Write to Read command delay + parameter TRP = 15000; // tRP ps Precharge command period + parameter TRPA = 20000; // tRPA ps Precharge All period + parameter TXARDS = 6; // tXARDS tCK Exit low power active power down to a read command + parameter TXARD = 2; // tXARD tCK Exit active power down to a read command + parameter TXP = 2; // tXP tCK Exit power down to a non-read command + parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency + parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency + parameter CL_TIME = 15000; // CL ps Minimum CAS Latency +`endif `endif `endif `endif `endif `endif + +`ifdef x16 + `ifdef sg187E + parameter TFAW = 45000; // tFAW ps Four Bank Activate window + `else `ifdef sg25E + parameter TFAW = 45000; // tFAW ps Four Bank Activate window + `else `ifdef sg25 + parameter TFAW = 45000; // tFAW ps Four Bank Activate window + `else // sg3E, sg3, sg37E, sg5E + parameter TFAW = 50000; // tFAW ps Four Bank Activate window + `endif `endif `endif +`else // x4, x8 + `ifdef sg187E + parameter TFAW = 35000; // tFAW ps Four Bank Activate window + `else `ifdef sg25E + parameter TFAW = 35000; // tFAW ps Four Bank Activate window + `else `ifdef sg25 + parameter TFAW = 35000; // tFAW ps Four Bank Activate window + `else // sg3E, sg3, sg37E, sg5E + parameter TFAW = 37500; // tFAW ps Four Bank Activate window + `endif `endif `endif +`endif + + // Timing Parameters + + // Mode Register + parameter AL_MIN = 0; // AL tCK Minimum Additive Latency + parameter AL_MAX = 6; // AL tCK Maximum Additive Latency + parameter CL_MIN = 3; // CL tCK Minimum CAS Latency + parameter CL_MAX = 7; // CL tCK Maximum CAS Latency + parameter WR_MIN = 2; // WR tCK Minimum Write Recovery + parameter WR_MAX = 8; // WR tCK Maximum Write Recovery + parameter BL_MIN = 4; // BL tCK Minimum Burst Length + parameter BL_MAX = 8; // BL tCK Minimum Burst Length + // Clock + parameter TCK_MAX = 8000; // tCK ps Maximum Clock Cycle Time + parameter TCH_MIN = 0.48; // tCH tCK Minimum Clock High-Level Pulse Width + parameter TCH_MAX = 0.52; // tCH tCK Maximum Clock High-Level Pulse Width + parameter TCL_MIN = 0.48; // tCL tCK Minimum Clock Low-Level Pulse Width + parameter TCL_MAX = 0.52; // tCL tCK Maximum Clock Low-Level Pulse Width + // Data + parameter TLZ = TAC; // tLZ ps Data-out low-impedance window from CK/CK# + parameter THZ = TAC; // tHZ ps Data-out high impedance window from CK/CK# + parameter TDIPW = 0.35; // tDIPW tCK DQ and DM input Pulse Width + // Data Strobe + parameter TDQSH = 0.35; // tDQSH tCK DQS input High Pulse Width + parameter TDQSL = 0.35; // tDQSL tCK DQS input Low Pulse Width + parameter TDSS = 0.20; // tDSS tCK DQS falling edge to CLK rising (setup time) + parameter TDSH = 0.20; // tDSH tCK DQS falling edge from CLK rising (hold time) + parameter TWPRE = 0.35; // tWPRE tCK DQS Write Preamble + parameter TWPST = 0.40; // tWPST tCK DQS Write Postamble + parameter TDQSS = 0.25; // tDQSS tCK Rising clock edge to DQS/DQS# latching transition + // Command and Address + parameter TIPW = 0.6; // tIPW tCK Control and Address input Pulse Width + parameter TCCD = 2; // tCCD tCK Cas to Cas command delay + parameter TRAS_MIN = 40000; // tRAS ps Minimum Active to Precharge command time + parameter TRAS_MAX =70000000; // tRAS ps Maximum Active to Precharge command time + parameter TRTP = 7500; // tRTP ps Read to Precharge command delay + parameter TWR = 15000; // tWR ps Write recovery time + parameter TMRD = 2; // tMRD tCK Load Mode Register command cycle time + parameter TDLLK = 200; // tDLLK tCK DLL locking time + // Refresh + parameter TRFC_MIN = 197500; // tRFC ps Refresh to Refresh Command interval minimum value + parameter TRFC_MAX =70000000; // tRFC ps Refresh to Refresh Command Interval maximum value + // Self Refresh + parameter TXSNR = TRFC_MIN + 10000; // tXSNR ps Exit self refesh to a non-read command + parameter TXSRD = 200; // tXSRD tCK Exit self refresh to a read command + parameter TISXR = TIS; // tISXR ps CKE setup time during self refresh exit. + // ODT + parameter TAOND = 2; // tAOND tCK ODT turn-on delay + parameter TAOFD = 2.5; // tAOFD tCK ODT turn-off delay + parameter TAONPD = 2000; // tAONPD ps ODT turn-on (precharge power-down mode) + parameter TAOFPD = 2000; // tAOFPD ps ODT turn-off (precharge power-down mode) + parameter TMOD = 12000; // tMOD ps ODT enable in EMR to ODT pin transition + // Power Down + parameter TCKE = 3; // tCKE tCK CKE minimum high or low pulse width + + // Size Parameters based on Part Width + +`ifdef x4 + parameter ADDR_BITS = 15; // Address Bits + parameter ROW_BITS = 15; // Number of Address bits + parameter COL_BITS = 11; // Number of Column bits + parameter DM_BITS = 1; // Number of Data Mask bits + parameter DQ_BITS = 4; // Number of Data bits + parameter DQS_BITS = 1; // Number of Dqs bits + parameter TRRD = 7500; // tRRD Active bank a to Active bank b command time +`else `ifdef x8 + parameter ADDR_BITS = 15; // Address Bits + parameter ROW_BITS = 15; // Number of Address bits + parameter COL_BITS = 10; // Number of Column bits + parameter DM_BITS = 1; // Number of Data Mask bits + parameter DQ_BITS = 8; // Number of Data bits + parameter DQS_BITS = 1; // Number of Dqs bits + parameter TRRD = 7500; // tRRD Active bank a to Active bank b command time +`else `define x16 + parameter ADDR_BITS = 14; // Address Bits + parameter ROW_BITS = 14; // Number of Address bits + parameter COL_BITS = 10; // Number of Column bits + parameter DM_BITS = 2; // Number of Data Mask bits + parameter DQ_BITS = 16; // Number of Data bits + parameter DQS_BITS = 2; // Number of Dqs bits + parameter TRRD = 10000; // tRRD Active bank a to Active bank b command time +`endif `endif + +`ifdef QUAD_RANK + `define DUAL_RANK // also define DUAL_RANK + parameter CS_BITS = 4; // Number of Chip Select Bits + parameter RANKS = 4; // Number of Chip Select Bits +`else `ifdef DUAL_RANK + parameter CS_BITS = 2; // Number of Chip Select Bits + parameter RANKS = 2; // Number of Chip Select Bits +`else + parameter CS_BITS = 2; // Number of Chip Select Bits + parameter RANKS = 1; // Number of Chip Select Bits +`endif `endif + + // Size Parameters + parameter BA_BITS = 3; // Set this parmaeter to control how many Bank Address bits + parameter MEM_BITS = 10; // Number of write data bursts can be stored in memory. The default is 2^10=1024. + parameter AP = 10; // the address bit that controls auto-precharge and precharge-all + parameter BL_BITS = 3; // the number of bits required to count to MAX_BL + parameter BO_BITS = 2; // the number of Burst Order Bits + + // Simulation parameters + parameter STOP_ON_ERROR = 1; // If set to 1, the model will halt on command sequence/major errors + parameter DEBUG = 1; // Turn on Debug messages + parameter BUS_DELAY = 0; // delay in nanoseconds + parameter RANDOM_OUT_DELAY = 0; // If set to 1, the model will put a random amount of delay on DQ/DQS during reads + parameter RANDOM_SEED = 711689044; //seed value for random generator. + + parameter RDQSEN_PRE = 2; // DQS driving time prior to first read strobe + parameter RDQSEN_PST = 1; // DQS driving time after last read strobe + parameter RDQS_PRE = 2; // DQS low time prior to first read strobe + parameter RDQS_PST = 1; // DQS low time after last valid read strobe + parameter RDQEN_PRE = 0; // DQ/DM driving time prior to first read data + parameter RDQEN_PST = 0; // DQ/DM driving time after last read data + parameter WDQS_PRE = 1; // DQS half clock periods prior to first write strobe + parameter WDQS_PST = 1; // DQS half clock periods after last valid write strobe diff --git a/sim/verilog/micron_2048Mb_ddr2/readme.txt b/sim/verilog/micron_2048Mb_ddr2/readme.txt new file mode 100644 index 0000000..cc0507d --- /dev/null +++ b/sim/verilog/micron_2048Mb_ddr2/readme.txt @@ -0,0 +1,190 @@ +Disclaimer of Warranty: +----------------------- +This software code and all associated documentation, comments or other +information (collectively "Software") is provided "AS IS" without +warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY +DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES +OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT +WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE +OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. +FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR +THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE +OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, +ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, +INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, +WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, +OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE +THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. Because some jurisdictions prohibit the exclusion or +limitation of liability for consequential or incidental damages, the +above limitation may not apply to you. + +Copyright 2003 Micron Technology, Inc. All rights reserved. + +Getting Started: +---------------- +Unzip the included files to a folder. +Compile ddr2.v, ddr2_mcp.v, and tb.v using a verilog simulator. +Simulate the top level test bench tb. +Or, if you are using the ModelSim simulator, type "do tb.do" at the prompt. + +File Descriptions: +------------------ +ddr2.v -ddr2 model +ddr2_mcp.v -structural wrapper for ddr2 - multi-chip package model +ddr2_module.v -structural wrapper for ddr2 - module model +ddr2_parameters.vh -file that contains all parameters used by the model +readme.txt -this file +tb.v -ddr2 model test bench +subtest.vh -example test included by the test bench. +tb.do -compiles and runs the ddr2 model and test bench + +Defining the Speed Grade: +------------------------- +The verilog compiler directive "`define" may be used to choose between +multiple speed grades supported by the ddr2 model. Allowable speed +grades are listed in the ddr2_parameters.vh file and begin with the +letters "sg". The speed grade is used to select a set of timing +parameters for the ddr2 model. The following are examples of defining +the speed grade. + + simulator command line + --------- ------------ + ModelSim vlog +define+sg5 ddr2.v + NC-Verilog ncverilog +define+sg5 ddr2.v + VCS vcs +define+sg5 ddr2.v + +Defining the Organization: +-------------------------- +The verilog compiler directive "`define" may be used to choose between +multiple organizations supported by the ddr2 model. Valid +organizations include "x4", "x8", and x16, and are listed in the +ddr2_parameters.vh file. The organization is used to select the amount +of memory and the port sizes of the ddr2 model. The following are +examples of defining the organization. + + simulator command line + --------- ------------ + ModelSim vlog +define+x8 ddr2.v + NC-Verilog ncverilog +define+x8 ddr2.v + VCS vcs +define+x8 ddr2.v + +All combinations of speed grade and organization are considered valid +by the ddr2 model even though a Micron part may not exist for every +combination. + +Allocating Memory: +------------------ +An associative array has been implemented to reduce the amount of +static memory allocated by the ddr2 model. Each entry in the +associative array is a burst length of eight in size. The number of +entries in the associative array is controlled by the MEM_BITS +parameter, and is equal to 2^MEM_BITS. For example, if the MEM_BITS +parameter is equal to 10, the associative array will be large enough +to store 1024 writes of burst length 8 to unique addresses. The +following are examples of setting the MEM_BITS parameter to 8. + + simulator command line + --------- ------------ + ModelSim vsim -GMEM_BITS=8 ddr2 + NC-Verilog ncverilog +defparam+ddr2.MEM_BITS=8 ddr2.v + VCS vcs -pvalue+MEM_BITS=8 ddr2.v + +It is possible to allocate memory for every address supported by the +ddr2 model by using the verilog compiler directive "`define MAX_MEM". +This procedure will improve simulation performance at the expense of +system memory. The following are examples of allocating memory for +every address. + + Simulator command line + --------- ------------ + ModelSim vlog +define+MAX_MEM ddr2.v + NC-Verilog ncverilog +define+MAX_MEM ddr2.v + VCS vcs +define+MAX_MEM ddr2.v + + +********************************************************************** +The following information is provided to assist the modeling engineer +in creating multi-chip package (mcp) models. ddr2_mcp.v is a +structural wrapper that instantiates ddr2 models. This wrapper can be +used to create single, dual, or quad rank mcp models. From the +perspective of the model, the only item that needs to be defined is the +number of ranks. +********************************************************************** + +Defining the Number of Ranks in a multi-chip package: +---------------------------------------------------- +The verilog compiler directive "`define" may be used to choose between +single, dual, and quad rank mcp configurations. The default is single +rank if nothing is defined. Dual rank configuration can be selected by +defining "DUAL_RANK" when the ddr2_mcp is compiled. Quad rank +configuration can be selected by defining "QUAD_RANK" when the ddr2_mcp +is compiled. The following are examples of defining a dual rank mcp +configuration. + + simulator command line + --------- ------------ + ModelSim vlog +define+DUAL_RANK ddr2.v ddr2_mcp.v + NC-Verilog ncverilog +define+DUAL_RANK ddr2.v ddr2_mcp.v + VCS vcs +define+DUAL_RANK ddr2.v ddr2_mcp.v + + +********************************************************************** +The following information is provided to assist the modeling engineer +in creating DIMM models. ddr2_module.v is a structural wrapper that +instantiates ddr2 models. This wrapper can be used to create UDIMM, +RDIMM or SODIMM models. Other form factors are not supported +(MiniDIMM, VLP DIMM, etc.). From the perspective of the model, the +items that need to be defined are the number of ranks, the module +type, and the presence of ECC. All combinations of ranks, module +type, and ECC are considered valid by the ddr2_module model even +though a Micron part may not exist for every combination. +********************************************************************** + +Defining the Number of Ranks on a module: +---------------------------------------- +The verilog compiler directive "`define" may be used to choose between +single, dual, and quad rank module configurations. The default is single +rank if nothing is defined. Dual rank configuration can be selected by +defining "DUAL_RANK" when the ddr2_module is compiled. Quad rank +configuration can be selected by defining "QUAD_RANK" when the ddr2_module +is compiled. The following are examples of defining a dual rank module +configuration. + + simulator command line + --------- ------------ + ModelSim vlog +define+DUAL_RANK ddr2.v ddr2_module.v + NC-Verilog ncverilog +define+DUAL_RANK ddr2.v ddr2_module.v + VCS vcs +define+DUAL_RANK ddr2.v ddr2_module.v + +Defining the Module Type: +----------------------------------- +The verilog compiler directive "`define" may be used to choose between +UDIMM, RDIMM, and SODIMM module configurations. The default is +unregistered (UDIMM) if nothing is defined. SODIMM configuration can be +selected by defining "SODIMM" when the ddr2_module is compiled. Registered +configuration can be selected by defining "RDIMM" when the ddr2_module is +compiled. The following are examples of defining a registered module +configuration. + + simulator command line + --------- ------------ + ModelSim vlog +define+RDIMM ddr2.v ddr2_module.v + NC-Verilog ncverilog +define+RDIMM ddr2.v ddr2_module.v + VCS vcs +define+RDIMM ddr2.v ddr2_module.v + +Defining the ECC for a module: +----------------------------- +The verilog compiler directive "`define" may be used to choose between +ECC and nonECC module configurations. The default is nonECC if nothing +is defined. ECC configuration can be selected by defining "ECC" when +the ddr2_module is compiled. The following are examples of defining an +ECC module configuration. + + simulator command line + --------- ------------ + ModelSim vlog +define+ECC ddr2.v ddr2_module.v + NC-Verilog ncverilog +define+ECC ddr2.v ddr2_module.v + VCS vcs +define+ECC ddr2.v ddr2_module.v diff --git a/sim/verilog/micron_2048Mb_ddr2/subtest.vh b/sim/verilog/micron_2048Mb_ddr2/subtest.vh new file mode 100644 index 0000000..ec1e8f3 --- /dev/null +++ b/sim/verilog/micron_2048Mb_ddr2/subtest.vh @@ -0,0 +1,225 @@ +/**************************************************************************************** +* +* File Name: subtest.vh +* +* Description: Micron SDRAM DDR2 (Double Data Rate 2) +* This file is included by tb.v +* +* Disclaimer This software code and all associated documentation, comments or other +* of Warranty: information (collectively "Software") is provided "AS IS" without +* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY +* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES +* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT +* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE +* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. +* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR +* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE +* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, +* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, +* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, +* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, +* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE +* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGES. Because some jurisdictions prohibit the exclusion or +* limitation of liability for consequential or incidental damages, the +* above limitation may not apply to you. +* +* Copyright 2003 Micron Technology, Inc. All rights reserved. +* +****************************************************************************************/ + + initial begin : test + cke <= 1'b0; + cs_n <= 1'b1; + ras_n <= 1'b1; + cas_n <= 1'b1; + we_n <= 1'b1; + ba <= {BA_BITS{1'bz}}; + a <= {ADDR_BITS{1'bz}}; + odt <= 1'b0; + dq_en <= 1'b0; + dqs_en <= 1'b0; + + cke <= 1'b1; + + // POWERUP SECTION + power_up; + + // INITIALIZE SECTION + precharge (0, 1); // Precharge all banks + nop (trp); + + load_mode (2, 0); // Extended Mode Register (2) + nop (tmrd-1); + + load_mode (3, 0); // Extended Mode Register (3) + nop (tmrd-1); + + load_mode (1, 13'b0_0_0_000_0_000_1_0_0); // Extended Mode Register with DLL Enable + nop (tmrd-1); + + load_mode (0, 13'b0_000_1_0_000_0_011 | (twr-1)<<9 | taa<<4); // Mode Register without DLL Reset (bl=8) + nop (tmrd-1); + + precharge (0, 1); // Precharge all banks + nop (trp); + + refresh; + nop (trfc-1); + + refresh; + nop (trfc-1); + + load_mode (0, 13'b0_000_0_0_000_0_011 | (twr-1)<<9 | taa<<4); // Mode Register without DLL Reset (bl=8) + nop (tmrd-1); + + load_mode (1, 13'b0_0_0_111_0_000_1_0_0); // Extended Mode Register with OCD Default + nop (tmrd-1); + + load_mode (1, 13'b0_0_0_000_0_000_1_0_0); // Extended Mode Register with OCD Exit + nop (tmrd-1); + + // DLL RESET ENABLE - you will need 200 TCK before any read command. + nop (200); + + // WRITE SECTION + activate (0, 0); // Activate Bank 0, Row 0 + nop (trcd-1); + write (0, 4, 0, 0, 'h3210); // Write Bank 0, Col 0 + nop (tccd-1); + write (0, 0, 1, 0, 'h0123); // Write Bank 0, Col 0 + + activate (1, 0); // Activate Bank 1, Row 0 + nop (trcd-1); + write (1, 0, 1, 0, 'h4567); // Write Bank 1, Col 0 + + activate (2, 0); // Activate Bank 2, Row 0 + nop (trcd-1); + write (2, 0, 1, 0, 'h89AB); // Write Bank 2, Col 0 + + activate (3, 0); // Activate Bank 3, Row 0 + nop (trcd-1); + write (3, 0, 1, 0, 'hCDEF); // Write Bank 3, Col 0 + + nop (cl - 1 + bl/2 + twtr-1); + + nop (tras); + + // READ SECTION + activate (0, 0); // Activate Bank 0, Row 0 + nop (trrd-1); + activate (1, 0); // Activate Bank 1, Row 0 + nop (trrd-1); + activate (2, 0); // Activate Bank 2, Row 0 + nop (trrd-1); + activate (3, 0); // Activate Bank 3, Row 0 + read (0, 0, 1); // Read Bank 0, Col 0 + nop (bl/2); + read (1, 1, 1); // Read Bank 1, Col 1 + nop (bl/2); + read (2, 2, 1); // Read Bank 2, Col 2 + nop (bl/2); + read (3, 3, 1); // Read Bank 3, Col 3 + nop (rl + bl/2); + + activate (0, 0); // Activate Bank 0, Row 0 + nop (trrd-1); + activate (1, 0); // Activate Bank 1, Row 0 + nop (trcd-1); + $display ("%m at time %t: Figure 22: Consecutive READ Bursts", $time); + read (0, 0, 0); // Read Bank 0, Col 0 + nop (bl/2-1); + read (0, 4, 0); // Read Bank 0, Col 4 + nop (rl + bl/2); + + $display ("%m at time %t: Figure 23: Nonconsecutive READ Bursts", $time); + read (0, 0, 0); // Read Bank 0, Col 0 + nop (bl/2); + read (0, 4, 0); // Read Bank 0, Col 4 + nop (rl + bl/2); + + $display ("%m at time %t: Figure 24: READ Interrupted by READ", $time); + read (0, 0, 0); // Read Bank 0, Col 0 + nop (tccd-1); + read (1, 0, 0); // Read Bank 0, Col 0 + nop (rl + bl/2); + + $display ("%m at time %t: Figure 25 & 26: READ to PRECHARGE", $time); + read (0, 0, 0); // Read Bank 0, Col 0 + nop (al + bl/2 + trtp - 2); + precharge (0, 0); // Precharge Bank 0 + nop (trp-1); + + activate (0, 0); // Activate Bank 0, Row 0 + nop (trcd-1); + $display ("%m at time %t: Figure 27: READ to WRITE", $time); + read (0, 0, 0); // Read Bank 0, Col 0 + nop (rl + bl/2 - wl); + write (0, 0, 1, 0, 'h0123); // Write Bank 0, Col 0 + nop (wl + bl/2 + twr + trp-1); + + activate (0, 0); // Activate Bank 0, Row 0 + nop (trcd-1); + $display ("%m at time %t: Figure 36: Nonconsecutive WRITE to WRITE", $time); + write (0, 0, 0, 0, 'h0123); // Write Bank 0, Col 0 + nop (bl/2); + write (0, 4, 0, 0, 'h0123); // Write Bank 0, Col 0 + nop (wl + bl/2); + + $display ("%m at time %t: Figure 37: Random WRITE Cycles", $time); + write (0, 0, 0, 0, 'h0123); // Write Bank 0, Col 0 + nop (bl/2-1); + write (0, 4, 0, 0, 'h0123); // Write Bank 0, Col 0 + nop (wl + bl/2); + + $display ("%m at time %t: Figure 37: Figure 38: WRITE Interrupted by WRITE", $time); + write (0, 0, 0, 0, 'h0123); // Write Bank 0, Col 0 + nop (tccd-1); + write (1, 4, 0, 0, 'h0123); // Write Bank 0, Col 0 + nop (wl + bl/2); + + $display ("%m at time %t: Figure 39: WRITE to READ", $time); + write (0, 0, 0, 0, 'h0123); // Write Bank 0, Col 0 + nop (wl + bl/2 + twtr-1); + read_verify (0, 0, 0, 0, 'h0123); // Read Bank 0, Col 0 + nop (rl + bl/2); + + $display ("%m at time %t: Figure 40: WRITE to PRECHARGE", $time); + write (0, 0, 0, 0, 'h0123); // Write Bank 0, Col 0 + nop (wl + bl/2 + twr-1); + precharge (0, 1); // Precharge all banks + nop (trp-1); + + // odt Section + $display ("%m at time %t: Figure 60: odt Timing for Active or Fast-Exit Power-Down Mode", $time); + odt = 1'b1; + nop (1); + odt = 1'b0; + nop (tanpd); + + $display ("%m at time %t: Figure 61: odt timing for Slow-Exit or Precharge Power-Down Modes", $time); + cke = 1'b0; + @(negedge ck); + odt = 1'b1; + @(negedge ck); + odt = 1'b0; + repeat(tanpd)@(negedge ck); + nop (taxpd); + + $display ("%m at time %t: Figure 62 & 63: odt Transition Timings when Entering Power-Down Mode", $time); + odt = 1'b1; + nop (tanpd); + power_down (tcke); + + // Self Refresh Section + nop (taxpd); + odt = 1'b0; + nop (3); // taofd + self_refresh (tcke); + nop (tdllk); + nop (tcke); + + test_done; + end diff --git a/sim/verilog/micron_2048Mb_ddr2/tb.do b/sim/verilog/micron_2048Mb_ddr2/tb.do new file mode 100644 index 0000000..7f5f482 --- /dev/null +++ b/sim/verilog/micron_2048Mb_ddr2/tb.do @@ -0,0 +1,31 @@ +######################################################################################### +# +# Disclaimer This software code and all associated documentation, comments or other +# of Warranty: information (collectively "Software") is provided "AS IS" without +# warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY +# DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +# TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES +# OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT +# WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE +# OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. +# FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR +# THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +# ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE +# OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, +# ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, +# INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, +# WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, +# OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE +# THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGES. Because some jurisdictions prohibit the exclusion or +# limitation of liability for consequential or incidental damages, the +# above limitation may not apply to you. +# +# Copyright 2003 Micron Technology, Inc. All rights reserved. +# +######################################################################################### + +vlog -novopt ddr2.v tb.v +vsim -novopt tb +add wave -p sdramddr2/* +run -all diff --git a/sim/verilog/micron_2048Mb_ddr2/tb.v b/sim/verilog/micron_2048Mb_ddr2/tb.v new file mode 100644 index 0000000..a08db2f --- /dev/null +++ b/sim/verilog/micron_2048Mb_ddr2/tb.v @@ -0,0 +1,468 @@ +/**************************************************************************************** +* +* File Name: tb.v +* +* Dependencies: ddr2.v, ddr2_parameters.vh +* +* Description: Micron SDRAM DDR2 (Double Data Rate 2) test bench +* +* Note: -Set simulator resolution to "ps" accuracy +* -Set Debug = 0 to disable $display messages +* +* Disclaimer This software code and all associated documentation, comments or other +* of Warranty: information (collectively "Software") is provided "AS IS" without +* warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY +* DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +* TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES +* OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT +* WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE +* OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. +* FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR +* THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, +* ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE +* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, +* ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, +* INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, +* WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, +* OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE +* THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGES. Because some jurisdictions prohibit the exclusion or +* limitation of liability for consequential or incidental damages, the +* above limitation may not apply to you. +* +* Copyright 2003 Micron Technology, Inc. All rights reserved. +* +****************************************************************************************/ + +// DO NOT CHANGE THE TIMESCALE + +`timescale 1ps / 1ps + +module tb; + +`include "ddr2_parameters.vh" + + // ports + reg ck; + wire ck_n = ~ck; + reg cke; + reg cs_n; + reg ras_n; + reg cas_n; + reg we_n; + reg [BA_BITS-1:0] ba; + reg [ADDR_BITS-1:0] a; + wire [DM_BITS-1:0] dm; + wire [DQ_BITS-1:0] dq; + wire [DQS_BITS-1:0] dqs; + wire [DQS_BITS-1:0] dqs_n; + wire [DQS_BITS-1:0] rdqs_n; + reg odt; + + // mode registers + reg [ADDR_BITS-1:0] mode_reg0; //Mode Register + reg [ADDR_BITS-1:0] mode_reg1; //Extended Mode Register + wire [2:0] cl = mode_reg0[6:4]; //CAS Latency + wire bo = mode_reg0[3]; //Burst Order + wire [7:0] bl = (1< $rtoi(number)) + ceil = $rtoi(number) + 1; + else + ceil = number; + endfunction + + function integer max; + input arg1; + input arg2; + integer arg1; + integer arg2; + if (arg1 > arg2) + max = arg1; + else + max = arg2; + endfunction + + task power_up; + begin + cke <= 1'b0; + odt <= 1'b0; + repeat(10) @(negedge ck); + cke <= 1'b1; + nop (400000/tck+1); + end + endtask + + task load_mode; + input [BA_BITS-1:0] bank; + input [ADDR_BITS-1:0] addr; + begin + case (bank) + 0: mode_reg0 = addr; + 1: mode_reg1 = addr; + endcase + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b0; + cas_n <= 1'b0; + we_n <= 1'b0; + ba <= bank; + a <= addr; + @(negedge ck); + end + endtask + + task refresh; + begin + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b0; + cas_n <= 1'b0; + we_n <= 1'b1; + @(negedge ck); + end + endtask + + task precharge; + input [BA_BITS-1:0] bank; + input ap; //precharge all + begin + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b0; + cas_n <= 1'b1; + we_n <= 1'b0; + ba <= bank; + a <= (ap<<10); + @(negedge ck); + end + endtask + + task activate; + input [BA_BITS-1:0] bank; + input [ROW_BITS-1:0] row; + begin + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b0; + cas_n <= 1'b1; + we_n <= 1'b1; + ba <= bank; + a <= row; + @(negedge ck); + end + endtask + + //write task supports burst lengths <= 8 + task write; + input [BA_BITS-1:0] bank; + input [COL_BITS-1:0] col; + input ap; //Auto Precharge + input [8*DM_BITS-1:0] dm; + input [8*DQ_BITS-1:0] dq; + reg [ADDR_BITS-1:0] atemp [1:0]; + integer i; + begin + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b1; + cas_n <= 1'b0; + we_n <= 1'b0; + ba <= bank; + atemp[0] = col & 10'h3ff; //addr[ 9: 0] = COL[ 9: 0] + atemp[1] = (col>>10)<<11; //addr[ N:11] = COL[ N:10] + a <= atemp[0] | atemp[1] | (ap<<10); + for (i=0; i<=bl; i=i+1) begin + + dqs_en <= #(wl*tck + i*tck/2) 1'b1; + if (i%2 == 0) begin + dqs_out <= #(wl*tck + i*tck/2) {DQS_BITS{1'b0}}; + end else begin + dqs_out <= #(wl*tck + i*tck/2) {DQS_BITS{1'b1}}; + end + + dq_en <= #(wl*tck + i*tck/2 + tck/4) 1'b1; + dm_out <= #(wl*tck + i*tck/2 + tck/4) dm>>i*DM_BITS; + dq_out <= #(wl*tck + i*tck/2 + tck/4) dq>>i*DQ_BITS; + end + dqs_en <= #(wl*tck + bl*tck/2 + tck/2) 1'b0; + dq_en <= #(wl*tck + bl*tck/2 + tck/4) 1'b0; + @(negedge ck); + end + endtask + + // read without data verification + task read; + input [BA_BITS-1:0] bank; + input [COL_BITS-1:0] col; + input ap; //Auto Precharge + reg [ADDR_BITS-1:0] atemp [1:0]; + begin + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b1; + cas_n <= 1'b0; + we_n <= 1'b1; + ba <= bank; + atemp[0] = col & 10'h3ff; //addr[ 9: 0] = COL[ 9: 0] + atemp[1] = (col>>10)<<11; //addr[ N:11] = COL[ N:10] + a <= atemp[0] | atemp[1] | (ap<<10); + @(negedge ck); + end + endtask + + task nop; + input [31:0] count; + begin + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b1; + cas_n <= 1'b1; + we_n <= 1'b1; + repeat(count) @(negedge ck); + end + endtask + + task deselect; + input [31:0] count; + begin + cke <= 1'b1; + cs_n <= 1'b1; + ras_n <= 1'b1; + cas_n <= 1'b1; + we_n <= 1'b1; + repeat(count) @(negedge ck); + end + endtask + + task power_down; + input [31:0] count; + begin + cke <= 1'b0; + cs_n <= 1'b1; + ras_n <= 1'b1; + cas_n <= 1'b1; + we_n <= 1'b1; + repeat(count) @(negedge ck); + end + endtask + + task self_refresh; + input [31:0] count; + begin + cke <= 1'b0; + cs_n <= 1'b0; + ras_n <= 1'b0; + cas_n <= 1'b0; + we_n <= 1'b1; + cs_n <= #(tck) 1'b1; + ras_n <= #(tck) 1'b1; + cas_n <= #(tck) 1'b1; + we_n <= #(tck) 1'b1; + repeat(count) @(negedge ck); + end + endtask + + // read with data verification + task read_verify; + input [BA_BITS-1:0] bank; + input [COL_BITS-1:0] col; + input ap; //Auto Precharge + input [8*DM_BITS-1:0] dm; //Expected Data Mask + input [8*DQ_BITS-1:0] dq; //Expected Data + integer i; + begin + read (bank, col, ap); + for (i=0; i> (i*DM_BITS); + dq_fifo[2*rl + i] = dq >> (i*DQ_BITS); + end + end + endtask + + // receiver(s) for data_verify process + dqrx dqrx[DQS_BITS-1:0] (dqs, dq, q0, q1, q2, q3); + + // perform data verification as a result of read_verify task call + always @(ck) begin:data_verify + integer i; + integer j; + reg [DQ_BITS-1:0] bit_mask; + reg [DM_BITS-1:0] dm_temp; + reg [DQ_BITS-1:0] dq_temp; + + for (i = !ck; (i < 2/(2.0 - !ck)); i=i+1) begin + if (dm_fifo[i] === {DM_BITS{1'bx}}) begin + burst_cntr = 0; + end else begin + + dm_temp = dm_fifo[i]; + for (j=0; j 2) | (neg_clk_time / pos_clk_time > 2)); + + // Check if NOP/DES when enter/exit clock stop mode + if ((clock_stop && diff_ck) && (~(prev_nop || prev_des) || ~(nop_enable || des_enable))) begin + $display ("%m: at time %t ERROR: Nop or Deselect is required when enter or exit Stop Clock Mode", $time); + end + + if ((pos_clk_time / clk_period < tCH_MIN) && ~clock_stop) begin + $display ("%m: at time %t ERROR: tCH minimum violation on CLK by %t", $time, tCH_MIN*clk_period - pos_clk_time); + end + if ((pos_clk_time / clk_period > tCH_MAX) && ~clock_stop) begin + $display ("%m: at time %t ERROR: tCH maximum violation on CLK by %t", $time, pos_clk_time - tCH_MAX*clk_period); + end + if ((neg_clk_time / clk_period < tCL_MIN) && ~clock_stop) begin + $display ("%m: at time %t ERROR: tCL minimum violation on CLK by %t", $time, tCL_MIN*clk_period - pos_clk_time); + end + if ((neg_clk_time / clk_period > tCL_MAX) && ~clock_stop) begin + $display ("%m: at time %t ERROR: tCL maximum violation on CLK by %t", $time, pos_clk_time - tCL_MAX*clk_period); + end + end + end + + //clock Frequency Check + always @(posedge diff_ck) begin + if (clk_pos_edge_cnt > 1) begin + if (Mode_reg[6:4] == 3'b011) begin + if (clk_period < (tCK3_min-0.001)) begin + $display ("%m : at time %t ERROR : Illegal clk period for CAS Latency 3", $realtime); + $display ("%m : at time %t CLK PERIOD = %t", $realtime, clk_period); + end + end + if (Mode_reg[6:4] == 3'b010) begin + if (clk_period < (tCK2_min-0.001)) begin + $display ("%m : at time %t ERROR : Illegal clk period for CAS Latency 2", $realtime); + $display ("%m : at time %t CLK PERIOD = %t", $realtime, clk_period); + end + end + end + end + + //SRR reg settings + always @(posedge power_up_done) begin + Srr_reg = 'b0 ; + Srr_reg[3:0] = 4'b1111 ; //Manufacturer(Micron) + Srr_reg[7:4] = 4'b0000 ; //Revision ID(Default to 0 in model) + Srr_reg[10:8] = 3'b100 ; //Refresh Rate(based on temp sensor - will default to 1x in model) + Srr_reg[11] = (DQ_BITS == 32)? 1'b1 : 1'b0 ; //Part width(x32 or x16) + Srr_reg[12] = 1'b0 ; //Device Type (LP DDR) + Srr_reg[15:13] = (part_size == 1024)? 3'b011 : + (part_size == 512 )? 3'b010 : + (part_size == 256 )? 3'b001 : + 3'b000 ; //Density(1024Mb, 512Mb, 256Mb, 128Mb) + end + + // System Clock + always begin + @ (posedge diff_ck) begin + Sys_clk = CkeZ; + CkeZ = Cke; + end + @ (negedge diff_ck) begin + Sys_clk = 1'b0; + end + end + + task store_prev_cmd; + begin + prev_Cs_n <= Cs_n ; + prev_Ras_n <= Ras_n ; + prev_Cas_n <= Cas_n ; + prev_We_n <= We_n ; + prev_Ba[1] <= Ba[1] ; + prev_Ba[0] <= Ba[0] ; + prev_cke <= Cke ; + end + endtask + + task MRD_counter; + begin + if (Cke) begin + if (MRD_cntr < tMRD) begin + MRD_cntr = MRD_cntr + 1'b1; + end + end + end + endtask + + task SRR_counter; + begin + if (Cke) begin + if (SRR_cntr < tSRR) begin + SRR_cntr = SRR_cntr + 1'b1; + end + end + end + endtask + + task SRC_counter; + begin + if (Cke) begin + if (SRC_cntr < ((Mode_reg[6:4])+1)) begin + SRC_cntr = SRC_cntr + 1'b1; + end + end + end + endtask + + task tWTR_counter; + begin + if (Cke) begin + if (tWTR_en) begin + tWTR_cntr = 0 ; + end else begin + tWTR_cntr = tWTR_cntr + 1'b1; + end + end + end + endtask + + task command_counter; + begin + if (Cke) begin + for (i=0; i<4;i=i+1) begin + if (Read_precharge_count[i] < 4'hf) begin + Read_precharge_count[i] = Read_precharge_count[i] + 1'b1; + end + end + for (i=0; i<4;i=i+1) begin + if (Write_precharge_count[i] < 4'hf) begin + Write_precharge_count[i] = Write_precharge_count[i] + 1'b1; + end + end + end + end + endtask + + + task PD_counter; + begin + if (~Cke) begin + if (PD_cntr < tCKE) begin + PD_cntr = PD_cntr + (enter_DPD | enter_PD | DPD_enable | PD_enable); + end + end else begin + PD_cntr = 4'h0 ; + end + end + endtask + + task tXP_check; + begin + if (Cke == 1'b1 && prev_cke == 1'b0) begin + tXP_chk = $realtime ; + end + if (Cke) begin + if (~nop_enable && ~des_enable) begin + if ($realtime-tXP_chk < tXP - 0.001) begin +`ifdef T25L + $display ("%m: At time %t ERROR: tPDX violation", $realtime); +`else + $display ("%m: At time %t ERROR: tXP violation", $realtime); +`endif + end + end + end + end + endtask + + // DPD pos edge clk cntr + always begin + @ (posedge diff_ck) begin + tXP_check ; + Power_down_chk ; + PD_counter ; + store_prev_cmd ; + end + end + + // Check to make sure that we have a Deselect or NOP command on the bus when CKE is brought high + always @(Cke) begin + if (Cke === 1'b1) begin + Init_Cmd_Chk = $realtime ; + if (SelfRefresh === 1'b1) begin + SelfRefresh = 1'b0; + end + if (!((Cs_n) || (~Cs_n & Ras_n & Cas_n & We_n))) begin + $display ("%m: At time %t MEMORY ERROR: You must have a Deselect or NOP command applied", $realtime); + $display ("%m: when the Clock Enable is brought High."); + end + end + end + + //BL Mode Reg settings + always@(Mode_reg[2:0] or mode_load_done) begin + if (mode_load_done) begin + case (Mode_reg[2:0]) + 3'b001 : burst_length = 5'b00010; + 3'b010 : burst_length = 5'b00100; + 3'b011 : burst_length = 5'b01000; + 3'b100 : burst_length = 5'b10000; + default : burst_length = 5'bxxxxx; + endcase + end + end + +// Init sequence +always @(current_init_state or Cke or Prech_enable or ext_mode_load_done or mode_load_done or aref_count) begin + if (current_init_state == begin_init) begin + if (Cke) begin + current_init_state = cke_init ; + power_up_done = 1'b0 ; + end + end + if (current_init_state == cke_init) begin + if (Prech_enable) begin + current_init_state = prech_init ; + aref_count = 0 ; + end + end + if (current_init_state == prech_init) begin + if (~Prech_enable) begin + current_init_state = begin_mode_init ; + end + end + if (current_init_state == begin_mode_init) begin + if (ext_mode_load_done) begin + current_init_state = ext_mode_init ; + end + if (mode_load_done) begin + current_init_state = mode_init ; + end + end + if (current_init_state == mode_init) begin + if (ext_mode_load_done) begin + current_init_state = mode_done_init ; + end + end + if (current_init_state == ext_mode_init) begin + if (mode_load_done) begin + current_init_state = mode_done_init ; + end + end + if (current_init_state == mode_done_init && aref_count >= 2) begin + power_up_done = 1'b1; + end +end + + + // this task will erase the contents of 0 or more banks + task erase_mem; + input [BA_BITS+1:0] bank_MSB_row; //bank bits + 2 row MSB + input DPD_mode ; //erase all memory locations + integer i; + begin + + if (DPD_mode) begin +`ifdef FULL_MEM + for (i=0; i<{(BA_BITS+ROW_BITS+COL_BITS){1'b1}}; i=i+1) begin + mem_array[i] = 'bx; + end +`else + memory_index = 0; + i = 0; + // remove the selected banks + for (memory_index=0; memory_index= burst_length) begin +// Data_in_enable = 1'b0; +// Data_out_enable = 1'b0; +// read_precharge_truncation = 1'b0; +// SRR_read = 1'b0; +// end + end + endtask + + + // SRC check + task Timing_chk_SRC; + begin + if (Active_enable || Aref_enable || Sref_enable || Burst_term || + Ext_mode_enable || Mode_reg_enable || Prech_enable || Read_enable || + Write_enable || DPD_enable || PD_enable || srr_enable) begin + if (part_size == 1024) begin + if (SRC_cntr < ((Mode_reg[6:4])+tSRC)) begin + $display ("%m: At time %t ERROR: tSRC Violation", $realtime); + end + end + end + end + endtask + + task ShiftPipelines; + begin + // read command pipeline + Read_pipeline = Read_pipeline >> 1; + Write_pipeline = Write_pipeline >> 1; + for (i = -2; i < `MAX_PIPE-1; i = i + 1) + begin + Write_col_pipeline [i] = Write_col_pipeline[i+1]; + Write_bank_pipeline [i] = Write_bank_pipeline[i+1]; + end + end + endtask + + // Dq and Dqs Drivers + task Dq_Dqs_Drivers; + begin + + // Initialize Read command + if (Read_pipeline [0] === 1'b1) begin +// Data_out_enable = 1'b1; + Bank_addr = Write_bank_pipeline[0]; + Cols_addr = Write_col_pipeline [0]; + Cols_brst = Cols_addr [2 : 0]; +// if (SRR_read == 1'b1) begin +// Burst_counter = burst_length - 2; +// end else begin +// Burst_counter = 0; +// end + + // Row Address Mux + case (Bank_addr) + 2'd0 : Rows_addr = B0_row_addr; + 2'd1 : Rows_addr = B1_row_addr; + 2'd2 : Rows_addr = B2_row_addr; + 2'd3 : Rows_addr = B3_row_addr; + default : $display ("%m: At time %t ERROR: Invalid Bank Address", $realtime); + endcase + end + + // Read latch + if (Read_pipeline[0] === 1'b1) begin + // output data + if (SRR_read == 1'b1) begin + if (Cols_addr == 0) begin + Dq_out_temp = Srr_reg[DQ_BITS-1:0]; + end else begin + Dq_out_temp = Srr_reg[2*DQ_BITS-1:DQ_BITS]; + SRR_read = 1'b0 ; + end + end else begin + read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_out_temp); + end + if (Debug) begin + $display ("At time %t %m:READ: Bank = %d, Row = %d, Col = %d, Data = %d", $realtime, Bank_addr, Rows_addr, Cols_addr, Dq_out); + end + + end + + Dq_out <= #(tAC_max) Dq_out_temp ; + Dqs_out <= #(tAC_max) ((|Read_pipeline[0]) & Sys_clk) ; + + if (cas_latency == 3) + Dqs_out_en <= #(tAC_max) (|Read_pipeline[2:0]); + else + Dqs_out_en <= #(tAC_max) (|Read_pipeline[1:0]); + if (Sys_clk) begin + Dq_out_en <= #(tAC_max) (Read_pipeline[0]); + end + + end + endtask + + // Write FIFO and DM Mask Logic + task Write_FIFO_DM_Mask_Logic; + begin + + // Initialize Write command + if (Write_pipeline [-2] === 1'b1) begin +// Data_in_enable = 1'b1; + Bank_addr = Write_bank_pipeline [-2]; + Cols_addr = Write_col_pipeline [-2]; + Cols_brst = Cols_addr [2 : 0]; +// Burst_counter = 0; + + // Row address mux + case (Bank_addr) + 2'd0 : Rows_addr = B0_row_addr; + 2'd1 : Rows_addr = B1_row_addr; + 2'd2 : Rows_addr = B2_row_addr; + 2'd3 : Rows_addr = B3_row_addr; + default : $display ("%m: At time %t ERROR: Invalid Row Address", $realtime); + endcase + end + + // Write data +// if (Data_in_enable === 1'b1) begin + if (Write_pipeline[-2] === 1'b1) begin + + // Data Buffer + read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf); + + // write negedge Dqs on posedge Sys_clk + if (Sys_clk) begin + if (!dm_fall[0]) begin + Dq_buf [ 7 : 0] = dq_fall [ 7 : 0]; + end + if (!dm_fall[1]) begin + Dq_buf [15 : 8] = dq_fall [15 : 8]; + end +`ifdef x32 + if (!dm_fall[2]) begin + Dq_buf [23 : 16] = dq_fall [23 : 16]; + end + if (!dm_fall[3]) begin + Dq_buf [31 : 24] = dq_fall [31 : 24]; + end +`endif + if (~&dm_fall) begin + if (Debug) begin + $display ("At time %t %m:WRITE: Bank = %d, Row = %d, Col = %d, Data = %h", $realtime, Bank_addr, Rows_addr, Cols_addr, Dq_buf[DQ_BITS-1:0]); + end + end + // write posedge Dqs on negedge Sys_clk + end else begin + if (!dm_rise[0]) begin + Dq_buf [ 7 : 0] = dq_rise [ 7 : 0]; + end + if (!dm_rise[1]) begin + Dq_buf [15 : 8] = dq_rise [15 : 8]; + end +`ifdef x32 + if (!dm_rise[2]) begin + Dq_buf [23 : 16] = dq_rise [23 : 16]; + end + if (!dm_rise[3]) begin + Dq_buf [31 : 24] = dq_rise [31 : 24]; + end +`endif + if (~&dm_rise) begin + if (Debug) begin + $display ("At time %t %m:WRITE: Bank = %d, Row = %d, Col = %d, Data = %h", $realtime, Bank_addr, Rows_addr, Cols_addr, Dq_buf[DQ_BITS-1:0]); + end + end + end + + // Write Data + write_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf); + // tWR start and tWTR check + if (Sys_clk && &dm_pair === 1'b0) begin + case (Bank_addr) + 2'd0 : WR_chk0 = $realtime; + 2'd1 : WR_chk1 = $realtime; + 2'd2 : WR_chk2 = $realtime; + 2'd3 : WR_chk3 = $realtime; + default : $display ("%m: At time %t ERROR: Invalid Bank Address (tWR)", $realtime); + endcase + +// // tWTR check +// if (Read_enable === 1'b1) begin +// $display ("%m: At time %t ERROR: tWTR violation during Read", $realtime); +// end + end + end + end + endtask + + // Auto Precharge Calculation + task Auto_Precharge_Calculation; + begin + // Precharge counter + if (Read_precharge_access [0] === 1'b1 || Write_precharge_access [0] === 1'b1) begin + Count_precharge [0] = Count_precharge [0] + 1; + end + if (Read_precharge_access [1] === 1'b1 || Write_precharge_access [1] === 1'b1) begin + Count_precharge [1] = Count_precharge [1] + 1; + end + if (Read_precharge_access [2] === 1'b1 || Write_precharge_access [2] === 1'b1) begin + Count_precharge [2] = Count_precharge [2] + 1; + end + if (Read_precharge_access [3] === 1'b1 || Write_precharge_access [3] === 1'b1) begin + Count_precharge [3] = Count_precharge [3] + 1; + end + + // Read with AutoPrecharge Calculation + // The device start internal precharge when: + // 1. BL/2 cycles after command + // 2. Meet tRAS requirement + if (Read_precharge_access[0] & (Count_precharge[0] >= burst_length/2)) begin + Read_precharge_access[0] = 1'b0 ; + Read_precharge_pre[0] = 1'b1 ; + end + if ((Read_precharge_pre[0] === 1'b1) && ($realtime - RAS_chk0 >= tRAS - 0.001)) begin + Pc_b0 = 1'b1; + Act_b0 = 1'b0; + RP_chk0 = $realtime; + Read_precharge_pre[0] = 1'b0; + end + + if (Read_precharge_access[1] & (Count_precharge[1] >= burst_length/2)) begin + Read_precharge_access[1] = 1'b0 ; + Read_precharge_pre[1] = 1'b1 ; + end + if ((Read_precharge_pre[1] === 1'b1) && ($realtime - RAS_chk1 >= tRAS - 0.001)) begin + Pc_b1 = 1'b1; + Act_b1 = 1'b0; + RP_chk1 = $realtime; + Read_precharge_pre[1] = 1'b0; + end + + if (Read_precharge_access[2] & (Count_precharge[2] >= burst_length/2)) begin + Read_precharge_access[2] = 1'b0 ; + Read_precharge_pre[2] = 1'b1 ; + end + if ((Read_precharge_pre[2] === 1'b1) && ($realtime - RAS_chk2 >= tRAS - 0.001)) begin + Pc_b2 = 1'b1; + Act_b2 = 1'b0; + RP_chk2 = $realtime; + Read_precharge_pre[2] = 1'b0; + end + + if (Read_precharge_access[3] & (Count_precharge[3] >= burst_length/2)) begin + Read_precharge_access[3] = 1'b0 ; + Read_precharge_pre[3] = 1'b1 ; + end + if ((Read_precharge_pre[3] === 1'b1) && ($realtime - RAS_chk3 >= tRAS - 0.001)) begin + Pc_b3 = 1'b1; + Act_b3 = 1'b0; + RP_chk3 = $realtime; + Read_precharge_pre[3] = 1'b0; + end + + // Write with AutoPrecharge Calculation + // The device start internal precharge when: + // 1. Meet tRAS requirement + // 2. Two clock after last burst + // Since tWR is time base, the model will compensate tRP + if (Write_precharge_access[0] & (Count_precharge[0] >= burst_length/2+3)) begin + Write_precharge_access[0] = 1'b0 ; + Write_precharge_pre[0] = 1'b1 ; + end + if (Write_precharge_pre[0] & ($realtime - RAS_chk0 >= tRAS - 0.001)) begin + Write_precharge_pre[0] = 1'b0; + Pc_b0 = 1'b1; + Act_b0 = 1'b0; + RP_chk0 = $realtime - ((2 * clk_period) - tWR); + end + + if (Write_precharge_access[1] & (Count_precharge[1] >= burst_length/2+3)) begin + Write_precharge_access[1] = 1'b0 ; + Write_precharge_pre[1] = 1'b1 ; + end + if (Write_precharge_pre[1] & ($realtime - RAS_chk1 >= tRAS - 0.001)) begin + Write_precharge_pre[1] = 1'b0; + Pc_b1 = 1'b1; + Act_b1 = 1'b0; + RP_chk1 = $realtime - ((2 * clk_period) - tWR); + end + + if (Write_precharge_access[2] & (Count_precharge[2] >= burst_length/2+3)) begin + Write_precharge_access[2] = 1'b0 ; + Write_precharge_pre[2] = 1'b1 ; + end + if (Write_precharge_pre[2] & ($realtime - RAS_chk2 >= tRAS - 0.001)) begin + Write_precharge_pre[2] = 1'b0; + Pc_b2 = 1'b1; + Act_b2 = 1'b0; + RP_chk2 = $realtime - ((2 * clk_period) - tWR); + end + + if (Write_precharge_access[3] & (Count_precharge[3] >= burst_length/2+3)) begin + Write_precharge_access[3] = 1'b0 ; + Write_precharge_pre[3] = 1'b1 ; + end + if (Write_precharge_pre[3] & ($realtime - RAS_chk3 >= tRAS - 0.001)) begin + Write_precharge_pre[3] = 1'b0; + Pc_b3 = 1'b1; + Act_b3 = 1'b0; + RP_chk3 = $realtime - ((2 * clk_period) - tWR); + end + end + endtask + + task Power_down_chk; + begin + if (DPD_enable == 1'b1 && enter_DPD == 1'b0) begin + if (prev_cke & Pc_b0 & Pc_b1 & Pc_b2 & Pc_b3) begin + erase_mem(4'b0000, 1'b1); + current_init_state = begin_init ; + ext_mode_load_done = 1'b0 ; + mode_load_done = 1'b0 ; + enter_DPD = 1'b1; + $display ("%m: at time %t Entering Deep Power-Down Mode", $realtime); + end + end + if (enter_DPD == 1'b1) begin + if (Cke == 1'b1 && prev_cke == 1'b0) begin + if (PD_cntr < tCKE) begin + $display ("%m: At time %t ERROR: tCKE violation during exiting of Deep Power-Down Mode", $realtime); + end + $display ("%m: at time %t Exiting Deep Power-Down Mode - A 200 us delay is required with either DESELECT or NOP commands present before the initialization sequence may begin", $realtime); + enter_DPD = 1'b0; + end + end + if (PD_enable == 1'b1 && enter_PD == 1'b0) begin + if (prev_cke) begin + if (Pc_b0 & Pc_b1 & Pc_b2 & Pc_b3) begin + $display ("%m: at time %t Entering Power-Down Mode", $realtime); + enter_PD = 1'b1; + end else if (~Pc_b0 | ~Pc_b1 | ~Pc_b2 | ~Pc_b3) begin + $display ("%m: at time %t Entering Active Power-Down Mode", $realtime); + enter_APD = 1'b1; + end + end + end + if (enter_PD == 1'b1 || enter_APD == 1'b1) begin + if (Cke == 1'b1 && prev_cke == 1'b0) begin + if (PD_cntr < tCKE) begin + if (enter_PD == 1'b1) begin + $display ("%m: At time %t ERROR: tCKE violation during exiting of Power-Down Mode", $realtime); + end else if (enter_APD == 1'b1) begin + $display ("%m: At time %t ERROR: tCKE violation during exiting of Active Power-Down Mode", $realtime); + end + end + if (enter_PD == 1'b1) begin + $display ("%m: at time %t Exiting Power-Down Mode", $realtime); + enter_PD = 1'b0 ; + end else if (enter_APD == 1'b1) begin + $display ("%m: at time %t Exiting Active Power-Down Mode", $realtime); + enter_APD = 1'b0 ; + end + end + end + + end + endtask + + reg [31:0] xx ; + function [COL_BITS-1:0] Burst_Order; + input [COL_BITS-1:0] Col; + input [31:0] i; + begin + if (Mode_reg[3] == 1'b1) //interleaved + Burst_Order = (Col & -1*burst_length) + (Col%burst_length ^ i); + else // sequential + begin + xx = -1*burst_length; + Burst_Order = (Col & xx) + (Col%burst_length + i) % (burst_length); + end + end + endfunction + + // Control Logic + task Control_Logic; + begin + + // Self Refresh + if (Sref_enable === 1'b1) begin + // Partial Array Self Refresh + if (part_size == 128) begin + case (Ext_Mode_reg[2:0]) + 3'b000 : ;//keep Bank 0-7 + 3'b001 : begin $display("%m: at time %t INFO: Banks 2-3 will be lost due to Partial Array Self Refresh", $realtime) ; erase_mem(4'b0111, 1'b0); end + 3'b010 : begin $display("%m: at time %t INFO: Banks 1-3 will be lost due to Partial Array Self Refresh", $realtime) ; erase_mem(4'b0011, 1'b0); end + 3'b011 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end + 3'b100 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end + 3'b101 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end + 3'b110 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end + endcase + end else begin + case (Ext_Mode_reg[2:0]) + 3'b000 : ;//keep Bank 0-7 + 3'b001 : begin $display("%m: at time %t INFO: Banks 2-3 will be lost due to Partial Array Self Refresh", $realtime) ; erase_mem(4'b0111, 1'b0); end + 3'b010 : begin $display("%m: at time %t INFO: Banks 1-3 will be lost due to Partial Array Self Refresh", $realtime) ; erase_mem(4'b0011, 1'b0); end + 3'b011 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end + 3'b100 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end + 3'b101 : begin $display("%m: at time %t INFO: Banks 1-3 and 1/2 of bank 0 will be lost due to Partial Array Self Refresh", $realtime); erase_mem(4'b0001, 1'b0); end + 3'b110 : begin $display("%m: at time %t INFO: Banks 1-3 and 3/4 of bank 0 will be lost due to Partial Array Self Refresh", $realtime); erase_mem(4'b0000, 1'b0); end + endcase + end + SelfRefresh = 1'b1; + end + if (Aref_enable === 1'b1) begin + if (Debug) begin + $display ("Debug: At time %t %m:AUTOREFRESH: Auto Refresh", $realtime); + end + // aref_count is to make sure we have met part of the initialization sequence + if (~power_up_done) begin + aref_count = aref_count + 1; + end + + // Auto Refresh to Auto Refresh + if ($realtime - RFC_chk < tRFC - 0.001) begin + $display ("%m: At time %t ERROR: tRFC violation during Auto Refresh", $realtime); + end + + // Precharge to Auto Refresh + if (($realtime - RP_chk0 < tRP - 0.001) || ($realtime - RP_chk1 < tRP - 0.001) || + ($realtime - RP_chk2 < tRP - 0.001) || ($realtime - RP_chk3 < tRP - 0.001)) begin + $display ("%m: At time %t ERROR: tRP violation during Auto Refresh", $realtime); + end + + // Precharge to Auto Refresh + if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin + $display ("%m: At time %t ERROR: All banks must be Precharged before Auto Refresh", $realtime); + end + + // Record Current tRFC time + RFC_chk = $realtime; + end + + // SRR Register + if (srr_enable == 1'b1) begin + if (Pc_b0 === 1'b1 && Pc_b1 === 1'b1 && Pc_b2 === 1'b1 && Pc_b3 === 1'b1 && + Data_out_enable === 1'b0 && Data_in_enable === 1'b0) begin + SRR_read = 1'b1; + SRR_chk = $realtime; + SRR_cntr = 0; + end + end + + + // Extended Mode Register + if (Ext_mode_enable == 1'b1) begin + if (Debug) begin + $display ("Debug: At time %t %m:EMR : Extended Mode Register", $realtime); + end + + // Register Mode + Ext_Mode_reg = Addr; + + if (Pc_b0 === 1'b1 && Pc_b1 === 1'b1 && Pc_b2 === 1'b1 && Pc_b3 === 1'b1) begin + // ensure that power sequence is met properly + if (~power_up_done) begin + ext_mode_load_done = 1'b1; + end + $display ("At time %t %m:ELMR : Extended Load Mode Register", $realtime); + if (part_size == 128) begin + // Self Refresh Coverage + case (Addr[2 : 0]) + 3'b000 : $display ("%m : Self Refresh Cov = 4 banks"); + 3'b001 : $display ("%m : Self Refresh Cov = 2 banks"); + 3'b010 : $display ("%m : Self Refresh Cov = 1 bank"); + 3'b101 : $display ("%m : PASR = Reserved"); + 3'b110 : $display ("%m : PASR = Reserved"); + default : $display ("%m : PASR = Reserved"); + endcase + end else begin + // Self Refresh Coverage + case (Addr[2 : 0]) + 3'b000 : $display ("%m : Self Refresh Cov = 4 banks"); + 3'b001 : $display ("%m : Self Refresh Cov = 2 banks"); + 3'b010 : $display ("%m : Self Refresh Cov = 1 bank"); + 3'b101 : $display ("%m : Self Refresh Cov = 1/2 bank"); + 3'b110 : $display ("%m : Self Refresh Cov = 1/4 bank"); + default : $display ("%m : PASR = Reserved"); + endcase + end + // Maximum Case Temp +// case (Addr[4 : 3]) +// 2'b11 : $display ("%m : Maximum Case Temp = 85C"); +// 2'b00 : $display ("%m : Maximum Case Temp = 70C"); +// 2'b01 : $display ("%m : Maximum Case Temp = 45C"); +// 2'b10 : $display ("%m : Maximum Case Temp = 15C"); +// endcase + + // Drive Strength + case (Addr[7 : 5]) + 3'b000 : $display ("%m : Drive Strength = Full Strength"); + 3'b001 : $display ("%m : Drive Strength = Half Strength"); + 3'b010 : $display ("%m : Drive Strength = Quarter Strength"); + 3'b011 : $display ("%m : Drive Strength = Three Quarter Strength"); + 3'b100 : $display ("%m : Drive Strength = Three Quarter Strength"); + endcase + + end else begin + $display ("%m: At time %t ERROR: all banks must be Precharged before Extended Mode Register", $realtime); + end + + // Precharge to EMR + if (($realtime - RP_chk0 < tRP - 0.001) || ($realtime - RP_chk1 < tRP - 0.001) || + ($realtime - RP_chk2 < tRP - 0.001) || ($realtime - RP_chk3 < tRP - 0.001)) begin + $display ("%m: At time %t ERROR: tRP violation during Extended Mode Register", $realtime); + end + + // LMR/EMR to LMR/EMR +// if ($realtime - MRD_chk < tMRD) begin +// $display ("%m: At time %t ERROR: tMRD violation during Extended Mode Register", $realtime); +// end + + if (MRD_cntr < tMRD) begin + $display ("%m: At time %t ERROR: tMRD violation during Extended Mode Register", $realtime); + end + + // Record current tMRD time +// MRD_chk = $realtime; + MRD_cntr = 0; + end + + // Load Mode Register + if (Mode_reg_enable === 1'b1) begin + if (Debug) begin + $display ("Debug: At time %t %m:LMR : Load Mode Register", $realtime); + end + + // Register Mode + Mode_reg = Addr; + + if (Mode_reg[6:4] == 3'b010) begin + if (tCK2_min == 0) begin + $display ("%m : at time %t ERROR : Illegal CAS Latency of 2 set for current speed grade", $realtime); + end + end + + // Precharge to LMR + if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin + $display ("%m: At time %t ERROR: all banks must be Precharged before Load Mode Register", $realtime); + end + + // Precharge to LMR + if (($realtime - RP_chk0 < tRP - 0.001) || ($realtime - RP_chk1 < tRP - 0.001) || + ($realtime - RP_chk2 < tRP - 0.001) || ($realtime - RP_chk3 < tRP - 0.001)) begin + $display ("%m: At time %t ERROR: tRP violation during Load Mode Register", $realtime); + end + + // LMR/EMR to LMR/EMR +// if ($realtime - MRD_chk < tMRD) begin +// $display ("%m: At time %t ERROR: tMRD violation during Load Mode Register", $realtime); +// end + if (MRD_cntr < tMRD) begin + $display ("%m: At time %t ERROR: tMRD violation during Load Mode Register", $realtime); + end + + if (Pc_b0 === 1'b1 && Pc_b1 === 1'b1 && Pc_b2 === 1'b1 && Pc_b3 === 1'b1) begin + // ensure that power sequence is met properly + if (~power_up_done) begin + mode_load_done = 1'b1; + end + // Burst Length + case (Addr [2 : 0]) + 3'b001 : $display ("At time %t %m:LMR : Burst Length = 2", $realtime); + 3'b010 : $display ("At time %t %m:LMR : Burst Length = 4", $realtime); + 3'b011 : $display ("At time %t %m:LMR : Burst Length = 8", $realtime); + 3'b100 : $display ("At time %t %m:LMR : Burst Length = 16",$realtime); + default : + begin + $display ("%m: At time %t ERROR: Undefined burst length selection", $realtime); + $stop; + end + endcase + + // CAS Latency + case (Addr [6 : 4]) + 3'b010 : $display ("At time %t %m:LMR : CAS Latency = 2", $realtime); + 3'b011 : $display ("At time %t %m:LMR : CAS Latency = 3", $realtime); + default : begin + $display ("%m: At time %t ERROR: CAS Latency not supported", $realtime); + $stop; + end + endcase + + end + // Record current tMRD time +// MRD_chk = $realtime; + MRD_cntr = 0; + end + + // Activate Block + if (Active_enable === 1'b1) begin + if (!(power_up_done)) begin + $display ("%m: At time %t ERROR: Power Up and Initialization Sequence not completed before executing Activate command", $realtime); + end + // Display Debug Message + if (Debug) begin + $display ("Debug: At time %t %m:ACTIVATE: Bank = %d, Row = %d", $realtime, Ba, Addr); + end + + // Activating an open bank can cause corruption. + if ((Ba === 2'b00 && Pc_b0 === 1'b0) || (Ba === 2'b01 && Pc_b1 === 1'b0) || + (Ba === 2'b10 && Pc_b2 === 1'b0) || (Ba === 2'b11 && Pc_b3 === 1'b0)) begin + $display ("%m: At time %t ERROR: Bank = %d is already activated - data can be corrupted", $realtime, Ba); + end + + // Activate Bank 0 + if (Ba === 2'b00 && Pc_b0 === 1'b1) begin + // Activate to Activate (same bank) + if ($realtime - RC_chk0 < tRC - 0.001) begin + $display ("%m: At time %t ERROR: tRC violation during Activate bank %d", $realtime, Ba); + end + + // Precharge to Activate + if ($realtime - RP_chk0 < tRP - 0.001) begin + $display ("%m: At time %t ERROR: tRP violation during Activate bank %d", $realtime, Ba); + end + + // Record variables for checking violation + Act_b0 = 1'b1; + Pc_b0 = 1'b0; + B0_row_addr = Addr; + RC_chk0 = $realtime; + RCD_chk0 = $realtime; + RAS_chk0 = $realtime; + RAP_chk0 = $realtime; + end + + // Activate Bank 1 + if (Ba === 2'b01 && Pc_b1 === 1'b1) begin + // Activate to Activate (same bank) + if ($realtime - RC_chk1 < tRC - 0.001) begin + $display ("%m: At time %t ERROR: tRC violation during Activate bank %d", $realtime, Ba); + end + + // Precharge to Activate + if ($realtime - RP_chk1 < tRP - 0.001) begin + $display ("%m: At time %t ERROR: tRP violation during Activate bank %d", $realtime, Ba); + end + + // Record variables for checking violation + Act_b1 = 1'b1; + Pc_b1 = 1'b0; + B1_row_addr = Addr; + RC_chk1 = $realtime; + RCD_chk1 = $realtime; + RAS_chk1 = $realtime; + RAP_chk1 = $realtime; + end + + // Activate Bank 2 + if (Ba === 2'b10 && Pc_b2 === 1'b1) begin + // Activate to Activate (same bank) + if ($realtime - RC_chk2 < tRC - 0.001) begin + $display ("%m: At time %t ERROR: tRC violation during Activate bank %d", $realtime, Ba); + end + + // Precharge to Activate + if ($realtime - RP_chk2 < tRP - 0.001) begin + $display ("%m: At time %t ERROR: tRP violation during Activate bank %d", $realtime, Ba); + end + + // Record variables for checking violation + Act_b2 = 1'b1; + Pc_b2 = 1'b0; + B2_row_addr = Addr; + RC_chk2 = $realtime; + RCD_chk2 = $realtime; + RAS_chk2 = $realtime; + RAP_chk2 = $realtime; + end + + // Activate Bank 3 + if (Ba === 2'b11 && Pc_b3 === 1'b1) begin + // Activate to Activate (same bank) + if ($realtime - RC_chk3 < tRC - 0.001) begin + $display ("%m: t time %t ERROR: tRC violation during Activate bank %d", $realtime, Ba); + end + + // Precharge to Activate + if ($realtime - RP_chk3 < tRP - 0.001) begin + $display ("%m: At time %t ERROR: tRP violation during Activate bank %d", $realtime, Ba); + end + + // Record variables for checking violation + Act_b3 = 1'b1; + Pc_b3 = 1'b0; + B3_row_addr = Addr; + RC_chk3 = $realtime; + RCD_chk3 = $realtime; + RAS_chk3 = $realtime; + RAP_chk3 = $realtime; + end + + // Activate to Activate (different bank) + if ((Prev_bank != Ba) && ($realtime - RRD_chk < tRRD - 0.001)) begin + $display ("%m: At time %t ERROR: tRRD violation during Activate bank = %d", $realtime, Ba); + end + + // AutoRefresh to Activate + if ($realtime - RFC_chk < tRFC - 0.001) begin + $display ("%m: At time %t ERROR: tRFC violation during Activate bank %d", $realtime, Ba); + end + + // Record variable for checking violation + RRD_chk = $realtime; + Prev_bank = Ba; + end + + // Precharge Block - consider NOP if bank already precharged or in process of precharging + if (Prech_enable === 1'b1) begin + // Display Debug Message + if (Debug) begin + $display ("Debug: At time %t %m:PRE: Addr[10] = %b, Bank = %b", $realtime, Addr[10], Ba); + end + + // EMR or LMR to Precharge +// if ($realtime - MRD_chk < tMRD) begin +// $display ("%m: At time %t ERROR: tMRD violation during Precharge", $realtime); +// end + if (MRD_cntr < tMRD) begin + $display ("%m: At time %t ERROR: tMRD violation during Precharge", $realtime); + end + + // Precharge bank 0 + if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b00)) && Act_b0 === 1'b1) begin + Act_b0 = 1'b0; + Pc_b0 = 1'b1; + RP_chk0 = $realtime; + + // Activate to Precharge Bank + if ($realtime - RAS_chk0 < tRAS - 0.001) begin + $display ("%m: At time %t ERROR: tRAS violation during Precharge", $realtime); + end + + // tWR violation check for Write + if ($realtime - WR_chk0 < tWR - 0.001) begin + $display ("%m: At time %t ERROR: tWR violation during Precharge", $realtime); + end + end + + // Precharge bank 1 + if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b01)) && Act_b1 === 1'b1) begin + Act_b1 = 1'b0; + Pc_b1 = 1'b1; + RP_chk1 = $realtime; + + // Activate to Precharge Bank 1 + if ($realtime - RAS_chk1 < tRAS - 0.001) begin + $display ("%m: At time %t ERROR: tRAS violation during Precharge", $realtime); + end + + // tWR violation check for Write + if ($realtime - WR_chk1 < tWR - 0.001) begin + $display ("%m: At time %t ERROR: tWR violation during Precharge", $realtime); + end + end + + // Precharge bank 2 + if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b10)) && Act_b2 === 1'b1) begin + Act_b2 = 1'b0; + Pc_b2 = 1'b1; + RP_chk2 = $realtime; + + // Activate to Precharge Bank 2 + if ($realtime - RAS_chk2 < tRAS - 0.001) begin + $display ("%m: At time %t ERROR: tRAS violation during Precharge", $realtime); + end + + // tWR violation check for Write + if ($realtime - WR_chk2 < tWR - 0.001) begin + $display ("%m: At time %t ERROR: tWR violation during Precharge", $realtime); + end + end + + // Precharge bank 3 + if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b11)) && Act_b3 === 1'b1) begin + Act_b3 = 1'b0; + Pc_b3 = 1'b1; + RP_chk3 = $realtime; + + // Activate to Precharge Bank 3 + if ($realtime - RAS_chk3 < tRAS - 0.001) begin + $display ("%m: At time %t ERROR: tRAS violation during Precharge", $realtime); + end + + // tWR violation check for Write + if ($realtime - WR_chk3 < tWR - 0.001) begin + $display ("%m: At time %t ERROR: tWR violation during Precharge", $realtime); + end + end + + // Pipeline for READ + if ((Addr[10] === 1'b1) | (Ba == Write_bank_pipeline[4])) + for (i = 4; i < `MAX_PIPE; i = i + 1) + Read_pipeline[i] = 1'b0 ; + + end + + // Burst terminate + if (Burst_term === 1'b1) begin + // Display Debug Message + if (Debug) begin + $display ("Debug: %m: At time %t BURST_TERMINATE): Burst Terminate",$realtime); + end + + // Burst Terminate Command Pipeline for Read + for (i = cas_latency_x2-1; i < `MAX_PIPE; i = i + 1) + Read_pipeline[i] = 1'b0 ; + // Illegal to burst terminate a Write + if ((Data_in_enable === 1'b1) & ~((&dm_rise) & (&dm_fall))) begin + $display ("%m: At time %t ERROR: It's illegal to burst terminate a Write", $realtime); + end + + // Illegal to burst terminate a Read with Auto Precharge + if (|Read_precharge_access) begin + $display ("%m: At time %t ERROR: It's illegal to burst terminate a Read with Auto Precharge", $realtime); + end + end + + // Read Command + if (Read_enable === 1'b1) begin + if (!(power_up_done)) begin + $display ("%m: At time %t ERROR: Power Up and Initialization Sequence not completed before executing Read Command", $realtime); + end + // Display Debug Message + if (Debug) begin + $display ("Debug: At time %t %m:READ: Bank = %d, Col = %d", $realtime, Ba, {Addr [11], Addr [9 : 0]}); + end + if (part_size == 1024) begin + if (SRR_read == 1'b1) begin + if (SRR_cntr < tSRR) begin + $display ("%m: At time %t ERROR: tSRR Violation", $realtime); + end + SRC_cntr = 0 ; + end + end else begin + if (SRR_read == 1'b1) begin + if ($realtime - SRR_chk < tSRR-0.01) begin + $display ("%m: At time %t ERROR: tSRR Violation", $realtime); + end + SRC_cntr = 0; + end + end + // CAS Latency pipeline + if (SRR_read) begin + if ({Ba, Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]} > 0) begin + $display ("%m: At time %t ERROR: Address must be all 0 during SRR Read", $realtime); + end + for (i=0; i<2; i=i+1) + begin + Read_pipeline[cas_latency_x2 - 2 + i + 1] = 1'b1; + Write_col_pipeline [cas_latency_x2 - 2 + i + 1] = i; + Write_bank_pipeline [cas_latency_x2 - 2 + i + 1] = 0; + end + end else begin + for (i=0; i $rtoi(number)) + ceil = $rtoi(number) + 1; + else + ceil = number; + endfunction + + function integer max; + input arg1; + input arg2; + integer arg1; + integer arg2; + if (arg1 > arg2) + max = arg1; + else + max = arg2; + endfunction + + function [8*DQ_BITS-1:0] burst_order; + input [8-1:0] col; + input [8*DQ_BITS-1:0] dq; + reg [3:0] i; + reg [2:0] j; + integer k; + begin + burst_order = dq; + for (i=0; i>10)<<11; //addr[ N:11] = COL[ N:10] + a <= atemp[0] | atemp[1] | (ap<<10); + for (i=0; i<=bl; i=i+1) begin + dqs_en <= #(wl*tck + i*tck/2) 1'b1; + if (i%2 == 0) begin + dqs_out <= #(wl*tck + i*tck/2) {DQS_BITS{1'b0}}; + end else begin + dqs_out <= #(wl*tck + i*tck/2) {DQS_BITS{1'b1}}; + end + + dq_en <= #(wl*tck + i*tck/2 + tck/4) 1'b1; + dm_out <= #(wl*tck + i*tck/2 + tck/4) dm>>i*DM_BITS; + dq_out <= #(wl*tck + i*tck/2 + tck/4) dq>>i*DQ_BITS; + end + dqs_en <= #(wl*tck + bl*tck/2 + tck/2) 1'b0; + dq_en <= #(wl*tck + bl*tck/2 + tck/4) 1'b0; + @(negedge ck_tb); + end + endtask + + // read without data verification + task read; + input [BA_BITS-1:0] bank; + input [COL_BITS-1:0] col; + input ap; //Auto Precharge + reg [ADDR_BITS-1:0] atemp [1:0]; + begin + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b1; + cas_n <= 1'b0; + we_n <= 1'b1; + ba <= bank; + atemp[0] = col & 10'h3ff; //addr[ 9: 0] = COL[ 9: 0] + atemp[1] = (col>>10)<<11; //addr[ N:11] = COL[ N:10] + a <= atemp[0] | atemp[1] | (ap<<10); + @(negedge ck_tb); + end + endtask + + task burst_term; + integer i; + begin + cke <= 1'b1; + cs_n <= 1'b0; + ras_n <= 1'b1; + cas_n <= 1'b1; + we_n <= 1'b0; + @(negedge ck_tb); + for (i=0; i>(i*DM_BITS); + dq_fifo[2*cl + i] <= dq>>(i*DQ_BITS); + end + end + endtask + + // receiver(s) for data_verify process + dqrx dqrx[DQS_BITS-1:0] (ptr_rst_n, dqs, dq, q0, q1, q2, q3); + + // perform data verification as a result of read_verify task call + reg [DQ_BITS-1:0] bit_mask; + reg [DM_BITS-1:0] dm_temp; + reg [DQ_BITS-1:0] dq_temp; + always @(ck) begin:data_verify + integer i; + integer j; + + for (i=!ck; (i<2/(2.0 - !ck)); i=i+1) begin + if (dm_fifo[i] === {DM_BITS{1'bx}}) begin + burst_cntr = 0; + end else begin + + dm_temp = dm_fifo[i]; + for (j=0; j