sim/verilog/micron_2048Mb_ddr2/ddr2.v |
| 1 | /**************************************************************************************** |
| 2 | * |
| 3 | * File Name: ddr2.v |
| 4 | * Version: 5.83 |
| 5 | * Model: BUS Functional |
| 6 | * |
| 7 | * Dependencies: ddr2_parameters.vh |
| 8 | * |
| 9 | * Description: Micron SDRAM DDR2 (Double Data Rate 2) |
| 10 | * |
| 11 | * Limitation: - doesn't check for average refresh timings |
| 12 | * - positive ck and ck_n edges are used to form internal clock |
| 13 | * - positive dqs and dqs_n edges are used to latch data |
| 14 | * - test mode is not modeled |
| 15 | * |
| 16 | * Note: - Set simulator resolution to "ps" accuracy |
| 17 | * - Set Debug = 0 to disable $display messages |
| 18 | * |
| 19 | * Disclaimer This software code and all associated documentation, comments or other |
| 20 | * of Warranty: information (collectively "Software") is provided "AS IS" without |
| 21 | * warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY |
| 22 | * DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
| 23 | * TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES |
| 24 | * OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT |
| 25 | * WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE |
| 26 | * OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. |
| 27 | * FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR |
| 28 | * THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, |
| 29 | * ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE |
| 30 | * OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, |
| 31 | * ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, |
| 32 | * INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, |
| 33 | * WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, |
| 34 | * OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE |
| 35 | * THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 36 | * DAMAGES. Because some jurisdictions prohibit the exclusion or |
| 37 | * limitation of liability for consequential or incidental damages, the |
| 38 | * above limitation may not apply to you. |
| 39 | * |
| 40 | * Copyright 2003 Micron Technology, Inc. All rights reserved. |
| 41 | * |
| 42 | * Rev Author Date Changes |
| 43 | * --------------------------------------------------------------------------------------- |
| 44 | * 1.00 JMK 07/29/03 Initial Release |
| 45 | * 1.10 JMK 08/09/03 Timing Parameter updates to tIS, tIH, tDS, tDH |
| 46 | * 2.20 JMK 08/07/03 General cleanup |
| 47 | * 2.30 JMK 11/26/03 Added CL_MIN, CL_MAX, wl_min and wl_max parameters. |
| 48 | * Added AL_MIN and AL_MAX parameters. |
| 49 | * Removed support for OCD. |
| 50 | * 2.40 JMK 01/15/04 Removed verilog 2001 constructs. |
| 51 | * 2.50 JMK 01/29/04 Removed tRP checks during Precharge command. |
| 52 | * 2.60 JMK 04/20/04 Fixed tWTR check. |
| 53 | * 2.70 JMK 04/30/04 Added tRFC maximum check. |
| 54 | * Combined Self Refresh and Power Down always blocks. |
| 55 | * Added Reset Function (CKE LOW Anytime). |
| 56 | * 2.80 JMK 08/19/04 Precharge is treated as NOP when bank is not active. |
| 57 | * Added checks for tRAS, tWR, tRTP to any bank during Pre-All. |
| 58 | * tRFC maximum violation will only display one time. |
| 59 | * 2.90 JMK 11/05/04 Fixed DQS checking during write. |
| 60 | * Fixed false tRFC max assertion during power up and self ref. |
| 61 | * Added warning for 200us CKE low time during initialization. |
| 62 | * Added -3, -3E, and -37V speed grades to ddr2_parameters.v |
| 63 | * 3.00 JMK 04/22/05 Removed ODT off requirement during power down. |
| 64 | * Added tAOND, tAOFD, tANPD, tAXPD, tAONPD, and tAOFPD parameters. |
| 65 | * Added ODT status messages. |
| 66 | * Updated the initialization sequence. |
| 67 | * Disable ODT and CLK pins during self refresh. |
| 68 | * Disable cmd and addr pins during power down and self refresh. |
| 69 | * 3.10 JMK 06/07/05 Disable trpa checking if the part does not have 8 banks. |
| 70 | * Changed tAXPD message from error to a warning. |
| 71 | * Added tDSS checking. |
| 72 | * Removed tDQSL checking during tWPRE and tWPST. |
| 73 | * Fixed a burst order error during writes. |
| 74 | * Renamed parameters file with .vh extension. |
| 75 | * 3.20 JMK 07/18/05 Removed 14 tCK requirement from LMR to READ. |
| 76 | * 3.30 JMK 08/03/05 Added check for interrupting a burst with auto precharge. |
| 77 | * 4.00 JMK 11/21/05 Parameter names all UPPERCASE, signal names all lowercase. |
| 78 | * Clock jitter can be tolerated within specification range. |
| 79 | * Clock frequency is sampled from the CK pin. |
| 80 | * Scaleable up to 64 DQ and 16 DQS bits. |
| 81 | * Read data can be randomly skewed using RANDOM_OUT_DELAY. |
| 82 | * Parameterized read and write DQS, and read DQ. |
| 83 | * Initialization can be bypassed using initialize task. |
| 84 | * 4.10 JMK 11/30/05 Fixed compile errors when `MAX_MEM was defined. |
| 85 | * 4.20 JMK 12/09/05 Fixed memory addressing error when `MAX_MEM was defined. |
| 86 | * 4.30 JMK 02/15/06 Added dummy write to initialization sequence. |
| 87 | * Removed tWPST maximum checking. |
| 88 | * Rising dqs_n edge latches data when enabled in EMR. |
| 89 | * Fixed a sign error in the tJIT(cc) calculation. |
| 90 | * 4.40 JMK 02/16/06 Fixed dummy write when`MAX_MEM was defined. |
| 91 | * 4.50 JMK 02/27/06 Fixed extra tDQSS assertions. |
| 92 | * Fixed tRCD and tWTR checking. |
| 93 | * Errors entering Power Down or Self Refresh will cause reset. |
| 94 | * Ignore dqs_n when disabled in EMR. |
| 95 | * 5.00 JMK 04/24/06 Test stimulus now included from external file (subtest.vh) |
| 96 | * Fixed tRFC max assertion during self refresh. |
| 97 | * Fixed tANPD checking during Power Down. |
| 98 | * Removed dummy write from initialization sequence. |
| 99 | * 5.01 JMK 04/28/06 Fixed Auto Precharge to Load Mode, Refresh and Self Refresh. |
| 100 | * Removed Auto Precharge error message during Power Down Enter. |
| 101 | * 5.10 JMK 07/26/06 Created internal clock using ck and ck_n. |
| 102 | * RDQS can only be enabled in EMR for x8 configurations. |
| 103 | * CAS latency is checked vs frequency when DLL locks. |
| 104 | * tMOD changed from tCK units to ns units. |
| 105 | * Added 50 Ohm setting for Rtt in EMR. |
| 106 | * Improved checking of DQS during writes. |
| 107 | * 5.20 JMK 10/02/06 Fixed DQS checking for interrupting write to write and x16. |
| 108 | * 5.30 JMK 05/25/07 Fixed checking for 0-Z transition on write postamble. |
| 109 | * 5.50 JMK 05/30/08 Renamed ddr2_dimm.v to ddr2_module.v and added SODIMM support. |
| 110 | * Added a register delay to ddr2_module.v when RDIMM is defined. |
| 111 | * Added multi-chip package model support in ddr2_mcp.v |
| 112 | * Added High Temp Self Refresh rate setting in EMRS2[7] |
| 113 | * 5.70 JMK 04/23/09 Updated tRPA definition |
| 114 | * Increased internal width to 72 bit DQ bus |
| 115 | * 5.80 SPH 08/12/09 Fixed tRAS maximum violation (only check if bank still open) |
| 116 | * 5.81 SPH 12/08/09 Only check tIH for cmd_addr if CS# LOW |
| 117 | * 5.82 SPH 04/08/10 Correct debug message for SRT in EMR2 |
| 118 | * 5.83 SPH 04/29/10 Correct tDQSS check on valid DQS group |
| 119 | ****************************************************************************************/ |
| 120 | |
| 121 | // DO NOT CHANGE THE TIMESCALE |
| 122 | // MAKE SURE YOUR SIMULATOR USES "PS" RESOLUTION |
| 123 | `timescale 1ps / 1ps |
| 124 | |
| 125 | module ddr2 ( |
| 126 | ck, |
| 127 | ck_n, |
| 128 | cke, |
| 129 | cs_n, |
| 130 | ras_n, |
| 131 | cas_n, |
| 132 | we_n, |
| 133 | dm_rdqs, |
| 134 | ba, |
| 135 | addr, |
| 136 | dq, |
| 137 | dqs, |
| 138 | dqs_n, |
| 139 | rdqs_n, |
| 140 | odt |
| 141 | ); |
| 142 | |
| 143 | `include "ddr2_parameters.vh" |
| 144 | |
| 145 | // text macros |
| 146 | `define DQ_PER_DQS DQ_BITS/DQS_BITS |
| 147 | `define BANKS (1<<BA_BITS) |
| 148 | `define MAX_BITS (BA_BITS+ROW_BITS+COL_BITS-BL_BITS) |
| 149 | `define MAX_SIZE (1<<(BA_BITS+ROW_BITS+COL_BITS-BL_BITS)) |
| 150 | `define MEM_SIZE (1<<MEM_BITS) |
| 151 | `define MAX_PIPE 2*(AL_MAX + CL_MAX) |
| 152 | |
| 153 | // Declare Ports |
| 154 | input ck; |
| 155 | input ck_n; |
| 156 | input cke; |
| 157 | input cs_n; |
| 158 | input ras_n; |
| 159 | input cas_n; |
| 160 | input we_n; |
| 161 | inout [DM_BITS-1:0] dm_rdqs; |
| 162 | input [BA_BITS-1:0] ba; |
| 163 | input [ADDR_BITS-1:0] addr; |
| 164 | inout [DQ_BITS-1:0] dq; |
| 165 | inout [DQS_BITS-1:0] dqs; |
| 166 | inout [DQS_BITS-1:0] dqs_n; |
| 167 | output [DQS_BITS-1:0] rdqs_n; |
| 168 | input odt; |
| 169 | |
| 170 | // clock jitter |
| 171 | real tck_avg; |
| 172 | time tck_sample [TDLLK-1:0]; |
| 173 | time tch_sample [TDLLK-1:0]; |
| 174 | time tcl_sample [TDLLK-1:0]; |
| 175 | time tck_i; |
| 176 | time tch_i; |
| 177 | time tcl_i; |
| 178 | real tch_avg; |
| 179 | real tcl_avg; |
| 180 | time tm_ck_pos; |
| 181 | time tm_ck_neg; |
| 182 | real tjit_per_rtime; |
| 183 | integer tjit_cc_time; |
| 184 | real terr_nper_rtime; |
| 185 | |
| 186 | // clock skew |
| 187 | real out_delay; |
| 188 | integer dqsck [DQS_BITS-1:0]; |
| 189 | integer dqsck_min; |
| 190 | integer dqsck_max; |
| 191 | integer dqsq_min; |
| 192 | integer dqsq_max; |
| 193 | integer seed; |
| 194 | |
| 195 | // Mode Registers |
| 196 | reg burst_order; |
| 197 | reg [BL_BITS:0] burst_length; |
| 198 | integer cas_latency; |
| 199 | integer additive_latency; |
| 200 | reg dll_reset; |
| 201 | reg dll_locked; |
| 202 | reg dll_en; |
| 203 | integer write_recovery; |
| 204 | reg low_power; |
| 205 | reg [1:0] odt_rtt; |
| 206 | reg odt_en; |
| 207 | reg [2:0] ocd; |
| 208 | reg dqs_n_en; |
| 209 | reg rdqs_en; |
| 210 | reg out_en; |
| 211 | integer read_latency; |
| 212 | integer write_latency; |
| 213 | |
| 214 | // cmd encoding |
| 215 | parameter |
| 216 | LOAD_MODE = 4'b0000, |
| 217 | REFRESH = 4'b0001, |
| 218 | PRECHARGE = 4'b0010, |
| 219 | ACTIVATE = 4'b0011, |
| 220 | WRITE = 4'b0100, |
| 221 | READ = 4'b0101, |
| 222 | NOP = 4'b0111, |
| 223 | PWR_DOWN = 4'b1000, |
| 224 | SELF_REF = 4'b1001 |
| 225 | ; |
| 226 | |
| 227 | reg [8*9-1:0] cmd_string [9:0]; |
| 228 | initial begin |
| 229 | cmd_string[LOAD_MODE] = "Load Mode"; |
| 230 | cmd_string[REFRESH ] = "Refresh "; |
| 231 | cmd_string[PRECHARGE] = "Precharge"; |
| 232 | cmd_string[ACTIVATE ] = "Activate "; |
| 233 | cmd_string[WRITE ] = "Write "; |
| 234 | cmd_string[READ ] = "Read "; |
| 235 | cmd_string[NOP ] = "No Op "; |
| 236 | cmd_string[PWR_DOWN ] = "Pwr Down "; |
| 237 | cmd_string[SELF_REF ] = "Self Ref "; |
| 238 | end |
| 239 | |
| 240 | // command state |
| 241 | reg [`BANKS-1:0] active_bank; |
| 242 | reg [`BANKS-1:0] auto_precharge_bank; |
| 243 | reg [`BANKS-1:0] write_precharge_bank; |
| 244 | reg [`BANKS-1:0] read_precharge_bank; |
| 245 | reg [ROW_BITS-1:0] active_row [`BANKS-1:0]; |
| 246 | reg in_power_down; |
| 247 | reg in_self_refresh; |
| 248 | reg [3:0] init_mode_reg; |
| 249 | reg init_done; |
| 250 | integer init_step; |
| 251 | reg er_trfc_max; |
| 252 | reg odt_state; |
| 253 | reg prev_odt; |
| 254 | |
| 255 | // cmd timers/counters |
| 256 | integer ref_cntr; |
| 257 | integer ck_cntr; |
| 258 | integer ck_load_mode; |
| 259 | integer ck_write; |
| 260 | integer ck_read; |
| 261 | integer ck_write_ap; |
| 262 | integer ck_power_down; |
| 263 | integer ck_slow_exit_pd; |
| 264 | integer ck_self_refresh; |
| 265 | integer ck_cke; |
| 266 | integer ck_odt; |
| 267 | integer ck_dll_reset; |
| 268 | integer ck_bank_write [`BANKS-1:0]; |
| 269 | integer ck_bank_read [`BANKS-1:0]; |
| 270 | time tm_refresh; |
| 271 | time tm_precharge; |
| 272 | time tm_precharge_all; |
| 273 | time tm_activate; |
| 274 | time tm_write_end; |
| 275 | time tm_self_refresh; |
| 276 | time tm_odt_en; |
| 277 | time tm_bank_precharge [`BANKS-1:0]; |
| 278 | time tm_bank_activate [`BANKS-1:0]; |
| 279 | time tm_bank_write_end [`BANKS-1:0]; |
| 280 | time tm_bank_read_end [`BANKS-1:0]; |
| 281 | |
| 282 | // pipelines |
| 283 | reg [`MAX_PIPE:0] al_pipeline; |
| 284 | reg [`MAX_PIPE:0] wr_pipeline; |
| 285 | reg [`MAX_PIPE:0] rd_pipeline; |
| 286 | reg [`MAX_PIPE:0] odt_pipeline; |
| 287 | reg [BA_BITS-1:0] ba_pipeline [`MAX_PIPE:0]; |
| 288 | reg [ROW_BITS-1:0] row_pipeline [`MAX_PIPE:0]; |
| 289 | reg [COL_BITS-1:0] col_pipeline [`MAX_PIPE:0]; |
| 290 | reg prev_cke; |
| 291 | |
| 292 | // data state |
| 293 | reg [BL_MAX*DQ_BITS-1:0] memory_data; |
| 294 | reg [BL_MAX*DQ_BITS-1:0] bit_mask; |
| 295 | reg [BL_BITS-1:0] burst_position; |
| 296 | reg [BL_BITS:0] burst_cntr; |
| 297 | reg [DQ_BITS-1:0] dq_temp; |
| 298 | reg [35:0] check_write_postamble; |
| 299 | reg [35:0] check_write_preamble; |
| 300 | reg [35:0] check_write_dqs_high; |
| 301 | reg [35:0] check_write_dqs_low; |
| 302 | reg [17:0] check_dm_tdipw; |
| 303 | reg [71:0] check_dq_tdipw; |
| 304 | |
| 305 | // data timers/counters |
| 306 | time tm_cke; |
| 307 | time tm_odt; |
| 308 | time tm_tdqss; |
| 309 | time tm_dm [17:0]; |
| 310 | time tm_dqs [17:0]; |
| 311 | time tm_dqs_pos [35:0]; |
| 312 | time tm_dqss_pos [35:0]; |
| 313 | time tm_dqs_neg [35:0]; |
| 314 | time tm_dq [71:0]; |
| 315 | time tm_cmd_addr [22:0]; |
| 316 | reg [8*7-1:0] cmd_addr_string [22:0]; |
| 317 | initial begin |
| 318 | cmd_addr_string[ 0] = "CS_N "; |
| 319 | cmd_addr_string[ 1] = "RAS_N "; |
| 320 | cmd_addr_string[ 2] = "CAS_N "; |
| 321 | cmd_addr_string[ 3] = "WE_N "; |
| 322 | cmd_addr_string[ 4] = "BA 0 "; |
| 323 | cmd_addr_string[ 5] = "BA 1 "; |
| 324 | cmd_addr_string[ 6] = "BA 2 "; |
| 325 | cmd_addr_string[ 7] = "ADDR 0"; |
| 326 | cmd_addr_string[ 8] = "ADDR 1"; |
| 327 | cmd_addr_string[ 9] = "ADDR 2"; |
| 328 | cmd_addr_string[10] = "ADDR 3"; |
| 329 | cmd_addr_string[11] = "ADDR 4"; |
| 330 | cmd_addr_string[12] = "ADDR 5"; |
| 331 | cmd_addr_string[13] = "ADDR 6"; |
| 332 | cmd_addr_string[14] = "ADDR 7"; |
| 333 | cmd_addr_string[15] = "ADDR 8"; |
| 334 | cmd_addr_string[16] = "ADDR 9"; |
| 335 | cmd_addr_string[17] = "ADDR 10"; |
| 336 | cmd_addr_string[18] = "ADDR 11"; |
| 337 | cmd_addr_string[19] = "ADDR 12"; |
| 338 | cmd_addr_string[20] = "ADDR 13"; |
| 339 | cmd_addr_string[21] = "ADDR 14"; |
| 340 | cmd_addr_string[22] = "ADDR 15"; |
| 341 | end |
| 342 | |
| 343 | reg [8*5-1:0] dqs_string [1:0]; |
| 344 | initial begin |
| 345 | dqs_string[0] = "DQS "; |
| 346 | dqs_string[1] = "DQS_N"; |
| 347 | end |
| 348 | |
| 349 | // Memory Storage |
| 350 | `ifdef MAX_MEM |
| 351 | reg [BL_MAX*DQ_BITS-1:0] memory [0:`MAX_SIZE-1]; |
| 352 | `else |
| 353 | reg [BL_MAX*DQ_BITS-1:0] memory [0:`MEM_SIZE-1]; |
| 354 | reg [`MAX_BITS-1:0] address [0:`MEM_SIZE-1]; |
| 355 | reg [MEM_BITS:0] memory_index; |
| 356 | reg [MEM_BITS:0] memory_used; |
| 357 | `endif |
| 358 | |
| 359 | // receive |
| 360 | reg ck_in; |
| 361 | reg ck_n_in; |
| 362 | reg cke_in; |
| 363 | reg cs_n_in; |
| 364 | reg ras_n_in; |
| 365 | reg cas_n_in; |
| 366 | reg we_n_in; |
| 367 | reg [17:0] dm_in; |
| 368 | reg [2:0] ba_in; |
| 369 | reg [15:0] addr_in; |
| 370 | reg [71:0] dq_in; |
| 371 | reg [35:0] dqs_in; |
| 372 | reg odt_in; |
| 373 | |
| 374 | reg [17:0] dm_in_pos; |
| 375 | reg [17:0] dm_in_neg; |
| 376 | reg [71:0] dq_in_pos; |
| 377 | reg [71:0] dq_in_neg; |
| 378 | reg dq_in_valid; |
| 379 | reg dqs_in_valid; |
| 380 | integer wdqs_cntr; |
| 381 | integer wdq_cntr; |
| 382 | integer wdqs_pos_cntr [35:0]; |
| 383 | reg b2b_write; |
| 384 | reg [35:0] prev_dqs_in; |
| 385 | reg diff_ck; |
| 386 | |
| 387 | always @(ck ) ck_in <= #BUS_DELAY ck; |
| 388 | always @(ck_n ) ck_n_in <= #BUS_DELAY ck_n; |
| 389 | always @(cke ) cke_in <= #BUS_DELAY cke; |
| 390 | always @(cs_n ) cs_n_in <= #BUS_DELAY cs_n; |
| 391 | always @(ras_n ) ras_n_in <= #BUS_DELAY ras_n; |
| 392 | always @(cas_n ) cas_n_in <= #BUS_DELAY cas_n; |
| 393 | always @(we_n ) we_n_in <= #BUS_DELAY we_n; |
| 394 | always @(dm_rdqs) dm_in <= #BUS_DELAY dm_rdqs; |
| 395 | always @(ba ) ba_in <= #BUS_DELAY ba; |
| 396 | always @(addr ) addr_in <= #BUS_DELAY addr; |
| 397 | always @(dq ) dq_in <= #BUS_DELAY dq; |
| 398 | always @(dqs or dqs_n) dqs_in <= #BUS_DELAY (dqs_n<<18) | dqs; |
| 399 | always @(odt ) odt_in <= #BUS_DELAY odt; |
| 400 | // create internal clock |
| 401 | always @(posedge ck_in) diff_ck <= ck_in; |
| 402 | always @(posedge ck_n_in) diff_ck <= ~ck_n_in; |
| 403 | |
| 404 | wire [17:0] dqs_even = dqs_in[17:0]; |
| 405 | wire [17:0] dqs_odd = dqs_n_en ? dqs_in[35:18] : ~dqs_in[17:0]; |
| 406 | wire [3:0] cmd_n_in = !cs_n_in ? {ras_n_in, cas_n_in, we_n_in} : NOP; //deselect = nop |
| 407 | |
| 408 | // transmit |
| 409 | reg dqs_out_en; |
| 410 | reg [DQS_BITS-1:0] dqs_out_en_dly; |
| 411 | reg dqs_out; |
| 412 | reg [DQS_BITS-1:0] dqs_out_dly; |
| 413 | reg dq_out_en; |
| 414 | reg [DQ_BITS-1:0] dq_out_en_dly; |
| 415 | reg [DQ_BITS-1:0] dq_out; |
| 416 | reg [DQ_BITS-1:0] dq_out_dly; |
| 417 | integer rdqsen_cntr; |
| 418 | integer rdqs_cntr; |
| 419 | integer rdqen_cntr; |
| 420 | integer rdq_cntr; |
| 421 | |
| 422 | bufif1 buf_dqs [DQS_BITS-1:0] (dqs, dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}}); |
| 423 | bufif1 buf_dm [DM_BITS-1:0] (dm_rdqs, dqs_out_dly, dqs_out_en_dly & {DM_BITS {out_en}} & {DM_BITS{rdqs_en}}); |
| 424 | bufif1 buf_dqs_n [DQS_BITS-1:0] (dqs_n, ~dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}} & {DQS_BITS{dqs_n_en}}); |
| 425 | bufif1 buf_rdqs_n [DQS_BITS-1:0] (rdqs_n, ~dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}} & {DQS_BITS{dqs_n_en}} & {DQS_BITS{rdqs_en}}); |
| 426 | bufif1 buf_dq [DQ_BITS-1:0] (dq, dq_out_dly, dq_out_en_dly & {DQ_BITS {out_en}}); |
| 427 | |
| 428 | initial begin |
| 429 | if (BL_MAX < 2) |
| 430 | $display("%m ERROR: BL_MAX parameter must be >= 2. \nBL_MAX = %d", BL_MAX); |
| 431 | if ((1<<BO_BITS) > BL_MAX) |
| 432 | $display("%m ERROR: 2^BO_BITS cannot be greater than BL_MAX parameter."); |
| 433 | $timeformat (-12, 1, " ps", 1); |
| 434 | reset_task; |
| 435 | seed = RANDOM_SEED; |
| 436 | ck_cntr = 0; |
| 437 | end |
| 438 | |
| 439 | // calculate the absolute value of a real number |
| 440 | function real abs_value; |
| 441 | input arg; |
| 442 | real arg; |
| 443 | begin |
| 444 | if (arg < 0.0) |
| 445 | abs_value = -1.0 * arg; |
| 446 | else |
| 447 | abs_value = arg; |
| 448 | end |
| 449 | endfunction |
| 450 | |
| 451 | `ifdef MAX_MEM |
| 452 | `else |
| 453 | function get_index; |
| 454 | input [`MAX_BITS-1:0] addr; |
| 455 | begin : index |
| 456 | get_index = 0; |
| 457 | for (memory_index=0; memory_index<memory_used; memory_index=memory_index+1) begin |
| 458 | if (address[memory_index] == addr) begin |
| 459 | get_index = 1; |
| 460 | disable index; |
| 461 | end |
| 462 | end |
| 463 | end |
| 464 | endfunction |
| 465 | `endif |
| 466 | |
| 467 | task memory_write; |
| 468 | input [BA_BITS-1:0] bank; |
| 469 | input [ROW_BITS-1:0] row; |
| 470 | input [COL_BITS-1:0] col; |
| 471 | input [BL_MAX*DQ_BITS-1:0] data; |
| 472 | reg [`MAX_BITS-1:0] addr; |
| 473 | begin |
| 474 | // chop off the lowest address bits |
| 475 | addr = {bank, row, col}/BL_MAX; |
| 476 | `ifdef MAX_MEM |
| 477 | memory[addr] = data; |
| 478 | `else |
| 479 | if (get_index(addr)) begin |
| 480 | address[memory_index] = addr; |
| 481 | memory[memory_index] = data; |
| 482 | end else if (memory_used == `MEM_SIZE) begin |
| 483 | $display ("%m: at time %t ERROR: Memory overflow. Write to Address %h with Data %h will be lost.\nYou must increase the MEM_BITS parameter or define MAX_MEM.", $time, addr, data); |
| 484 | if (STOP_ON_ERROR) $stop(0); |
| 485 | end else begin |
| 486 | address[memory_used] = addr; |
| 487 | memory[memory_used] = data; |
| 488 | memory_used = memory_used + 1; |
| 489 | end |
| 490 | `endif |
| 491 | end |
| 492 | endtask |
| 493 | |
| 494 | task memory_read; |
| 495 | input [BA_BITS-1:0] bank; |
| 496 | input [ROW_BITS-1:0] row; |
| 497 | input [COL_BITS-1:0] col; |
| 498 | output [BL_MAX*DQ_BITS-1:0] data; |
| 499 | reg [`MAX_BITS-1:0] addr; |
| 500 | begin |
| 501 | // chop off the lowest address bits |
| 502 | addr = {bank, row, col}/BL_MAX; |
| 503 | `ifdef MAX_MEM |
| 504 | data = memory[addr]; |
| 505 | `else |
| 506 | if (get_index(addr)) begin |
| 507 | data = memory[memory_index]; |
| 508 | end else begin |
| 509 | data = {BL_MAX*DQ_BITS{1'bx}}; |
| 510 | end |
| 511 | `endif |
| 512 | end |
| 513 | endtask |
| 514 | |
| 515 | // Before this task runs, the model must be in a valid state for precharge power down. |
| 516 | // After this task runs, NOP commands must be issued until tRFC has been met |
| 517 | task initialize; |
| 518 | input [ADDR_BITS-1:0] mode_reg0; |
| 519 | input [ADDR_BITS-1:0] mode_reg1; |
| 520 | input [ADDR_BITS-1:0] mode_reg2; |
| 521 | input [ADDR_BITS-1:0] mode_reg3; |
| 522 | begin |
| 523 | if (DEBUG) $display ("%m: at time %t INFO: Performing Initialization Sequence", $time); |
| 524 | cmd_task(1, NOP, 'bx, 'bx); |
| 525 | cmd_task(1, PRECHARGE, 'bx, 1<<AP); // Precharege ALL |
| 526 | cmd_task(1, LOAD_MODE, 3, mode_reg3); |
| 527 | cmd_task(1, LOAD_MODE, 2, mode_reg2); |
| 528 | cmd_task(1, LOAD_MODE, 1, mode_reg1); |
| 529 | cmd_task(1, LOAD_MODE, 0, mode_reg0 | 'h100); // DLL Reset |
| 530 | cmd_task(1, PRECHARGE, 'bx, 1<<AP); // Precharege ALL |
| 531 | cmd_task(1, REFRESH, 'bx, 'bx); |
| 532 | cmd_task(1, REFRESH, 'bx, 'bx); |
| 533 | cmd_task(1, LOAD_MODE, 0, mode_reg0); |
| 534 | cmd_task(1, LOAD_MODE, 1, mode_reg1 | 'h380); // OCD Default |
| 535 | cmd_task(1, LOAD_MODE, 1, mode_reg1); |
| 536 | cmd_task(0, NOP, 'bx, 'bx); |
| 537 | end |
| 538 | endtask |
| 539 | |
| 540 | task reset_task; |
| 541 | integer i; |
| 542 | begin |
| 543 | // disable inputs |
| 544 | dq_in_valid = 0; |
| 545 | dqs_in_valid <= 0; |
| 546 | wdqs_cntr = 0; |
| 547 | wdq_cntr = 0; |
| 548 | for (i=0; i<36; i=i+1) begin |
| 549 | wdqs_pos_cntr[i] <= 0; |
| 550 | end |
| 551 | b2b_write <= 0; |
| 552 | // disable outputs |
| 553 | out_en = 0; |
| 554 | dqs_n_en = 0; |
| 555 | rdqs_en = 0; |
| 556 | dq_out_en = 0; |
| 557 | rdq_cntr = 0; |
| 558 | dqs_out_en = 0; |
| 559 | rdqs_cntr = 0; |
| 560 | // disable ODT |
| 561 | odt_en = 0; |
| 562 | odt_state = 0; |
| 563 | // reset bank state |
| 564 | active_bank = {`BANKS{1'b1}}; |
| 565 | auto_precharge_bank = 0; |
| 566 | read_precharge_bank = 0; |
| 567 | write_precharge_bank = 0; |
| 568 | // require initialization sequence |
| 569 | init_done = 0; |
| 570 | init_step = 0; |
| 571 | init_mode_reg = 0; |
| 572 | // reset DLL |
| 573 | dll_en = 0; |
| 574 | dll_reset = 0; |
| 575 | dll_locked = 0; |
| 576 | ocd = 0; |
| 577 | // exit power down and self refresh |
| 578 | in_power_down = 0; |
| 579 | in_self_refresh = 0; |
| 580 | // clear pipelines |
| 581 | al_pipeline = 0; |
| 582 | wr_pipeline = 0; |
| 583 | rd_pipeline = 0; |
| 584 | odt_pipeline = 0; |
| 585 | // clear memory |
| 586 | `ifdef MAX_MEM |
| 587 | for (i=0; i<=`MAX_SIZE; i=i+1) begin //erase memory ... one address at a time |
| 588 | memory[i] <= 'bx; |
| 589 | end |
| 590 | `else |
| 591 | memory_used <= 0; //erase memory |
| 592 | `endif |
| 593 | // clear maximum timing checks |
| 594 | tm_refresh <= 'bx; |
| 595 | for (i=0; i<`BANKS; i=i+1) begin |
| 596 | tm_bank_activate[i] <= 'bx; |
| 597 | end |
| 598 | end |
| 599 | endtask |
| 600 | |
| 601 | task chk_err; |
| 602 | input samebank; |
| 603 | input [BA_BITS-1:0] bank; |
| 604 | input [3:0] fromcmd; |
| 605 | input [3:0] cmd; |
| 606 | reg err; |
| 607 | begin |
| 608 | // all matching case expressions will be evaluated |
| 609 | casex ({samebank, fromcmd, cmd}) |
| 610 | {1'b0, LOAD_MODE, 4'b0xxx } : begin if (ck_cntr - ck_load_mode < TMRD) $display ("%m: at time %t ERROR: tMRD violation during %s", $time, cmd_string[cmd]); end |
| 611 | {1'b0, LOAD_MODE, 4'b100x } : begin if (ck_cntr - ck_load_mode < TMRD) begin $display ("%m: at time %t INFO: Load Mode to Reset condition.", $time); init_done = 0; end end |
| 612 | {1'b0, REFRESH , 4'b0xxx } : begin if ($time - tm_refresh < TRFC_MIN) $display ("%m: at time %t ERROR: tRFC violation during %s", $time, cmd_string[cmd]); end |
| 613 | {1'b0, REFRESH , PWR_DOWN } : ; // 1 tCK |
| 614 | {1'b0, REFRESH , SELF_REF } : begin if ($time - tm_refresh < TRFC_MIN) begin $display ("%m: at time %t INFO: Refresh to Reset condition", $time); init_done = 0; end end |
| 615 | {1'b0, PRECHARGE, 4'b000x } : begin if ($time - tm_precharge_all < TRPA) $display ("%m: at time %t ERROR: tRPA violation during %s", $time, cmd_string[cmd]); |
| 616 | if ($time - tm_precharge < TRP) $display ("%m: at time %t ERROR: tRP violation during %s", $time, cmd_string[cmd]); end |
| 617 | {1'b1, PRECHARGE, PRECHARGE} : begin if (DEBUG && ($time - tm_precharge_all < TRPA)) $display ("%m: at time %t INFO: Precharge All interruption during %s", $time, cmd_string[cmd]); |
| 618 | if (DEBUG && ($time - tm_bank_precharge[bank] < TRP)) $display ("%m: at time %t INFO: Precharge bank %d interruption during %s", $time, cmd_string[cmd], bank); end |
| 619 | {1'b1, PRECHARGE, ACTIVATE } : begin if ($time - tm_precharge_all < TRPA) $display ("%m: at time %t ERROR: tRPA violation during %s", $time, cmd_string[cmd]); |
| 620 | if ($time - tm_bank_precharge[bank] < TRP) $display ("%m: at time %t ERROR: tRP violation during %s to bank %d", $time, cmd_string[cmd], bank); end |
| 621 | {1'b0, PRECHARGE, PWR_DOWN } : ; //1 tCK, can be concurrent with auto precharge |
| 622 | {1'b0, PRECHARGE, SELF_REF } : begin if (($time - tm_precharge_all < TRPA) || ($time - tm_precharge < TRP)) begin $display ("%m: at time %t INFO: Precharge to Reset condition", $time); init_done = 0; end end |
| 623 | {1'b0, ACTIVATE , REFRESH } : begin if ($time - tm_activate < TRC) $display ("%m: at time %t ERROR: tRC violation during %s", $time, cmd_string[cmd]); end |
| 624 | {1'b1, ACTIVATE , PRECHARGE} : begin if (($time - tm_bank_activate[bank] > 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); |
| 625 | 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 |
| 626 | {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 |
| 627 | {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 |
| 628 | {1'b1, ACTIVATE , 4'b010x } : ; // tRCD is checked outside this task |
| 629 | {1'b1, ACTIVATE , PWR_DOWN } : ; // 1 tCK |
| 630 | {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 |
| 631 | {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 |
| 632 | {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 |
| 633 | {1'b0, WRITE , PWR_DOWN } : begin if ((ck_load_mode < ck_write) && ( |
| 634 | |write_precharge_bank |
| 635 | || (ck_cntr - ck_write_ap < 1) |
| 636 | || (ck_cntr - ck_write < write_latency + burst_length/2 + 2) |
| 637 | || ($time - tm_write_end < TWTR))) begin $display ("%m: at time %t INFO: Write to Reset condition", $time); init_done = 0; end end |
| 638 | {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 |
| 639 | {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 |
| 640 | {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 |
| 641 | {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 |
| 642 | {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 |
| 643 | {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 |
| 644 | {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]); |
| 645 | else if (ck_cntr - ck_power_down < TXARD) $display ("%m: at time %t ERROR: tXARD violation during %s", $time, cmd_string[cmd]); end |
| 646 | {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 |
| 647 | {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 |
| 648 | {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 |
| 649 | {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 |
| 650 | endcase |
| 651 | end |
| 652 | endtask |
| 653 | |
| 654 | task cmd_task; |
| 655 | input cke; |
| 656 | input [2:0] cmd; |
| 657 | input [BA_BITS-1:0] bank; |
| 658 | input [ADDR_BITS-1:0] addr; |
| 659 | reg [`BANKS:0] i; |
| 660 | integer j; |
| 661 | reg [`BANKS:0] tfaw_cntr; |
| 662 | reg [COL_BITS-1:0] col; |
| 663 | begin |
| 664 | |
| 665 | // tRFC max check |
| 666 | if (!er_trfc_max && !in_self_refresh) begin |
| 667 | if ($time - tm_refresh > TRFC_MAX) begin |
| 668 | $display ("%m: at time %t ERROR: tRFC maximum violation during %s", $time, cmd_string[cmd]); |
| 669 | er_trfc_max = 1; |
| 670 | end |
| 671 | end |
| 672 | if (cke) begin |
| 673 | if ((cmd < NOP) && ((cmd != PRECHARGE) || !addr[AP])) begin |
| 674 | for (j=0; j<NOP; j=j+1) begin |
| 675 | chk_err(1'b0, bank, j, cmd); |
| 676 | chk_err(1'b1, bank, j, cmd); |
| 677 | end |
| 678 | chk_err(1'b0, bank, PWR_DOWN, cmd); |
| 679 | chk_err(1'b0, bank, SELF_REF, cmd); |
| 680 | end |
| 681 | |
| 682 | case (cmd) |
| 683 | LOAD_MODE : begin |
| 684 | if (|active_bank) begin |
| 685 | $display ("%m: at time %t ERROR: %s Failure. All banks must be Precharged.", $time, cmd_string[cmd]); |
| 686 | if (STOP_ON_ERROR) $stop(0); |
| 687 | end else begin |
| 688 | if (DEBUG) $display ("%m: at time %t INFO: %s %d", $time, cmd_string[cmd], bank); |
| 689 | case (bank) |
| 690 | 0 : begin |
| 691 | // Burst Length |
| 692 | burst_length = 1<<addr[2:0]; |
| 693 | if ((burst_length >= BL_MIN) && (burst_length <= BL_MAX)) begin |
| 694 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Length = %d", $time, cmd_string[cmd], bank, burst_length); |
| 695 | end else begin |
| 696 | $display ("%m: at time %t ERROR: %s %d Illegal Burst Length = %d", $time, cmd_string[cmd], bank, burst_length); |
| 697 | end |
| 698 | // Burst Order |
| 699 | burst_order = addr[3]; |
| 700 | if (!burst_order) begin |
| 701 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Order = Sequential", $time, cmd_string[cmd], bank); |
| 702 | end else if (burst_order) begin |
| 703 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Burst Order = Interleaved", $time, cmd_string[cmd], bank); |
| 704 | end else begin |
| 705 | $display ("%m: at time %t ERROR: %s %d Illegal Burst Order = %d", $time, cmd_string[cmd], bank, burst_order); |
| 706 | end |
| 707 | // CAS Latency |
| 708 | cas_latency = addr[6:4]; |
| 709 | read_latency = cas_latency + additive_latency; |
| 710 | write_latency = read_latency - 1; |
| 711 | if ((cas_latency >= CL_MIN) && (cas_latency <= CL_MAX)) begin |
| 712 | if (DEBUG) $display ("%m: at time %t INFO: %s %d CAS Latency = %d", $time, cmd_string[cmd], bank, cas_latency); |
| 713 | end else begin |
| 714 | $display ("%m: at time %t ERROR: %s %d Illegal CAS Latency = %d", $time, cmd_string[cmd], bank, cas_latency); |
| 715 | end |
| 716 | // Test Mode |
| 717 | if (!addr[7]) begin |
| 718 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Test Mode = Normal", $time, cmd_string[cmd], bank); |
| 719 | end else begin |
| 720 | $display ("%m: at time %t ERROR: %s %d Illegal Test Mode = %d", $time, cmd_string[cmd], bank, addr[7]); |
| 721 | end |
| 722 | // DLL Reset |
| 723 | dll_reset = addr[8]; |
| 724 | if (!dll_reset) begin |
| 725 | if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Reset = Normal", $time, cmd_string[cmd], bank); |
| 726 | end else if (dll_reset) begin |
| 727 | if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Reset = Reset DLL", $time, cmd_string[cmd], bank); |
| 728 | dll_locked = 0; |
| 729 | ck_dll_reset <= ck_cntr; |
| 730 | end else begin |
| 731 | $display ("%m: at time %t ERROR: %s %d Illegal DLL Reset = %d", $time, cmd_string[cmd], bank, dll_reset); |
| 732 | end |
| 733 | // Write Recovery |
| 734 | write_recovery = addr[11:9] + 1; |
| 735 | if ((write_recovery >= WR_MIN) && (write_recovery <= WR_MAX)) begin |
| 736 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Write Recovery = %d", $time, cmd_string[cmd], bank, write_recovery); |
| 737 | end else begin |
| 738 | $display ("%m: at time %t ERROR: %s %d Illegal Write Recovery = %d", $time, cmd_string[cmd], bank, write_recovery); |
| 739 | end |
| 740 | // Power Down Mode |
| 741 | low_power = addr[12]; |
| 742 | if (!low_power) begin |
| 743 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Power Down Mode = Fast Exit", $time, cmd_string[cmd], bank); |
| 744 | end else if (low_power) begin |
| 745 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Power Down Mode = Slow Exit", $time, cmd_string[cmd], bank); |
| 746 | end else begin |
| 747 | $display ("%m: at time %t ERROR: %s %d Illegal Power Down Mode = %d", $time, cmd_string[cmd], bank, low_power); |
| 748 | end |
| 749 | end |
| 750 | 1 : begin |
| 751 | // DLL Enable |
| 752 | dll_en = !addr[0]; |
| 753 | if (!dll_en) begin |
| 754 | if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Enable = Disabled", $time, cmd_string[cmd], bank); |
| 755 | end else if (dll_en) begin |
| 756 | if (DEBUG) $display ("%m: at time %t INFO: %s %d DLL Enable = Enabled", $time, cmd_string[cmd], bank); |
| 757 | end else begin |
| 758 | $display ("%m: at time %t ERROR: %s %d Illegal DLL Enable = %d", $time, cmd_string[cmd], bank, dll_en); |
| 759 | end |
| 760 | // Output Drive Strength |
| 761 | if (!addr[1]) begin |
| 762 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Drive Strength = Full", $time, cmd_string[cmd], bank); |
| 763 | end else if (addr[1]) begin |
| 764 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Drive Strength = Reduced", $time, cmd_string[cmd], bank); |
| 765 | end else begin |
| 766 | $display ("%m: at time %t ERROR: %s %d Illegal Output Drive Strength = %d", $time, cmd_string[cmd], bank, addr[1]); |
| 767 | end |
| 768 | // ODT Rtt |
| 769 | odt_rtt = {addr[6], addr[2]}; |
| 770 | if (odt_rtt == 2'b00) begin |
| 771 | if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = Disabled", $time, cmd_string[cmd], bank); |
| 772 | odt_en = 0; |
| 773 | end else if (odt_rtt == 2'b01) begin |
| 774 | if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 75 Ohm", $time, cmd_string[cmd], bank); |
| 775 | odt_en = 1; |
| 776 | tm_odt_en <= $time; |
| 777 | end else if (odt_rtt == 2'b10) begin |
| 778 | if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 150 Ohm", $time, cmd_string[cmd], bank); |
| 779 | odt_en = 1; |
| 780 | tm_odt_en <= $time; |
| 781 | end else if (odt_rtt == 2'b11) begin |
| 782 | if (DEBUG) $display ("%m: at time %t INFO: %s %d ODT Rtt = 50 Ohm", $time, cmd_string[cmd], bank); |
| 783 | odt_en = 1; |
| 784 | tm_odt_en <= $time; |
| 785 | end else begin |
| 786 | $display ("%m: at time %t ERROR: %s %d Illegal ODT Rtt = %d", $time, cmd_string[cmd], bank, odt_rtt); |
| 787 | odt_en = 0; |
| 788 | end |
| 789 | // Additive Latency |
| 790 | additive_latency = addr[5:3]; |
| 791 | read_latency = cas_latency + additive_latency; |
| 792 | write_latency = read_latency - 1; |
| 793 | if ((additive_latency >= AL_MIN) && (additive_latency <= AL_MAX)) begin |
| 794 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Additive Latency = %d", $time, cmd_string[cmd], bank, additive_latency); |
| 795 | end else begin |
| 796 | $display ("%m: at time %t ERROR: %s %d Illegal Additive Latency = %d", $time, cmd_string[cmd], bank, additive_latency); |
| 797 | end |
| 798 | // OCD Program |
| 799 | ocd = addr[9:7]; |
| 800 | if (ocd == 3'b000) begin |
| 801 | if (DEBUG) $display ("%m: at time %t INFO: %s %d OCD Program = OCD Exit", $time, cmd_string[cmd], bank); |
| 802 | end else if (ocd == 3'b111) begin |
| 803 | if (DEBUG) $display ("%m: at time %t INFO: %s %d OCD Program = OCD Default", $time, cmd_string[cmd], bank); |
| 804 | end else begin |
| 805 | $display ("%m: at time %t ERROR: %s %d Illegal OCD Program = %b", $time, cmd_string[cmd], bank, ocd); |
| 806 | end |
| 807 | |
| 808 | // DQS_N Enable |
| 809 | dqs_n_en = !addr[10]; |
| 810 | if (!dqs_n_en) begin |
| 811 | if (DEBUG) $display ("%m: at time %t INFO: %s %d DQS_N Enable = Disabled", $time, cmd_string[cmd], bank); |
| 812 | end else if (dqs_n_en) begin |
| 813 | if (DEBUG) $display ("%m: at time %t INFO: %s %d DQS_N Enable = Enabled", $time, cmd_string[cmd], bank); |
| 814 | end else begin |
| 815 | $display ("%m: at time %t ERROR: %s %d Illegal DQS_N Enable = %d", $time, cmd_string[cmd], bank, dqs_n_en); |
| 816 | end |
| 817 | // RDQS Enable |
| 818 | rdqs_en = addr[11]; |
| 819 | if (!rdqs_en) begin |
| 820 | if (DEBUG) $display ("%m: at time %t INFO: %s %d RDQS Enable = Disabled", $time, cmd_string[cmd], bank); |
| 821 | end else if (rdqs_en) begin |
| 822 | `ifdef x8 |
| 823 | if (DEBUG) $display ("%m: at time %t INFO: %s %d RDQS Enable = Enabled", $time, cmd_string[cmd], bank); |
| 824 | `else |
| 825 | $display ("%m: at time %t WARNING: %s %d Illegal RDQS Enable. RDQS only exists on a x8 part", $time, cmd_string[cmd], bank); |
| 826 | rdqs_en = 0; |
| 827 | `endif |
| 828 | end else begin |
| 829 | $display ("%m: at time %t ERROR: %s %d Illegal RDQS Enable = %d", $time, cmd_string[cmd], bank, rdqs_en); |
| 830 | end |
| 831 | // Output Enable |
| 832 | out_en = !addr[12]; |
| 833 | if (!out_en) begin |
| 834 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Enable = Disabled", $time, cmd_string[cmd], bank); |
| 835 | end else if (out_en) begin |
| 836 | if (DEBUG) $display ("%m: at time %t INFO: %s %d Output Enable = Enabled", $time, cmd_string[cmd], bank); |
| 837 | end else begin |
| 838 | $display ("%m: at time %t ERROR: %s %d Illegal Output Enable = %d", $time, cmd_string[cmd], bank, out_en); |
| 839 | end |
| 840 | end |
| 841 | 2 : begin |
| 842 | // High Temperature Self Refresh rate |
| 843 | if (!addr[7]) begin |
| 844 | if (DEBUG) $display ("%m: at time %t INFO: %s %d High Temperature Self Refresh rate = 1X (0C-85C)", $time, cmd_string[cmd], bank); |
| 845 | end else if (addr[7]) begin |
| 846 | if (DEBUG) $display ("%m: at time %t INFO: %s %d High Temperature Self Refresh rate = 2X (>85C)", $time, cmd_string[cmd], bank); |
| 847 | end else begin |
| 848 | $display ("%m: at time %t ERROR: %s %d Illegal High Temperature Self Refresh rate = %d", $time, cmd_string[cmd], bank, addr[7]); |
| 849 | end |
| 850 | if ((addr & ~(1<<7)) !== 0) begin |
| 851 | $display ("%m: at time %t ERROR: %s %d Illegal value. Reserved bits must be programmed to zero", $time, cmd_string[cmd], bank); |
| 852 | end |
| 853 | end |
| 854 | 3 : begin |
| 855 | if (addr !== 0) begin |
| 856 | $display ("%m: at time %t ERROR: %s %d Illegal value. Reserved bits must be programmed to zero", $time, cmd_string[cmd], bank); |
| 857 | end |
| 858 | end |
| 859 | endcase |
| 860 | init_mode_reg[bank] = 1; |
| 861 | ck_load_mode <= ck_cntr; |
| 862 | end |
| 863 | end |
| 864 | REFRESH : begin |
| 865 | if (|active_bank) begin |
| 866 | $display ("%m: at time %t ERROR: %s Failure. All banks must be Precharged.", $time, cmd_string[cmd]); |
| 867 | if (STOP_ON_ERROR) $stop(0); |
| 868 | end else begin |
| 869 | if (DEBUG) $display ("%m: at time %t INFO: %s", $time, cmd_string[cmd]); |
| 870 | er_trfc_max = 0; |
| 871 | ref_cntr = ref_cntr + 1; |
| 872 | tm_refresh <= $time; |
| 873 | end |
| 874 | end |
| 875 | PRECHARGE : begin |
| 876 | if (addr[AP]) begin |
| 877 | // tRPA timing applies when the PRECHARGE (ALL) command is issued, regardless of |
| 878 | // the number of banks already open or closed. |
| 879 | for (i=0; i<`BANKS; i=i+1) begin |
| 880 | for (j=0; j<NOP; j=j+1) begin |
| 881 | chk_err(1'b0, i, j, cmd); |
| 882 | chk_err(1'b1, i, j, cmd); |
| 883 | end |
| 884 | chk_err(1'b0, i, PWR_DOWN, cmd); |
| 885 | chk_err(1'b0, i, SELF_REF, cmd); |
| 886 | end |
| 887 | if (|auto_precharge_bank) begin |
| 888 | $display ("%m: at time %t ERROR: %s All Failure. Auto Precharge is scheduled.", $time, cmd_string[cmd]); |
| 889 | if (STOP_ON_ERROR) $stop(0); |
| 890 | end else begin |
| 891 | if (DEBUG) $display ("%m: at time %t INFO: %s All", $time, cmd_string[cmd]); |
| 892 | active_bank = 0; |
| 893 | tm_precharge_all <= $time; |
| 894 | end |
| 895 | end else begin |
| 896 | // A PRECHARGE command is allowed if there is no open row in that bank (idle state) |
| 897 | // or if the previously open row is already in the process of precharging. |
| 898 | // However, the precharge period will be determined by the last PRECHARGE command issued to the bank. |
| 899 | if (auto_precharge_bank[bank]) begin |
| 900 | $display ("%m: at time %t ERROR: %s Failure. Auto Precharge is scheduled to bank %d.", $time, cmd_string[cmd], bank); |
| 901 | if (STOP_ON_ERROR) $stop(0); |
| 902 | end else begin |
| 903 | if (DEBUG) $display ("%m: at time %t INFO: %s bank %d", $time, cmd_string[cmd], bank); |
| 904 | active_bank[bank] = 1'b0; |
| 905 | tm_bank_precharge[bank] <= $time; |
| 906 | tm_precharge <= $time; |
| 907 | end |
| 908 | end |
| 909 | end |
| 910 | ACTIVATE : begin |
| 911 | if (`BANKS == 8) begin |
| 912 | tfaw_cntr = 0; |
| 913 | for (i=0; i<`BANKS; i=i+1) begin |
| 914 | if ($time - tm_bank_activate[i] < TFAW) begin |
| 915 | tfaw_cntr = tfaw_cntr + 1; |
| 916 | end |
| 917 | end |
| 918 | if (tfaw_cntr > 3) begin |
| 919 | $display ("%m: at time %t ERROR: tFAW violation during %s to bank %d", $time, cmd_string[cmd], bank); |
| 920 | end |
| 921 | end |
| 922 | |
| 923 | if (!init_done) begin |
| 924 | $display ("%m: at time %t ERROR: %s Failure. Initialization sequence is not complete.", $time, cmd_string[cmd]); |
| 925 | if (STOP_ON_ERROR) $stop(0); |
| 926 | end else if (active_bank[bank]) begin |
| 927 | $display ("%m: at time %t ERROR: %s Failure. Bank %d must be Precharged.", $time, cmd_string[cmd], bank); |
| 928 | if (STOP_ON_ERROR) $stop(0); |
| 929 | end else begin |
| 930 | if (addr >= 1<<ROW_BITS) begin |
| 931 | $display ("%m: at time %t WARNING: row = %h does not exist. Maximum row = %h", $time, addr, (1<<ROW_BITS)-1); |
| 932 | end |
| 933 | if (DEBUG) $display ("%m: at time %t INFO: %s bank %d row %h", $time, cmd_string[cmd], bank, addr); |
| 934 | active_bank[bank] = 1'b1; |
| 935 | active_row[bank] = addr; |
| 936 | tm_bank_activate[bank] <= $time; |
| 937 | tm_activate <= $time; |
| 938 | end |
| 939 | |
| 940 | end |
| 941 | WRITE : begin |
| 942 | if (!init_done) begin |
| 943 | $display ("%m: at time %t ERROR: %s Failure. Initialization sequence is not complete.", $time, cmd_string[cmd]); |
| 944 | if (STOP_ON_ERROR) $stop(0); |
| 945 | end else if (!active_bank[bank]) begin |
| 946 | $display ("%m: at time %t ERROR: %s Failure. Bank %d must be Activated.", $time, cmd_string[cmd], bank); |
| 947 | if (STOP_ON_ERROR) $stop(0); |
| 948 | end else if (auto_precharge_bank[bank]) begin |
| 949 | $display ("%m: at time %t ERROR: %s Failure. Auto Precharge is scheduled to bank %d.", $time, cmd_string[cmd], bank); |
| 950 | if (STOP_ON_ERROR) $stop(0); |
| 951 | end else if ((ck_cntr - ck_write < burst_length/2) && (ck_cntr - ck_write)%2) begin |
| 952 | $display ("%m: at time %t ERROR: %s Failure. Illegal burst interruption.", $time, cmd_string[cmd]); |
| 953 | if (STOP_ON_ERROR) $stop(0); |
| 954 | end else begin |
| 955 | if (addr[AP]) begin |
| 956 | auto_precharge_bank[bank] = 1'b1; |
| 957 | write_precharge_bank[bank] = 1'b1; |
| 958 | end |
| 959 | col = ((addr>>1) & -1*(1<<AP)) | (addr & {AP{1'b1}}); |
| 960 | if (col >= 1<<COL_BITS) begin |
| 961 | $display ("%m: at time %t WARNING: col = %h does not exist. Maximum col = %h", $time, col, (1<<COL_BITS)-1); |
| 962 | end |
| 963 | if (DEBUG) $display ("%m: at time %t INFO: %s bank %d col %h, auto precharge %d", $time, cmd_string[cmd], bank, col, addr[AP]); |
| 964 | wr_pipeline[2*write_latency + 1] = 1; |
| 965 | ba_pipeline[2*write_latency + 1] = bank; |
| 966 | row_pipeline[2*write_latency + 1] = active_row[bank]; |
| 967 | col_pipeline[2*write_latency + 1] = col; |
| 968 | ck_bank_write[bank] <= ck_cntr; |
| 969 | ck_write <= ck_cntr; |
| 970 | end |
| 971 | end |
| 972 | READ : begin |
| 973 | if (!dll_locked) |
| 974 | $display ("%m: at time %t WARNING: %s prior to DLL locked. Failing to wait for synchronization to occur may result in a violation of the tAC or tDQSCK parameters.", $time, cmd_string[cmd]); |
| 975 | if (!init_done) begin |
| 976 | $display ("%m: at time %t ERROR: %s Failure. Initialization sequence is not complete.", $time, cmd_string[cmd]); |
| 977 | if (STOP_ON_ERROR) $stop(0); |
| 978 | end else if (!active_bank[bank]) begin |
| 979 | $display ("%m: at time %t ERROR: %s Failure. Bank %d must be Activated.", $time, cmd_string[cmd], bank); |
| 980 | if (STOP_ON_ERROR) $stop(0); |
| 981 | end else if (auto_precharge_bank[bank]) begin |
| 982 | $display ("%m: at time %t ERROR: %s Failure. Auto Precharge is scheduled to bank %d.", $time, cmd_string[cmd], bank); |
| 983 | if (STOP_ON_ERROR) $stop(0); |
| 984 | end else if ((ck_cntr - ck_read < burst_length/2) && (ck_cntr - ck_read)%2) begin |
| 985 | $display ("%m: at time %t ERROR: %s Failure. Illegal burst interruption.", $time, cmd_string[cmd]); |
| 986 | if (STOP_ON_ERROR) $stop(0); |
| 987 | end else begin |
| 988 | if (addr[AP]) begin |
| 989 | auto_precharge_bank[bank] = 1'b1; |
| 990 | read_precharge_bank[bank] = 1'b1; |
| 991 | end |
| 992 | col = ((addr>>1) & -1*(1<<AP)) | (addr & {AP{1'b1}}); |
| 993 | if (col >= 1<<COL_BITS) begin |
| 994 | $display ("%m: at time %t WARNING: col = %h does not exist. Maximum col = %h", $time, col, (1<<COL_BITS)-1); |
| 995 | end |
| 996 | if (DEBUG) $display ("%m: at time %t INFO: %s bank %d col %h, auto precharge %d", $time, cmd_string[cmd], bank, col, addr[AP]); |
| 997 | rd_pipeline[2*read_latency - 1] = 1; |
| 998 | ba_pipeline[2*read_latency - 1] = bank; |
| 999 | row_pipeline[2*read_latency - 1] = active_row[bank]; |
| 1000 | col_pipeline[2*read_latency - 1] = col; |
| 1001 | ck_bank_read[bank] <= ck_cntr; |
| 1002 | ck_read <= ck_cntr; |
| 1003 | end |
| 1004 | end |
| 1005 | NOP: begin |
| 1006 | if (in_power_down) begin |
| 1007 | if (DEBUG) $display ("%m: at time %t INFO: Power Down Exit", $time); |
| 1008 | in_power_down = 0; |
| 1009 | if (|active_bank & low_power) begin // slow exit active power down |
| 1010 | ck_slow_exit_pd <= ck_cntr; |
| 1011 | end |
| 1012 | ck_power_down <= ck_cntr; |
| 1013 | end |
| 1014 | if (in_self_refresh) begin |
| 1015 | if ($time - tm_cke < TISXR) |
| 1016 | $display ("%m: at time %t ERROR: tISXR violation during Self Refresh Exit", $time); |
| 1017 | if (DEBUG) $display ("%m: at time %t INFO: Self Refresh Exit", $time); |
| 1018 | in_self_refresh = 0; |
| 1019 | ck_dll_reset <= ck_cntr; |
| 1020 | ck_self_refresh <= ck_cntr; |
| 1021 | tm_self_refresh <= $time; |
| 1022 | tm_refresh <= $time; |
| 1023 | end |
| 1024 | end |
| 1025 | endcase |
| 1026 | if ((prev_cke !== 1) && (cmd !== NOP)) begin |
| 1027 | $display ("%m: at time %t ERROR: NOP or Deselect is required when CKE goes active.", $time); |
| 1028 | end |
| 1029 | if (!init_done) begin |
| 1030 | case (init_step) |
| 1031 | 0 : begin |
| 1032 | if ($time < 200000000) |
| 1033 | $display ("%m: at time %t WARNING: 200 us is required before CKE goes active.", $time); |
| 1034 | // if (cmd_chk + 200000000 > $time) |
| 1035 | // $display("%m: at time %t WARNING: NOP or DESELECT is required for 200 us before CKE is brought high", $time); |
| 1036 | init_step = init_step + 1; |
| 1037 | end |
| 1038 | 1 : if (dll_en) init_step = init_step + 1; |
| 1039 | 2 : begin |
| 1040 | if (&init_mode_reg && dll_reset) begin |
| 1041 | active_bank = {`BANKS{1'b1}}; // require Precharge All or bank Precharges |
| 1042 | ref_cntr = 0; // require refresh |
| 1043 | init_step = init_step + 1; |
| 1044 | end |
| 1045 | end |
| 1046 | 3 : if (ref_cntr == 2) begin |
| 1047 | init_step = init_step + 1; |
| 1048 | end |
| 1049 | 4 : if (!dll_reset) init_step = init_step + 1; |
| 1050 | 5 : if (ocd == 3'b111) init_step = init_step + 1; |
| 1051 | 6 : begin |
| 1052 | if (ocd == 3'b000) begin |
| 1053 | if (DEBUG) $display ("%m: at time %t INFO: Initialization Sequence is complete", $time); |
| 1054 | init_done = 1; |
| 1055 | end |
| 1056 | end |
| 1057 | endcase |
| 1058 | end |
| 1059 | end else if (prev_cke) begin |
| 1060 | if ((!init_done) && (init_step > 1)) begin |
| 1061 | $display ("%m: at time %t ERROR: CKE must remain active until the initialization sequence is complete.", $time); |
| 1062 | if (STOP_ON_ERROR) $stop(0); |
| 1063 | end |
| 1064 | case (cmd) |
| 1065 | REFRESH : begin |
| 1066 | for (j=0; j<NOP; j=j+1) begin |
| 1067 | chk_err(1'b0, bank, j, SELF_REF); |
| 1068 | end |
| 1069 | chk_err(1'b0, bank, PWR_DOWN, SELF_REF); |
| 1070 | chk_err(1'b0, bank, SELF_REF, SELF_REF); |
| 1071 | if (|active_bank) begin |
| 1072 | $display ("%m: at time %t ERROR: Self Refresh Failure. All banks must be Precharged.", $time); |
| 1073 | if (STOP_ON_ERROR) $stop(0); |
| 1074 | init_done = 0; |
| 1075 | end else if (odt_en && odt_state) begin |
| 1076 | $display ("%m: at time %t ERROR: ODT must be off prior to entering Self Refresh", $time); |
| 1077 | if (STOP_ON_ERROR) $stop(0); |
| 1078 | init_done = 0; |
| 1079 | end else if (!init_done) begin |
| 1080 | $display ("%m: at time %t ERROR: Self Refresh Failure. Initialization sequence is not complete.", $time); |
| 1081 | if (STOP_ON_ERROR) $stop(0); |
| 1082 | end else begin |
| 1083 | if (DEBUG) $display ("%m: at time %t INFO: Self Refresh Enter", $time); |
| 1084 | in_self_refresh = 1; |
| 1085 | dll_locked = 0; |
| 1086 | end |
| 1087 | end |
| 1088 | NOP : begin |
| 1089 | // entering slow_exit or precharge power down and tANPD has not been satisfied |
| 1090 | if ((low_power || (active_bank == 0)) && (ck_cntr - ck_odt < TANPD)) |
| 1091 | $display ("%m: at time %t WARNING: tANPD violation during %s. Synchronous or asynchronous change in termination resistance is possible.", $time, cmd_string[PWR_DOWN]); |
| 1092 | for (j=0; j<NOP; j=j+1) begin |
| 1093 | chk_err(1'b0, bank, j, PWR_DOWN); |
| 1094 | end |
| 1095 | chk_err(1'b0, bank, PWR_DOWN, PWR_DOWN); |
| 1096 | chk_err(1'b0, bank, SELF_REF, PWR_DOWN); |
| 1097 | |
| 1098 | if (!init_done) begin |
| 1099 | $display ("%m: at time %t ERROR: Power Down Failure. Initialization sequence is not complete.", $time); |
| 1100 | if (STOP_ON_ERROR) $stop(0); |
| 1101 | end else begin |
| 1102 | if (DEBUG) begin |
| 1103 | if (|active_bank) begin |
| 1104 | $display ("%m: at time %t INFO: Active Power Down Enter", $time); |
| 1105 | end else begin |
| 1106 | $display ("%m: at time %t INFO: Precharge Power Down Enter", $time); |
| 1107 | end |
| 1108 | end |
| 1109 | in_power_down = 1; |
| 1110 | end |
| 1111 | end |
| 1112 | default : begin |
| 1113 | $display ("%m: at time %t ERROR: NOP, Deselect, or Refresh is required when CKE goes inactive.", $time); |
| 1114 | init_done = 0; |
| 1115 | end |
| 1116 | endcase |
| 1117 | if (!init_done) begin |
| 1118 | if (DEBUG) $display ("%m: at time %t WARNING: Reset has occurred. Device must be re-initialized.", $time); |
| 1119 | reset_task; |
| 1120 | end |
| 1121 | end |
| 1122 | prev_cke = cke; |
| 1123 | end |
| 1124 | endtask |
| 1125 | |
| 1126 | task data_task; |
| 1127 | reg [BA_BITS-1:0] bank; |
| 1128 | reg [ROW_BITS-1:0] row; |
| 1129 | reg [COL_BITS-1:0] col; |
| 1130 | integer i; |
| 1131 | integer j; |
| 1132 | begin |
| 1133 | |
| 1134 | if (diff_ck) begin |
| 1135 | for (i=0; i<36; i=i+1) begin |
| 1136 | if (dq_in_valid && dll_locked && ($time - tm_dqs_neg[i] < $rtoi(TDSS*tck_avg))) |
| 1137 | $display ("%m: at time %t ERROR: tDSS violation on %s bit %d", $time, dqs_string[i/18], i%18); |
| 1138 | if (check_write_dqs_high[i]) |
| 1139 | $display ("%m: at time %t ERROR: %s bit %d latching edge required during the preceding clock period.", $time, dqs_string[i/18], i%18); |
| 1140 | end |
| 1141 | check_write_dqs_high <= 0; |
| 1142 | end else begin |
| 1143 | for (i=0; i<36; i=i+1) begin |
| 1144 | if (dll_locked && dq_in_valid && (i % 18 < DQS_BITS)) begin // Only check valid DQS group |
| 1145 | tm_tdqss = abs_value($itor(tm_ck_pos) - tm_dqss_pos[i]); |
| 1146 | //$display ("at time %t, tm_tdqss = %0d, tm_ck_pos = %0d, tm_dqss_pos [%0d] = %0d", $time, tm_tdqss, tm_ck_pos, i, tm_dqss_pos[i]); |
| 1147 | if ((tm_tdqss < tck_avg/2.0) && (tm_tdqss > TDQSS*tck_avg)) |
| 1148 | $display ("%m: at time %t ERROR: tDQSS violation on %s bit %d", $time, dqs_string[i/18], i%18); |
| 1149 | end |
| 1150 | if (check_write_dqs_low[i]) |
| 1151 | $display ("%m: at time %t ERROR: %s bit %d latching edge required during the preceding clock period", $time, dqs_string[i/18], i%18); |
| 1152 | end |
| 1153 | check_write_preamble <= 0; |
| 1154 | check_write_postamble <= 0; |
| 1155 | check_write_dqs_low <= 0; |
| 1156 | end |
| 1157 | |
| 1158 | if (wr_pipeline[0] || rd_pipeline[0]) begin |
| 1159 | bank = ba_pipeline[0]; |
| 1160 | row = row_pipeline[0]; |
| 1161 | col = col_pipeline[0]; |
| 1162 | burst_cntr = 0; |
| 1163 | memory_read(bank, row, col, memory_data); |
| 1164 | end |
| 1165 | |
| 1166 | // burst counter |
| 1167 | if (burst_cntr < burst_length) begin |
| 1168 | burst_position = col ^ burst_cntr; |
| 1169 | if (!burst_order) begin |
| 1170 | burst_position[BO_BITS-1:0] = col + burst_cntr; |
| 1171 | end |
| 1172 | burst_cntr = burst_cntr + 1; |
| 1173 | end |
| 1174 | |
| 1175 | // write dqs counter |
| 1176 | if (wr_pipeline[WDQS_PRE + 1]) begin |
| 1177 | wdqs_cntr = WDQS_PRE + burst_length + WDQS_PST - 1; |
| 1178 | end |
| 1179 | // write dqs |
| 1180 | if ((wdqs_cntr == burst_length + WDQS_PST) && (wdq_cntr == 0)) begin //write preamble |
| 1181 | check_write_preamble <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}}; |
| 1182 | end |
| 1183 | if (wdqs_cntr > 1) begin // write data |
| 1184 | if ((wdqs_cntr - WDQS_PST)%2) begin |
| 1185 | check_write_dqs_high <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}}; |
| 1186 | end else begin |
| 1187 | check_write_dqs_low <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}}; |
| 1188 | end |
| 1189 | end |
| 1190 | if (wdqs_cntr == WDQS_PST) begin // write postamble |
| 1191 | check_write_postamble <= ({DQS_BITS{dqs_n_en}}<<18) | {DQS_BITS{1'b1}}; |
| 1192 | end |
| 1193 | if (wdqs_cntr > 0) begin |
| 1194 | wdqs_cntr = wdqs_cntr - 1; |
| 1195 | end |
| 1196 | |
| 1197 | // write dq |
| 1198 | if (dq_in_valid) begin // write data |
| 1199 | bit_mask = 0; |
| 1200 | if (diff_ck) begin |
| 1201 | for (i=0; i<DM_BITS; i=i+1) begin |
| 1202 | bit_mask = bit_mask | ({`DQ_PER_DQS{~dm_in_neg[i]}}<<(burst_position*DQ_BITS + i*`DQ_PER_DQS)); |
| 1203 | end |
| 1204 | memory_data = (dq_in_neg<<(burst_position*DQ_BITS) & bit_mask) | (memory_data & ~bit_mask); |
| 1205 | end else begin |
| 1206 | for (i=0; i<DM_BITS; i=i+1) begin |
| 1207 | bit_mask = bit_mask | ({`DQ_PER_DQS{~dm_in_pos[i]}}<<(burst_position*DQ_BITS + i*`DQ_PER_DQS)); |
| 1208 | end |
| 1209 | memory_data = (dq_in_pos<<(burst_position*DQ_BITS) & bit_mask) | (memory_data & ~bit_mask); |
| 1210 | end |
| 1211 | dq_temp = memory_data>>(burst_position*DQ_BITS); |
| 1212 | 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); |
| 1213 | if (burst_cntr%BL_MIN == 0) begin |
| 1214 | memory_write(bank, row, col, memory_data); |
| 1215 | end |
| 1216 | end |
| 1217 | if (wr_pipeline[1]) begin |
| 1218 | wdq_cntr = burst_length; |
| 1219 | end |
| 1220 | if (wdq_cntr > 0) begin |
| 1221 | wdq_cntr = wdq_cntr - 1; |
| 1222 | dq_in_valid = 1'b1; |
| 1223 | end else begin |
| 1224 | dq_in_valid = 1'b0; |
| 1225 | dqs_in_valid <= 1'b0; |
| 1226 | for (i=0; i<36; i=i+1) begin |
| 1227 | wdqs_pos_cntr[i] <= 0; |
| 1228 | end |
| 1229 | end |
| 1230 | if (wr_pipeline[0]) begin |
| 1231 | b2b_write <= 1'b0; |
| 1232 | end |
| 1233 | if (wr_pipeline[2]) begin |
| 1234 | if (dqs_in_valid) begin |
| 1235 | b2b_write <= 1'b1; |
| 1236 | end |
| 1237 | dqs_in_valid <= 1'b1; |
| 1238 | end |
| 1239 | // read dqs enable counter |
| 1240 | if (rd_pipeline[RDQSEN_PRE]) begin |
| 1241 | rdqsen_cntr = RDQSEN_PRE + burst_length + RDQSEN_PST - 1; |
| 1242 | end |
| 1243 | if (rdqsen_cntr > 0) begin |
| 1244 | rdqsen_cntr = rdqsen_cntr - 1; |
| 1245 | dqs_out_en = 1'b1; |
| 1246 | end else begin |
| 1247 | dqs_out_en = 1'b0; |
| 1248 | end |
| 1249 | |
| 1250 | // read dqs counter |
| 1251 | if (rd_pipeline[RDQS_PRE]) begin |
| 1252 | rdqs_cntr = RDQS_PRE + burst_length + RDQS_PST - 1; |
| 1253 | end |
| 1254 | // read dqs |
| 1255 | if ((rdqs_cntr >= burst_length + RDQS_PST) && (rdq_cntr == 0)) begin //read preamble |
| 1256 | dqs_out = 1'b0; |
| 1257 | end else if (rdqs_cntr > RDQS_PST) begin // read data |
| 1258 | dqs_out = rdqs_cntr - RDQS_PST; |
| 1259 | end else if (rdqs_cntr > 0) begin // read postamble |
| 1260 | dqs_out = 1'b0; |
| 1261 | end else begin |
| 1262 | dqs_out = 1'b1; |
| 1263 | end |
| 1264 | if (rdqs_cntr > 0) begin |
| 1265 | rdqs_cntr = rdqs_cntr - 1; |
| 1266 | end |
| 1267 | |
| 1268 | // read dq enable counter |
| 1269 | if (rd_pipeline[RDQEN_PRE]) begin |
| 1270 | rdqen_cntr = RDQEN_PRE + burst_length + RDQEN_PST; |
| 1271 | end |
| 1272 | if (rdqen_cntr > 0) begin |
| 1273 | rdqen_cntr = rdqen_cntr - 1; |
| 1274 | dq_out_en = 1'b1; |
| 1275 | end else begin |
| 1276 | dq_out_en = 1'b0; |
| 1277 | end |
| 1278 | // read dq |
| 1279 | if (rd_pipeline[0]) begin |
| 1280 | rdq_cntr = burst_length; |
| 1281 | end |
| 1282 | if (rdq_cntr > 0) begin // read data |
| 1283 | dq_temp = memory_data>>(burst_position*DQ_BITS); |
| 1284 | dq_out = dq_temp; |
| 1285 | 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); |
| 1286 | rdq_cntr = rdq_cntr - 1; |
| 1287 | end else begin |
| 1288 | dq_out = {DQ_BITS{1'b1}}; |
| 1289 | end |
| 1290 | |
| 1291 | // delay signals prior to output |
| 1292 | if (RANDOM_OUT_DELAY && (dqs_out_en || |dqs_out_en_dly || dq_out_en || |dq_out_en_dly)) begin |
| 1293 | for (i=0; i<DQS_BITS; i=i+1) begin |
| 1294 | // DQSCK requirements |
| 1295 | // 1.) less than tDQSCK |
| 1296 | // 2.) greater than -tDQSCK |
| 1297 | // 3.) cannot change more than tQHS + tDQSQ from previous DQS edge |
| 1298 | dqsck_max = TDQSCK; |
| 1299 | if (dqsck_max > dqsck[i] + TQHS + TDQSQ) begin |
| 1300 | dqsck_max = dqsck[i] + TQHS + TDQSQ; |
| 1301 | end |
| 1302 | dqsck_min = -1*TDQSCK; |
| 1303 | if (dqsck_min < dqsck[i] - TQHS - TDQSQ) begin |
| 1304 | dqsck_min = dqsck[i] - TQHS - TDQSQ; |
| 1305 | end |
| 1306 | |
| 1307 | // DQSQ requirements |
| 1308 | // 1.) less than tAC - DQSCK |
| 1309 | // 2.) less than tDQSQ |
| 1310 | // 3.) greater than -tAC |
| 1311 | // 4.) greater than tQH from previous DQS edge |
| 1312 | dqsq_min = -1*TAC; |
| 1313 | if (dqsq_min < dqsck[i] - TQHS) begin |
| 1314 | dqsq_min = dqsck[i] - TQHS; |
| 1315 | end |
| 1316 | if (dqsck_min == dqsck_max) begin |
| 1317 | dqsck[i] = dqsck_min; |
| 1318 | end else begin |
| 1319 | dqsck[i] = $dist_uniform(seed, dqsck_min, dqsck_max); |
| 1320 | end |
| 1321 | dqsq_max = TAC; |
| 1322 | if (dqsq_max > TDQSQ + dqsck[i]) begin |
| 1323 | dqsq_max = TDQSQ + dqsck[i]; |
| 1324 | end |
| 1325 | |
| 1326 | dqs_out_en_dly[i] <= #(tck_avg/2.0 + ($random % TAC)) dqs_out_en; |
| 1327 | dqs_out_dly[i] <= #(tck_avg/2.0 + dqsck[i]) dqs_out; |
| 1328 | for (j=0; j<`DQ_PER_DQS; j=j+1) begin |
| 1329 | if (dq_out_en) begin // tLZ2 |
| 1330 | dq_out_en_dly[i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + $dist_uniform(seed, -2*TAC, dqsq_max)) dq_out_en; |
| 1331 | end else begin // tHZ |
| 1332 | dq_out_en_dly[i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + ($random % TAC)) dq_out_en; |
| 1333 | end |
| 1334 | if (dqsq_min == dqsq_max) begin |
| 1335 | dq_out_dly [i*`DQ_PER_DQS + j] <= #(tck_avg/2.0 + dqsq_min) dq_out[i*`DQ_PER_DQS + j]; |
| 1336 | end else begin |
| 1337 | 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]; |
| 1338 | end |
| 1339 | end |
| 1340 | end |
| 1341 | end else begin |
| 1342 | out_delay = tck_avg/2.0; |
| 1343 | dqs_out_en_dly <= #(out_delay) {DQS_BITS{dqs_out_en}}; |
| 1344 | dqs_out_dly <= #(out_delay) {DQS_BITS{dqs_out }}; |
| 1345 | dq_out_en_dly <= #(out_delay) {DQ_BITS {dq_out_en }}; |
| 1346 | dq_out_dly <= #(out_delay) {DQ_BITS {dq_out }}; |
| 1347 | end |
| 1348 | end |
| 1349 | endtask |
| 1350 | |
| 1351 | always @(diff_ck) begin : main |
| 1352 | integer i; |
| 1353 | |
| 1354 | if (!in_self_refresh && (diff_ck !== 1'b0) && (diff_ck !== 1'b1)) |
| 1355 | $display ("%m: at time %t ERROR: CK and CK_N are not allowed to go to an unknown state.", $time); |
| 1356 | data_task; |
| 1357 | if (diff_ck) begin |
| 1358 | // check setup of command signals |
| 1359 | if ($time > TIS) begin |
| 1360 | if ($time - tm_cke < TIS) |
| 1361 | $display ("%m: at time %t ERROR: tIS violation on CKE by %t", $time, tm_cke + TIS - $time); |
| 1362 | if (cke_in) begin |
| 1363 | for (i=0; i<22; i=i+1) begin |
| 1364 | if ($time - tm_cmd_addr[i] < TIS) |
| 1365 | $display ("%m: at time %t ERROR: tIS violation on %s by %t", $time, cmd_addr_string[i], tm_cmd_addr[i] + TIS - $time); |
| 1366 | end |
| 1367 | end |
| 1368 | end |
| 1369 | |
| 1370 | // update current state |
| 1371 | if (!dll_locked && !in_self_refresh && (ck_cntr - ck_dll_reset == TDLLK)) begin |
| 1372 | // check CL value against the clock frequency |
| 1373 | if (cas_latency*tck_avg < CL_TIME) |
| 1374 | $display ("%m: at time %t ERROR: CAS Latency = %d is illegal @tCK(avg) = %f", $time, cas_latency, tck_avg); |
| 1375 | // check WR value against the clock frequency |
| 1376 | if (write_recovery*tck_avg < TWR) |
| 1377 | $display ("%m: at time %t ERROR: Write Recovery = %d is illegal @tCK(avg) = %f", $time, write_recovery, tck_avg); |
| 1378 | dll_locked = 1; |
| 1379 | end |
| 1380 | if (|auto_precharge_bank) begin |
| 1381 | for (i=0; i<`BANKS; i=i+1) begin |
| 1382 | // Write with Auto Precharge Calculation |
| 1383 | // 1. Meet minimum tRAS requirement |
| 1384 | // 2. Write Latency PLUS BL/2 cycles PLUS WR after Write command |
| 1385 | if (write_precharge_bank[i] |
| 1386 | && ($time - tm_bank_activate[i] >= TRAS_MIN) |
| 1387 | && (ck_cntr - ck_bank_write[i] >= write_latency + burst_length/2 + write_recovery)) begin |
| 1388 | |
| 1389 | if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", $time, i); |
| 1390 | write_precharge_bank[i] = 0; |
| 1391 | active_bank[i] = 0; |
| 1392 | auto_precharge_bank[i] = 0; |
| 1393 | ck_write_ap = ck_cntr; |
| 1394 | tm_bank_precharge[i] = $time; |
| 1395 | tm_precharge = $time; |
| 1396 | end |
| 1397 | // Read with Auto Precharge Calculation |
| 1398 | // 1. Meet minimum tRAS requirement |
| 1399 | // 2. Additive Latency plus BL/2 cycles after Read command |
| 1400 | // 3. tRTP after the last 4-bit prefetch |
| 1401 | if (read_precharge_bank[i] |
| 1402 | && ($time - tm_bank_activate[i] >= TRAS_MIN) |
| 1403 | && (ck_cntr - ck_bank_read[i] >= additive_latency + burst_length/2)) begin |
| 1404 | |
| 1405 | read_precharge_bank[i] = 0; |
| 1406 | // In case the internal precharge is pushed out by tRTP, tRP starts at the point where |
| 1407 | // the internal precharge happens (not at the next rising clock edge after this event). |
| 1408 | if ($time - tm_bank_read_end[i] < TRTP) begin |
| 1409 | if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", tm_bank_read_end[i] + TRTP, i); |
| 1410 | active_bank[i] <= #(tm_bank_read_end[i] + TRTP - $time) 0; |
| 1411 | auto_precharge_bank[i] <= #(tm_bank_read_end[i] + TRTP - $time) 0; |
| 1412 | tm_bank_precharge[i] <= #(tm_bank_read_end[i] + TRTP - $time) tm_bank_read_end[i] + TRTP; |
| 1413 | tm_precharge <= #(tm_bank_read_end[i] + TRTP - $time) tm_bank_read_end[i] + TRTP; |
| 1414 | end else begin |
| 1415 | if (DEBUG) $display ("%m: at time %t INFO: Auto Precharge bank %d", $time, i); |
| 1416 | active_bank[i] = 0; |
| 1417 | auto_precharge_bank[i] = 0; |
| 1418 | tm_bank_precharge[i] = $time; |
| 1419 | tm_precharge = $time; |
| 1420 | end |
| 1421 | end |
| 1422 | end |
| 1423 | end |
| 1424 | |
| 1425 | // respond to incoming command |
| 1426 | if (cke_in ^ prev_cke) begin |
| 1427 | ck_cke <= ck_cntr; |
| 1428 | end |
| 1429 | |
| 1430 | cmd_task(cke_in, cmd_n_in, ba_in, addr_in); |
| 1431 | if ((cmd_n_in == WRITE) || (cmd_n_in == READ)) begin |
| 1432 | al_pipeline[2*additive_latency] = 1'b1; |
| 1433 | end |
| 1434 | if (al_pipeline[0]) begin |
| 1435 | // check tRCD after additive latency |
| 1436 | if ($time - tm_bank_activate[ba_pipeline[2*cas_latency - 1]] < TRCD) begin |
| 1437 | if (rd_pipeline[2*cas_latency - 1]) begin |
| 1438 | $display ("%m: at time %t ERROR: tRCD violation during %s", $time, cmd_string[READ]); |
| 1439 | end else begin |
| 1440 | $display ("%m: at time %t ERROR: tRCD violation during %s", $time, cmd_string[WRITE]); |
| 1441 | end |
| 1442 | end |
| 1443 | // check tWTR after additive latency |
| 1444 | if (rd_pipeline[2*cas_latency - 1]) begin |
| 1445 | if ($time - tm_write_end < TWTR) |
| 1446 | $display ("%m: at time %t ERROR: tWTR violation during %s", $time, cmd_string[READ]); |
| 1447 | end |
| 1448 | end |
| 1449 | if (rd_pipeline[2*(cas_latency - burst_length/2 + 2) - 1]) begin |
| 1450 | tm_bank_read_end[ba_pipeline[2*(cas_latency - burst_length/2 + 2) - 1]] <= $time; |
| 1451 | end |
| 1452 | for (i=0; i<`BANKS; i=i+1) begin |
| 1453 | if ((ck_cntr - ck_bank_write[i] > write_latency) && (ck_cntr - ck_bank_write[i] <= write_latency + burst_length/2)) begin |
| 1454 | tm_bank_write_end[i] <= $time; |
| 1455 | tm_write_end <= $time; |
| 1456 | end |
| 1457 | end |
| 1458 | |
| 1459 | // clk pin is disabled during self refresh |
| 1460 | if (!in_self_refresh) begin |
| 1461 | tjit_cc_time = $time - tm_ck_pos - tck_i; |
| 1462 | tck_i = $time - tm_ck_pos; |
| 1463 | tck_avg = tck_avg - tck_sample[ck_cntr%TDLLK]/$itor(TDLLK); |
| 1464 | tck_avg = tck_avg + tck_i/$itor(TDLLK); |
| 1465 | tck_sample[ck_cntr%TDLLK] = tck_i; |
| 1466 | tjit_per_rtime = tck_i - tck_avg; |
| 1467 | |
| 1468 | if (dll_locked) begin |
| 1469 | // check accumulated error |
| 1470 | terr_nper_rtime = 0; |
| 1471 | for (i=0; i<50; i=i+1) begin |
| 1472 | terr_nper_rtime = terr_nper_rtime + tck_sample[i] - tck_avg; |
| 1473 | terr_nper_rtime = abs_value(terr_nper_rtime); |
| 1474 | case (i) |
| 1475 | 0 :; |
| 1476 | 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); |
| 1477 | 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); |
| 1478 | 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); |
| 1479 | 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); |
| 1480 | 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); |
| 1481 | 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); |
| 1482 | endcase |
| 1483 | end |
| 1484 | |
| 1485 | // check tCK min/max/jitter |
| 1486 | if (abs_value(tjit_per_rtime) - TJIT_PER >= 1.0) |
| 1487 | $display ("%m: at time %t ERROR: tJIT(per) violation by %f ps.", $time, abs_value(tjit_per_rtime) - TJIT_PER); |
| 1488 | if (abs_value(tjit_cc_time) - TJIT_CC >= 1.0) |
| 1489 | $display ("%m: at time %t ERROR: tJIT(cc) violation by %f ps.", $time, abs_value(tjit_cc_time) - TJIT_CC); |
| 1490 | if (TCK_MIN - tck_avg >= 1.0) |
| 1491 | $display ("%m: at time %t ERROR: tCK(avg) minimum violation by %f ps.", $time, TCK_MIN - tck_avg); |
| 1492 | if (tck_avg - TCK_MAX >= 1.0) |
| 1493 | $display ("%m: at time %t ERROR: tCK(avg) maximum violation by %f ps.", $time, tck_avg - TCK_MAX); |
| 1494 | if (tm_ck_pos + TCK_MIN - TJIT_PER > $time) |
| 1495 | $display ("%m: at time %t ERROR: tCK(abs) minimum violation by %t", $time, tm_ck_pos + TCK_MIN - TJIT_PER - $time); |
| 1496 | if (tm_ck_pos + TCK_MAX + TJIT_PER < $time) |
| 1497 | $display ("%m: at time %t ERROR: tCK(abs) maximum violation by %t", $time, $time - tm_ck_pos - TCK_MAX - TJIT_PER); |
| 1498 | |
| 1499 | // check tCL |
| 1500 | if (tm_ck_neg + TCL_MIN*tck_avg - TJIT_DUTY > $time) |
| 1501 | $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); |
| 1502 | if (tm_ck_neg + TCL_MAX*tck_avg + TJIT_DUTY < $time) |
| 1503 | $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); |
| 1504 | if (tcl_avg < TCL_MIN*tck_avg) |
| 1505 | $display ("%m: at time %t ERROR: tCL(avg) minimum violation on CLK by %t", $time, TCL_MIN*tck_avg - tcl_avg); |
| 1506 | if (tcl_avg > TCL_MAX*tck_avg) |
| 1507 | $display ("%m: at time %t ERROR: tCL(avg) maximum violation on CLK by %t", $time, tcl_avg - TCL_MAX*tck_avg); |
| 1508 | end |
| 1509 | |
| 1510 | // calculate the tch avg jitter |
| 1511 | tch_avg = tch_avg - tch_sample[ck_cntr%TDLLK]/$itor(TDLLK); |
| 1512 | tch_avg = tch_avg + tch_i/$itor(TDLLK); |
| 1513 | tch_sample[ck_cntr%TDLLK] = tch_i; |
| 1514 | |
| 1515 | // update timers/counters |
| 1516 | tcl_i <= $time - tm_ck_neg; |
| 1517 | end |
| 1518 | |
| 1519 | prev_odt <= odt_in; |
| 1520 | // update timers/counters |
| 1521 | ck_cntr <= ck_cntr + 1; |
| 1522 | tm_ck_pos <= $time; |
| 1523 | end else begin |
| 1524 | // clk pin is disabled during self refresh |
| 1525 | if (!in_self_refresh) begin |
| 1526 | if (dll_locked) begin |
| 1527 | if (tm_ck_pos + TCH_MIN*tck_avg - TJIT_DUTY > $time) |
| 1528 | $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); |
| 1529 | if (tm_ck_pos + TCH_MAX*tck_avg + TJIT_DUTY < $time) |
| 1530 | $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); |
| 1531 | if (tch_avg < TCH_MIN*tck_avg) |
| 1532 | $display ("%m: at time %t ERROR: tCH(avg) minimum violation on CLK by %t", $time, TCH_MIN*tck_avg - tch_avg); |
| 1533 | if (tch_avg > TCH_MAX*tck_avg) |
| 1534 | $display ("%m: at time %t ERROR: tCH(avg) maximum violation on CLK by %t", $time, tch_avg - TCH_MAX*tck_avg); |
| 1535 | end |
| 1536 | |
| 1537 | // calculate the tcl avg jitter |
| 1538 | tcl_avg = tcl_avg - tcl_sample[ck_cntr%TDLLK]/$itor(TDLLK); |
| 1539 | tcl_avg = tcl_avg + tcl_i/$itor(TDLLK); |
| 1540 | tcl_sample[ck_cntr%TDLLK] = tcl_i; |
| 1541 | |
| 1542 | // update timers/counters |
| 1543 | tch_i <= $time - tm_ck_pos; |
| 1544 | end |
| 1545 | tm_ck_neg <= $time; |
| 1546 | end |
| 1547 | |
| 1548 | // on die termination |
| 1549 | if (odt_en) begin |
| 1550 | // clk pin is disabled during self refresh |
| 1551 | if (!in_self_refresh && diff_ck) begin |
| 1552 | if ($time - tm_odt < TIS) begin |
| 1553 | $display ("%m: at time %t ERROR: tIS violation on ODT by %t", $time, tm_odt + TIS - $time); |
| 1554 | end |
| 1555 | if (prev_odt ^ odt_in) begin |
| 1556 | if (!dll_locked) |
| 1557 | $display ("%m: at time %t WARNING: tDLLK violation during ODT transition.", $time); |
| 1558 | if (odt_in && ($time - tm_odt_en < TMOD)) |
| 1559 | $display ("%m: at time %t ERROR: tMOD violation during ODT transition", $time); |
| 1560 | if ($time - tm_self_refresh < TXSNR) |
| 1561 | $display ("%m: at time %t ERROR: tXSNR violation during ODT transition", $time); |
| 1562 | if (in_self_refresh) |
| 1563 | $display ("%m: at time %t ERROR: Illegal ODT transition during Self Refresh.", $time); |
| 1564 | |
| 1565 | // async ODT mode applies: |
| 1566 | // 1.) during active power down with slow exit |
| 1567 | // 2.) during precharge power down |
| 1568 | // 3.) if tANPD has not been satisfied |
| 1569 | // 4.) until tAXPD has been satisfied |
| 1570 | if ((in_power_down && (low_power || (active_bank == 0))) || (ck_cntr - ck_slow_exit_pd < TAXPD)) begin |
| 1571 | if (ck_cntr - ck_slow_exit_pd < TAXPD) |
| 1572 | $display ("%m: at time %t WARNING: tAXPD violation during ODT transition. Synchronous or asynchronous change in termination resistance is possible.", $time); |
| 1573 | if (odt_in) begin |
| 1574 | if (DEBUG) $display ("%m: at time %t INFO: Async On Die Termination = %d", $time + TAONPD, 1'b1); |
| 1575 | odt_state <= #(TAONPD) 1'b1; |
| 1576 | end else begin |
| 1577 | if (DEBUG) $display ("%m: at time %t INFO: Async On Die Termination = %d", $time + TAOFPD, 1'b0); |
| 1578 | odt_state <= #(TAOFPD) 1'b0; |
| 1579 | end |
| 1580 | // sync ODT mode applies: |
| 1581 | // 1.) during normal operation |
| 1582 | // 2.) during active power down with fast exit |
| 1583 | end else begin |
| 1584 | if (odt_in) begin |
| 1585 | i = TAOND*2; |
| 1586 | odt_pipeline[i] = 1'b1; |
| 1587 | end else begin |
| 1588 | i = TAOFD*2; |
| 1589 | odt_pipeline[i] = 1'b1; |
| 1590 | end |
| 1591 | end |
| 1592 | ck_odt <= ck_cntr; |
| 1593 | end |
| 1594 | end |
| 1595 | if (odt_pipeline[0]) begin |
| 1596 | odt_state = ~odt_state; |
| 1597 | if (DEBUG) $display ("%m: at time %t INFO: Sync On Die Termination = %d", $time, odt_state); |
| 1598 | end |
| 1599 | end |
| 1600 | |
| 1601 | // shift pipelines |
| 1602 | if (|wr_pipeline || |rd_pipeline || |al_pipeline) begin |
| 1603 | al_pipeline = al_pipeline>>1; |
| 1604 | wr_pipeline = wr_pipeline>>1; |
| 1605 | rd_pipeline = rd_pipeline>>1; |
| 1606 | for (i=0; i<`MAX_PIPE; i=i+1) begin |
| 1607 | ba_pipeline[i] = ba_pipeline[i+1]; |
| 1608 | row_pipeline[i] = row_pipeline[i+1]; |
| 1609 | col_pipeline[i] = col_pipeline[i+1]; |
| 1610 | end |
| 1611 | end |
| 1612 | if (|odt_pipeline) begin |
| 1613 | odt_pipeline = odt_pipeline>>1; |
| 1614 | end |
| 1615 | end |
| 1616 | |
| 1617 | // receiver(s) |
| 1618 | task dqs_even_receiver; |
| 1619 | input [4:0] i; |
| 1620 | reg [71:0] bit_mask; |
| 1621 | begin |
| 1622 | bit_mask = {`DQ_PER_DQS{1'b1}}<<(i*`DQ_PER_DQS); |
| 1623 | if (dqs_even[i]) begin |
| 1624 | if (rdqs_en) begin // rdqs disables dm |
| 1625 | dm_in_pos[i] = 1'b0; |
| 1626 | end else begin |
| 1627 | dm_in_pos[i] = dm_in[i]; |
| 1628 | end |
| 1629 | dq_in_pos = (dq_in & bit_mask) | (dq_in_pos & ~bit_mask); |
| 1630 | end |
| 1631 | end |
| 1632 | endtask |
| 1633 | |
| 1634 | always @(posedge dqs_even[ 0]) dqs_even_receiver( 0); |
| 1635 | always @(posedge dqs_even[ 1]) dqs_even_receiver( 1); |
| 1636 | always @(posedge dqs_even[ 2]) dqs_even_receiver( 2); |
| 1637 | always @(posedge dqs_even[ 3]) dqs_even_receiver( 3); |
| 1638 | always @(posedge dqs_even[ 4]) dqs_even_receiver( 4); |
| 1639 | always @(posedge dqs_even[ 5]) dqs_even_receiver( 5); |
| 1640 | always @(posedge dqs_even[ 6]) dqs_even_receiver( 6); |
| 1641 | always @(posedge dqs_even[ 7]) dqs_even_receiver( 7); |
| 1642 | always @(posedge dqs_even[ 8]) dqs_even_receiver( 8); |
| 1643 | always @(posedge dqs_even[ 9]) dqs_even_receiver( 9); |
| 1644 | always @(posedge dqs_even[10]) dqs_even_receiver(10); |
| 1645 | always @(posedge dqs_even[11]) dqs_even_receiver(11); |
| 1646 | always @(posedge dqs_even[12]) dqs_even_receiver(12); |
| 1647 | always @(posedge dqs_even[13]) dqs_even_receiver(13); |
| 1648 | always @(posedge dqs_even[14]) dqs_even_receiver(14); |
| 1649 | always @(posedge dqs_even[15]) dqs_even_receiver(15); |
| 1650 | always @(posedge dqs_even[16]) dqs_even_receiver(16); |
| 1651 | always @(posedge dqs_even[17]) dqs_even_receiver(17); |
| 1652 | |
| 1653 | task dqs_odd_receiver; |
| 1654 | input [4:0] i; |
| 1655 | reg [71:0] bit_mask; |
| 1656 | begin |
| 1657 | bit_mask = {`DQ_PER_DQS{1'b1}}<<(i*`DQ_PER_DQS); |
| 1658 | if (dqs_odd[i]) begin |
| 1659 | if (rdqs_en) begin // rdqs disables dm |
| 1660 | dm_in_neg[i] = 1'b0; |
| 1661 | end else begin |
| 1662 | dm_in_neg[i] = dm_in[i]; |
| 1663 | end |
| 1664 | dq_in_neg = (dq_in & bit_mask) | (dq_in_neg & ~bit_mask); |
| 1665 | end |
| 1666 | end |
| 1667 | endtask |
| 1668 | |
| 1669 | always @(posedge dqs_odd[ 0]) dqs_odd_receiver( 0); |
| 1670 | always @(posedge dqs_odd[ 1]) dqs_odd_receiver( 1); |
| 1671 | always @(posedge dqs_odd[ 2]) dqs_odd_receiver( 2); |
| 1672 | always @(posedge dqs_odd[ 3]) dqs_odd_receiver( 3); |
| 1673 | always @(posedge dqs_odd[ 4]) dqs_odd_receiver( 4); |
| 1674 | always @(posedge dqs_odd[ 5]) dqs_odd_receiver( 5); |
| 1675 | always @(posedge dqs_odd[ 6]) dqs_odd_receiver( 6); |
| 1676 | always @(posedge dqs_odd[ 7]) dqs_odd_receiver( 7); |
| 1677 | always @(posedge dqs_odd[ 8]) dqs_odd_receiver( 8); |
| 1678 | always @(posedge dqs_odd[ 9]) dqs_odd_receiver( 9); |
| 1679 | always @(posedge dqs_odd[10]) dqs_odd_receiver(10); |
| 1680 | always @(posedge dqs_odd[11]) dqs_odd_receiver(11); |
| 1681 | always @(posedge dqs_odd[12]) dqs_odd_receiver(12); |
| 1682 | always @(posedge dqs_odd[13]) dqs_odd_receiver(13); |
| 1683 | always @(posedge dqs_odd[14]) dqs_odd_receiver(14); |
| 1684 | always @(posedge dqs_odd[15]) dqs_odd_receiver(15); |
| 1685 | always @(posedge dqs_odd[16]) dqs_odd_receiver(16); |
| 1686 | always @(posedge dqs_odd[17]) dqs_odd_receiver(17); |
| 1687 | |
| 1688 | // Processes to check hold and pulse width of control signals |
| 1689 | always @(cke_in) begin |
| 1690 | if ($time > TIH) begin |
| 1691 | if ($time - tm_ck_pos < TIH) |
| 1692 | $display ("%m: at time %t ERROR: tIH violation on CKE by %t", $time, tm_ck_pos + TIH - $time); |
| 1693 | end |
| 1694 | if (dll_locked && ($time - tm_cke < $rtoi(TIPW*tck_avg))) |
| 1695 | $display ("%m: at time %t ERROR: tIPW violation on CKE by %t", $time, tm_cke + TIPW*tck_avg - $time); |
| 1696 | tm_cke = $time; |
| 1697 | end |
| 1698 | always @(odt_in) begin |
| 1699 | if (odt_en && !in_self_refresh) begin |
| 1700 | if ($time - tm_ck_pos < TIH) |
| 1701 | $display ("%m: at time %t ERROR: tIH violation on ODT by %t", $time, tm_ck_pos + TIH - $time); |
| 1702 | if (dll_locked && ($time - tm_odt < $rtoi(TIPW*tck_avg))) |
| 1703 | $display ("%m: at time %t ERROR: tIPW violation on ODT by %t", $time, tm_odt + TIPW*tck_avg - $time); |
| 1704 | end |
| 1705 | tm_odt = $time; |
| 1706 | end |
| 1707 | |
| 1708 | task cmd_addr_timing_check; |
| 1709 | input i; |
| 1710 | reg [4:0] i; |
| 1711 | begin |
| 1712 | if (prev_cke) begin |
| 1713 | if ((i == 0) && ($time - tm_ck_pos < TIH)) // Always check tIH for CS# |
| 1714 | $display ("%m: at time %t ERROR: tIH violation on %s by %t", $time, cmd_addr_string[i], tm_ck_pos + TIH - $time); |
| 1715 | if ((i > 0) && (cs_n_in == 1'b0) && ($time - tm_ck_pos < TIH)) // Only check tIH for cmd_addr if CS# low |
| 1716 | $display ("%m: at time %t ERROR: tIH violation on %s by %t", $time, cmd_addr_string[i], tm_ck_pos + TIH - $time); |
| 1717 | if (dll_locked && ($time - tm_cmd_addr[i] < $rtoi(TIPW*tck_avg))) |
| 1718 | $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); |
| 1719 | end |
| 1720 | tm_cmd_addr[i] = $time; |
| 1721 | end |
| 1722 | endtask |
| 1723 | |
| 1724 | always @(cs_n_in ) cmd_addr_timing_check( 0); |
| 1725 | always @(ras_n_in ) cmd_addr_timing_check( 1); |
| 1726 | always @(cas_n_in ) cmd_addr_timing_check( 2); |
| 1727 | always @(we_n_in ) cmd_addr_timing_check( 3); |
| 1728 | always @(ba_in [ 0]) cmd_addr_timing_check( 4); |
| 1729 | always @(ba_in [ 1]) cmd_addr_timing_check( 5); |
| 1730 | always @(ba_in [ 2]) cmd_addr_timing_check( 6); |
| 1731 | always @(addr_in[ 0]) cmd_addr_timing_check( 7); |
| 1732 | always @(addr_in[ 1]) cmd_addr_timing_check( 8); |
| 1733 | always @(addr_in[ 2]) cmd_addr_timing_check( 9); |
| 1734 | always @(addr_in[ 3]) cmd_addr_timing_check(10); |
| 1735 | always @(addr_in[ 4]) cmd_addr_timing_check(11); |
| 1736 | always @(addr_in[ 5]) cmd_addr_timing_check(12); |
| 1737 | always @(addr_in[ 6]) cmd_addr_timing_check(13); |
| 1738 | always @(addr_in[ 7]) cmd_addr_timing_check(14); |
| 1739 | always @(addr_in[ 8]) cmd_addr_timing_check(15); |
| 1740 | always @(addr_in[ 9]) cmd_addr_timing_check(16); |
| 1741 | always @(addr_in[10]) cmd_addr_timing_check(17); |
| 1742 | always @(addr_in[11]) cmd_addr_timing_check(18); |
| 1743 | always @(addr_in[12]) cmd_addr_timing_check(19); |
| 1744 | always @(addr_in[13]) cmd_addr_timing_check(20); |
| 1745 | always @(addr_in[14]) cmd_addr_timing_check(21); |
| 1746 | always @(addr_in[15]) cmd_addr_timing_check(22); |
| 1747 | |
| 1748 | // Processes to check setup and hold of data signals |
| 1749 | task dm_timing_check; |
| 1750 | input i; |
| 1751 | reg [4:0] i; |
| 1752 | begin |
| 1753 | if (dqs_in_valid) begin |
| 1754 | if ($time - tm_dqs[i] < TDH) |
| 1755 | $display ("%m: at time %t ERROR: tDH violation on DM bit %d by %t", $time, i, tm_dqs[i] + TDH - $time); |
| 1756 | if (check_dm_tdipw[i]) begin |
| 1757 | if (dll_locked && ($time - tm_dm[i] < $rtoi(TDIPW*tck_avg))) |
| 1758 | $display ("%m: at time %t ERROR: tDIPW violation on DM bit %d by %t", $time, i, tm_dm[i] + TDIPW*tck_avg - $time); |
| 1759 | end |
| 1760 | end |
| 1761 | check_dm_tdipw[i] <= 1'b0; |
| 1762 | tm_dm[i] = $time; |
| 1763 | end |
| 1764 | endtask |
| 1765 | |
| 1766 | always @(dm_in[ 0]) dm_timing_check( 0); |
| 1767 | always @(dm_in[ 1]) dm_timing_check( 1); |
| 1768 | always @(dm_in[ 2]) dm_timing_check( 2); |
| 1769 | always @(dm_in[ 3]) dm_timing_check( 3); |
| 1770 | always @(dm_in[ 4]) dm_timing_check( 4); |
| 1771 | always @(dm_in[ 5]) dm_timing_check( 5); |
| 1772 | always @(dm_in[ 6]) dm_timing_check( 6); |
| 1773 | always @(dm_in[ 7]) dm_timing_check( 7); |
| 1774 | always @(dm_in[ 8]) dm_timing_check( 8); |
| 1775 | always @(dm_in[ 9]) dm_timing_check( 9); |
| 1776 | always @(dm_in[10]) dm_timing_check(10); |
| 1777 | always @(dm_in[11]) dm_timing_check(11); |
| 1778 | always @(dm_in[12]) dm_timing_check(12); |
| 1779 | always @(dm_in[13]) dm_timing_check(13); |
| 1780 | always @(dm_in[14]) dm_timing_check(14); |
| 1781 | always @(dm_in[15]) dm_timing_check(15); |
| 1782 | always @(dm_in[16]) dm_timing_check(16); |
| 1783 | always @(dm_in[17]) dm_timing_check(17); |
| 1784 | |
| 1785 | task dq_timing_check; |
| 1786 | input i; |
| 1787 | reg [6:0] i; |
| 1788 | begin |
| 1789 | if (dqs_in_valid) begin |
| 1790 | if ($time - tm_dqs[i/`DQ_PER_DQS] < TDH) |
| 1791 | $display ("%m: at time %t ERROR: tDH violation on DQ bit %d by %t", $time, i, tm_dqs[i/`DQ_PER_DQS] + TDH - $time); |
| 1792 | if (check_dq_tdipw[i]) begin |
| 1793 | if (dll_locked && ($time - tm_dq[i] < $rtoi(TDIPW*tck_avg))) |
| 1794 | $display ("%m: at time %t ERROR: tDIPW violation on DQ bit %d by %t", $time, i, tm_dq[i] + TDIPW*tck_avg - $time); |
| 1795 | end |
| 1796 | end |
| 1797 | check_dq_tdipw[i] <= 1'b0; |
| 1798 | tm_dq[i] = $time; |
| 1799 | end |
| 1800 | endtask |
| 1801 | |
| 1802 | always @(dq_in[ 0]) dq_timing_check( 0); |
| 1803 | always @(dq_in[ 1]) dq_timing_check( 1); |
| 1804 | always @(dq_in[ 2]) dq_timing_check( 2); |
| 1805 | always @(dq_in[ 3]) dq_timing_check( 3); |
| 1806 | always @(dq_in[ 4]) dq_timing_check( 4); |
| 1807 | always @(dq_in[ 5]) dq_timing_check( 5); |
| 1808 | always @(dq_in[ 6]) dq_timing_check( 6); |
| 1809 | always @(dq_in[ 7]) dq_timing_check( 7); |
| 1810 | always @(dq_in[ 8]) dq_timing_check( 8); |
| 1811 | always @(dq_in[ 9]) dq_timing_check( 9); |
| 1812 | always @(dq_in[10]) dq_timing_check(10); |
| 1813 | always @(dq_in[11]) dq_timing_check(11); |
| 1814 | always @(dq_in[12]) dq_timing_check(12); |
| 1815 | always @(dq_in[13]) dq_timing_check(13); |
| 1816 | always @(dq_in[14]) dq_timing_check(14); |
| 1817 | always @(dq_in[15]) dq_timing_check(15); |
| 1818 | always @(dq_in[16]) dq_timing_check(16); |
| 1819 | always @(dq_in[17]) dq_timing_check(17); |
| 1820 | always @(dq_in[18]) dq_timing_check(18); |
| 1821 | always @(dq_in[19]) dq_timing_check(19); |
| 1822 | always @(dq_in[20]) dq_timing_check(20); |
| 1823 | always @(dq_in[21]) dq_timing_check(21); |
| 1824 | always @(dq_in[22]) dq_timing_check(22); |
| 1825 | always @(dq_in[23]) dq_timing_check(23); |
| 1826 | always @(dq_in[24]) dq_timing_check(24); |
| 1827 | always @(dq_in[25]) dq_timing_check(25); |
| 1828 | always @(dq_in[26]) dq_timing_check(26); |
| 1829 | always @(dq_in[27]) dq_timing_check(27); |
| 1830 | always @(dq_in[28]) dq_timing_check(28); |
| 1831 | always @(dq_in[29]) dq_timing_check(29); |
| 1832 | always @(dq_in[30]) dq_timing_check(30); |
| 1833 | always @(dq_in[31]) dq_timing_check(31); |
| 1834 | always @(dq_in[32]) dq_timing_check(32); |
| 1835 | always @(dq_in[33]) dq_timing_check(33); |
| 1836 | always @(dq_in[34]) dq_timing_check(34); |
| 1837 | always @(dq_in[35]) dq_timing_check(35); |
| 1838 | always @(dq_in[36]) dq_timing_check(36); |
| 1839 | always @(dq_in[37]) dq_timing_check(37); |
| 1840 | always @(dq_in[38]) dq_timing_check(38); |
| 1841 | always @(dq_in[39]) dq_timing_check(39); |
| 1842 | always @(dq_in[40]) dq_timing_check(40); |
| 1843 | always @(dq_in[41]) dq_timing_check(41); |
| 1844 | always @(dq_in[42]) dq_timing_check(42); |
| 1845 | always @(dq_in[43]) dq_timing_check(43); |
| 1846 | always @(dq_in[44]) dq_timing_check(44); |
| 1847 | always @(dq_in[45]) dq_timing_check(45); |
| 1848 | always @(dq_in[46]) dq_timing_check(46); |
| 1849 | always @(dq_in[47]) dq_timing_check(47); |
| 1850 | always @(dq_in[48]) dq_timing_check(48); |
| 1851 | always @(dq_in[49]) dq_timing_check(49); |
| 1852 | always @(dq_in[50]) dq_timing_check(50); |
| 1853 | always @(dq_in[51]) dq_timing_check(51); |
| 1854 | always @(dq_in[52]) dq_timing_check(52); |
| 1855 | always @(dq_in[53]) dq_timing_check(53); |
| 1856 | always @(dq_in[54]) dq_timing_check(54); |
| 1857 | always @(dq_in[55]) dq_timing_check(55); |
| 1858 | always @(dq_in[56]) dq_timing_check(56); |
| 1859 | always @(dq_in[57]) dq_timing_check(57); |
| 1860 | always @(dq_in[58]) dq_timing_check(58); |
| 1861 | always @(dq_in[59]) dq_timing_check(59); |
| 1862 | always @(dq_in[60]) dq_timing_check(60); |
| 1863 | always @(dq_in[61]) dq_timing_check(61); |
| 1864 | always @(dq_in[62]) dq_timing_check(62); |
| 1865 | always @(dq_in[63]) dq_timing_check(63); |
| 1866 | always @(dq_in[64]) dq_timing_check(64); |
| 1867 | always @(dq_in[65]) dq_timing_check(65); |
| 1868 | always @(dq_in[66]) dq_timing_check(66); |
| 1869 | always @(dq_in[67]) dq_timing_check(67); |
| 1870 | always @(dq_in[68]) dq_timing_check(68); |
| 1871 | always @(dq_in[69]) dq_timing_check(69); |
| 1872 | always @(dq_in[70]) dq_timing_check(70); |
| 1873 | always @(dq_in[71]) dq_timing_check(71); |
| 1874 | |
| 1875 | task dqs_pos_timing_check; |
| 1876 | input i; |
| 1877 | reg [5:0] i; |
| 1878 | reg [3:0] j; |
| 1879 | begin |
| 1880 | if (dqs_in_valid && ((wdqs_pos_cntr[i] < burst_length/2) || b2b_write) && (dqs_n_en || i<18)) begin |
| 1881 | if (dqs_in[i] ^ prev_dqs_in[i]) begin |
| 1882 | if (dll_locked) begin |
| 1883 | if (check_write_preamble[i]) begin |
| 1884 | if ($time - tm_dqs_neg[i] < $rtoi(TWPRE*tck_avg)) |
| 1885 | $display ("%m: at time %t ERROR: tWPRE violation on &s bit %d", $time, dqs_string[i/18], i%18); |
| 1886 | end else if (check_write_postamble[i]) begin |
| 1887 | if ($time - tm_dqs_neg[i] < $rtoi(TWPST*tck_avg)) |
| 1888 | $display ("%m: at time %t ERROR: tWPST violation on %s bit %d", $time, dqs_string[i/18], i%18); |
| 1889 | end else begin |
| 1890 | if ($time - tm_dqs_neg[i] < $rtoi(TDQSL*tck_avg)) |
| 1891 | $display ("%m: at time %t ERROR: tDQSL violation on %s bit %d", $time, dqs_string[i/18], i%18); |
| 1892 | end |
| 1893 | end |
| 1894 | if ($time - tm_dm[i%18] < TDS) |
| 1895 | $display ("%m: at time %t ERROR: tDS violation on DM bit %d by %t", $time, i, tm_dm[i%18] + TDS - $time); |
| 1896 | if (!dq_out_en) begin |
| 1897 | for (j=0; j<`DQ_PER_DQS; j=j+1) begin |
| 1898 | if ($time - tm_dq[i*`DQ_PER_DQS+j] < TDS) |
| 1899 | $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); |
| 1900 | check_dq_tdipw[i*`DQ_PER_DQS+j] <= 1'b1; |
| 1901 | end |
| 1902 | end |
| 1903 | if ((wdqs_pos_cntr[i] < burst_length/2) && !b2b_write) begin |
| 1904 | wdqs_pos_cntr[i] <= wdqs_pos_cntr[i] + 1; |
| 1905 | end else begin |
| 1906 | wdqs_pos_cntr[i] <= 1; |
| 1907 | end |
| 1908 | check_dm_tdipw[i%18] <= 1'b1; |
| 1909 | check_write_preamble[i] <= 1'b0; |
| 1910 | check_write_postamble[i] <= 1'b0; |
| 1911 | check_write_dqs_low[i] <= 1'b0; |
| 1912 | tm_dqs[i%18] <= $time; |
| 1913 | end else begin |
| 1914 | $display ("%m: at time %t ERROR: Invalid latching edge on %s bit %d", $time, dqs_string[i/18], i%18); |
| 1915 | end |
| 1916 | end |
| 1917 | tm_dqss_pos[i] <= $time; |
| 1918 | tm_dqs_pos[i] = $time; |
| 1919 | prev_dqs_in[i] <= dqs_in[i]; |
| 1920 | end |
| 1921 | endtask |
| 1922 | |
| 1923 | always @(posedge dqs_in[ 0]) dqs_pos_timing_check( 0); |
| 1924 | always @(posedge dqs_in[ 1]) dqs_pos_timing_check( 1); |
| 1925 | always @(posedge dqs_in[ 2]) dqs_pos_timing_check( 2); |
| 1926 | always @(posedge dqs_in[ 3]) dqs_pos_timing_check( 3); |
| 1927 | always @(posedge dqs_in[ 4]) dqs_pos_timing_check( 4); |
| 1928 | always @(posedge dqs_in[ 5]) dqs_pos_timing_check( 5); |
| 1929 | always @(posedge dqs_in[ 6]) dqs_pos_timing_check( 6); |
| 1930 | always @(posedge dqs_in[ 7]) dqs_pos_timing_check( 7); |
| 1931 | always @(posedge dqs_in[ 8]) dqs_pos_timing_check( 8); |
| 1932 | always @(posedge dqs_in[ 9]) dqs_pos_timing_check( 9); |
| 1933 | always @(posedge dqs_in[10]) dqs_pos_timing_check(10); |
| 1934 | always @(posedge dqs_in[11]) dqs_pos_timing_check(11); |
| 1935 | always @(posedge dqs_in[12]) dqs_pos_timing_check(12); |
| 1936 | always @(posedge dqs_in[13]) dqs_pos_timing_check(13); |
| 1937 | always @(posedge dqs_in[14]) dqs_pos_timing_check(14); |
| 1938 | always @(posedge dqs_in[15]) dqs_pos_timing_check(15); |
| 1939 | always @(posedge dqs_in[16]) dqs_pos_timing_check(16); |
| 1940 | always @(posedge dqs_in[17]) dqs_pos_timing_check(17); |
| 1941 | always @(negedge dqs_in[18]) dqs_pos_timing_check(18); |
| 1942 | always @(negedge dqs_in[19]) dqs_pos_timing_check(19); |
| 1943 | always @(negedge dqs_in[20]) dqs_pos_timing_check(20); |
| 1944 | always @(negedge dqs_in[21]) dqs_pos_timing_check(21); |
| 1945 | always @(negedge dqs_in[22]) dqs_pos_timing_check(22); |
| 1946 | always @(negedge dqs_in[23]) dqs_pos_timing_check(23); |
| 1947 | always @(negedge dqs_in[24]) dqs_pos_timing_check(24); |
| 1948 | always @(negedge dqs_in[25]) dqs_pos_timing_check(25); |
| 1949 | always @(negedge dqs_in[26]) dqs_pos_timing_check(26); |
| 1950 | always @(negedge dqs_in[27]) dqs_pos_timing_check(27); |
| 1951 | always @(negedge dqs_in[28]) dqs_pos_timing_check(28); |
| 1952 | always @(negedge dqs_in[29]) dqs_pos_timing_check(29); |
| 1953 | always @(negedge dqs_in[30]) dqs_pos_timing_check(30); |
| 1954 | always @(negedge dqs_in[31]) dqs_pos_timing_check(31); |
| 1955 | always @(negedge dqs_in[32]) dqs_neg_timing_check(32); |
| 1956 | always @(negedge dqs_in[33]) dqs_neg_timing_check(33); |
| 1957 | always @(negedge dqs_in[34]) dqs_neg_timing_check(34); |
| 1958 | always @(negedge dqs_in[35]) dqs_neg_timing_check(35); |
| 1959 | |
| 1960 | task dqs_neg_timing_check; |
| 1961 | input i; |
| 1962 | reg [5:0] i; |
| 1963 | reg [3:0] j; |
| 1964 | begin |
| 1965 | if (dqs_in_valid && (wdqs_pos_cntr[i] > 0) && check_write_dqs_high[i] && (dqs_n_en || i < 18)) begin |
| 1966 | if (dqs_in[i] ^ prev_dqs_in[i]) begin |
| 1967 | if (dll_locked) begin |
| 1968 | if ($time - tm_dqs_pos[i] < $rtoi(TDQSH*tck_avg)) |
| 1969 | $display ("%m: at time %t ERROR: tDQSH violation on %s bit %d", $time, dqs_string[i/18], i%18); |
| 1970 | if ($time - tm_ck_pos < $rtoi(TDSH*tck_avg)) |
| 1971 | $display ("%m: at time %t ERROR: tDSH violation on %s bit %d", $time, dqs_string[i/18], i%18); |
| 1972 | end |
| 1973 | if ($time - tm_dm[i%18] < TDS) |
| 1974 | $display ("%m: at time %t ERROR: tDS violation on DM bit %d by %t", $time, i, tm_dm[i%18] + TDS - $time); |
| 1975 | if (!dq_out_en) begin |
| 1976 | for (j=0; j<`DQ_PER_DQS; j=j+1) begin |
| 1977 | if ($time - tm_dq[i*`DQ_PER_DQS+j] < TDS) |
| 1978 | $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); |
| 1979 | check_dq_tdipw[i*`DQ_PER_DQS+j] <= 1'b1; |
| 1980 | end |
| 1981 | end |
| 1982 | check_dm_tdipw[i%18] <= 1'b1; |
| 1983 | check_write_dqs_high[i] <= 1'b0; |
| 1984 | tm_dqs[i%18] <= $time; |
| 1985 | end else begin |
| 1986 | $display ("%m: at time %t ERROR: Invalid latching edge on %s bit %d", $time, dqs_string[i/18], i%18); |
| 1987 | end |
| 1988 | end |
| 1989 | tm_dqs_neg[i] = $time; |
| 1990 | prev_dqs_in[i] <= dqs_in[i]; |
| 1991 | end |
| 1992 | endtask |
| 1993 | |
| 1994 | always @(negedge dqs_in[ 0]) dqs_neg_timing_check( 0); |
| 1995 | always @(negedge dqs_in[ 1]) dqs_neg_timing_check( 1); |
| 1996 | always @(negedge dqs_in[ 2]) dqs_neg_timing_check( 2); |
| 1997 | always @(negedge dqs_in[ 3]) dqs_neg_timing_check( 3); |
| 1998 | always @(negedge dqs_in[ 4]) dqs_neg_timing_check( 4); |
| 1999 | always @(negedge dqs_in[ 5]) dqs_neg_timing_check( 5); |
| 2000 | always @(negedge dqs_in[ 6]) dqs_neg_timing_check( 6); |
| 2001 | always @(negedge dqs_in[ 7]) dqs_neg_timing_check( 7); |
| 2002 | always @(negedge dqs_in[ 8]) dqs_neg_timing_check( 8); |
| 2003 | always @(negedge dqs_in[ 9]) dqs_neg_timing_check( 9); |
| 2004 | always @(negedge dqs_in[10]) dqs_neg_timing_check(10); |
| 2005 | always @(negedge dqs_in[11]) dqs_neg_timing_check(11); |
| 2006 | always @(negedge dqs_in[12]) dqs_neg_timing_check(12); |
| 2007 | always @(negedge dqs_in[13]) dqs_neg_timing_check(13); |
| 2008 | always @(negedge dqs_in[14]) dqs_neg_timing_check(14); |
| 2009 | always @(negedge dqs_in[15]) dqs_neg_timing_check(15); |
| 2010 | always @(negedge dqs_in[16]) dqs_neg_timing_check(16); |
| 2011 | always @(negedge dqs_in[17]) dqs_neg_timing_check(17); |
| 2012 | always @(posedge dqs_in[18]) dqs_neg_timing_check(18); |
| 2013 | always @(posedge dqs_in[19]) dqs_neg_timing_check(19); |
| 2014 | always @(posedge dqs_in[20]) dqs_neg_timing_check(20); |
| 2015 | always @(posedge dqs_in[21]) dqs_neg_timing_check(21); |
| 2016 | always @(posedge dqs_in[22]) dqs_neg_timing_check(22); |
| 2017 | always @(posedge dqs_in[23]) dqs_neg_timing_check(23); |
| 2018 | always @(posedge dqs_in[24]) dqs_neg_timing_check(24); |
| 2019 | always @(posedge dqs_in[25]) dqs_neg_timing_check(25); |
| 2020 | always @(posedge dqs_in[26]) dqs_neg_timing_check(26); |
| 2021 | always @(posedge dqs_in[27]) dqs_neg_timing_check(27); |
| 2022 | always @(posedge dqs_in[28]) dqs_neg_timing_check(28); |
| 2023 | always @(posedge dqs_in[29]) dqs_neg_timing_check(29); |
| 2024 | always @(posedge dqs_in[30]) dqs_neg_timing_check(30); |
| 2025 | always @(posedge dqs_in[31]) dqs_neg_timing_check(31); |
| 2026 | always @(posedge dqs_in[32]) dqs_neg_timing_check(32); |
| 2027 | always @(posedge dqs_in[33]) dqs_neg_timing_check(33); |
| 2028 | always @(posedge dqs_in[34]) dqs_neg_timing_check(34); |
| 2029 | always @(posedge dqs_in[35]) dqs_neg_timing_check(35); |
| 2030 | |
| 2031 | endmodule |
sim/verilog/micron_2048Mb_ddr2/ddr2_module.v |
| 1 | /**************************************************************************************** |
| 2 | * |
| 3 | * File Name: ddr2_module.v |
| 4 | * |
| 5 | * Dependencies: ddr2.v, ddr2.v, ddr2_parameters.vh |
| 6 | * |
| 7 | * Description: Micron SDRAM DDR2 (Double Data Rate 2) module model |
| 8 | * |
| 9 | * Limitation: - SPD (Serial Presence-Detect) is not modeled |
| 10 | * |
| 11 | * Disclaimer This software code and all associated documentation, comments or other |
| 12 | * of Warranty: information (collectively "Software") is provided "AS IS" without |
| 13 | * warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY |
| 14 | * DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
| 15 | * TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES |
| 16 | * OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT |
| 17 | * WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE |
| 18 | * OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. |
| 19 | * FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR |
| 20 | * THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, |
| 21 | * ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE |
| 22 | * OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, |
| 23 | * ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, |
| 24 | * INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, |
| 25 | * WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, |
| 26 | * OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE |
| 27 | * THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 28 | * DAMAGES. Because some jurisdictions prohibit the exclusion or |
| 29 | * limitation of liability for consequential or incidental damages, the |
| 30 | * above limitation may not apply to you. |
| 31 | * |
| 32 | * Copyright 2003 Micron Technology, Inc. All rights reserved. |
| 33 | * |
| 34 | * Rev Author Date Changes |
| 35 | * --------------------------------------------------------------------------------------- |
| 36 | * 1.00 SPH 09/18/09 Fixed cb connection in ECC mode |
| 37 | * Added invalid ECC mode error message in x16 configuration |
| 38 | ****************************************************************************************/ |
| 39 | `timescale 1ps / 1ps |
| 40 | |
| 41 | module ddr2_module ( |
| 42 | `ifdef SODIMM |
| 43 | `else |
| 44 | reset_n, |
| 45 | cb , |
| 46 | `endif |
| 47 | ck , |
| 48 | ck_n , |
| 49 | cke , |
| 50 | s_n , |
| 51 | ras_n , |
| 52 | cas_n , |
| 53 | we_n , |
| 54 | ba , |
| 55 | addr , |
| 56 | odt , |
| 57 | dqs , |
| 58 | dqs_n , |
| 59 | dq , |
| 60 | scl , |
| 61 | sa , |
| 62 | sda |
| 63 | ); |
| 64 | |
| 65 | `include "ddr2_parameters.vh" |
| 66 | |
| 67 | input [1:0] cke ; |
| 68 | input ras_n ; |
| 69 | input cas_n ; |
| 70 | input we_n ; |
| 71 | input [2:0] ba ; |
| 72 | input [15:0] addr ; |
| 73 | input [1:0] odt ; |
| 74 | inout [17:0] dqs ; |
| 75 | inout [17:0] dqs_n ; |
| 76 | inout [63:0] dq ; |
| 77 | input scl ; // no connect |
| 78 | inout sda ; // no connect |
| 79 | |
| 80 | `ifdef QUAD_RANK |
| 81 | initial if (DEBUG) $display("%m: Quad Rank"); |
| 82 | `else `ifdef DUAL_RANK |
| 83 | initial if (DEBUG) $display("%m: Dual Rank"); |
| 84 | `else |
| 85 | initial if (DEBUG) $display("%m: Single Rank"); |
| 86 | `endif `endif |
| 87 | |
| 88 | `ifdef ECC |
| 89 | initial if (DEBUG) $display("%m: ECC"); |
| 90 | `ifdef SODIMM |
| 91 | initial begin |
| 92 | $display("%m ERROR: ECC is not available on SODIMM configurations"); |
| 93 | if (STOP_ON_ERROR) $stop(0); |
| 94 | end |
| 95 | `endif |
| 96 | `ifdef x16 |
| 97 | initial begin |
| 98 | $display("%m ERROR: ECC is not available on x16 configurations"); |
| 99 | if (STOP_ON_ERROR) $stop(0); |
| 100 | end |
| 101 | `endif |
| 102 | `else |
| 103 | initial if (DEBUG) $display("%m: non ECC"); |
| 104 | `endif |
| 105 | |
| 106 | `ifdef RDIMM |
| 107 | initial if (DEBUG) $display("%m: RDIMM"); |
| 108 | input reset_n; |
| 109 | input ck ; |
| 110 | input ck_n ; |
| 111 | input [3:0] s_n ; |
| 112 | inout [7:0] cb ; |
| 113 | input [2:0] sa ; // no connect |
| 114 | |
| 115 | wire [5:0] rck = {6{ck}}; |
| 116 | wire [5:0] rck_n = {6{ck_n}}; |
| 117 | reg [3:0] rs_n ; |
| 118 | reg rras_n ; |
| 119 | reg rcas_n ; |
| 120 | reg rwe_n ; |
| 121 | reg [2:0] rba ; |
| 122 | reg [15:0] raddr ; |
| 123 | reg [3:0] rcke ; |
| 124 | reg [3:0] rodt ; |
| 125 | |
| 126 | always @(negedge reset_n or posedge ck) begin |
| 127 | if (!reset_n) begin |
| 128 | rs_n <= #(500) 0; |
| 129 | rras_n <= #(500) 0; |
| 130 | rcas_n <= #(500) 0; |
| 131 | rwe_n <= #(500) 0; |
| 132 | rba <= #(500) 0; |
| 133 | raddr <= #(500) 0; |
| 134 | rcke <= #(500) 0; |
| 135 | rodt <= #(500) 0; |
| 136 | end else begin |
| 137 | rs_n <= #(500) s_n ; |
| 138 | rras_n <= #(500) ras_n; |
| 139 | rcas_n <= #(500) cas_n; |
| 140 | rwe_n <= #(500) we_n ; |
| 141 | rba <= #(500) ba ; |
| 142 | raddr <= #(500) addr ; |
| 143 | `ifdef QUAD_RANK |
| 144 | rcke <= #(500) {{2{cke[1]}}, {2{cke[0]}}}; |
| 145 | rodt <= #(500) {{2{odt[1]}}, {2{odt[0]}}}; |
| 146 | `else |
| 147 | rcke <= #(500) {2'b00, cke}; |
| 148 | rodt <= #(500) {2'b00, odt}; |
| 149 | `endif |
| 150 | |
| 151 | end |
| 152 | end |
| 153 | `else |
| 154 | `ifdef SODIMM |
| 155 | initial if (DEBUG) $display("%m: SODIMM"); |
| 156 | input [1:0] ck ; |
| 157 | input [1:0] ck_n ; |
| 158 | input [1:0] s_n ; |
| 159 | input [1:0] sa ; // no connect |
| 160 | |
| 161 | wire [7:0] cb; |
| 162 | wire [5:0] rck = {{3{ck[1]}}, {3{ck[0]}}}; |
| 163 | wire [5:0] rck_n = {{3{ck_n[1]}}, {3{ck_n[0]}}}; |
| 164 | `else |
| 165 | initial if (DEBUG) $display("%m: UDIMM"); |
| 166 | input reset_n; |
| 167 | input [2:0] ck ; |
| 168 | input [2:0] ck_n ; |
| 169 | input [1:0] s_n ; |
| 170 | inout [7:0] cb ; |
| 171 | input [2:0] sa ; // no connect |
| 172 | |
| 173 | wire [5:0] rck = {2{ck}}; |
| 174 | wire [5:0] rck_n = {2{ck_n}}; |
| 175 | `endif |
| 176 | |
| 177 | wire [2:0] rba = ba ; |
| 178 | wire [15:0] raddr = addr ; |
| 179 | wire rras_n = ras_n; |
| 180 | wire rcas_n = cas_n; |
| 181 | wire rwe_n = we_n ; |
| 182 | `ifdef QUAD_RANK |
| 183 | wire [3:0] rs_n = {{2{s_n[1]}}, {2{s_n[0]}}}; |
| 184 | wire [3:0] rcke = {{2{cke[1]}}, {2{cke[0]}}}; |
| 185 | wire [3:0] rodt = {{2{odt[1]}}, {2{odt[0]}}}; |
| 186 | `else |
| 187 | wire [3:0] rs_n = {2'b00, s_n}; |
| 188 | wire [3:0] rcke = {2'b00, cke}; |
| 189 | wire [3:0] rodt = {2'b00, odt}; |
| 190 | `endif |
| 191 | `endif |
| 192 | wire [15:0] rcb = {8'b0, cb}; |
| 193 | wire zero = 1'b0; |
| 194 | wire one = 1'b1; |
| 195 | |
| 196 | //ddr2 (ck , ck_n , cke , cs_n , ras_n , cas_n , we_n , dm_rdqs , ba , addr , dq , dqs , dqs_n , rdqs_n , odt ); |
| 197 | `ifdef x4 |
| 198 | initial if (DEBUG) $display("%m: Component Width = x4"); |
| 199 | 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]); |
| 200 | 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]); |
| 201 | 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]); |
| 202 | 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]); |
| 203 | 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]); |
| 204 | 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]); |
| 205 | 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]); |
| 206 | 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]); |
| 207 | `ifdef ECC |
| 208 | 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]); |
| 209 | `endif |
| 210 | 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]); |
| 211 | 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]); |
| 212 | 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]); |
| 213 | 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]); |
| 214 | 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]); |
| 215 | 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]); |
| 216 | 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]); |
| 217 | 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]); |
| 218 | `ifdef ECC |
| 219 | 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]); |
| 220 | `endif |
| 221 | `ifdef DUAL_RANK |
| 222 | 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]); |
| 223 | 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]); |
| 224 | 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]); |
| 225 | 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]); |
| 226 | 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]); |
| 227 | 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]); |
| 228 | 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]); |
| 229 | 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]); |
| 230 | `ifdef ECC |
| 231 | 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]); |
| 232 | `endif |
| 233 | 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]); |
| 234 | 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]); |
| 235 | 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]); |
| 236 | 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]); |
| 237 | 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]); |
| 238 | 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]); |
| 239 | 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]); |
| 240 | 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]); |
| 241 | `ifdef ECC |
| 242 | 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]); |
| 243 | `endif |
| 244 | `endif |
| 245 | `ifdef QUAD_RANK |
| 246 | 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]); |
| 247 | 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]); |
| 248 | 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]); |
| 249 | 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]); |
| 250 | 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]); |
| 251 | 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]); |
| 252 | 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]); |
| 253 | 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]); |
| 254 | `ifdef ECC |
| 255 | 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]); |
| 256 | `endif |
| 257 | 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]); |
| 258 | 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]); |
| 259 | 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]); |
| 260 | 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]); |
| 261 | 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]); |
| 262 | 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]); |
| 263 | 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]); |
| 264 | 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]); |
| 265 | `ifdef ECC |
| 266 | 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]); |
| 267 | `endif |
| 268 | 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]); |
| 269 | 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]); |
| 270 | 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]); |
| 271 | 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]); |
| 272 | 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]); |
| 273 | 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]); |
| 274 | 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]); |
| 275 | 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]); |
| 276 | `ifdef ECC |
| 277 | 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]); |
| 278 | `endif |
| 279 | 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]); |
| 280 | 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]); |
| 281 | 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]); |
| 282 | 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]); |
| 283 | 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]); |
| 284 | 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]); |
| 285 | 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]); |
| 286 | 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]); |
| 287 | `ifdef ECC |
| 288 | 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]); |
| 289 | `endif |
| 290 | `endif |
| 291 | `else `ifdef x8 |
| 292 | initial if (DEBUG) $display("%m: Component Width = x8"); |
| 293 | 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]); |
| 294 | 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]); |
| 295 | 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]); |
| 296 | 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]); |
| 297 | 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]); |
| 298 | 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]); |
| 299 | 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]); |
| 300 | 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]); |
| 301 | `ifdef ECC |
| 302 | 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]); |
| 303 | `endif |
| 304 | `ifdef DUAL_RANK |
| 305 | 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]); |
| 306 | 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]); |
| 307 | 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]); |
| 308 | 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]); |
| 309 | 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]); |
| 310 | 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]); |
| 311 | 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]); |
| 312 | 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]); |
| 313 | `ifdef ECC |
| 314 | 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]); |
| 315 | `endif |
| 316 | `endif |
| 317 | `ifdef QUAD_RANK |
| 318 | 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]); |
| 319 | 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]); |
| 320 | 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]); |
| 321 | 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]); |
| 322 | 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]); |
| 323 | 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]); |
| 324 | 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]); |
| 325 | 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]); |
| 326 | `ifdef ECC |
| 327 | 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]); |
| 328 | `endif |
| 329 | 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]); |
| 330 | 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]); |
| 331 | 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]); |
| 332 | 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]); |
| 333 | 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]); |
| 334 | 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]); |
| 335 | 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]); |
| 336 | 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]); |
| 337 | `ifdef ECC |
| 338 | 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]); |
| 339 | `endif |
| 340 | `endif |
| 341 | `else `ifdef x16 |
| 342 | initial if (DEBUG) $display("%m: Component Width = x16"); |
| 343 | 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]); |
| 344 | 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]); |
| 345 | 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]); |
| 346 | 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]); |
| 347 | `ifdef ECC |
| 348 | 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]); |
| 349 | `endif |
| 350 | `ifdef DUAL_RANK |
| 351 | 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]); |
| 352 | 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]); |
| 353 | 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]); |
| 354 | 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]); |
| 355 | `ifdef ECC |
| 356 | 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]); |
| 357 | `endif |
| 358 | `endif |
| 359 | `ifdef QUAD_RANK |
| 360 | 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]); |
| 361 | 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]); |
| 362 | 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]); |
| 363 | 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]); |
| 364 | `ifdef ECC |
| 365 | 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]); |
| 366 | `endif |
| 367 | 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]); |
| 368 | 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]); |
| 369 | 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]); |
| 370 | 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]); |
| 371 | `ifdef ECC |
| 372 | 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]); |
| 373 | `endif |
| 374 | `endif |
| 375 | `endif `endif `endif |
| 376 | |
| 377 | endmodule |
sim/verilog/micron_2048Mb_ddr2/ddr2_parameters.vh |
| 1 | /**************************************************************************************** |
| 2 | * |
| 3 | * Disclaimer This software code and all associated documentation, comments or other |
| 4 | * of Warranty: information (collectively "Software") is provided "AS IS" without |
| 5 | * warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY |
| 6 | * DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
| 7 | * TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES |
| 8 | * OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT |
| 9 | * WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE |
| 10 | * OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. |
| 11 | * FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR |
| 12 | * THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, |
| 13 | * ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE |
| 14 | * OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, |
| 15 | * ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, |
| 16 | * INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, |
| 17 | * WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, |
| 18 | * OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE |
| 19 | * THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 20 | * DAMAGES. Because some jurisdictions prohibit the exclusion or |
| 21 | * limitation of liability for consequential or incidental damages, the |
| 22 | * above limitation may not apply to you. |
| 23 | * |
| 24 | * Copyright 2003 Micron Technology, Inc. All rights reserved. |
| 25 | * |
| 26 | ****************************************************************************************/ |
| 27 | |
| 28 | // Parameters current with 2Gb datasheet rev B |
| 29 | |
| 30 | // Timing parameters based on Speed Grade |
| 31 | |
| 32 | // SYMBOL UNITS DESCRIPTION |
| 33 | // ------ ----- ----------- |
| 34 | `ifdef sg187E |
| 35 | parameter TCK_MIN = 1875; // tCK ps Minimum Clock Cycle Time |
| 36 | parameter TJIT_PER = 90; // tJIT(per) ps Period JItter |
| 37 | parameter TJIT_DUTY = 75; // tJIT(duty) ps Half Period Jitter |
| 38 | parameter TJIT_CC = 180; // tJIT(cc) ps Cycle to Cycle jitter |
| 39 | parameter TERR_2PER = 132; // tERR(nper) ps Accumulated Error (2-cycle) |
| 40 | parameter TERR_3PER = 157; // tERR(nper) ps Accumulated Error (3-cycle) |
| 41 | parameter TERR_4PER = 175; // tERR(nper) ps Accumulated Error (4-cycle) |
| 42 | parameter TERR_5PER = 188; // tERR(nper) ps Accumulated Error (5-cycle) |
| 43 | parameter TERR_N1PER = 250; // tERR(nper) ps Accumulated Error (6-10-cycle) |
| 44 | parameter TERR_N2PER = 425; // tERR(nper) ps Accumulated Error (11-50-cycle) |
| 45 | parameter TQHS = 250; // tQHS ps Data hold skew factor |
| 46 | parameter TAC = 350; // tAC ps DQ output access time from CK/CK# |
| 47 | parameter TDS = 0; // tDS ps DQ and DM input setup time relative to DQS |
| 48 | parameter TDH = 75; // tDH ps DQ and DM input hold time relative to DQS |
| 49 | parameter TDQSCK = 300; // tDQSCK ps DQS output access time from CK/CK# |
| 50 | parameter TDQSQ = 175; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access |
| 51 | parameter TIS = 125; // tIS ps Input Setup Time |
| 52 | parameter TIH = 200; // tIH ps Input Hold Time |
| 53 | parameter TRC = 54000; // tRC ps Active to Active/Auto Refresh command time |
| 54 | parameter TRCD = 13125; // tRCD ps Active to Read/Write command time |
| 55 | parameter TWTR = 7500; // tWTR ps Write to Read command delay |
| 56 | parameter TRP = 13125; // tRP ps Precharge command period |
| 57 | parameter TRPA = 15000; // tRPA ps Precharge All period |
| 58 | parameter TXARDS = 10; // tXARDS tCK Exit low power active power down to a read command |
| 59 | parameter TXARD = 3; // tXARD tCK Exit active power down to a read command |
| 60 | parameter TXP = 3; // tXP tCK Exit power down to a non-read command |
| 61 | parameter TANPD = 4; // tANPD tCK ODT to power-down entry latency |
| 62 | parameter TAXPD = 11; // tAXPD tCK ODT power-down exit latency |
| 63 | parameter CL_TIME = 13125; // CL ps Minimum CAS Latency |
| 64 | `else `ifdef sg25E |
| 65 | parameter TCK_MIN = 2500; // tCK ps Minimum Clock Cycle Time |
| 66 | parameter TJIT_PER = 100; // tJIT(per) ps Period JItter |
| 67 | parameter TJIT_DUTY = 100; // tJIT(duty) ps Half Period Jitter |
| 68 | parameter TJIT_CC = 200; // tJIT(cc) ps Cycle to Cycle jitter |
| 69 | parameter TERR_2PER = 150; // tERR(nper) ps Accumulated Error (2-cycle) |
| 70 | parameter TERR_3PER = 175; // tERR(nper) ps Accumulated Error (3-cycle) |
| 71 | parameter TERR_4PER = 200; // tERR(nper) ps Accumulated Error (4-cycle) |
| 72 | parameter TERR_5PER = 200; // tERR(nper) ps Accumulated Error (5-cycle) |
| 73 | parameter TERR_N1PER = 300; // tERR(nper) ps Accumulated Error (6-10-cycle) |
| 74 | parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) |
| 75 | parameter TQHS = 300; // tQHS ps Data hold skew factor |
| 76 | parameter TAC = 400; // tAC ps DQ output access time from CK/CK# |
| 77 | parameter TDS = 50; // tDS ps DQ and DM input setup time relative to DQS |
| 78 | parameter TDH = 125; // tDH ps DQ and DM input hold time relative to DQS |
| 79 | parameter TDQSCK = 350; // tDQSCK ps DQS output access time from CK/CK# |
| 80 | parameter TDQSQ = 200; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access |
| 81 | parameter TIS = 175; // tIS ps Input Setup Time |
| 82 | parameter TIH = 250; // tIH ps Input Hold Time |
| 83 | parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time |
| 84 | parameter TRCD = 12500; // tRCD ps Active to Read/Write command time |
| 85 | parameter TWTR = 7500; // tWTR ps Write to Read command delay |
| 86 | parameter TRP = 12500; // tRP ps Precharge command period |
| 87 | parameter TRPA = 15000; // tRPA ps Precharge All period |
| 88 | parameter TXARDS = 8; // tXARDS tCK Exit low power active power down to a read command |
| 89 | parameter TXARD = 2; // tXARD tCK Exit active power down to a read command |
| 90 | parameter TXP = 2; // tXP tCK Exit power down to a non-read command |
| 91 | parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency |
| 92 | parameter TAXPD = 10; // tAXPD tCK ODT power-down exit latency |
| 93 | parameter CL_TIME = 12500; // CL ps Minimum CAS Latency |
| 94 | `else `ifdef sg25 |
| 95 | parameter TCK_MIN = 2500; // tCK ps Minimum Clock Cycle Time |
| 96 | parameter TJIT_PER = 100; // tJIT(per) ps Period JItter |
| 97 | parameter TJIT_DUTY = 100; // tJIT(duty) ps Half Period Jitter |
| 98 | parameter TJIT_CC = 200; // tJIT(cc) ps Cycle to Cycle jitter |
| 99 | parameter TERR_2PER = 150; // tERR(nper) ps Accumulated Error (2-cycle) |
| 100 | parameter TERR_3PER = 175; // tERR(nper) ps Accumulated Error (3-cycle) |
| 101 | parameter TERR_4PER = 200; // tERR(nper) ps Accumulated Error (4-cycle) |
| 102 | parameter TERR_5PER = 200; // tERR(nper) ps Accumulated Error (5-cycle) |
| 103 | parameter TERR_N1PER = 300; // tERR(nper) ps Accumulated Error (6-10-cycle) |
| 104 | parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) |
| 105 | parameter TQHS = 300; // tQHS ps Data hold skew factor |
| 106 | parameter TAC = 400; // tAC ps DQ output access time from CK/CK# |
| 107 | parameter TDS = 50; // tDS ps DQ and DM input setup time relative to DQS |
| 108 | parameter TDH = 125; // tDH ps DQ and DM input hold time relative to DQS |
| 109 | parameter TDQSCK = 350; // tDQSCK ps DQS output access time from CK/CK# |
| 110 | parameter TDQSQ = 200; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access |
| 111 | parameter TIS = 175; // tIS ps Input Setup Time |
| 112 | parameter TIH = 250; // tIH ps Input Hold Time |
| 113 | parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time |
| 114 | parameter TRCD = 15000; // tRCD ps Active to Read/Write command time |
| 115 | parameter TWTR = 7500; // tWTR ps Write to Read command delay |
| 116 | parameter TRP = 15000; // tRP ps Precharge command period |
| 117 | parameter TRPA = 17500; // tRPA ps Precharge All period |
| 118 | parameter TXARDS = 8; // tXARDS tCK Exit low power active power down to a read command |
| 119 | parameter TXARD = 2; // tXARD tCK Exit active power down to a read command |
| 120 | parameter TXP = 2; // tXP tCK Exit power down to a non-read command |
| 121 | parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency |
| 122 | parameter TAXPD = 10; // tAXPD tCK ODT power-down exit latency |
| 123 | parameter CL_TIME = 15000; // CL ps Minimum CAS Latency |
| 124 | `else `ifdef sg3E |
| 125 | parameter TCK_MIN = 3000; // tCK ps Minimum Clock Cycle Time |
| 126 | parameter TJIT_PER = 125; // tJIT(per) ps Period JItter |
| 127 | parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter |
| 128 | parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter |
| 129 | parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle) |
| 130 | parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle) |
| 131 | parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle) |
| 132 | parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle) |
| 133 | parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle) |
| 134 | parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) |
| 135 | parameter TQHS = 340; // tQHS ps Data hold skew factor |
| 136 | parameter TAC = 450; // tAC ps DQ output access time from CK/CK# |
| 137 | parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS |
| 138 | parameter TDH = 175; // tDH ps DQ and DM input hold time relative to DQS |
| 139 | parameter TDQSCK = 400; // tDQSCK ps DQS output access time from CK/CK# |
| 140 | parameter TDQSQ = 240; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access |
| 141 | parameter TIS = 200; // tIS ps Input Setup Time |
| 142 | parameter TIH = 275; // tIH ps Input Hold Time |
| 143 | parameter TRC = 54000; // tRC ps Active to Active/Auto Refresh command time |
| 144 | parameter TRCD = 12000; // tRCD ps Active to Read/Write command time |
| 145 | parameter TWTR = 7500; // tWTR ps Write to Read command delay |
| 146 | parameter TRP = 12000; // tRP ps Precharge command period |
| 147 | parameter TRPA = 15000; // tRPA ps Precharge All period |
| 148 | parameter TXARDS = 7; // tXARDS tCK Exit low power active power down to a read command |
| 149 | parameter TXARD = 2; // tXARD tCK Exit active power down to a read command |
| 150 | parameter TXP = 2; // tXP tCK Exit power down to a non-read command |
| 151 | parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency |
| 152 | parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency |
| 153 | parameter CL_TIME = 12000; // CL ps Minimum CAS Latency |
| 154 | `else `ifdef sg3 |
| 155 | parameter TCK_MIN = 3000; // tCK ps Minimum Clock Cycle Time |
| 156 | parameter TJIT_PER = 125; // tJIT(per) ps Period JItter |
| 157 | parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter |
| 158 | parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter |
| 159 | parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle) |
| 160 | parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle) |
| 161 | parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle) |
| 162 | parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle) |
| 163 | parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle) |
| 164 | parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) |
| 165 | parameter TQHS = 340; // tQHS ps Data hold skew factor |
| 166 | parameter TAC = 450; // tAC ps DQ output access time from CK/CK# |
| 167 | parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS |
| 168 | parameter TDH = 175; // tDH ps DQ and DM input hold time relative to DQS |
| 169 | parameter TDQSCK = 400; // tDQSCK ps DQS output access time from CK/CK# |
| 170 | parameter TDQSQ = 240; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access |
| 171 | parameter TIS = 200; // tIS ps Input Setup Time |
| 172 | parameter TIH = 275; // tIH ps Input Hold Time |
| 173 | parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time |
| 174 | parameter TRCD = 15000; // tRCD ps Active to Read/Write command time |
| 175 | parameter TWTR = 7500; // tWTR ps Write to Read command delay |
| 176 | parameter TRP = 15000; // tRP ps Precharge command period |
| 177 | parameter TRPA = 18000; // tRPA ps Precharge All period |
| 178 | parameter TXARDS = 7; // tXARDS tCK Exit low power active power down to a read command |
| 179 | parameter TXARD = 2; // tXARD tCK Exit active power down to a read command |
| 180 | parameter TXP = 2; // tXP tCK Exit power down to a non-read command |
| 181 | parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency |
| 182 | parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency |
| 183 | parameter CL_TIME = 15000; // CL ps Minimum CAS Latency |
| 184 | `else `ifdef sg37E |
| 185 | parameter TCK_MIN = 3750; // tCK ps Minimum Clock Cycle Time |
| 186 | parameter TJIT_PER = 125; // tJIT(per) ps Period JItter |
| 187 | parameter TJIT_DUTY = 125; // tJIT(duty) ps Half Period Jitter |
| 188 | parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter |
| 189 | parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle) |
| 190 | parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle) |
| 191 | parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle) |
| 192 | parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle) |
| 193 | parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle) |
| 194 | parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) |
| 195 | parameter TQHS = 400; // tQHS ps Data hold skew factor |
| 196 | parameter TAC = 500; // tAC ps DQ output access time from CK/CK# |
| 197 | parameter TDS = 100; // tDS ps DQ and DM input setup time relative to DQS |
| 198 | parameter TDH = 225; // tDH ps DQ and DM input hold time relative to DQS |
| 199 | parameter TDQSCK = 450; // tDQSCK ps DQS output access time from CK/CK# |
| 200 | parameter TDQSQ = 300; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access |
| 201 | parameter TIS = 250; // tIS ps Input Setup Time |
| 202 | parameter TIH = 375; // tIH ps Input Hold Time |
| 203 | parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time |
| 204 | parameter TRCD = 15000; // tRCD ps Active to Read/Write command time |
| 205 | parameter TWTR = 7500; // tWTR ps Write to Read command delay |
| 206 | parameter TRP = 15000; // tRP ps Precharge command period |
| 207 | parameter TRPA = 18750; // tRPA ps Precharge All period |
| 208 | parameter TXARDS = 6; // tXARDS tCK Exit low power active power down to a read command |
| 209 | parameter TXARD = 2; // tXARD tCK Exit active power down to a read command |
| 210 | parameter TXP = 2; // tXP tCK Exit power down to a non-read command |
| 211 | parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency |
| 212 | parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency |
| 213 | parameter CL_TIME = 15000; // CL ps Minimum CAS Latency |
| 214 | `else `define sg5E |
| 215 | parameter TCK_MIN = 5000; // tCK ps Minimum Clock Cycle Time |
| 216 | parameter TJIT_PER = 125; // tJIT(per) ps Period JItter |
| 217 | parameter TJIT_DUTY = 150; // tJIT(duty) ps Half Period Jitter |
| 218 | parameter TJIT_CC = 250; // tJIT(cc) ps Cycle to Cycle jitter |
| 219 | parameter TERR_2PER = 175; // tERR(nper) ps Accumulated Error (2-cycle) |
| 220 | parameter TERR_3PER = 225; // tERR(nper) ps Accumulated Error (3-cycle) |
| 221 | parameter TERR_4PER = 250; // tERR(nper) ps Accumulated Error (4-cycle) |
| 222 | parameter TERR_5PER = 250; // tERR(nper) ps Accumulated Error (5-cycle) |
| 223 | parameter TERR_N1PER = 350; // tERR(nper) ps Accumulated Error (6-10-cycle) |
| 224 | parameter TERR_N2PER = 450; // tERR(nper) ps Accumulated Error (11-50-cycle) |
| 225 | parameter TQHS = 450; // tQHS ps Data hold skew factor |
| 226 | parameter TAC = 600; // tAC ps DQ output access time from CK/CK# |
| 227 | parameter TDS = 150; // tDS ps DQ and DM input setup time relative to DQS |
| 228 | parameter TDH = 275; // tDH ps DQ and DM input hold time relative to DQS |
| 229 | parameter TDQSCK = 500; // tDQSCK ps DQS output access time from CK/CK# |
| 230 | parameter TDQSQ = 350; // tDQSQ ps DQS-DQ skew, DQS to last DQ valid, per group, per access |
| 231 | parameter TIS = 350; // tIS ps Input Setup Time |
| 232 | parameter TIH = 475; // tIH ps Input Hold Time |
| 233 | parameter TRC = 55000; // tRC ps Active to Active/Auto Refresh command time |
| 234 | parameter TRCD = 15000; // tRCD ps Active to Read/Write command time |
| 235 | parameter TWTR = 10000; // tWTR ps Write to Read command delay |
| 236 | parameter TRP = 15000; // tRP ps Precharge command period |
| 237 | parameter TRPA = 20000; // tRPA ps Precharge All period |
| 238 | parameter TXARDS = 6; // tXARDS tCK Exit low power active power down to a read command |
| 239 | parameter TXARD = 2; // tXARD tCK Exit active power down to a read command |
| 240 | parameter TXP = 2; // tXP tCK Exit power down to a non-read command |
| 241 | parameter TANPD = 3; // tANPD tCK ODT to power-down entry latency |
| 242 | parameter TAXPD = 8; // tAXPD tCK ODT power-down exit latency |
| 243 | parameter CL_TIME = 15000; // CL ps Minimum CAS Latency |
| 244 | `endif `endif `endif `endif `endif `endif |
| 245 | |
| 246 | `ifdef x16 |
| 247 | `ifdef sg187E |
| 248 | parameter TFAW = 45000; // tFAW ps Four Bank Activate window |
| 249 | `else `ifdef sg25E |
| 250 | parameter TFAW = 45000; // tFAW ps Four Bank Activate window |
| 251 | `else `ifdef sg25 |
| 252 | parameter TFAW = 45000; // tFAW ps Four Bank Activate window |
| 253 | `else // sg3E, sg3, sg37E, sg5E |
| 254 | parameter TFAW = 50000; // tFAW ps Four Bank Activate window |
| 255 | `endif `endif `endif |
| 256 | `else // x4, x8 |
| 257 | `ifdef sg187E |
| 258 | parameter TFAW = 35000; // tFAW ps Four Bank Activate window |
| 259 | `else `ifdef sg25E |
| 260 | parameter TFAW = 35000; // tFAW ps Four Bank Activate window |
| 261 | `else `ifdef sg25 |
| 262 | parameter TFAW = 35000; // tFAW ps Four Bank Activate window |
| 263 | `else // sg3E, sg3, sg37E, sg5E |
| 264 | parameter TFAW = 37500; // tFAW ps Four Bank Activate window |
| 265 | `endif `endif `endif |
| 266 | `endif |
| 267 | |
| 268 | // Timing Parameters |
| 269 | |
| 270 | // Mode Register |
| 271 | parameter AL_MIN = 0; // AL tCK Minimum Additive Latency |
| 272 | parameter AL_MAX = 6; // AL tCK Maximum Additive Latency |
| 273 | parameter CL_MIN = 3; // CL tCK Minimum CAS Latency |
| 274 | parameter CL_MAX = 7; // CL tCK Maximum CAS Latency |
| 275 | parameter WR_MIN = 2; // WR tCK Minimum Write Recovery |
| 276 | parameter WR_MAX = 8; // WR tCK Maximum Write Recovery |
| 277 | parameter BL_MIN = 4; // BL tCK Minimum Burst Length |
| 278 | parameter BL_MAX = 8; // BL tCK Minimum Burst Length |
| 279 | // Clock |
| 280 | parameter TCK_MAX = 8000; // tCK ps Maximum Clock Cycle Time |
| 281 | parameter TCH_MIN = 0.48; // tCH tCK Minimum Clock High-Level Pulse Width |
| 282 | parameter TCH_MAX = 0.52; // tCH tCK Maximum Clock High-Level Pulse Width |
| 283 | parameter TCL_MIN = 0.48; // tCL tCK Minimum Clock Low-Level Pulse Width |
| 284 | parameter TCL_MAX = 0.52; // tCL tCK Maximum Clock Low-Level Pulse Width |
| 285 | // Data |
| 286 | parameter TLZ = TAC; // tLZ ps Data-out low-impedance window from CK/CK# |
| 287 | parameter THZ = TAC; // tHZ ps Data-out high impedance window from CK/CK# |
| 288 | parameter TDIPW = 0.35; // tDIPW tCK DQ and DM input Pulse Width |
| 289 | // Data Strobe |
| 290 | parameter TDQSH = 0.35; // tDQSH tCK DQS input High Pulse Width |
| 291 | parameter TDQSL = 0.35; // tDQSL tCK DQS input Low Pulse Width |
| 292 | parameter TDSS = 0.20; // tDSS tCK DQS falling edge to CLK rising (setup time) |
| 293 | parameter TDSH = 0.20; // tDSH tCK DQS falling edge from CLK rising (hold time) |
| 294 | parameter TWPRE = 0.35; // tWPRE tCK DQS Write Preamble |
| 295 | parameter TWPST = 0.40; // tWPST tCK DQS Write Postamble |
| 296 | parameter TDQSS = 0.25; // tDQSS tCK Rising clock edge to DQS/DQS# latching transition |
| 297 | // Command and Address |
| 298 | parameter TIPW = 0.6; // tIPW tCK Control and Address input Pulse Width |
| 299 | parameter TCCD = 2; // tCCD tCK Cas to Cas command delay |
| 300 | parameter TRAS_MIN = 40000; // tRAS ps Minimum Active to Precharge command time |
| 301 | parameter TRAS_MAX =70000000; // tRAS ps Maximum Active to Precharge command time |
| 302 | parameter TRTP = 7500; // tRTP ps Read to Precharge command delay |
| 303 | parameter TWR = 15000; // tWR ps Write recovery time |
| 304 | parameter TMRD = 2; // tMRD tCK Load Mode Register command cycle time |
| 305 | parameter TDLLK = 200; // tDLLK tCK DLL locking time |
| 306 | // Refresh |
| 307 | parameter TRFC_MIN = 197500; // tRFC ps Refresh to Refresh Command interval minimum value |
| 308 | parameter TRFC_MAX =70000000; // tRFC ps Refresh to Refresh Command Interval maximum value |
| 309 | // Self Refresh |
| 310 | parameter TXSNR = TRFC_MIN + 10000; // tXSNR ps Exit self refesh to a non-read command |
| 311 | parameter TXSRD = 200; // tXSRD tCK Exit self refresh to a read command |
| 312 | parameter TISXR = TIS; // tISXR ps CKE setup time during self refresh exit. |
| 313 | // ODT |
| 314 | parameter TAOND = 2; // tAOND tCK ODT turn-on delay |
| 315 | parameter TAOFD = 2.5; // tAOFD tCK ODT turn-off delay |
| 316 | parameter TAONPD = 2000; // tAONPD ps ODT turn-on (precharge power-down mode) |
| 317 | parameter TAOFPD = 2000; // tAOFPD ps ODT turn-off (precharge power-down mode) |
| 318 | parameter TMOD = 12000; // tMOD ps ODT enable in EMR to ODT pin transition |
| 319 | // Power Down |
| 320 | parameter TCKE = 3; // tCKE tCK CKE minimum high or low pulse width |
| 321 | |
| 322 | // Size Parameters based on Part Width |
| 323 | |
| 324 | `ifdef x4 |
| 325 | parameter ADDR_BITS = 15; // Address Bits |
| 326 | parameter ROW_BITS = 15; // Number of Address bits |
| 327 | parameter COL_BITS = 11; // Number of Column bits |
| 328 | parameter DM_BITS = 1; // Number of Data Mask bits |
| 329 | parameter DQ_BITS = 4; // Number of Data bits |
| 330 | parameter DQS_BITS = 1; // Number of Dqs bits |
| 331 | parameter TRRD = 7500; // tRRD Active bank a to Active bank b command time |
| 332 | `else `ifdef x8 |
| 333 | parameter ADDR_BITS = 15; // Address Bits |
| 334 | parameter ROW_BITS = 15; // Number of Address bits |
| 335 | parameter COL_BITS = 10; // Number of Column bits |
| 336 | parameter DM_BITS = 1; // Number of Data Mask bits |
| 337 | parameter DQ_BITS = 8; // Number of Data bits |
| 338 | parameter DQS_BITS = 1; // Number of Dqs bits |
| 339 | parameter TRRD = 7500; // tRRD Active bank a to Active bank b command time |
| 340 | `else `define x16 |
| 341 | parameter ADDR_BITS = 14; // Address Bits |
| 342 | parameter ROW_BITS = 14; // Number of Address bits |
| 343 | parameter COL_BITS = 10; // Number of Column bits |
| 344 | parameter DM_BITS = 2; // Number of Data Mask bits |
| 345 | parameter DQ_BITS = 16; // Number of Data bits |
| 346 | parameter DQS_BITS = 2; // Number of Dqs bits |
| 347 | parameter TRRD = 10000; // tRRD Active bank a to Active bank b command time |
| 348 | `endif `endif |
| 349 | |
| 350 | `ifdef QUAD_RANK |
| 351 | `define DUAL_RANK // also define DUAL_RANK |
| 352 | parameter CS_BITS = 4; // Number of Chip Select Bits |
| 353 | parameter RANKS = 4; // Number of Chip Select Bits |
| 354 | `else `ifdef DUAL_RANK |
| 355 | parameter CS_BITS = 2; // Number of Chip Select Bits |
| 356 | parameter RANKS = 2; // Number of Chip Select Bits |
| 357 | `else |
| 358 | parameter CS_BITS = 2; // Number of Chip Select Bits |
| 359 | parameter RANKS = 1; // Number of Chip Select Bits |
| 360 | `endif `endif |
| 361 | |
| 362 | // Size Parameters |
| 363 | parameter BA_BITS = 3; // Set this parmaeter to control how many Bank Address bits |
| 364 | parameter MEM_BITS = 10; // Number of write data bursts can be stored in memory. The default is 2^10=1024. |
| 365 | parameter AP = 10; // the address bit that controls auto-precharge and precharge-all |
| 366 | parameter BL_BITS = 3; // the number of bits required to count to MAX_BL |
| 367 | parameter BO_BITS = 2; // the number of Burst Order Bits |
| 368 | |
| 369 | // Simulation parameters |
| 370 | parameter STOP_ON_ERROR = 1; // If set to 1, the model will halt on command sequence/major errors |
| 371 | parameter DEBUG = 1; // Turn on Debug messages |
| 372 | parameter BUS_DELAY = 0; // delay in nanoseconds |
| 373 | parameter RANDOM_OUT_DELAY = 0; // If set to 1, the model will put a random amount of delay on DQ/DQS during reads |
| 374 | parameter RANDOM_SEED = 711689044; //seed value for random generator. |
| 375 | |
| 376 | parameter RDQSEN_PRE = 2; // DQS driving time prior to first read strobe |
| 377 | parameter RDQSEN_PST = 1; // DQS driving time after last read strobe |
| 378 | parameter RDQS_PRE = 2; // DQS low time prior to first read strobe |
| 379 | parameter RDQS_PST = 1; // DQS low time after last valid read strobe |
| 380 | parameter RDQEN_PRE = 0; // DQ/DM driving time prior to first read data |
| 381 | parameter RDQEN_PST = 0; // DQ/DM driving time after last read data |
| 382 | parameter WDQS_PRE = 1; // DQS half clock periods prior to first write strobe |
| 383 | parameter WDQS_PST = 1; // DQS half clock periods after last valid write strobe |
sim/verilog/micron_mobile_ddr/mobile_ddr.v |
| 1 | /**************************************************************************************** |
| 2 | * |
| 3 | * File Name: mobile_ddr.v |
| 4 | * Version: 6.03 |
| 5 | * Model: BUS Functional |
| 6 | * |
| 7 | * Dependencies: mobile_ddr_parameters.vh |
| 8 | * |
| 9 | * Description: Micron MOBILE DDR SDRAM |
| 10 | * |
| 11 | * Limitation: - Doesn't check for 8K-cycle refresh |
| 12 | * |
| 13 | * Note: - Set simulator resolution to "ps" accuracy |
| 14 | * - Set Debug = 0 to disable $display messages |
| 15 | * - Model assume Clk and Clk# crossing at both edge |
| 16 | * |
| 17 | * Disclaimer This software code and all associated documentation, comments or other |
| 18 | * of Warranty: information (collectively "Software") is provided "AS IS" without |
| 19 | * warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY |
| 20 | * DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
| 21 | * TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES |
| 22 | * OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT |
| 23 | * WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE |
| 24 | * OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. |
| 25 | * FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR |
| 26 | * THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, |
| 27 | * ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE |
| 28 | * OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, |
| 29 | * ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, |
| 30 | * INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, |
| 31 | * WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, |
| 32 | * OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE |
| 33 | * THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 34 | * DAMAGES. Because some jurisdictions prohibit the exclusion or |
| 35 | * limitation of liability for consequential or incidental damages, the |
| 36 | * above limitation may not apply to you. |
| 37 | * |
| 38 | * Copyright 2008 Micron Technology, Inc. All rights reserved. |
| 39 | * |
| 40 | * Rev Author Date Changes |
| 41 | * --- ------ ---------- --------------------------------------- |
| 42 | * 1.0 NMB 03/19/02 - Initial Release of Mobile DDR model |
| 43 | * based off of version 5.0 of DDR model |
| 44 | * 1.1 ritz 12/03/04 - New feature: 1/8th strength driver in Drive Strength (Ext Mode Reg). |
| 45 | * Bugfix - ba[0] ba[1] were swapped for determening ext_mode_enable |
| 46 | * thus ext_mode_reg wasnt being programmed. |
| 47 | * 1.2 ritz 12/07/04 - Logging transactions in transcript for automated testing |
| 48 | * 1.3 ritz 01/31/05 - updated to SMG DDR model version 5.2 (dqs edge checking errors fix) |
| 49 | * 1.4 ritz 02/15/05 - Fixed display.*WRITE to use hex for "data". |
| 50 | * 1.5 ritz 03/22/05 - Fixed read latency (#0.5 and 2*Read_latency-1) for MMG latency |
| 51 | * 2.0 bas 07/19/06 - Added PASR support and clk_n checking |
| 52 | * 3.0 bas 08/07/06 - Added tXP check, tCke check, Power-down/Deep power down enter/exit messages |
| 53 | FULL_MEM fix |
| 54 | * 3.11 bas 10/18/06 - Added clk spd chk, added RP support, added T48M part, added SRR functionality, changed tMRD checker to measure in tck pos edge, DPD optimization for FULL_MEM mode |
| 55 | * 3.12 bas 10/19/06 - Fixed PASR in FULL_MEM mode |
| 56 | * 3.20 bas 10/23/06 - changed tXP check to tPDX check for T25L, Initial release to web |
| 57 | * 3.30 bas 01/15/07 - Updated T48M Parameters (updated as of 12/06) |
| 58 | * 3.35 bas 02/28/07 - Model uses tAC correctly to calculate strobe/data launch |
| 59 | * 3.36 bas 03/05/07 - fixed error messages for different banks interrupting |
| 60 | reads/writes w/autoprecharge |
| 61 | * 3.37 bas 03/21/07 - Added T47M Part to 512Mb parameter file |
| 62 | * 3.40 bas 06/25/07 - Removed RP options from 1024Mb |
| 63 | - Updated 128Mb, 256Mb, and 512Mb parts to 05/07 datasheet |
| 64 | - Updated 1024Mb part to 02/07 |
| 65 | - Added illegal Cas Latency check per speed grade |
| 66 | * 3.40 jwm 08/02/07 - Support for 512Mb T47M |
| 67 | * 3.80 clk 10/29/07 - Support for 1024Mb T48M |
| 68 | * 4.00 clk 12/30/07 - Fixed Read terminated by precharge testcase |
| 69 | * 4.70 clk 03/30/08 - Fixed typo in SRR code |
| 70 | * 4.80 clk 04/03/08 - Disable clk checking during initialization |
| 71 | * 4.90 clk 04/16/08 - Fixed tInit, added mpc support, updated t35m timing |
| 72 | * 5.00 clk 05/14/08 - Fixed back to back auto precharge commands |
| 73 | * 5.20 clk 05/21/08 - Fixed read interrupt by pre (BL8), fixed 1024Mb parameter file |
| 74 | * 5.30 clk 05/22/08 - Fixed DM signal which cause false tWTR errors |
| 75 | 05/27/08 - Rewrote write and read pipelines, strobes |
| 76 | * 5.40 clk 05/28/08 - Fixed Addressing problem in Burst Order logic |
| 77 | * 5.50 clk 07/25/08 - Added T36N part type |
| 78 | * 5.60 clk 09/05/08 - Fixed tXP in 256Mb part type |
| 79 | * 5.70 clk 09/17/08 - Fixed burst term check for write w/ all DM active |
| 80 | * 5.80 clk 11/18/08 - Fixed internally latched dq & mask widths |
| 81 | * 5.90 clk 12/10/08 - Updated T36N parameters to latest datasheet |
| 82 | * 6.00 clk 03/05/09 - Fixed DQS problem w/ CL = 2, Fix Wr Pipeline during Rd interrupt |
| 83 | * 6.01 sph 01/20/10 - Added clock stop detection to fix tCH/tCL timing violation |
| 84 | * 6.02 sph 01/22/10 - Added check for nop/des is used when enter/exit stop clock mode |
| 85 | * 6.03 sph 06/07/10 - Include all the mobile_ddr_parameters.vh into a single package |
| 86 | ****************************************************************************************/ |
| 87 | |
| 88 | // DO NOT CHANGE THE TIMESCALE |
| 89 | // MAKE SURE YOUR SIMULATOR USES "PS" RESOLUTION |
| 90 | `timescale 1ns / 1ps |
| 91 | |
| 92 | module mobile_ddr (Dq, Dqs, Addr, Ba, Clk, Clk_n, Cke, Cs_n, Ras_n, Cas_n, We_n, Dm); |
| 93 | |
| 94 | `ifdef den128Mb |
| 95 | `include "128Mb_mobile_ddr_parameters.vh" |
| 96 | `elsif den256Mb |
| 97 | `include "256Mb_mobile_ddr_parameters.vh" |
| 98 | `elsif den512Mb |
| 99 | `include "512Mb_mobile_ddr_parameters.vh" |
| 100 | `elsif den1024Mb |
| 101 | `include "1024Mb_mobile_ddr_parameters.vh" |
| 102 | `elsif den2048Mb |
| 103 | `include "2048Mb_mobile_ddr_parameters.vh" |
| 104 | `else |
| 105 | // NOTE: Intentionally cause a compile fail here to force the users |
| 106 | // to select the correct component density before continuing |
| 107 | ERROR: You must specify component density with +define+den____Mb. |
| 108 | `endif |
| 109 | |
| 110 | `define MAX_PIPE 2*(CL_MAX + BL_MAX) |
| 111 | |
| 112 | // Port Declarations |
| 113 | input Clk; |
| 114 | input Clk_n; |
| 115 | input Cke; |
| 116 | input Cs_n; |
| 117 | input Ras_n; |
| 118 | input Cas_n; |
| 119 | input We_n; |
| 120 | input [ADDR_BITS - 1 : 0] Addr; |
| 121 | input [1 : 0] Ba; |
| 122 | inout [DQ_BITS - 1 : 0] Dq; |
| 123 | inout [DQS_BITS - 1 : 0] Dqs; |
| 124 | input [DM_BITS - 1 : 0] Dm; |
| 125 | |
| 126 | //time variables |
| 127 | realtime tXP_chk ; |
| 128 | reg enter_DPD ; |
| 129 | reg enter_PD ; |
| 130 | reg enter_APD ; |
| 131 | |
| 132 | //integer clk checks |
| 133 | |
| 134 | // Internal Wires (fixed width) |
| 135 | wire [31 : 0] Dq_in; |
| 136 | wire [3 : 0] Dqs_in; |
| 137 | wire [3 : 0] Dm_in; |
| 138 | |
| 139 | assign Dq_in [DQ_BITS - 1 : 0] = Dq; |
| 140 | assign Dqs_in [DQS_BITS - 1 : 0] = Dqs; |
| 141 | assign Dm_in [DM_BITS - 1 : 0] = Dm; |
| 142 | |
| 143 | // Data pair |
| 144 | reg [DQ_BITS-1 : 0] dq_rise; |
| 145 | reg [DM_BITS-1 : 0] dm_rise; |
| 146 | reg [DQ_BITS-1 : 0] dq_fall; |
| 147 | reg [DM_BITS-1 : 0] dm_fall; |
| 148 | reg [DM_BITS*2-1 : 0] dm_pair; |
| 149 | reg [DQ_BITS-1 : 0] Dq_buf; |
| 150 | |
| 151 | // Power-down cycle counter |
| 152 | reg [03:00] PD_cntr ; |
| 153 | |
| 154 | // prev cmd value |
| 155 | |
| 156 | reg prev_Cs_n ; |
| 157 | reg prev_Ras_n ; |
| 158 | reg prev_Cas_n ; |
| 159 | reg prev_We_n ; |
| 160 | reg [01:00] prev_Ba ; |
| 161 | reg prev_cke ; |
| 162 | |
| 163 | wire prev_nop = ~prev_Cs_n & prev_Ras_n & prev_Cas_n & prev_We_n ; |
| 164 | wire prev_des = prev_Cs_n ; |
| 165 | wire prev_bt = ~prev_Cs_n & prev_Ras_n & prev_Cas_n & ~prev_We_n ; |
| 166 | wire prev_rd = ~prev_Cs_n & prev_Ras_n & ~prev_Cas_n & prev_We_n ; |
| 167 | reg Clk_Chk_enable = 1'b0 ; |
| 168 | |
| 169 | //differential clk |
| 170 | reg diff_ck; |
| 171 | always @(posedge Clk) diff_ck <= Clk; |
| 172 | always @(posedge Clk_n) diff_ck <= ~Clk_n; |
| 173 | |
| 174 | //measure clock period |
| 175 | realtime clk_period ; |
| 176 | realtime pos_clk_edge ; |
| 177 | integer clk_pos_edge_cnt ; |
| 178 | always @(posedge diff_ck) begin |
| 179 | clk_period = $realtime - pos_clk_edge ; |
| 180 | pos_clk_edge = $realtime ; |
| 181 | if ((Cke == 1'b1) && (clk_pos_edge_cnt < 2)) begin |
| 182 | clk_pos_edge_cnt = clk_pos_edge_cnt + 1 ; |
| 183 | end else if (Cke == 1'b0) begin |
| 184 | clk_pos_edge_cnt = 2'b00 ; |
| 185 | end |
| 186 | end |
| 187 | |
| 188 | //measure duty cycle |
| 189 | realtime neg_clk_edge ; |
| 190 | always @(negedge diff_ck) begin |
| 191 | neg_clk_edge = $realtime ; |
| 192 | end |
| 193 | realtime pos_clk_time ; |
| 194 | realtime neg_clk_time ; |
| 195 | reg clock_stop = 0; |
| 196 | |
| 197 | // Mode Register |
| 198 | reg [ADDR_BITS - 1 : 0] Mode_reg; |
| 199 | reg [ADDR_BITS - 1 : 0] Ext_Mode_reg; |
| 200 | reg [2*DQ_BITS - 1 : 0] Srr_reg; |
| 201 | |
| 202 | |
| 203 | // SRR Registers |
| 204 | reg SRR_read; |
| 205 | |
| 206 | // Internal System Clock |
| 207 | reg CkeZ, Sys_clk; |
| 208 | |
| 209 | // Internal Dqs initialize |
| 210 | // reg Dqs_int; |
| 211 | |
| 212 | // Dqs buffer |
| 213 | reg Dqs_out; |
| 214 | // reg [DQS_BITS - 1 : 0] Dqs_gen; |
| 215 | reg Dqs_out_en; |
| 216 | // Dq buffer |
| 217 | reg [DQ_BITS - 1 : 0] Dq_out_temp; |
| 218 | reg [DQ_BITS - 1 : 0] Dq_out; |
| 219 | reg Dq_out_en; |
| 220 | |
| 221 | // Read pipeline variables |
| 222 | reg [`MAX_PIPE : 0] Read_pipeline ; |
| 223 | reg [1 : 0] Read_bank [0 : 6]; |
| 224 | reg [COL_BITS - 1 : 0] Read_cols [0 : 6]; |
| 225 | |
| 226 | // Write pipeline variables |
| 227 | reg [`MAX_PIPE :-2] Write_pipeline; |
| 228 | reg [BA_BITS-1 : 0] Write_bank_pipeline [`MAX_PIPE :-2]; |
| 229 | reg [COL_BITS - 1 : 0] Write_col_pipeline [`MAX_PIPE :-2]; |
| 230 | |
| 231 | // Auto precharge variables |
| 232 | reg [3:0] Read_precharge_access ; |
| 233 | reg [3:0] Read_precharge_pre ; |
| 234 | reg [3:0] Write_precharge_access ; |
| 235 | reg [3:0] Write_precharge_pre ; |
| 236 | integer Count_precharge [0:3]; |
| 237 | reg SelfRefresh; |
| 238 | reg [3:0] Read_precharge_count [3:0] ; |
| 239 | reg [3:0] Write_precharge_count [3:0]; |
| 240 | |
| 241 | |
| 242 | reg wr_ap_display_msg ; |
| 243 | reg rd_ap_display_msg ; |
| 244 | |
| 245 | // Manual precharge variables |
| 246 | // reg [0 : 6] A10_precharge ; |
| 247 | // reg [1 : 0] Bank_precharge [0 : 6]; |
| 248 | // reg [0 : 6] Cmnd_precharge ; |
| 249 | |
| 250 | // Burst terminate variables |
| 251 | // reg Cmnd_bst [0 : 6]; |
| 252 | |
| 253 | // tMRD counter |
| 254 | integer MRD_cntr ; |
| 255 | integer SRR_cntr ; |
| 256 | integer SRC_cntr ; |
| 257 | integer tWTR_cntr ; |
| 258 | |
| 259 | // Memory Banks |
| 260 | `ifdef FULL_MEM |
| 261 | reg [DQ_BITS - 1 : 0] mem_array [0 : (1<<full_mem_bits)-1]; |
| 262 | `else |
| 263 | reg [DQ_BITS - 1 : 0] mem_array [0 : (1<<part_mem_bits)-1]; |
| 264 | reg [full_mem_bits - 1 : 0] addr_array [0 : (1<<part_mem_bits)-1]; |
| 265 | reg [part_mem_bits : 0] mem_used; |
| 266 | reg [part_mem_bits : 0] memory_index; |
| 267 | initial mem_used = 0; |
| 268 | `endif |
| 269 | |
| 270 | // Dqs edge checking |
| 271 | integer i; |
| 272 | reg [3:0] expect_pos_dqs; |
| 273 | reg [3:0] expect_neg_dqs; |
| 274 | |
| 275 | // Burst counter |
| 276 | reg [COL_BITS - 1 : 0] Burst_counter; |
| 277 | |
| 278 | // Burst counter delay |
| 279 | reg [COL_BITS - 1 : 0] Burst_counter_dly; |
| 280 | always @(Mode_reg or Burst_counter) begin |
| 281 | if (Mode_reg[6:4] == 3'b010) begin |
| 282 | // Burst_counter_dly <= #tAC2_max Burst_counter; |
| 283 | end else if (Mode_reg[6:4] == 3'b011) begin |
| 284 | // Burst_counter_dly <= #tAC3_max Burst_counter; |
| 285 | end |
| 286 | end |
| 287 | |
| 288 | // Precharge variables |
| 289 | reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; |
| 290 | |
| 291 | // Activate variables |
| 292 | reg Act_b0, Act_b1, Act_b2, Act_b3; |
| 293 | |
| 294 | // Data IO variables |
| 295 | // reg Data_in_enable; |
| 296 | wire Data_in_enable = Write_pipeline[-2]; |
| 297 | // reg Data_out_enable; |
| 298 | wire Data_out_enable = Read_pipeline[0]; |
| 299 | wire tWTR_en = ((|Write_pipeline[`MAX_PIPE : 0]) & ~(&Dm)); |
| 300 | |
| 301 | // Data Out Enable delay |
| 302 | // reg Data_out_enable_dly; |
| 303 | // always @(Mode_reg or Data_out_enable) begin |
| 304 | // if (Mode_reg[6:4] == 3'b010) begin |
| 305 | // Data_out_enable_dly <= #tAC2_max Data_out_enable; |
| 306 | // end else if (Mode_reg[6:4] == 3'b011) begin |
| 307 | // Data_out_enable_dly <= #tAC3_max Data_out_enable; |
| 308 | // end |
| 309 | // end |
| 310 | |
| 311 | // Internal address mux variables |
| 312 | reg [1 : 0] Prev_bank; |
| 313 | reg [1 : 0] Bank_addr; |
| 314 | reg [COL_BITS - 1 : 0] Cols_addr, Cols_brst, Cols_temp; |
| 315 | reg [ADDR_BITS - 1 : 0] Rows_addr; |
| 316 | reg [ADDR_BITS - 1 : 0] B0_row_addr; |
| 317 | reg [ADDR_BITS - 1 : 0] B1_row_addr; |
| 318 | reg [ADDR_BITS - 1 : 0] B2_row_addr; |
| 319 | reg [ADDR_BITS - 1 : 0] B3_row_addr; |
| 320 | |
| 321 | integer aref_count; |
| 322 | reg ext_mode_load_done; |
| 323 | reg mode_load_done; |
| 324 | reg power_up_done; |
| 325 | |
| 326 | // Write DQS for tDSS , tDSH, tDQSH, tDQSL checks |
| 327 | wire wdqs_valid = Write_pipeline[`MAX_PIPE:0]; |
| 328 | |
| 329 | // Commands Decode |
| 330 | wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n; |
| 331 | wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n & Cke; |
| 332 | wire Sref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n & ~Cke; |
| 333 | wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n; |
| 334 | wire Ext_mode_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & Ba[1] & ~Ba[0]; |
| 335 | wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & ~Ba[1] & ~Ba[0]; |
| 336 | wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n; |
| 337 | wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n; |
| 338 | wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n; |
| 339 | wire DPD_enable = ~Cs_n & Ras_n & Cas_n & ~We_n & ~Cke; |
| 340 | wire PD_enable = ((~Cs_n & Ras_n & Cas_n & We_n) | Cs_n) & ~Cke; |
| 341 | wire nop_enable = ~Cs_n & Ras_n & Cas_n & We_n ; |
| 342 | wire des_enable = Cs_n ; |
| 343 | wire srr_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & ~Ba[1] & Ba[0] & ((part_size==128)|(part_size==512)|(part_size==1024)) ; |
| 344 | |
| 345 | reg Cke_Chk = 0 ; |
| 346 | parameter tInit = 200000 ; |
| 347 | reg Cke_Print = 1'b0 ; |
| 348 | real Init_Cmd_Chk ; |
| 349 | |
| 350 | |
| 351 | // Burst Length Decode |
| 352 | // reg [4:0] burst_length = 1 << (Mode_reg[2:0]); |
| 353 | reg [4:0] burst_length ; |
| 354 | reg read_precharge_truncation; |
| 355 | |
| 356 | // CAS Latency Decode |
| 357 | wire [2:0] cas_latency = Mode_reg[6:4] ; |
| 358 | wire [2:0] cas_latency_x2 = ((2*Mode_reg[6:4])-1); |
| 359 | |
| 360 | real tAC_max ; |
| 361 | always @ (Mode_reg) |
| 362 | begin |
| 363 | if (Mode_reg[6:4] == 3'b011) |
| 364 | tAC_max = tAC3_max ; |
| 365 | else if (Mode_reg[6:4] == 3'b010) |
| 366 | tAC_max = tAC2_max ; |
| 367 | end |
| 368 | |
| 369 | // DQS Buffer |
| 370 | reg [DQS_BITS - 1 : 0] dqs_delayed ; |
| 371 | // always@* begin |
| 372 | // dqs_delayed <= Dqs_out ; |
| 373 | // end |
| 374 | |
| 375 | assign Dqs = (Dqs_out_en) ? {DQS_BITS{Dqs_out}} : 'bz; |
| 376 | assign Dq = (Dq_out_en ) ? Dq_out : 'bz; |
| 377 | |
| 378 | // Debug message |
| 379 | wire Debug = 1'b0; |
| 380 | |
| 381 | // Timing Check |
| 382 | // realtime MRD_chk; |
| 383 | realtime RFC_chk; |
| 384 | realtime RRD_chk; |
| 385 | realtime RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3; |
| 386 | realtime RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3; |
| 387 | realtime RC_chk0, RC_chk1, RC_chk2, RC_chk3; |
| 388 | realtime RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3; |
| 389 | realtime RP_chk0, RP_chk1, RP_chk2, RP_chk3; |
| 390 | realtime WR_chk0, WR_chk1, WR_chk2, WR_chk3; |
| 391 | realtime SRR_chk; |
| 392 | |
| 393 | // |
| 394 | reg [2:0] current_init_state ; |
| 395 | parameter [2:0] begin_init = 3'b000 ; |
| 396 | parameter [2:0] cke_init = 3'b001 ; |
| 397 | parameter [2:0] prech_init = 3'b010 ; |
| 398 | parameter [2:0] begin_mode_init = 3'b011 ; |
| 399 | parameter [2:0] mode_init = 3'b100 ; |
| 400 | parameter [2:0] ext_mode_init = 3'b101 ; |
| 401 | parameter [2:0] mode_done_init = 3'b110 ; |
| 402 | |
| 403 | initial begin |
| 404 | CkeZ = 1'b0; |
| 405 | Sys_clk = 1'b0; |
| 406 | {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000; |
| 407 | {Act_b0, Act_b1, Act_b2, Act_b3} = 4'b1111; |
| 408 | // Dqs_int = 1'b0; |
| 409 | Dqs_out_en = {DQS_BITS{1'b0}}; |
| 410 | Dqs_out = {DQS_BITS{1'bz}}; |
| 411 | // Dqs_gen = {DQS_BITS{1'bz}}; |
| 412 | Dq_out = {DQ_BITS{1'bz}}; |
| 413 | Dq_out_en = {DQ_BITS{1'b0}}; |
| 414 | // dq_delayed = {DQ_BITS{1'bz}}; |
| 415 | // Data_in_enable = 1'b0; |
| 416 | // Data_out_enable = 1'b0; |
| 417 | aref_count = 0; |
| 418 | SelfRefresh = 1'b0; |
| 419 | power_up_done = 0; |
| 420 | ext_mode_load_done = 0; |
| 421 | mode_load_done = 0; |
| 422 | // MRD_chk = 0; |
| 423 | RFC_chk = 0; |
| 424 | RRD_chk = 0; |
| 425 | RAS_chk0 = 0; |
| 426 | RAS_chk1 = 0; |
| 427 | RAS_chk2 = 0; |
| 428 | RAS_chk3 = 0; |
| 429 | RAP_chk0 = 0; |
| 430 | RAP_chk1 = 0; |
| 431 | RAP_chk2 = 0; |
| 432 | RAP_chk3 = 0; |
| 433 | RC_chk0 = 0; |
| 434 | RC_chk1 = 0; |
| 435 | RC_chk2 = 0; |
| 436 | RC_chk3 = 0; |
| 437 | RCD_chk0 = 0; |
| 438 | RCD_chk1 = 0; |
| 439 | RCD_chk2 = 0; |
| 440 | RCD_chk3 = 0; |
| 441 | RP_chk0 = 0; |
| 442 | RP_chk1 = 0; |
| 443 | RP_chk2 = 0; |
| 444 | RP_chk3 = 0; |
| 445 | WR_chk0 = 0; |
| 446 | WR_chk1 = 0; |
| 447 | WR_chk2 = 0; |
| 448 | WR_chk3 = 0; |
| 449 | SRR_chk = 0; |
| 450 | $timeformat (-9, 3, " ns", 12); |
| 451 | pos_clk_time = 0; |
| 452 | neg_clk_time = 0; |
| 453 | enter_DPD = 0; |
| 454 | enter_PD = 0; |
| 455 | enter_APD = 0; |
| 456 | current_init_state = begin_init ; |
| 457 | SRR_read = 1'b0; |
| 458 | MRD_cntr = 8; |
| 459 | SRR_cntr = 8; |
| 460 | SRC_cntr = 8; |
| 461 | tWTR_cntr = 8; |
| 462 | Read_precharge_access[0] = 1'b0 ; |
| 463 | Read_precharge_access[1] = 1'b0 ; |
| 464 | Read_precharge_access[2] = 1'b0 ; |
| 465 | Read_precharge_access[3] = 1'b0 ; |
| 466 | Read_precharge_pre[0] = 1'b0 ; |
| 467 | Read_precharge_pre[1] = 1'b0 ; |
| 468 | Read_precharge_pre[2] = 1'b0 ; |
| 469 | Read_precharge_pre[3] = 1'b0 ; |
| 470 | Write_precharge_access[0] = 1'b0 ; |
| 471 | Write_precharge_access[1] = 1'b0 ; |
| 472 | Write_precharge_access[2] = 1'b0 ; |
| 473 | Write_precharge_access[3] = 1'b0 ; |
| 474 | Write_precharge_pre[0] = 1'b0 ; |
| 475 | Write_precharge_pre[1] = 1'b0 ; |
| 476 | Write_precharge_pre[2] = 1'b0 ; |
| 477 | Write_precharge_pre[3] = 1'b0 ; |
| 478 | wr_ap_display_msg = 1'b0 ; |
| 479 | rd_ap_display_msg = 1'b0 ; |
| 480 | Read_precharge_count[0] = 4'hf; |
| 481 | Read_precharge_count[1] = 4'hf; |
| 482 | Read_precharge_count[2] = 4'hf; |
| 483 | Read_precharge_count[3] = 4'hf; |
| 484 | Write_precharge_count[0] = 4'hf; |
| 485 | Write_precharge_count[1] = 4'hf; |
| 486 | Write_precharge_count[2] = 4'hf; |
| 487 | Write_precharge_count[3] = 4'hf; |
| 488 | end |
| 489 | |
| 490 | // make sure 200 us has passed since cke for first command |
| 491 | always @ (Clk_Chk_enable or nop_enable or des_enable) |
| 492 | begin |
| 493 | if (~Clk_Chk_enable) begin |
| 494 | if (~nop_enable & ~des_enable) begin |
| 495 | Clk_Chk_enable = 1'b1 ; |
| 496 | if (~Cke_Chk) begin |
| 497 | if (($realtime - Init_Cmd_Chk < tInit - 0.001) & ~Cke_Print) begin |
| 498 | $display("Warning: You must wait 200 us from CKE assertion before you perform a command. Current wait time: %3.0f ns", $realtime - (Init_Cmd_Chk)); |
| 499 | Cke_Print = 1'b1 ; |
| 500 | end |
| 501 | end |
| 502 | end |
| 503 | end |
| 504 | end |
| 505 | |
| 506 | // Check for tCH, tCK, and clock stop mode |
| 507 | always @(diff_ck) begin |
| 508 | if (diff_ck) begin |
| 509 | neg_clk_time = $realtime - neg_clk_edge ; |
| 510 | end |
| 511 | if (~diff_ck) begin |
| 512 | pos_clk_time = $realtime - pos_clk_edge ; |
| 513 | end |
| 514 | if (Cke & Clk_Chk_enable) begin |
| 515 | // clock stop mode when either pulse width is 2x bigger than the other (reasonable assumption???) |
| 516 | clock_stop = ((pos_clk_time / neg_clk_time > 2) | (neg_clk_time / pos_clk_time > 2)); |
| 517 | |
| 518 | // Check if NOP/DES when enter/exit clock stop mode |
| 519 | if ((clock_stop && diff_ck) && (~(prev_nop || prev_des) || ~(nop_enable || des_enable))) begin |
| 520 | $display ("%m: at time %t ERROR: Nop or Deselect is required when enter or exit Stop Clock Mode", $time); |
| 521 | end |
| 522 | |
| 523 | if ((pos_clk_time / clk_period < tCH_MIN) && ~clock_stop) begin |
| 524 | $display ("%m: at time %t ERROR: tCH minimum violation on CLK by %t", $time, tCH_MIN*clk_period - pos_clk_time); |
| 525 | end |
| 526 | if ((pos_clk_time / clk_period > tCH_MAX) && ~clock_stop) begin |
| 527 | $display ("%m: at time %t ERROR: tCH maximum violation on CLK by %t", $time, pos_clk_time - tCH_MAX*clk_period); |
| 528 | end |
| 529 | if ((neg_clk_time / clk_period < tCL_MIN) && ~clock_stop) begin |
| 530 | $display ("%m: at time %t ERROR: tCL minimum violation on CLK by %t", $time, tCL_MIN*clk_period - pos_clk_time); |
| 531 | end |
| 532 | if ((neg_clk_time / clk_period > tCL_MAX) && ~clock_stop) begin |
| 533 | $display ("%m: at time %t ERROR: tCL maximum violation on CLK by %t", $time, pos_clk_time - tCL_MAX*clk_period); |
| 534 | end |
| 535 | end |
| 536 | end |
| 537 | |
| 538 | //clock Frequency Check |
| 539 | always @(posedge diff_ck) begin |
| 540 | if (clk_pos_edge_cnt > 1) begin |
| 541 | if (Mode_reg[6:4] == 3'b011) begin |
| 542 | if (clk_period < (tCK3_min-0.001)) begin |
| 543 | $display ("%m : at time %t ERROR : Illegal clk period for CAS Latency 3", $realtime); |
| 544 | $display ("%m : at time %t CLK PERIOD = %t", $realtime, clk_period); |
| 545 | end |
| 546 | end |
| 547 | if (Mode_reg[6:4] == 3'b010) begin |
| 548 | if (clk_period < (tCK2_min-0.001)) begin |
| 549 | $display ("%m : at time %t ERROR : Illegal clk period for CAS Latency 2", $realtime); |
| 550 | $display ("%m : at time %t CLK PERIOD = %t", $realtime, clk_period); |
| 551 | end |
| 552 | end |
| 553 | end |
| 554 | end |
| 555 | |
| 556 | //SRR reg settings |
| 557 | always @(posedge power_up_done) begin |
| 558 | Srr_reg = 'b0 ; |
| 559 | Srr_reg[3:0] = 4'b1111 ; //Manufacturer(Micron) |
| 560 | Srr_reg[7:4] = 4'b0000 ; //Revision ID(Default to 0 in model) |
| 561 | Srr_reg[10:8] = 3'b100 ; //Refresh Rate(based on temp sensor - will default to 1x in model) |
| 562 | Srr_reg[11] = (DQ_BITS == 32)? 1'b1 : 1'b0 ; //Part width(x32 or x16) |
| 563 | Srr_reg[12] = 1'b0 ; //Device Type (LP DDR) |
| 564 | Srr_reg[15:13] = (part_size == 1024)? 3'b011 : |
| 565 | (part_size == 512 )? 3'b010 : |
| 566 | (part_size == 256 )? 3'b001 : |
| 567 | 3'b000 ; //Density(1024Mb, 512Mb, 256Mb, 128Mb) |
| 568 | end |
| 569 | |
| 570 | // System Clock |
| 571 | always begin |
| 572 | @ (posedge diff_ck) begin |
| 573 | Sys_clk = CkeZ; |
| 574 | CkeZ = Cke; |
| 575 | end |
| 576 | @ (negedge diff_ck) begin |
| 577 | Sys_clk = 1'b0; |
| 578 | end |
| 579 | end |
| 580 | |
| 581 | task store_prev_cmd; |
| 582 | begin |
| 583 | prev_Cs_n <= Cs_n ; |
| 584 | prev_Ras_n <= Ras_n ; |
| 585 | prev_Cas_n <= Cas_n ; |
| 586 | prev_We_n <= We_n ; |
| 587 | prev_Ba[1] <= Ba[1] ; |
| 588 | prev_Ba[0] <= Ba[0] ; |
| 589 | prev_cke <= Cke ; |
| 590 | end |
| 591 | endtask |
| 592 | |
| 593 | task MRD_counter; |
| 594 | begin |
| 595 | if (Cke) begin |
| 596 | if (MRD_cntr < tMRD) begin |
| 597 | MRD_cntr = MRD_cntr + 1'b1; |
| 598 | end |
| 599 | end |
| 600 | end |
| 601 | endtask |
| 602 | |
| 603 | task SRR_counter; |
| 604 | begin |
| 605 | if (Cke) begin |
| 606 | if (SRR_cntr < tSRR) begin |
| 607 | SRR_cntr = SRR_cntr + 1'b1; |
| 608 | end |
| 609 | end |
| 610 | end |
| 611 | endtask |
| 612 | |
| 613 | task SRC_counter; |
| 614 | begin |
| 615 | if (Cke) begin |
| 616 | if (SRC_cntr < ((Mode_reg[6:4])+1)) begin |
| 617 | SRC_cntr = SRC_cntr + 1'b1; |
| 618 | end |
| 619 | end |
| 620 | end |
| 621 | endtask |
| 622 | |
| 623 | task tWTR_counter; |
| 624 | begin |
| 625 | if (Cke) begin |
| 626 | if (tWTR_en) begin |
| 627 | tWTR_cntr = 0 ; |
| 628 | end else begin |
| 629 | tWTR_cntr = tWTR_cntr + 1'b1; |
| 630 | end |
| 631 | end |
| 632 | end |
| 633 | endtask |
| 634 | |
| 635 | task command_counter; |
| 636 | begin |
| 637 | if (Cke) begin |
| 638 | for (i=0; i<4;i=i+1) begin |
| 639 | if (Read_precharge_count[i] < 4'hf) begin |
| 640 | Read_precharge_count[i] = Read_precharge_count[i] + 1'b1; |
| 641 | end |
| 642 | end |
| 643 | for (i=0; i<4;i=i+1) begin |
| 644 | if (Write_precharge_count[i] < 4'hf) begin |
| 645 | Write_precharge_count[i] = Write_precharge_count[i] + 1'b1; |
| 646 | end |
| 647 | end |
| 648 | end |
| 649 | end |
| 650 | endtask |
| 651 | |
| 652 | |
| 653 | task PD_counter; |
| 654 | begin |
| 655 | if (~Cke) begin |
| 656 | if (PD_cntr < tCKE) begin |
| 657 | PD_cntr = PD_cntr + (enter_DPD | enter_PD | DPD_enable | PD_enable); |
| 658 | end |
| 659 | end else begin |
| 660 | PD_cntr = 4'h0 ; |
| 661 | end |
| 662 | end |
| 663 | endtask |
| 664 | |
| 665 | task tXP_check; |
| 666 | begin |
| 667 | if (Cke == 1'b1 && prev_cke == 1'b0) begin |
| 668 | tXP_chk = $realtime ; |
| 669 | end |
| 670 | if (Cke) begin |
| 671 | if (~nop_enable && ~des_enable) begin |
| 672 | if ($realtime-tXP_chk < tXP - 0.001) begin |
| 673 | `ifdef T25L |
| 674 | $display ("%m: At time %t ERROR: tPDX violation", $realtime); |
| 675 | `else |
| 676 | $display ("%m: At time %t ERROR: tXP violation", $realtime); |
| 677 | `endif |
| 678 | end |
| 679 | end |
| 680 | end |
| 681 | end |
| 682 | endtask |
| 683 | |
| 684 | // DPD pos edge clk cntr |
| 685 | always begin |
| 686 | @ (posedge diff_ck) begin |
| 687 | tXP_check ; |
| 688 | Power_down_chk ; |
| 689 | PD_counter ; |
| 690 | store_prev_cmd ; |
| 691 | end |
| 692 | end |
| 693 | |
| 694 | // Check to make sure that we have a Deselect or NOP command on the bus when CKE is brought high |
| 695 | always @(Cke) begin |
| 696 | if (Cke === 1'b1) begin |
| 697 | Init_Cmd_Chk = $realtime ; |
| 698 | if (SelfRefresh === 1'b1) begin |
| 699 | SelfRefresh = 1'b0; |
| 700 | end |
| 701 | if (!((Cs_n) || (~Cs_n & Ras_n & Cas_n & We_n))) begin |
| 702 | $display ("%m: At time %t MEMORY ERROR: You must have a Deselect or NOP command applied", $realtime); |
| 703 | $display ("%m: when the Clock Enable is brought High."); |
| 704 | end |
| 705 | end |
| 706 | end |
| 707 | |
| 708 | //BL Mode Reg settings |
| 709 | always@(Mode_reg[2:0] or mode_load_done) begin |
| 710 | if (mode_load_done) begin |
| 711 | case (Mode_reg[2:0]) |
| 712 | 3'b001 : burst_length = 5'b00010; |
| 713 | 3'b010 : burst_length = 5'b00100; |
| 714 | 3'b011 : burst_length = 5'b01000; |
| 715 | 3'b100 : burst_length = 5'b10000; |
| 716 | default : burst_length = 5'bxxxxx; |
| 717 | endcase |
| 718 | end |
| 719 | end |
| 720 | |
| 721 | // Init sequence |
| 722 | always @(current_init_state or Cke or Prech_enable or ext_mode_load_done or mode_load_done or aref_count) begin |
| 723 | if (current_init_state == begin_init) begin |
| 724 | if (Cke) begin |
| 725 | current_init_state = cke_init ; |
| 726 | power_up_done = 1'b0 ; |
| 727 | end |
| 728 | end |
| 729 | if (current_init_state == cke_init) begin |
| 730 | if (Prech_enable) begin |
| 731 | current_init_state = prech_init ; |
| 732 | aref_count = 0 ; |
| 733 | end |
| 734 | end |
| 735 | if (current_init_state == prech_init) begin |
| 736 | if (~Prech_enable) begin |
| 737 | current_init_state = begin_mode_init ; |
| 738 | end |
| 739 | end |
| 740 | if (current_init_state == begin_mode_init) begin |
| 741 | if (ext_mode_load_done) begin |
| 742 | current_init_state = ext_mode_init ; |
| 743 | end |
| 744 | if (mode_load_done) begin |
| 745 | current_init_state = mode_init ; |
| 746 | end |
| 747 | end |
| 748 | if (current_init_state == mode_init) begin |
| 749 | if (ext_mode_load_done) begin |
| 750 | current_init_state = mode_done_init ; |
| 751 | end |
| 752 | end |
| 753 | if (current_init_state == ext_mode_init) begin |
| 754 | if (mode_load_done) begin |
| 755 | current_init_state = mode_done_init ; |
| 756 | end |
| 757 | end |
| 758 | if (current_init_state == mode_done_init && aref_count >= 2) begin |
| 759 | power_up_done = 1'b1; |
| 760 | end |
| 761 | end |
| 762 | |
| 763 | |
| 764 | // this task will erase the contents of 0 or more banks |
| 765 | task erase_mem; |
| 766 | input [BA_BITS+1:0] bank_MSB_row; //bank bits + 2 row MSB |
| 767 | input DPD_mode ; //erase all memory locations |
| 768 | integer i; |
| 769 | begin |
| 770 | |
| 771 | if (DPD_mode) begin |
| 772 | `ifdef FULL_MEM |
| 773 | for (i=0; i<{(BA_BITS+ROW_BITS+COL_BITS){1'b1}}; i=i+1) begin |
| 774 | mem_array[i] = 'bx; |
| 775 | end |
| 776 | `else |
| 777 | memory_index = 0; |
| 778 | i = 0; |
| 779 | // remove the selected banks |
| 780 | for (memory_index=0; memory_index<mem_used; memory_index=memory_index+1) begin |
| 781 | addr_array[i] = 'bx; |
| 782 | mem_array[i] = 'bx; |
| 783 | i = i + 1; |
| 784 | end |
| 785 | `endif |
| 786 | end else begin |
| 787 | `ifdef FULL_MEM |
| 788 | for (i={bank_MSB_row, {(ROW_BITS+COL_BITS-2){1'b1}}}; i<={1'b0, {(BA_BITS+ROW_BITS+COL_BITS){1'b1}}}; i=i+1) begin |
| 789 | mem_array[i] = 'bx; |
| 790 | end |
| 791 | `else |
| 792 | memory_index = 0; |
| 793 | i = 0; |
| 794 | // remove the selected banks |
| 795 | for (memory_index=0; memory_index<mem_used; memory_index=memory_index+1) begin |
| 796 | if (addr_array[memory_index]>({bank_MSB_row, {(ROW_BITS+COL_BITS-2){1'b1}}})) begin |
| 797 | addr_array[i] = 'bx; |
| 798 | mem_array[i] = 'bx; |
| 799 | i = i + 1; |
| 800 | end else begin |
| 801 | i = i + 1; |
| 802 | end |
| 803 | end |
| 804 | `endif |
| 805 | end |
| 806 | end |
| 807 | endtask |
| 808 | |
| 809 | // Write Memory |
| 810 | task write_mem; |
| 811 | input [full_mem_bits - 1 : 0] addr; |
| 812 | input [DQ_BITS - 1 : 0] data; |
| 813 | reg [part_mem_bits : 0] i; |
| 814 | begin |
| 815 | `ifdef FULL_MEM |
| 816 | mem_array[addr] = data; |
| 817 | `else |
| 818 | begin : loop |
| 819 | for (i = 0; i < mem_used; i = i + 1) begin |
| 820 | if (addr_array[i] === addr) begin |
| 821 | disable loop; |
| 822 | end |
| 823 | end |
| 824 | end |
| 825 | if (i === mem_used) begin |
| 826 | if (i === (1<<part_mem_bits)) begin |
| 827 | $display ("%m: At time %t ERROR: Memory overflow.\n Write to Address %d with Data %d will be lost.\n You must increase the part_mem_bits parameter or `define FULL_MEM.", $realtime, addr, data); |
| 828 | end else begin |
| 829 | mem_used = mem_used + 1; |
| 830 | addr_array[i] = addr; |
| 831 | end |
| 832 | end |
| 833 | mem_array[i] = data; |
| 834 | `endif |
| 835 | end |
| 836 | endtask |
| 837 | |
| 838 | // Read Memory |
| 839 | task read_mem; |
| 840 | input [full_mem_bits - 1 : 0] addr; |
| 841 | output [DQ_BITS - 1 : 0] data; |
| 842 | reg [part_mem_bits : 0] i; |
| 843 | begin |
| 844 | `ifdef FULL_MEM |
| 845 | data = mem_array[addr]; |
| 846 | `else |
| 847 | begin : loop |
| 848 | for (i = 0; i < mem_used; i = i + 1) begin |
| 849 | if (addr_array[i] === addr) begin |
| 850 | disable loop; |
| 851 | end |
| 852 | end |
| 853 | end |
| 854 | if (i <= mem_used) begin |
| 855 | data = mem_array[i]; |
| 856 | end else begin |
| 857 | data = 'bx; |
| 858 | end |
| 859 | `endif |
| 860 | end |
| 861 | endtask |
| 862 | |
| 863 | // Burst Decode |
| 864 | task Burst_Decode; |
| 865 | begin |
| 866 | |
| 867 | // Advance Burst Counter |
| 868 | // if (Burst_counter < burst_length) begin |
| 869 | if (Write_pipeline[-2]) begin |
| 870 | Burst_counter = Burst_counter + 1; |
| 871 | end |
| 872 | |
| 873 | // Burst Type |
| 874 | if (Mode_reg[3] === 1'b0) begin // Sequential Burst |
| 875 | Cols_temp = Cols_addr + 1; |
| 876 | end else if (Mode_reg[3] === 1'b1) begin // Interleaved Burst |
| 877 | Cols_temp[2] = Burst_counter[2] ^ Cols_brst[2]; |
| 878 | Cols_temp[1] = Burst_counter[1] ^ Cols_brst[1]; |
| 879 | Cols_temp[0] = Burst_counter[0] ^ Cols_brst[0]; |
| 880 | end |
| 881 | |
| 882 | // Burst Length |
| 883 | if (burst_length === 2) begin |
| 884 | Cols_addr [0] = Cols_temp [0]; |
| 885 | end else if (burst_length === 4) begin |
| 886 | Cols_addr [1 : 0] = Cols_temp [1 : 0]; |
| 887 | end else if (burst_length === 8) begin |
| 888 | Cols_addr [2 : 0] = Cols_temp [2 : 0]; |
| 889 | end else if (burst_length === 16) begin |
| 890 | Cols_addr [3 : 0] = Cols_temp [3 : 0]; |
| 891 | end else begin |
| 892 | Cols_addr = Cols_temp; |
| 893 | end |
| 894 | |
| 895 | // Data Counter |
| 896 | // if (Burst_counter >= burst_length) begin |
| 897 | // Data_in_enable = 1'b0; |
| 898 | // Data_out_enable = 1'b0; |
| 899 | // read_precharge_truncation = 1'b0; |
| 900 | // SRR_read = 1'b0; |
| 901 | // end |
| 902 | end |
| 903 | endtask |
| 904 | |
| 905 | |
| 906 | // SRC check |
| 907 | task Timing_chk_SRC; |
| 908 | begin |
| 909 | if (Active_enable || Aref_enable || Sref_enable || Burst_term || |
| 910 | Ext_mode_enable || Mode_reg_enable || Prech_enable || Read_enable || |
| 911 | Write_enable || DPD_enable || PD_enable || srr_enable) begin |
| 912 | if (part_size == 1024) begin |
| 913 | if (SRC_cntr < ((Mode_reg[6:4])+tSRC)) begin |
| 914 | $display ("%m: At time %t ERROR: tSRC Violation", $realtime); |
| 915 | end |
| 916 | end |
| 917 | end |
| 918 | end |
| 919 | endtask |
| 920 | |
| 921 | task ShiftPipelines; |
| 922 | begin |
| 923 | // read command pipeline |
| 924 | Read_pipeline = Read_pipeline >> 1; |
| 925 | Write_pipeline = Write_pipeline >> 1; |
| 926 | for (i = -2; i < `MAX_PIPE-1; i = i + 1) |
| 927 | begin |
| 928 | Write_col_pipeline [i] = Write_col_pipeline[i+1]; |
| 929 | Write_bank_pipeline [i] = Write_bank_pipeline[i+1]; |
| 930 | end |
| 931 | end |
| 932 | endtask |
| 933 | |
| 934 | // Dq and Dqs Drivers |
| 935 | task Dq_Dqs_Drivers; |
| 936 | begin |
| 937 | |
| 938 | // Initialize Read command |
| 939 | if (Read_pipeline [0] === 1'b1) begin |
| 940 | // Data_out_enable = 1'b1; |
| 941 | Bank_addr = Write_bank_pipeline[0]; |
| 942 | Cols_addr = Write_col_pipeline [0]; |
| 943 | Cols_brst = Cols_addr [2 : 0]; |
| 944 | // if (SRR_read == 1'b1) begin |
| 945 | // Burst_counter = burst_length - 2; |
| 946 | // end else begin |
| 947 | // Burst_counter = 0; |
| 948 | // end |
| 949 | |
| 950 | // Row Address Mux |
| 951 | case (Bank_addr) |
| 952 | 2'd0 : Rows_addr = B0_row_addr; |
| 953 | 2'd1 : Rows_addr = B1_row_addr; |
| 954 | 2'd2 : Rows_addr = B2_row_addr; |
| 955 | 2'd3 : Rows_addr = B3_row_addr; |
| 956 | default : $display ("%m: At time %t ERROR: Invalid Bank Address", $realtime); |
| 957 | endcase |
| 958 | end |
| 959 | |
| 960 | // Read latch |
| 961 | if (Read_pipeline[0] === 1'b1) begin |
| 962 | // output data |
| 963 | if (SRR_read == 1'b1) begin |
| 964 | if (Cols_addr == 0) begin |
| 965 | Dq_out_temp = Srr_reg[DQ_BITS-1:0]; |
| 966 | end else begin |
| 967 | Dq_out_temp = Srr_reg[2*DQ_BITS-1:DQ_BITS]; |
| 968 | SRR_read = 1'b0 ; |
| 969 | end |
| 970 | end else begin |
| 971 | read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_out_temp); |
| 972 | end |
| 973 | if (Debug) begin |
| 974 | $display ("At time %t %m:READ: Bank = %d, Row = %d, Col = %d, Data = %d", $realtime, Bank_addr, Rows_addr, Cols_addr, Dq_out); |
| 975 | end |
| 976 | |
| 977 | end |
| 978 | |
| 979 | Dq_out <= #(tAC_max) Dq_out_temp ; |
| 980 | Dqs_out <= #(tAC_max) ((|Read_pipeline[0]) & Sys_clk) ; |
| 981 | |
| 982 | if (cas_latency == 3) |
| 983 | Dqs_out_en <= #(tAC_max) (|Read_pipeline[2:0]); |
| 984 | else |
| 985 | Dqs_out_en <= #(tAC_max) (|Read_pipeline[1:0]); |
| 986 | if (Sys_clk) begin |
| 987 | Dq_out_en <= #(tAC_max) (Read_pipeline[0]); |
| 988 | end |
| 989 | |
| 990 | end |
| 991 | endtask |
| 992 | |
| 993 | // Write FIFO and DM Mask Logic |
| 994 | task Write_FIFO_DM_Mask_Logic; |
| 995 | begin |
| 996 | |
| 997 | // Initialize Write command |
| 998 | if (Write_pipeline [-2] === 1'b1) begin |
| 999 | // Data_in_enable = 1'b1; |
| 1000 | Bank_addr = Write_bank_pipeline [-2]; |
| 1001 | Cols_addr = Write_col_pipeline [-2]; |
| 1002 | Cols_brst = Cols_addr [2 : 0]; |
| 1003 | // Burst_counter = 0; |
| 1004 | |
| 1005 | // Row address mux |
| 1006 | case (Bank_addr) |
| 1007 | 2'd0 : Rows_addr = B0_row_addr; |
| 1008 | 2'd1 : Rows_addr = B1_row_addr; |
| 1009 | 2'd2 : Rows_addr = B2_row_addr; |
| 1010 | 2'd3 : Rows_addr = B3_row_addr; |
| 1011 | default : $display ("%m: At time %t ERROR: Invalid Row Address", $realtime); |
| 1012 | endcase |
| 1013 | end |
| 1014 | |
| 1015 | // Write data |
| 1016 | // if (Data_in_enable === 1'b1) begin |
| 1017 | if (Write_pipeline[-2] === 1'b1) begin |
| 1018 | |
| 1019 | // Data Buffer |
| 1020 | read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf); |
| 1021 | |
| 1022 | // write negedge Dqs on posedge Sys_clk |
| 1023 | if (Sys_clk) begin |
| 1024 | if (!dm_fall[0]) begin |
| 1025 | Dq_buf [ 7 : 0] = dq_fall [ 7 : 0]; |
| 1026 | end |
| 1027 | if (!dm_fall[1]) begin |
| 1028 | Dq_buf [15 : 8] = dq_fall [15 : 8]; |
| 1029 | end |
| 1030 | `ifdef x32 |
| 1031 | if (!dm_fall[2]) begin |
| 1032 | Dq_buf [23 : 16] = dq_fall [23 : 16]; |
| 1033 | end |
| 1034 | if (!dm_fall[3]) begin |
| 1035 | Dq_buf [31 : 24] = dq_fall [31 : 24]; |
| 1036 | end |
| 1037 | `endif |
| 1038 | if (~&dm_fall) begin |
| 1039 | if (Debug) begin |
| 1040 | $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]); |
| 1041 | end |
| 1042 | end |
| 1043 | // write posedge Dqs on negedge Sys_clk |
| 1044 | end else begin |
| 1045 | if (!dm_rise[0]) begin |
| 1046 | Dq_buf [ 7 : 0] = dq_rise [ 7 : 0]; |
| 1047 | end |
| 1048 | if (!dm_rise[1]) begin |
| 1049 | Dq_buf [15 : 8] = dq_rise [15 : 8]; |
| 1050 | end |
| 1051 | `ifdef x32 |
| 1052 | if (!dm_rise[2]) begin |
| 1053 | Dq_buf [23 : 16] = dq_rise [23 : 16]; |
| 1054 | end |
| 1055 | if (!dm_rise[3]) begin |
| 1056 | Dq_buf [31 : 24] = dq_rise [31 : 24]; |
| 1057 | end |
| 1058 | `endif |
| 1059 | if (~&dm_rise) begin |
| 1060 | if (Debug) begin |
| 1061 | $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]); |
| 1062 | end |
| 1063 | end |
| 1064 | end |
| 1065 | |
| 1066 | // Write Data |
| 1067 | write_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf); |
| 1068 | // tWR start and tWTR check |
| 1069 | if (Sys_clk && &dm_pair === 1'b0) begin |
| 1070 | case (Bank_addr) |
| 1071 | 2'd0 : WR_chk0 = $realtime; |
| 1072 | 2'd1 : WR_chk1 = $realtime; |
| 1073 | 2'd2 : WR_chk2 = $realtime; |
| 1074 | 2'd3 : WR_chk3 = $realtime; |
| 1075 | default : $display ("%m: At time %t ERROR: Invalid Bank Address (tWR)", $realtime); |
| 1076 | endcase |
| 1077 | |
| 1078 | // // tWTR check |
| 1079 | // if (Read_enable === 1'b1) begin |
| 1080 | // $display ("%m: At time %t ERROR: tWTR violation during Read", $realtime); |
| 1081 | // end |
| 1082 | end |
| 1083 | end |
| 1084 | end |
| 1085 | endtask |
| 1086 | |
| 1087 | // Auto Precharge Calculation |
| 1088 | task Auto_Precharge_Calculation; |
| 1089 | begin |
| 1090 | // Precharge counter |
| 1091 | if (Read_precharge_access [0] === 1'b1 || Write_precharge_access [0] === 1'b1) begin |
| 1092 | Count_precharge [0] = Count_precharge [0] + 1; |
| 1093 | end |
| 1094 | if (Read_precharge_access [1] === 1'b1 || Write_precharge_access [1] === 1'b1) begin |
| 1095 | Count_precharge [1] = Count_precharge [1] + 1; |
| 1096 | end |
| 1097 | if (Read_precharge_access [2] === 1'b1 || Write_precharge_access [2] === 1'b1) begin |
| 1098 | Count_precharge [2] = Count_precharge [2] + 1; |
| 1099 | end |
| 1100 | if (Read_precharge_access [3] === 1'b1 || Write_precharge_access [3] === 1'b1) begin |
| 1101 | Count_precharge [3] = Count_precharge [3] + 1; |
| 1102 | end |
| 1103 | |
| 1104 | // Read with AutoPrecharge Calculation |
| 1105 | // The device start internal precharge when: |
| 1106 | // 1. BL/2 cycles after command |
| 1107 | // 2. Meet tRAS requirement |
| 1108 | if (Read_precharge_access[0] & (Count_precharge[0] >= burst_length/2)) begin |
| 1109 | Read_precharge_access[0] = 1'b0 ; |
| 1110 | Read_precharge_pre[0] = 1'b1 ; |
| 1111 | end |
| 1112 | if ((Read_precharge_pre[0] === 1'b1) && ($realtime - RAS_chk0 >= tRAS - 0.001)) begin |
| 1113 | Pc_b0 = 1'b1; |
| 1114 | Act_b0 = 1'b0; |
| 1115 | RP_chk0 = $realtime; |
| 1116 | Read_precharge_pre[0] = 1'b0; |
| 1117 | end |
| 1118 | |
| 1119 | if (Read_precharge_access[1] & (Count_precharge[1] >= burst_length/2)) begin |
| 1120 | Read_precharge_access[1] = 1'b0 ; |
| 1121 | Read_precharge_pre[1] = 1'b1 ; |
| 1122 | end |
| 1123 | if ((Read_precharge_pre[1] === 1'b1) && ($realtime - RAS_chk1 >= tRAS - 0.001)) begin |
| 1124 | Pc_b1 = 1'b1; |
| 1125 | Act_b1 = 1'b0; |
| 1126 | RP_chk1 = $realtime; |
| 1127 | Read_precharge_pre[1] = 1'b0; |
| 1128 | end |
| 1129 | |
| 1130 | if (Read_precharge_access[2] & (Count_precharge[2] >= burst_length/2)) begin |
| 1131 | Read_precharge_access[2] = 1'b0 ; |
| 1132 | Read_precharge_pre[2] = 1'b1 ; |
| 1133 | end |
| 1134 | if ((Read_precharge_pre[2] === 1'b1) && ($realtime - RAS_chk2 >= tRAS - 0.001)) begin |
| 1135 | Pc_b2 = 1'b1; |
| 1136 | Act_b2 = 1'b0; |
| 1137 | RP_chk2 = $realtime; |
| 1138 | Read_precharge_pre[2] = 1'b0; |
| 1139 | end |
| 1140 | |
| 1141 | if (Read_precharge_access[3] & (Count_precharge[3] >= burst_length/2)) begin |
| 1142 | Read_precharge_access[3] = 1'b0 ; |
| 1143 | Read_precharge_pre[3] = 1'b1 ; |
| 1144 | end |
| 1145 | if ((Read_precharge_pre[3] === 1'b1) && ($realtime - RAS_chk3 >= tRAS - 0.001)) begin |
| 1146 | Pc_b3 = 1'b1; |
| 1147 | Act_b3 = 1'b0; |
| 1148 | RP_chk3 = $realtime; |
| 1149 | Read_precharge_pre[3] = 1'b0; |
| 1150 | end |
| 1151 | |
| 1152 | // Write with AutoPrecharge Calculation |
| 1153 | // The device start internal precharge when: |
| 1154 | // 1. Meet tRAS requirement |
| 1155 | // 2. Two clock after last burst |
| 1156 | // Since tWR is time base, the model will compensate tRP |
| 1157 | if (Write_precharge_access[0] & (Count_precharge[0] >= burst_length/2+3)) begin |
| 1158 | Write_precharge_access[0] = 1'b0 ; |
| 1159 | Write_precharge_pre[0] = 1'b1 ; |
| 1160 | end |
| 1161 | if (Write_precharge_pre[0] & ($realtime - RAS_chk0 >= tRAS - 0.001)) begin |
| 1162 | Write_precharge_pre[0] = 1'b0; |
| 1163 | Pc_b0 = 1'b1; |
| 1164 | Act_b0 = 1'b0; |
| 1165 | RP_chk0 = $realtime - ((2 * clk_period) - tWR); |
| 1166 | end |
| 1167 | |
| 1168 | if (Write_precharge_access[1] & (Count_precharge[1] >= burst_length/2+3)) begin |
| 1169 | Write_precharge_access[1] = 1'b0 ; |
| 1170 | Write_precharge_pre[1] = 1'b1 ; |
| 1171 | end |
| 1172 | if (Write_precharge_pre[1] & ($realtime - RAS_chk1 >= tRAS - 0.001)) begin |
| 1173 | Write_precharge_pre[1] = 1'b0; |
| 1174 | Pc_b1 = 1'b1; |
| 1175 | Act_b1 = 1'b0; |
| 1176 | RP_chk1 = $realtime - ((2 * clk_period) - tWR); |
| 1177 | end |
| 1178 | |
| 1179 | if (Write_precharge_access[2] & (Count_precharge[2] >= burst_length/2+3)) begin |
| 1180 | Write_precharge_access[2] = 1'b0 ; |
| 1181 | Write_precharge_pre[2] = 1'b1 ; |
| 1182 | end |
| 1183 | if (Write_precharge_pre[2] & ($realtime - RAS_chk2 >= tRAS - 0.001)) begin |
| 1184 | Write_precharge_pre[2] = 1'b0; |
| 1185 | Pc_b2 = 1'b1; |
| 1186 | Act_b2 = 1'b0; |
| 1187 | RP_chk2 = $realtime - ((2 * clk_period) - tWR); |
| 1188 | end |
| 1189 | |
| 1190 | if (Write_precharge_access[3] & (Count_precharge[3] >= burst_length/2+3)) begin |
| 1191 | Write_precharge_access[3] = 1'b0 ; |
| 1192 | Write_precharge_pre[3] = 1'b1 ; |
| 1193 | end |
| 1194 | if (Write_precharge_pre[3] & ($realtime - RAS_chk3 >= tRAS - 0.001)) begin |
| 1195 | Write_precharge_pre[3] = 1'b0; |
| 1196 | Pc_b3 = 1'b1; |
| 1197 | Act_b3 = 1'b0; |
| 1198 | RP_chk3 = $realtime - ((2 * clk_period) - tWR); |
| 1199 | end |
| 1200 | end |
| 1201 | endtask |
| 1202 | |
| 1203 | task Power_down_chk; |
| 1204 | begin |
| 1205 | if (DPD_enable == 1'b1 && enter_DPD == 1'b0) begin |
| 1206 | if (prev_cke & Pc_b0 & Pc_b1 & Pc_b2 & Pc_b3) begin |
| 1207 | erase_mem(4'b0000, 1'b1); |
| 1208 | current_init_state = begin_init ; |
| 1209 | ext_mode_load_done = 1'b0 ; |
| 1210 | mode_load_done = 1'b0 ; |
| 1211 | enter_DPD = 1'b1; |
| 1212 | $display ("%m: at time %t Entering Deep Power-Down Mode", $realtime); |
| 1213 | end |
| 1214 | end |
| 1215 | if (enter_DPD == 1'b1) begin |
| 1216 | if (Cke == 1'b1 && prev_cke == 1'b0) begin |
| 1217 | if (PD_cntr < tCKE) begin |
| 1218 | $display ("%m: At time %t ERROR: tCKE violation during exiting of Deep Power-Down Mode", $realtime); |
| 1219 | end |
| 1220 | $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); |
| 1221 | enter_DPD = 1'b0; |
| 1222 | end |
| 1223 | end |
| 1224 | if (PD_enable == 1'b1 && enter_PD == 1'b0) begin |
| 1225 | if (prev_cke) begin |
| 1226 | if (Pc_b0 & Pc_b1 & Pc_b2 & Pc_b3) begin |
| 1227 | $display ("%m: at time %t Entering Power-Down Mode", $realtime); |
| 1228 | enter_PD = 1'b1; |
| 1229 | end else if (~Pc_b0 | ~Pc_b1 | ~Pc_b2 | ~Pc_b3) begin |
| 1230 | $display ("%m: at time %t Entering Active Power-Down Mode", $realtime); |
| 1231 | enter_APD = 1'b1; |
| 1232 | end |
| 1233 | end |
| 1234 | end |
| 1235 | if (enter_PD == 1'b1 || enter_APD == 1'b1) begin |
| 1236 | if (Cke == 1'b1 && prev_cke == 1'b0) begin |
| 1237 | if (PD_cntr < tCKE) begin |
| 1238 | if (enter_PD == 1'b1) begin |
| 1239 | $display ("%m: At time %t ERROR: tCKE violation during exiting of Power-Down Mode", $realtime); |
| 1240 | end else if (enter_APD == 1'b1) begin |
| 1241 | $display ("%m: At time %t ERROR: tCKE violation during exiting of Active Power-Down Mode", $realtime); |
| 1242 | end |
| 1243 | end |
| 1244 | if (enter_PD == 1'b1) begin |
| 1245 | $display ("%m: at time %t Exiting Power-Down Mode", $realtime); |
| 1246 | enter_PD = 1'b0 ; |
| 1247 | end else if (enter_APD == 1'b1) begin |
| 1248 | $display ("%m: at time %t Exiting Active Power-Down Mode", $realtime); |
| 1249 | enter_APD = 1'b0 ; |
| 1250 | end |
| 1251 | end |
| 1252 | end |
| 1253 | |
| 1254 | end |
| 1255 | endtask |
| 1256 | |
| 1257 | reg [31:0] xx ; |
| 1258 | function [COL_BITS-1:0] Burst_Order; |
| 1259 | input [COL_BITS-1:0] Col; |
| 1260 | input [31:0] i; |
| 1261 | begin |
| 1262 | if (Mode_reg[3] == 1'b1) //interleaved |
| 1263 | Burst_Order = (Col & -1*burst_length) + (Col%burst_length ^ i); |
| 1264 | else // sequential |
| 1265 | begin |
| 1266 | xx = -1*burst_length; |
| 1267 | Burst_Order = (Col & xx) + (Col%burst_length + i) % (burst_length); |
| 1268 | end |
| 1269 | end |
| 1270 | endfunction |
| 1271 | |
| 1272 | // Control Logic |
| 1273 | task Control_Logic; |
| 1274 | begin |
| 1275 | |
| 1276 | // Self Refresh |
| 1277 | if (Sref_enable === 1'b1) begin |
| 1278 | // Partial Array Self Refresh |
| 1279 | if (part_size == 128) begin |
| 1280 | case (Ext_Mode_reg[2:0]) |
| 1281 | 3'b000 : ;//keep Bank 0-7 |
| 1282 | 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 |
| 1283 | 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 |
| 1284 | 3'b011 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end |
| 1285 | 3'b100 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end |
| 1286 | 3'b101 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end |
| 1287 | 3'b110 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end |
| 1288 | endcase |
| 1289 | end else begin |
| 1290 | case (Ext_Mode_reg[2:0]) |
| 1291 | 3'b000 : ;//keep Bank 0-7 |
| 1292 | 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 |
| 1293 | 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 |
| 1294 | 3'b011 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end |
| 1295 | 3'b100 : begin $display("%m: at time %t INFO: Reserved", $realtime) ; end |
| 1296 | 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 |
| 1297 | 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 |
| 1298 | endcase |
| 1299 | end |
| 1300 | SelfRefresh = 1'b1; |
| 1301 | end |
| 1302 | if (Aref_enable === 1'b1) begin |
| 1303 | if (Debug) begin |
| 1304 | $display ("Debug: At time %t %m:AUTOREFRESH: Auto Refresh", $realtime); |
| 1305 | end |
| 1306 | // aref_count is to make sure we have met part of the initialization sequence |
| 1307 | if (~power_up_done) begin |
| 1308 | aref_count = aref_count + 1; |
| 1309 | end |
| 1310 | |
| 1311 | // Auto Refresh to Auto Refresh |
| 1312 | if ($realtime - RFC_chk < tRFC - 0.001) begin |
| 1313 | $display ("%m: At time %t ERROR: tRFC violation during Auto Refresh", $realtime); |
| 1314 | end |
| 1315 | |
| 1316 | // Precharge to Auto Refresh |
| 1317 | if (($realtime - RP_chk0 < tRP - 0.001) || ($realtime - RP_chk1 < tRP - 0.001) || |
| 1318 | ($realtime - RP_chk2 < tRP - 0.001) || ($realtime - RP_chk3 < tRP - 0.001)) begin |
| 1319 | $display ("%m: At time %t ERROR: tRP violation during Auto Refresh", $realtime); |
| 1320 | end |
| 1321 | |
| 1322 | // Precharge to Auto Refresh |
| 1323 | if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin |
| 1324 | $display ("%m: At time %t ERROR: All banks must be Precharged before Auto Refresh", $realtime); |
| 1325 | end |
| 1326 | |
| 1327 | // Record Current tRFC time |
| 1328 | RFC_chk = $realtime; |
| 1329 | end |
| 1330 | |
| 1331 | // SRR Register |
| 1332 | if (srr_enable == 1'b1) begin |
| 1333 | if (Pc_b0 === 1'b1 && Pc_b1 === 1'b1 && Pc_b2 === 1'b1 && Pc_b3 === 1'b1 && |
| 1334 | Data_out_enable === 1'b0 && Data_in_enable === 1'b0) begin |
| 1335 | SRR_read = 1'b1; |
| 1336 | SRR_chk = $realtime; |
| 1337 | SRR_cntr = 0; |
| 1338 | end |
| 1339 | end |
| 1340 | |
| 1341 | |
| 1342 | // Extended Mode Register |
| 1343 | if (Ext_mode_enable == 1'b1) begin |
| 1344 | if (Debug) begin |
| 1345 | $display ("Debug: At time %t %m:EMR : Extended Mode Register", $realtime); |
| 1346 | end |
| 1347 | |
| 1348 | // Register Mode |
| 1349 | Ext_Mode_reg = Addr; |
| 1350 | |
| 1351 | if (Pc_b0 === 1'b1 && Pc_b1 === 1'b1 && Pc_b2 === 1'b1 && Pc_b3 === 1'b1) begin |
| 1352 | // ensure that power sequence is met properly |
| 1353 | if (~power_up_done) begin |
| 1354 | ext_mode_load_done = 1'b1; |
| 1355 | end |
| 1356 | $display ("At time %t %m:ELMR : Extended Load Mode Register", $realtime); |
| 1357 | if (part_size == 128) begin |
| 1358 | // Self Refresh Coverage |
| 1359 | case (Addr[2 : 0]) |
| 1360 | 3'b000 : $display ("%m : Self Refresh Cov = 4 banks"); |
| 1361 | 3'b001 : $display ("%m : Self Refresh Cov = 2 banks"); |
| 1362 | 3'b010 : $display ("%m : Self Refresh Cov = 1 bank"); |
| 1363 | 3'b101 : $display ("%m : PASR = Reserved"); |
| 1364 | 3'b110 : $display ("%m : PASR = Reserved"); |
| 1365 | default : $display ("%m : PASR = Reserved"); |
| 1366 | endcase |
| 1367 | end else begin |
| 1368 | // Self Refresh Coverage |
| 1369 | case (Addr[2 : 0]) |
| 1370 | 3'b000 : $display ("%m : Self Refresh Cov = 4 banks"); |
| 1371 | 3'b001 : $display ("%m : Self Refresh Cov = 2 banks"); |
| 1372 | 3'b010 : $display ("%m : Self Refresh Cov = 1 bank"); |
| 1373 | 3'b101 : $display ("%m : Self Refresh Cov = 1/2 bank"); |
| 1374 | 3'b110 : $display ("%m : Self Refresh Cov = 1/4 bank"); |
| 1375 | default : $display ("%m : PASR = Reserved"); |
| 1376 | endcase |
| 1377 | end |
| 1378 | // Maximum Case Temp |
| 1379 | // case (Addr[4 : 3]) |
| 1380 | // 2'b11 : $display ("%m : Maximum Case Temp = 85C"); |
| 1381 | // 2'b00 : $display ("%m : Maximum Case Temp = 70C"); |
| 1382 | // 2'b01 : $display ("%m : Maximum Case Temp = 45C"); |
| 1383 | // 2'b10 : $display ("%m : Maximum Case Temp = 15C"); |
| 1384 | // endcase |
| 1385 | |
| 1386 | // Drive Strength |
| 1387 | case (Addr[7 : 5]) |
| 1388 | 3'b000 : $display ("%m : Drive Strength = Full Strength"); |
| 1389 | 3'b001 : $display ("%m : Drive Strength = Half Strength"); |
| 1390 | 3'b010 : $display ("%m : Drive Strength = Quarter Strength"); |
| 1391 | 3'b011 : $display ("%m : Drive Strength = Three Quarter Strength"); |
| 1392 | 3'b100 : $display ("%m : Drive Strength = Three Quarter Strength"); |
| 1393 | endcase |
| 1394 | |
| 1395 | end else begin |
| 1396 | $display ("%m: At time %t ERROR: all banks must be Precharged before Extended Mode Register", $realtime); |
| 1397 | end |
| 1398 | |
| 1399 | // Precharge to EMR |
| 1400 | if (($realtime - RP_chk0 < tRP - 0.001) || ($realtime - RP_chk1 < tRP - 0.001) || |
| 1401 | ($realtime - RP_chk2 < tRP - 0.001) || ($realtime - RP_chk3 < tRP - 0.001)) begin |
| 1402 | $display ("%m: At time %t ERROR: tRP violation during Extended Mode Register", $realtime); |
| 1403 | end |
| 1404 | |
| 1405 | // LMR/EMR to LMR/EMR |
| 1406 | // if ($realtime - MRD_chk < tMRD) begin |
| 1407 | // $display ("%m: At time %t ERROR: tMRD violation during Extended Mode Register", $realtime); |
| 1408 | // end |
| 1409 | |
| 1410 | if (MRD_cntr < tMRD) begin |
| 1411 | $display ("%m: At time %t ERROR: tMRD violation during Extended Mode Register", $realtime); |
| 1412 | end |
| 1413 | |
| 1414 | // Record current tMRD time |
| 1415 | // MRD_chk = $realtime; |
| 1416 | MRD_cntr = 0; |
| 1417 | end |
| 1418 | |
| 1419 | // Load Mode Register |
| 1420 | if (Mode_reg_enable === 1'b1) begin |
| 1421 | if (Debug) begin |
| 1422 | $display ("Debug: At time %t %m:LMR : Load Mode Register", $realtime); |
| 1423 | end |
| 1424 | |
| 1425 | // Register Mode |
| 1426 | Mode_reg = Addr; |
| 1427 | |
| 1428 | if (Mode_reg[6:4] == 3'b010) begin |
| 1429 | if (tCK2_min == 0) begin |
| 1430 | $display ("%m : at time %t ERROR : Illegal CAS Latency of 2 set for current speed grade", $realtime); |
| 1431 | end |
| 1432 | end |
| 1433 | |
| 1434 | // Precharge to LMR |
| 1435 | if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin |
| 1436 | $display ("%m: At time %t ERROR: all banks must be Precharged before Load Mode Register", $realtime); |
| 1437 | end |
| 1438 | |
| 1439 | // Precharge to LMR |
| 1440 | if (($realtime - RP_chk0 < tRP - 0.001) || ($realtime - RP_chk1 < tRP - 0.001) || |
| 1441 | ($realtime - RP_chk2 < tRP - 0.001) || ($realtime - RP_chk3 < tRP - 0.001)) begin |
| 1442 | $display ("%m: At time %t ERROR: tRP violation during Load Mode Register", $realtime); |
| 1443 | end |
| 1444 | |
| 1445 | // LMR/EMR to LMR/EMR |
| 1446 | // if ($realtime - MRD_chk < tMRD) begin |
| 1447 | // $display ("%m: At time %t ERROR: tMRD violation during Load Mode Register", $realtime); |
| 1448 | // end |
| 1449 | if (MRD_cntr < tMRD) begin |
| 1450 | $display ("%m: At time %t ERROR: tMRD violation during Load Mode Register", $realtime); |
| 1451 | end |
| 1452 | |
| 1453 | if (Pc_b0 === 1'b1 && Pc_b1 === 1'b1 && Pc_b2 === 1'b1 && Pc_b3 === 1'b1) begin |
| 1454 | // ensure that power sequence is met properly |
| 1455 | if (~power_up_done) begin |
| 1456 | mode_load_done = 1'b1; |
| 1457 | end |
| 1458 | // Burst Length |
| 1459 | case (Addr [2 : 0]) |
| 1460 | 3'b001 : $display ("At time %t %m:LMR : Burst Length = 2", $realtime); |
| 1461 | 3'b010 : $display ("At time %t %m:LMR : Burst Length = 4", $realtime); |
| 1462 | 3'b011 : $display ("At time %t %m:LMR : Burst Length = 8", $realtime); |
| 1463 | 3'b100 : $display ("At time %t %m:LMR : Burst Length = 16",$realtime); |
| 1464 | default : |
| 1465 | begin |
| 1466 | $display ("%m: At time %t ERROR: Undefined burst length selection", $realtime); |
| 1467 | $stop; |
| 1468 | end |
| 1469 | endcase |
| 1470 | |
| 1471 | // CAS Latency |
| 1472 | case (Addr [6 : 4]) |
| 1473 | 3'b010 : $display ("At time %t %m:LMR : CAS Latency = 2", $realtime); |
| 1474 | 3'b011 : $display ("At time %t %m:LMR : CAS Latency = 3", $realtime); |
| 1475 | default : begin |
| 1476 | $display ("%m: At time %t ERROR: CAS Latency not supported", $realtime); |
| 1477 | $stop; |
| 1478 | end |
| 1479 | endcase |
| 1480 | |
| 1481 | end |
| 1482 | // Record current tMRD time |
| 1483 | // MRD_chk = $realtime; |
| 1484 | MRD_cntr = 0; |
| 1485 | end |
| 1486 | |
| 1487 | // Activate Block |
| 1488 | if (Active_enable === 1'b1) begin |
| 1489 | if (!(power_up_done)) begin |
| 1490 | $display ("%m: At time %t ERROR: Power Up and Initialization Sequence not completed before executing Activate command", $realtime); |
| 1491 | end |
| 1492 | // Display Debug Message |
| 1493 | if (Debug) begin |
| 1494 | $display ("Debug: At time %t %m:ACTIVATE: Bank = %d, Row = %d", $realtime, Ba, Addr); |
| 1495 | end |
| 1496 | |
| 1497 | // Activating an open bank can cause corruption. |
| 1498 | if ((Ba === 2'b00 && Pc_b0 === 1'b0) || (Ba === 2'b01 && Pc_b1 === 1'b0) || |
| 1499 | (Ba === 2'b10 && Pc_b2 === 1'b0) || (Ba === 2'b11 && Pc_b3 === 1'b0)) begin |
| 1500 | $display ("%m: At time %t ERROR: Bank = %d is already activated - data can be corrupted", $realtime, Ba); |
| 1501 | end |
| 1502 | |
| 1503 | // Activate Bank 0 |
| 1504 | if (Ba === 2'b00 && Pc_b0 === 1'b1) begin |
| 1505 | // Activate to Activate (same bank) |
| 1506 | if ($realtime - RC_chk0 < tRC - 0.001) begin |
| 1507 | $display ("%m: At time %t ERROR: tRC violation during Activate bank %d", $realtime, Ba); |
| 1508 | end |
| 1509 | |
| 1510 | // Precharge to Activate |
| 1511 | if ($realtime - RP_chk0 < tRP - 0.001) begin |
| 1512 | $display ("%m: At time %t ERROR: tRP violation during Activate bank %d", $realtime, Ba); |
| 1513 | end |
| 1514 | |
| 1515 | // Record variables for checking violation |
| 1516 | Act_b0 = 1'b1; |
| 1517 | Pc_b0 = 1'b0; |
| 1518 | B0_row_addr = Addr; |
| 1519 | RC_chk0 = $realtime; |
| 1520 | RCD_chk0 = $realtime; |
| 1521 | RAS_chk0 = $realtime; |
| 1522 | RAP_chk0 = $realtime; |
| 1523 | end |
| 1524 | |
| 1525 | // Activate Bank 1 |
| 1526 | if (Ba === 2'b01 && Pc_b1 === 1'b1) begin |
| 1527 | // Activate to Activate (same bank) |
| 1528 | if ($realtime - RC_chk1 < tRC - 0.001) begin |
| 1529 | $display ("%m: At time %t ERROR: tRC violation during Activate bank %d", $realtime, Ba); |
| 1530 | end |
| 1531 | |
| 1532 | // Precharge to Activate |
| 1533 | if ($realtime - RP_chk1 < tRP - 0.001) begin |
| 1534 | $display ("%m: At time %t ERROR: tRP violation during Activate bank %d", $realtime, Ba); |
| 1535 | end |
| 1536 | |
| 1537 | // Record variables for checking violation |
| 1538 | Act_b1 = 1'b1; |
| 1539 | Pc_b1 = 1'b0; |
| 1540 | B1_row_addr = Addr; |
| 1541 | RC_chk1 = $realtime; |
| 1542 | RCD_chk1 = $realtime; |
| 1543 | RAS_chk1 = $realtime; |
| 1544 | RAP_chk1 = $realtime; |
| 1545 | end |
| 1546 | |
| 1547 | // Activate Bank 2 |
| 1548 | if (Ba === 2'b10 && Pc_b2 === 1'b1) begin |
| 1549 | // Activate to Activate (same bank) |
| 1550 | if ($realtime - RC_chk2 < tRC - 0.001) begin |
| 1551 | $display ("%m: At time %t ERROR: tRC violation during Activate bank %d", $realtime, Ba); |
| 1552 | end |
| 1553 | |
| 1554 | // Precharge to Activate |
| 1555 | if ($realtime - RP_chk2 < tRP - 0.001) begin |
| 1556 | $display ("%m: At time %t ERROR: tRP violation during Activate bank %d", $realtime, Ba); |
| 1557 | end |
| 1558 | |
| 1559 | // Record variables for checking violation |
| 1560 | Act_b2 = 1'b1; |
| 1561 | Pc_b2 = 1'b0; |
| 1562 | B2_row_addr = Addr; |
| 1563 | RC_chk2 = $realtime; |
| 1564 | RCD_chk2 = $realtime; |
| 1565 | RAS_chk2 = $realtime; |
| 1566 | RAP_chk2 = $realtime; |
| 1567 | end |
| 1568 | |
| 1569 | // Activate Bank 3 |
| 1570 | if (Ba === 2'b11 && Pc_b3 === 1'b1) begin |
| 1571 | // Activate to Activate (same bank) |
| 1572 | if ($realtime - RC_chk3 < tRC - 0.001) begin |
| 1573 | $display ("%m: t time %t ERROR: tRC violation during Activate bank %d", $realtime, Ba); |
| 1574 | end |
| 1575 | |
| 1576 | // Precharge to Activate |
| 1577 | if ($realtime - RP_chk3 < tRP - 0.001) begin |
| 1578 | $display ("%m: At time %t ERROR: tRP violation during Activate bank %d", $realtime, Ba); |
| 1579 | end |
| 1580 | |
| 1581 | // Record variables for checking violation |
| 1582 | Act_b3 = 1'b1; |
| 1583 | Pc_b3 = 1'b0; |
| 1584 | B3_row_addr = Addr; |
| 1585 | RC_chk3 = $realtime; |
| 1586 | RCD_chk3 = $realtime; |
| 1587 | RAS_chk3 = $realtime; |
| 1588 | RAP_chk3 = $realtime; |
| 1589 | end |
| 1590 | |
| 1591 | // Activate to Activate (different bank) |
| 1592 | if ((Prev_bank != Ba) && ($realtime - RRD_chk < tRRD - 0.001)) begin |
| 1593 | $display ("%m: At time %t ERROR: tRRD violation during Activate bank = %d", $realtime, Ba); |
| 1594 | end |
| 1595 | |
| 1596 | // AutoRefresh to Activate |
| 1597 | if ($realtime - RFC_chk < tRFC - 0.001) begin |
| 1598 | $display ("%m: At time %t ERROR: tRFC violation during Activate bank %d", $realtime, Ba); |
| 1599 | end |
| 1600 | |
| 1601 | // Record variable for checking violation |
| 1602 | RRD_chk = $realtime; |
| 1603 | Prev_bank = Ba; |
| 1604 | end |
| 1605 | |
| 1606 | // Precharge Block - consider NOP if bank already precharged or in process of precharging |
| 1607 | if (Prech_enable === 1'b1) begin |
| 1608 | // Display Debug Message |
| 1609 | if (Debug) begin |
| 1610 | $display ("Debug: At time %t %m:PRE: Addr[10] = %b, Bank = %b", $realtime, Addr[10], Ba); |
| 1611 | end |
| 1612 | |
| 1613 | // EMR or LMR to Precharge |
| 1614 | // if ($realtime - MRD_chk < tMRD) begin |
| 1615 | // $display ("%m: At time %t ERROR: tMRD violation during Precharge", $realtime); |
| 1616 | // end |
| 1617 | if (MRD_cntr < tMRD) begin |
| 1618 | $display ("%m: At time %t ERROR: tMRD violation during Precharge", $realtime); |
| 1619 | end |
| 1620 | |
| 1621 | // Precharge bank 0 |
| 1622 | if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b00)) && Act_b0 === 1'b1) begin |
| 1623 | Act_b0 = 1'b0; |
| 1624 | Pc_b0 = 1'b1; |
| 1625 | RP_chk0 = $realtime; |
| 1626 | |
| 1627 | // Activate to Precharge Bank |
| 1628 | if ($realtime - RAS_chk0 < tRAS - 0.001) begin |
| 1629 | $display ("%m: At time %t ERROR: tRAS violation during Precharge", $realtime); |
| 1630 | end |
| 1631 | |
| 1632 | // tWR violation check for Write |
| 1633 | if ($realtime - WR_chk0 < tWR - 0.001) begin |
| 1634 | $display ("%m: At time %t ERROR: tWR violation during Precharge", $realtime); |
| 1635 | end |
| 1636 | end |
| 1637 | |
| 1638 | // Precharge bank 1 |
| 1639 | if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b01)) && Act_b1 === 1'b1) begin |
| 1640 | Act_b1 = 1'b0; |
| 1641 | Pc_b1 = 1'b1; |
| 1642 | RP_chk1 = $realtime; |
| 1643 | |
| 1644 | // Activate to Precharge Bank 1 |
| 1645 | if ($realtime - RAS_chk1 < tRAS - 0.001) begin |
| 1646 | $display ("%m: At time %t ERROR: tRAS violation during Precharge", $realtime); |
| 1647 | end |
| 1648 | |
| 1649 | // tWR violation check for Write |
| 1650 | if ($realtime - WR_chk1 < tWR - 0.001) begin |
| 1651 | $display ("%m: At time %t ERROR: tWR violation during Precharge", $realtime); |
| 1652 | end |
| 1653 | end |
| 1654 | |
| 1655 | // Precharge bank 2 |
| 1656 | if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b10)) && Act_b2 === 1'b1) begin |
| 1657 | Act_b2 = 1'b0; |
| 1658 | Pc_b2 = 1'b1; |
| 1659 | RP_chk2 = $realtime; |
| 1660 | |
| 1661 | // Activate to Precharge Bank 2 |
| 1662 | if ($realtime - RAS_chk2 < tRAS - 0.001) begin |
| 1663 | $display ("%m: At time %t ERROR: tRAS violation during Precharge", $realtime); |
| 1664 | end |
| 1665 | |
| 1666 | // tWR violation check for Write |
| 1667 | if ($realtime - WR_chk2 < tWR - 0.001) begin |
| 1668 | $display ("%m: At time %t ERROR: tWR violation during Precharge", $realtime); |
| 1669 | end |
| 1670 | end |
| 1671 | |
| 1672 | // Precharge bank 3 |
| 1673 | if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b11)) && Act_b3 === 1'b1) begin |
| 1674 | Act_b3 = 1'b0; |
| 1675 | Pc_b3 = 1'b1; |
| 1676 | RP_chk3 = $realtime; |
| 1677 | |
| 1678 | // Activate to Precharge Bank 3 |
| 1679 | if ($realtime - RAS_chk3 < tRAS - 0.001) begin |
| 1680 | $display ("%m: At time %t ERROR: tRAS violation during Precharge", $realtime); |
| 1681 | end |
| 1682 | |
| 1683 | // tWR violation check for Write |
| 1684 | if ($realtime - WR_chk3 < tWR - 0.001) begin |
| 1685 | $display ("%m: At time %t ERROR: tWR violation during Precharge", $realtime); |
| 1686 | end |
| 1687 | end |
| 1688 | |
| 1689 | // Pipeline for READ |
| 1690 | if ((Addr[10] === 1'b1) | (Ba == Write_bank_pipeline[4])) |
| 1691 | for (i = 4; i < `MAX_PIPE; i = i + 1) |
| 1692 | Read_pipeline[i] = 1'b0 ; |
| 1693 | |
| 1694 | end |
| 1695 | |
| 1696 | // Burst terminate |
| 1697 | if (Burst_term === 1'b1) begin |
| 1698 | // Display Debug Message |
| 1699 | if (Debug) begin |
| 1700 | $display ("Debug: %m: At time %t BURST_TERMINATE): Burst Terminate",$realtime); |
| 1701 | end |
| 1702 | |
| 1703 | // Burst Terminate Command Pipeline for Read |
| 1704 | for (i = cas_latency_x2-1; i < `MAX_PIPE; i = i + 1) |
| 1705 | Read_pipeline[i] = 1'b0 ; |
| 1706 | // Illegal to burst terminate a Write |
| 1707 | if ((Data_in_enable === 1'b1) & ~((&dm_rise) & (&dm_fall))) begin |
| 1708 | $display ("%m: At time %t ERROR: It's illegal to burst terminate a Write", $realtime); |
| 1709 | end |
| 1710 | |
| 1711 | // Illegal to burst terminate a Read with Auto Precharge |
| 1712 | if (|Read_precharge_access) begin |
| 1713 | $display ("%m: At time %t ERROR: It's illegal to burst terminate a Read with Auto Precharge", $realtime); |
| 1714 | end |
| 1715 | end |
| 1716 | |
| 1717 | // Read Command |
| 1718 | if (Read_enable === 1'b1) begin |
| 1719 | if (!(power_up_done)) begin |
| 1720 | $display ("%m: At time %t ERROR: Power Up and Initialization Sequence not completed before executing Read Command", $realtime); |
| 1721 | end |
| 1722 | // Display Debug Message |
| 1723 | if (Debug) begin |
| 1724 | $display ("Debug: At time %t %m:READ: Bank = %d, Col = %d", $realtime, Ba, {Addr [11], Addr [9 : 0]}); |
| 1725 | end |
| 1726 | if (part_size == 1024) begin |
| 1727 | if (SRR_read == 1'b1) begin |
| 1728 | if (SRR_cntr < tSRR) begin |
| 1729 | $display ("%m: At time %t ERROR: tSRR Violation", $realtime); |
| 1730 | end |
| 1731 | SRC_cntr = 0 ; |
| 1732 | end |
| 1733 | end else begin |
| 1734 | if (SRR_read == 1'b1) begin |
| 1735 | if ($realtime - SRR_chk < tSRR-0.01) begin |
| 1736 | $display ("%m: At time %t ERROR: tSRR Violation", $realtime); |
| 1737 | end |
| 1738 | SRC_cntr = 0; |
| 1739 | end |
| 1740 | end |
| 1741 | // CAS Latency pipeline |
| 1742 | if (SRR_read) begin |
| 1743 | if ({Ba, Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]} > 0) begin |
| 1744 | $display ("%m: At time %t ERROR: Address must be all 0 during SRR Read", $realtime); |
| 1745 | end |
| 1746 | for (i=0; i<2; i=i+1) |
| 1747 | begin |
| 1748 | Read_pipeline[cas_latency_x2 - 2 + i + 1] = 1'b1; |
| 1749 | Write_col_pipeline [cas_latency_x2 - 2 + i + 1] = i; |
| 1750 | Write_bank_pipeline [cas_latency_x2 - 2 + i + 1] = 0; |
| 1751 | end |
| 1752 | end else begin |
| 1753 | for (i=0; i<burst_length; i=i+1) |
| 1754 | begin |
| 1755 | Read_pipeline[cas_latency_x2 - 2 + i + 1] = 1'b1; |
| 1756 | Write_bank_pipeline [cas_latency_x2 - 2 + i + 1] = Ba; |
| 1757 | Write_col_pipeline [cas_latency_x2 - 2 + i + 1] = Burst_Order({Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]}, i); |
| 1758 | end |
| 1759 | end |
| 1760 | |
| 1761 | // Clear out Write Pipeline |
| 1762 | Write_pipeline = 64'b0; |
| 1763 | |
| 1764 | // Interrupt a Read with Auto Precharge |
| 1765 | if (Read_precharge_access [Ba] === 1'b1) begin |
| 1766 | $display ("%m: At time %t ERROR: It's illegal to interrupt a Read with Auto Precharge (same bank)", $realtime); |
| 1767 | end else if ((Read_precharge_access [0] === 1'b1) | |
| 1768 | (Read_precharge_access [1] === 1'b1) | |
| 1769 | (Read_precharge_access [2] === 1'b1) | |
| 1770 | (Read_precharge_access [3] === 1'b1) ) begin |
| 1771 | $display ("%m: At time %t ERROR: It's illegal to interrupt a Read with Auto Precharge (different banks)", $realtime); |
| 1772 | end |
| 1773 | |
| 1774 | // Interrupt a Write with Auto Precharge |
| 1775 | if (Write_precharge_access [Ba] === 1'b1) begin |
| 1776 | // $display ("%m: At time %t ERROR: It's illegal to interrupt a Write with Auto Precharge (same banks)", $realtime); |
| 1777 | end else if ((Write_precharge_count [0] < (burst_length/2 )) & (Mode_reg[6:4] == 3'b010) | |
| 1778 | (Write_precharge_count [1] < (burst_length/2 )) & (Mode_reg[6:4] == 3'b010) | |
| 1779 | (Write_precharge_count [2] < (burst_length/2 )) & (Mode_reg[6:4] == 3'b010) | |
| 1780 | (Write_precharge_count [3] < (burst_length/2 )) & (Mode_reg[6:4] == 3'b010) | |
| 1781 | (Write_precharge_count [0] < (burst_length/2-1)) & (Mode_reg[6:4] == 3'b011) | |
| 1782 | (Write_precharge_count [1] < (burst_length/2-1)) & (Mode_reg[6:4] == 3'b011) | |
| 1783 | (Write_precharge_count [2] < (burst_length/2-1)) & (Mode_reg[6:4] == 3'b011) | |
| 1784 | (Write_precharge_count [3] < (burst_length/2-1)) & (Mode_reg[6:4] == 3'b011) ) begin |
| 1785 | $display ("%m: At time %t ERROR: It's illegal to interrupt a data transfer on a Write with Auto Precharge (different banks)", $realtime); |
| 1786 | end |
| 1787 | |
| 1788 | // Activate to Read |
| 1789 | if (((Ba === 2'b00 && Pc_b0 === 1'b1) || (Ba === 2'b01 && Pc_b1 === 1'b1) || |
| 1790 | (Ba === 2'b10 && Pc_b2 === 1'b1) || (Ba === 2'b11 && Pc_b3 === 1'b1)) && |
| 1791 | (SRR_read == 1'b0)) begin |
| 1792 | $display("%m: At time %t ERROR: Bank is not Activated for Read", $realtime); |
| 1793 | end |
| 1794 | |
| 1795 | // Activate to Read without Auto Precharge |
| 1796 | if ((Addr [10] === 1'b0 && Ba === 2'b00 && $realtime - RCD_chk0 < tRCD - 0.001) || |
| 1797 | (Addr [10] === 1'b0 && Ba === 2'b01 && $realtime - RCD_chk1 < tRCD - 0.001) || |
| 1798 | (Addr [10] === 1'b0 && Ba === 2'b10 && $realtime - RCD_chk2 < tRCD - 0.001) || |
| 1799 | (Addr [10] === 1'b0 && Ba === 2'b11 && $realtime - RCD_chk3 < tRCD - 0.001)) begin |
| 1800 | $display("%m: At time %t ERROR: tRCD violation during Read", $realtime); |
| 1801 | end |
| 1802 | |
| 1803 | // Auto Precharge |
| 1804 | if (Addr[10] === 1'b1) begin |
| 1805 | Read_precharge_access [Ba]= 1'b1; |
| 1806 | Count_precharge [Ba]= 0; |
| 1807 | Read_precharge_count[Ba] = 4'h0; |
| 1808 | end |
| 1809 | |
| 1810 | // tWTR |
| 1811 | if (tWTR_cntr < tWTR - 0.001) begin |
| 1812 | $display("%m: At time %t ERROR: tWTR violation during Read", $realtime); |
| 1813 | end |
| 1814 | end |
| 1815 | |
| 1816 | // Write Command |
| 1817 | if (Write_enable === 1'b1) begin |
| 1818 | if (!(power_up_done)) begin |
| 1819 | $display ("%m: At time %t ERROR: Power Up and Initialization Sequence not completed before executing Write Command", $realtime); |
| 1820 | end |
| 1821 | // display debug message |
| 1822 | if (Debug) begin |
| 1823 | $display ("Debug: At time %t %m:WRITE: Bank = %d, Col = %d", $realtime, Ba, {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]}); |
| 1824 | end |
| 1825 | |
| 1826 | // Pipeline for Write |
| 1827 | // Write_pipeline [3] = 1'b1; |
| 1828 | for (i=0; i<burst_length; i=i+1) |
| 1829 | begin |
| 1830 | Write_pipeline[1 + i] = 1'b1; |
| 1831 | // Write_col_pipeline [1 + i] = {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]} + i; |
| 1832 | Write_col_pipeline [1 + i] = Burst_Order({Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]}, i); |
| 1833 | Write_bank_pipeline [1 + i] = Ba; |
| 1834 | |
| 1835 | end |
| 1836 | |
| 1837 | // Interrupt a Write with Auto Precharge (same bank only) |
| 1838 | if (Write_precharge_access [Ba] === 1'b1) begin |
| 1839 | $display ("%m: At time %t ERROR: It's illegal to interrupt a Write with Auto Precharge", $realtime); |
| 1840 | end |
| 1841 | |
| 1842 | // Activate to Write |
| 1843 | if ((Ba === 2'b00 && Pc_b0 === 1'b1) || (Ba === 2'b01 && Pc_b1 === 1'b1) || |
| 1844 | (Ba === 2'b10 && Pc_b2 === 1'b1) || (Ba === 2'b11 && Pc_b3 === 1'b1)) begin |
| 1845 | $display("%m: At time %t ERROR: Bank is not Activated for Write", $realtime); |
| 1846 | end |
| 1847 | |
| 1848 | // Activate to Write |
| 1849 | if ((Ba === 2'b00 && $realtime - RCD_chk0 < tRCD - 0.001) || |
| 1850 | (Ba === 2'b01 && $realtime - RCD_chk1 < tRCD - 0.001) || |
| 1851 | (Ba === 2'b10 && $realtime - RCD_chk2 < tRCD - 0.001) || |
| 1852 | (Ba === 2'b11 && $realtime - RCD_chk3 < tRCD - 0.001)) begin |
| 1853 | $display("%m: At time %t ERROR: tRCD violation during Write to Bank %d", $realtime, Ba); |
| 1854 | end |
| 1855 | |
| 1856 | if (Read_pipeline[0]) begin |
| 1857 | $display("%m: At time %t ERROR: Read to Write violation", $realtime); |
| 1858 | end |
| 1859 | |
| 1860 | // Interrupt a Write with Auto Precharge |
| 1861 | if (Write_precharge_access [Ba] === 1'b1) begin |
| 1862 | $display ("%m: At time %t ERROR: It's illegal to interrupt a Write with Auto Precharge (same bank)", $realtime); |
| 1863 | end else if (((Write_precharge_access [0] === 1'b1) & (Count_precharge[0] < (burst_length/2))) | |
| 1864 | ((Write_precharge_access [1] === 1'b1) & (Count_precharge[1] < (burst_length/2))) | |
| 1865 | ((Write_precharge_access [2] === 1'b1) & (Count_precharge[2] < (burst_length/2))) | |
| 1866 | ((Write_precharge_access [3] === 1'b1) & (Count_precharge[3] < (burst_length/2))) ) begin |
| 1867 | $display ("%m: At time %t ERROR: It's illegal to interrupt a Write with Auto Precharge (different bank)", $realtime); |
| 1868 | end |
| 1869 | |
| 1870 | // Interrupt a Read with Auto Precharge |
| 1871 | if (((Read_precharge_count [Ba] < (4'h2 + (burst_length/2))) & (Mode_reg[6:4] == 3'b010)) | |
| 1872 | ((Read_precharge_count [Ba] < (4'h3 + (burst_length/2))) & (Mode_reg[6:4] == 3'b011)) ) begin |
| 1873 | // $display ("%m: At time %t ERROR: It's illegal to interrupt a Read with Auto Precharge (same bank)", $realtime); |
| 1874 | end else if (((Read_precharge_count [0] < (4'h2 + (burst_length/2))) & (Mode_reg[6:4] == 3'b010)) | |
| 1875 | ((Read_precharge_count [1] < (4'h2 + (burst_length/2))) & (Mode_reg[6:4] == 3'b010)) | |
| 1876 | ((Read_precharge_count [2] < (4'h2 + (burst_length/2))) & (Mode_reg[6:4] == 3'b010)) | |
| 1877 | ((Read_precharge_count [3] < (4'h2 + (burst_length/2))) & (Mode_reg[6:4] == 3'b010)) | |
| 1878 | ((Read_precharge_count [0] < (4'h3 + (burst_length/2))) & (Mode_reg[6:4] == 3'b011)) | |
| 1879 | ((Read_precharge_count [1] < (4'h3 + (burst_length/2))) & (Mode_reg[6:4] == 3'b011)) | |
| 1880 | ((Read_precharge_count [2] < (4'h3 + (burst_length/2))) & (Mode_reg[6:4] == 3'b011)) | |
| 1881 | ((Read_precharge_count [3] < (4'h3 + (burst_length/2))) & (Mode_reg[6:4] == 3'b011)) ) begin |
| 1882 | $display ("%m: At time %t ERROR: It's illegal to interrupt a data transfer on a Read with Auto Precharge (different bank)", $realtime); |
| 1883 | end |
| 1884 | |
| 1885 | // Auto Precharge |
| 1886 | if (Addr[10] === 1'b1) begin |
| 1887 | Write_precharge_access [Ba]= 1'b1; |
| 1888 | Count_precharge [Ba]= 0; |
| 1889 | Write_precharge_count[Ba] = 4'h0; |
| 1890 | end |
| 1891 | end |
| 1892 | |
| 1893 | end |
| 1894 | endtask |
| 1895 | |
| 1896 | // Main Logic |
| 1897 | always @ (posedge Sys_clk) begin |
| 1898 | ShiftPipelines; |
| 1899 | // Manual_Precharge_Pipeline; |
| 1900 | // Burst_Terminate_Pipeline; |
| 1901 | Dq_Dqs_Drivers; |
| 1902 | Write_FIFO_DM_Mask_Logic; |
| 1903 | Burst_Decode; |
| 1904 | Auto_Precharge_Calculation; |
| 1905 | Timing_chk_SRC; |
| 1906 | Control_Logic; |
| 1907 | MRD_counter; |
| 1908 | SRR_counter; |
| 1909 | SRC_counter; |
| 1910 | tWTR_counter; |
| 1911 | command_counter; |
| 1912 | end |
| 1913 | |
| 1914 | always @ (negedge Sys_clk) begin |
| 1915 | ShiftPipelines; |
| 1916 | // Manual_Precharge_Pipeline; |
| 1917 | // Burst_Terminate_Pipeline; |
| 1918 | Dq_Dqs_Drivers; |
| 1919 | Write_FIFO_DM_Mask_Logic; |
| 1920 | Burst_Decode; |
| 1921 | end |
| 1922 | |
| 1923 | // Dqs Receiver |
| 1924 | always @ (posedge Dqs_in[0]) begin |
| 1925 | // Latch data at posedge Dqs |
| 1926 | dq_rise[7 : 0] = Dq_in[7 : 0]; |
| 1927 | dm_rise[0] = Dm_in[0]; |
| 1928 | expect_pos_dqs[0] = 0; |
| 1929 | end |
| 1930 | |
| 1931 | always @ (posedge Dqs_in[1]) begin |
| 1932 | // Latch data at posedge Dqs |
| 1933 | dq_rise[15 : 8] = Dq_in[15 : 8]; |
| 1934 | dm_rise[1] = Dm_in[1]; |
| 1935 | expect_pos_dqs[1] = 0; |
| 1936 | end |
| 1937 | |
| 1938 | `ifdef x32 |
| 1939 | always @ (posedge Dqs_in[2]) begin |
| 1940 | // Latch data at posedge Dqs |
| 1941 | dq_rise[23 : 16] = Dq_in[23 : 16]; |
| 1942 | dm_rise[2] = Dm_in[2]; |
| 1943 | expect_pos_dqs[2] = 0; |
| 1944 | end |
| 1945 | |
| 1946 | always @ (posedge Dqs_in[3]) begin |
| 1947 | // Latch data at posedge Dqs |
| 1948 | dq_rise[31 : 24] = Dq_in[31 : 24]; |
| 1949 | dm_rise[3] = Dm_in[3]; |
| 1950 | expect_pos_dqs[3] = 0; |
| 1951 | end |
| 1952 | `endif |
| 1953 | |
| 1954 | always @ (negedge Dqs_in[0]) begin |
| 1955 | // Latch data at negedge Dqs |
| 1956 | dq_fall[7 : 0] = Dq_in[7 : 0]; |
| 1957 | dm_fall[0] = Dm_in[0]; |
| 1958 | dm_pair[1:0] = {dm_rise[0], dm_fall[0]}; |
| 1959 | expect_neg_dqs[0] = 0; |
| 1960 | end |
| 1961 | |
| 1962 | always @ (negedge Dqs_in[1]) begin |
| 1963 | // Latch data at negedge Dqs |
| 1964 | dq_fall[15: 8] = Dq_in[15 : 8]; |
| 1965 | dm_fall[1] = Dm_in[1]; |
| 1966 | dm_pair[3:2] = {dm_rise[1], dm_fall[1]}; |
| 1967 | expect_neg_dqs[1] = 0; |
| 1968 | end |
| 1969 | |
| 1970 | `ifdef x32 |
| 1971 | always @ (negedge Dqs_in[2]) begin |
| 1972 | // Latch data at negedge Dqs |
| 1973 | dq_fall[23: 16] = Dq_in[23 : 16]; |
| 1974 | dm_fall[2] = Dm_in[2]; |
| 1975 | dm_pair[5:4] = {dm_rise[2], dm_fall[2]}; |
| 1976 | expect_neg_dqs[2] = 0; |
| 1977 | end |
| 1978 | |
| 1979 | always @ (negedge Dqs_in[3]) begin |
| 1980 | // Latch data at negedge Dqs |
| 1981 | dq_fall[31: 24] = Dq_in[31 : 24]; |
| 1982 | dm_fall[3] = Dm_in[3]; |
| 1983 | dm_pair[7:6] = {dm_rise[3], dm_fall[3]}; |
| 1984 | expect_neg_dqs[3] = 0; |
| 1985 | end |
| 1986 | `endif |
| 1987 | |
| 1988 | // Dqs edge checking |
| 1989 | always @ (posedge Sys_clk) begin |
| 1990 | // if (Write_pipeline[2] || Write_pipeline[1] || Data_in_enable) begin |
| 1991 | if (Write_pipeline[-1]) begin |
| 1992 | for (i=0; i<DQS_BITS; i=i+1) begin |
| 1993 | if (expect_neg_dqs[i]) begin |
| 1994 | $display ("%m: At time %t ERROR: Negative DQS[%1d] transition required.", $realtime, i); |
| 1995 | end |
| 1996 | expect_neg_dqs[i] = 1'b1; |
| 1997 | end |
| 1998 | end else begin |
| 1999 | expect_neg_dqs = 0; |
| 2000 | expect_pos_dqs = 0; |
| 2001 | end |
| 2002 | end |
| 2003 | |
| 2004 | always @ (negedge Sys_clk) begin |
| 2005 | // if (Write_pipeline[2] || Write_pipeline[1] || Data_in_enable) begin |
| 2006 | if (Write_pipeline[-1]) begin |
| 2007 | for (i=0; i<DQS_BITS; i=i+1) begin |
| 2008 | if (expect_pos_dqs[i]) begin |
| 2009 | $display ("%m: At time %t ERROR: Positive DQS[%1d] transition required.", $realtime, i); |
| 2010 | end |
| 2011 | expect_pos_dqs[i] = 1'b1; |
| 2012 | end |
| 2013 | end else begin |
| 2014 | expect_neg_dqs = 0; |
| 2015 | expect_pos_dqs = 0; |
| 2016 | end |
| 2017 | end |
| 2018 | |
| 2019 | specify |
| 2020 | // SYMBOL UNITS DESCRIPTION |
| 2021 | // ------ ----- ----------- |
| 2022 | `ifdef sg5 // specparams for -6 (CL = 3) |
| 2023 | specparam tCLK_MIN = 5.0 ; // tCLK ns minimum clk cycle time |
| 2024 | specparam tDSS = 1.0 ; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2025 | specparam tDSH = 1.0 ; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2026 | specparam tIH = 1.0 ; // tIH ns Input Hold Time (fast) |
| 2027 | specparam tIS = 1.0 ; // tIS ns Input Setup Time (fast) |
| 2028 | specparam tDQSH = 1.75; // tDQSH ns DQS input High Pulse Width |
| 2029 | specparam tDQSL = 1.75; // tDQSL ns DQS input Low Pulse Width |
| 2030 | `elsif sg54 // specparams for -6 (CL = 3) |
| 2031 | specparam tCLK_MIN = 5.4; // tCLK ns minimum clk cycle time |
| 2032 | specparam tDSS = 1.08; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2033 | specparam tDSH = 1.08; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2034 | specparam tIH = 1.0; // tIH ns Input Hold Time (fast) |
| 2035 | specparam tIS = 1.0; // tIS ns Input Setup Time (fast) |
| 2036 | specparam tDQSH = 2.16; // tDQSH ns DQS input High Pulse Width |
| 2037 | specparam tDQSL = 2.16; // tDQSL ns DQS input Low Pulse Width |
| 2038 | `elsif sg6 // specparams for -6 (CL = 3) |
| 2039 | specparam tCLK_MIN = 6.0; // tCLK ns minimum clk cycle time |
| 2040 | specparam tDSS = 1.2; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2041 | specparam tDSH = 1.2; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2042 | specparam tIH = 1.1; // tIH ns Input Hold Time (fast) |
| 2043 | specparam tIS = 1.1; // tIS ns Input Setup Time (fast) |
| 2044 | specparam tDQSH = 2.1; // tDQSH ns DQS input High Pulse Width |
| 2045 | specparam tDQSL = 2.1; // tDQSL ns DQS input Low Pulse Width |
| 2046 | `elsif sg75 // specparams for -75 (CL = 3) |
| 2047 | specparam tCLK_MIN = 7.5; // tCLK ns minimum clk cycle time |
| 2048 | specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2049 | specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2050 | specparam tIH = 1.3; // tIH ns Input Hold Time (fast) |
| 2051 | specparam tIS = 1.3; // tIS ns Input Setup Time (fast) |
| 2052 | specparam tDQSH = 3.0; // tDQSH ns DQS input High Pulse Width |
| 2053 | specparam tDQSL = 3.0; // tDQSL ns DQS input Low Pulse Width |
| 2054 | `elsif sg5v18 // specparams for -6 (CL = 3) |
| 2055 | specparam tCLK_MIN = 5.0 ; // tCLK ns minimum clk cycle time |
| 2056 | specparam tDSS = 1.0 ; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2057 | specparam tDSH = 1.0 ; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2058 | specparam tIH = 0.9 ; // tIH ns Input Hold Time (fast) |
| 2059 | specparam tIS = 0.9 ; // tIS ns Input Setup Time (fast) |
| 2060 | specparam tDQSH = 2.0 ; // tDQSH ns DQS input High Pulse Width |
| 2061 | specparam tDQSL = 2.0 ; // tDQSL ns DQS input Low Pulse Width |
| 2062 | `elsif sg6v18 // specparams for -6 (CL = 3) |
| 2063 | specparam tCLK_MIN = 6.0; // tCLK ns minimum clk cycle time |
| 2064 | specparam tDSS = 1.2; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2065 | specparam tDSH = 1.2; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2066 | specparam tIH = 1.1; // tIH ns Input Hold Time (fast) |
| 2067 | specparam tIS = 1.1; // tIS ns Input Setup Time (fast) |
| 2068 | specparam tDQSH = 2.4; // tDQSH ns DQS input High Pulse Width |
| 2069 | specparam tDQSL = 2.4; // tDQSL ns DQS input Low Pulse Width |
| 2070 | `elsif sg75v18 // specparams for -75 (CL = 3) |
| 2071 | specparam tCLK_MIN = 7.5; // tCLK ns minimum clk cycle time |
| 2072 | specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2073 | specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2074 | specparam tIH = 1.3; // tIH ns Input Hold Time (fast) |
| 2075 | specparam tIS = 1.3; // tIS ns Input Setup Time (fast) |
| 2076 | specparam tDQSH = 3.0; // tDQSH ns DQS input High Pulse Width |
| 2077 | specparam tDQSL = 3.0; // tDQSL ns DQS input Low Pulse Width |
| 2078 | `elsif sg6v12 // specparams for -6 (CL = 3) |
| 2079 | specparam tCLK_MIN = 6.0; // tCLK ns minimum clk cycle time |
| 2080 | specparam tDSS = 1.2; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2081 | specparam tDSH = 1.2; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2082 | specparam tIH = 1.1; // tIH ns Input Hold Time (fast) |
| 2083 | specparam tIS = 1.1; // tIS ns Input Setup Time (fast) |
| 2084 | specparam tDQSH = 2.1; // tDQSH ns DQS input High Pulse Width |
| 2085 | specparam tDQSL = 2.1; // tDQSL ns DQS input Low Pulse Width |
| 2086 | `elsif sg75v12 // specparams for -75 (CL = 3) |
| 2087 | specparam tCLK_MIN = 7.5; // tCLK ns minimum clk cycle time |
| 2088 | specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2089 | specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2090 | specparam tIH = 1.3; // tIH ns Input Hold Time (fast) |
| 2091 | specparam tIS = 1.3; // tIS ns Input Setup Time (fast) |
| 2092 | specparam tDQSH = 3.0; // tDQSH ns DQS input High Pulse Width |
| 2093 | specparam tDQSL = 3.0; // tDQSL ns DQS input Low Pulse Width |
| 2094 | `elsif sg10v12 // specparams for -10 (CL = 3) |
| 2095 | specparam tCLK_MIN = 9.6; // tCLK ns minimum clk cycle time |
| 2096 | specparam tDSS = 1.92; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2097 | specparam tDSH = 1.92; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2098 | specparam tIH = 1.7; // tIH ns Input Hold Time (fast) |
| 2099 | specparam tIS = 1.7; // tIS ns Input Setup Time (fast) |
| 2100 | specparam tDQSH = 3.84; // tDQSH ns DQS input High Pulse Width |
| 2101 | specparam tDQSL = 3.84; // tDQSL ns DQS input Low Pulse Width |
| 2102 | `else `define sg10 // specparams for -10 (CL = 3) |
| 2103 | specparam tCLK_MIN = 9.6; // tCLK ns minimum clk cycle time |
| 2104 | specparam tDSS = 1.92; // tDSS ns DQS falling edge to CLK rising (setup time) |
| 2105 | specparam tDSH = 1.92; // tDSH ns DQS falling edge from CLK rising (hold time) |
| 2106 | specparam tIH = 1.5; // tIH ns Input Hold Time (fast) |
| 2107 | specparam tIS = 1.5; // tIS ns Input Setup Time (fast) |
| 2108 | specparam tDQSH = 3.84; // tDQSH ns DQS input High Pulse Width |
| 2109 | specparam tDQSL = 3.84; // tDQSL ns DQS input Low Pulse Width |
| 2110 | `endif |
| 2111 | $period (posedge Clk, tCLK_MIN); |
| 2112 | $width (posedge Dqs_in[0] &&& wdqs_valid, tDQSH); |
| 2113 | $width (posedge Dqs_in[1] &&& wdqs_valid, tDQSH); |
| 2114 | $width (negedge Dqs_in[0] &&& wdqs_valid, tDQSL); |
| 2115 | $width (negedge Dqs_in[1] &&& wdqs_valid, tDQSL); |
| 2116 | $setuphold(posedge Clk, Cke, tIS, tIH); |
| 2117 | $setuphold(posedge Clk, Cs_n, tIS, tIH); |
| 2118 | $setuphold(posedge Clk, Cas_n, tIS, tIH); |
| 2119 | $setuphold(posedge Clk, Ras_n, tIS, tIH); |
| 2120 | $setuphold(posedge Clk, We_n, tIS, tIH); |
| 2121 | $setuphold(posedge Clk, Addr, tIS, tIH); |
| 2122 | $setuphold(posedge Clk, Ba, tIS, tIH); |
| 2123 | $setuphold(posedge Clk, negedge Dqs &&& wdqs_valid, tDSS , tDSH); |
| 2124 | endspecify |
| 2125 | |
| 2126 | endmodule |