Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
| 1 | /**************************************************************************************** |
| 2 | * |
| 3 | * File Name: ddr.v |
| 4 | * Version: 5.7 |
| 5 | * Model: BUS Functional |
| 6 | * |
| 7 | * Dependencies: ddr_parameters.v |
| 8 | * |
| 9 | * Description: Micron SDRAM DDR (Double Data Rate) |
| 10 | * |
| 11 | * Limitation: - Doesn't check for 8K-cycle refresh. |
| 12 | * - Doesn't check power-down entry/exit |
| 13 | * - Doesn't check self-refresh entry/exit. |
| 14 | * |
| 15 | * Note: - Set simulator resolution to "ps" accuracy |
| 16 | * - Set Debug = 0 to disable $display messages |
| 17 | * - Model assume Clk and Clk# crossing at both edge |
| 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 | * 2.1 SPH 03/19/2002 - Second Release |
| 45 | * - Fix tWR and several incompatability |
| 46 | * between different simulators |
| 47 | * 3.0 TFK 02/18/2003 - Added tDSS and tDSH timing checks. |
| 48 | * - Added tDQSH and tDQSL timing checks. |
| 49 | * 3.1 CAH 05/28/2003 - update all models to release version 3.1 |
| 50 | * (no changes to this model) |
| 51 | * 3.2 JMK 06/16/2003 - updated all DDR400 models to support CAS Latency 3 |
| 52 | * 3.3 JMK 09/11/2003 - Added initialization sequence checks. |
| 53 | * 4.0 JMK 12/01/2003 - Grouped parameters into "ddr_parameters.v" |
| 54 | * - Fixed tWTR check |
| 55 | * 4.1 JMK 01/14/2004 - Grouped specify parameters by speed grade |
| 56 | * - Fixed mem_sizes parameter |
| 57 | * 4.2 JMK 03/19/2004 - Fixed pulse width checking on Dqs |
| 58 | * 4.3 JMK 04/27/2004 - Changed BL wire size in tb module |
| 59 | * - Changed Dq_buf size to [15:0] |
| 60 | * 5.0 JMK 06/16/2004 - Added read to write checking. |
| 61 | * - Added read with precharge truncation to write checking. |
| 62 | * - Added associative memory array to reduce memory consumption. |
| 63 | * - Added checking for required DQS edges during write. |
| 64 | * 5.1 JMK 08/16/2004 - Fixed checking for required DQS edges during write. |
| 65 | * - Fixed wdqs_valid window. |
| 66 | * 5.2 JMK 09/24/2004 - Read or Write without activate will be ignored. |
| 67 | * 5.3 JMK 10/27/2004 - Added tMRD checking during Auto Refresh and Activate. |
| 68 | * - Added tRFC checking during Load Mode and Precharge. |
| 69 | * 5.4 JMK 12/13/2004 - The model will not respond to illegal command sequences. |
| 70 | * 5.5 SPH 01/13/2005 - The model will issue a halt on illegal command sequences. |
| 71 | * JMK 02/11/2005 - Changed the display format for numbers to hex. |
| 72 | * 5.6 JMK 04/22/2005 - Fixed Write with auto precharge calculation. |
| 73 | * 5.7 JMK 08/05/2005 - Changed conditions for read with precharge truncation error. |
| 74 | * - Renamed parameters file with .vh extension. |
| 75 | ****************************************************************************************/ |
| 76 | |
| 77 | // DO NOT CHANGE THE TIMESCALE |
| 78 | // MAKE SURE YOUR SIMULATOR USE "PS" RESOLUTION |
| 79 | `timescale 1ns / 1ps |
| 80 | |
| 81 | module ddr (Dq, Dqs, Addr, Ba, Clk, Clk_n, Cke, Cs_n, Ras_n, Cas_n, We_n, Dm); |
| 82 | |
| 83 | `include "ddr_parameters.vh" |
| 84 | |
| 85 | // Port Declarations |
| 86 | inout [DQ_BITS - 1 : 0] Dq; |
| 87 | inout [DQS_BITS - 1 : 0] Dqs; |
| 88 | input [ADDR_BITS - 1 : 0] Addr; |
| 89 | input [1 : 0] Ba; |
| 90 | input Clk; |
| 91 | input Clk_n; |
| 92 | input Cke; |
| 93 | input Cs_n; |
| 94 | input Ras_n; |
| 95 | input Cas_n; |
| 96 | input We_n; |
| 97 | input [DM_BITS - 1 : 0] Dm; |
| 98 | |
| 99 | // Internal Wires (fixed width) |
| 100 | wire [15 : 0] Dq_in; |
| 101 | wire [1 : 0] Dqs_in; |
| 102 | wire [1 : 0] Dm_in; |
| 103 | |
| 104 | assign Dq_in [DQ_BITS - 1 : 0] = Dq; |
| 105 | assign Dqs_in [DQS_BITS - 1 : 0] = Dqs; |
| 106 | assign Dm_in [DM_BITS - 1 : 0] = Dm; |
| 107 | |
| 108 | // Data pair |
| 109 | reg [15 : 0] dq_rise; |
| 110 | reg [1 : 0] dm_rise; |
| 111 | reg [15 : 0] dq_fall; |
| 112 | reg [1 : 0] dm_fall; |
| 113 | reg [3 : 0] dm_pair; |
| 114 | reg [15 : 0] Dq_buf; |
| 115 | |
| 116 | // Mode Register |
| 117 | reg [ADDR_BITS - 1 : 0] Mode_reg; |
| 118 | |
| 119 | // Internal System Clock |
| 120 | reg CkeZ, Sys_clk; |
| 121 | |
| 122 | // Internal Dqs initialize |
| 123 | reg Dqs_int; |
| 124 | |
| 125 | // Dqs buffer |
| 126 | reg [DQS_BITS - 1 : 0] Dqs_out; |
| 127 | |
| 128 | // Dq buffer |
| 129 | reg [DQ_BITS - 1 : 0] Dq_out; |
| 130 | |
| 131 | // Read pipeline variables |
| 132 | reg Read_cmnd [0 : 6]; |
| 133 | reg [1 : 0] Read_bank [0 : 6]; |
| 134 | reg [COL_BITS - 1 : 0] Read_cols [0 : 6]; |
| 135 | |
| 136 | // Write pipeline variables |
| 137 | reg Write_cmnd [0 : 3]; |
| 138 | reg [1 : 0] Write_bank [0 : 3]; |
| 139 | reg [COL_BITS - 1 : 0] Write_cols [0 : 3]; |
| 140 | |
| 141 | // Auto precharge variables |
| 142 | reg Read_precharge [0 : 3]; |
| 143 | reg Write_precharge [0 : 3]; |
| 144 | integer Count_precharge [0 : 3]; |
| 145 | |
| 146 | // Manual precharge variables |
| 147 | reg A10_precharge [0 : 6]; |
| 148 | reg [1 : 0] Bank_precharge [0 : 6]; |
| 149 | reg Cmnd_precharge [0 : 6]; |
| 150 | |
| 151 | // Burst terminate variables |
| 152 | reg Cmnd_bst [0 : 6]; |
| 153 | |
| 154 | // Memory Banks |
| 155 | `ifdef FULL_MEM |
| 156 | reg [DQ_BITS - 1 : 0] mem_array [0 : (1<<full_mem_bits)-1]; |
| 157 | `else |
| 158 | reg [DQ_BITS - 1 : 0] mem_array [0 : (1<<part_mem_bits)-1]; |
| 159 | reg [full_mem_bits - 1 : 0] addr_array [0 : (1<<part_mem_bits)-1]; |
| 160 | reg [part_mem_bits : 0] mem_used; |
| 161 | initial mem_used = 0; |
| 162 | `endif |
| 163 | |
| 164 | // Dqs edge checking |
| 165 | integer i; |
| 166 | reg [1:0] expect_pos_dqs; |
| 167 | reg [1:0] expect_neg_dqs; |
| 168 | |
| 169 | // Burst counter |
| 170 | reg [COL_BITS - 1 : 0] Burst_counter; |
| 171 | |
| 172 | // Precharge variables |
| 173 | reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; |
| 174 | |
| 175 | // Activate variables |
| 176 | reg Act_b0, Act_b1, Act_b2, Act_b3; |
| 177 | |
| 178 | // Data IO variables |
| 179 | reg Data_in_enable; |
| 180 | reg Data_out_enable; |
| 181 | |
| 182 | // Internal address mux variables |
| 183 | reg [1 : 0] Prev_bank; |
| 184 | reg [1 : 0] Bank_addr; |
| 185 | reg [COL_BITS - 1 : 0] Cols_addr, Cols_brst, Cols_temp; |
| 186 | reg [ADDR_BITS - 1 : 0] Rows_addr; |
| 187 | reg [ADDR_BITS - 1 : 0] B0_row_addr; |
| 188 | reg [ADDR_BITS - 1 : 0] B1_row_addr; |
| 189 | reg [ADDR_BITS - 1 : 0] B2_row_addr; |
| 190 | reg [ADDR_BITS - 1 : 0] B3_row_addr; |
| 191 | |
| 192 | // DLL Reset variable |
| 193 | reg DLL_enable; |
| 194 | reg DLL_reset; |
| 195 | reg DLL_done; |
| 196 | integer DLL_count; |
| 197 | integer aref_count; |
| 198 | integer Prech_count; |
| 199 | reg power_up_done; |
| 200 | |
| 201 | // Write DQS for tDSS, tDSH, tDQSH, tDQSL checks |
| 202 | wire wdqs_valid = Write_cmnd[2] || Write_cmnd[1] || Data_in_enable; |
| 203 | |
| 204 | // Commands Decode |
| 205 | wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n; |
| 206 | wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n; |
| 207 | wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n; |
| 208 | wire Ext_mode_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & Ba[0] & ~Ba[1]; |
| 209 | wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & ~Ba[0] & ~Ba[1]; |
| 210 | wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n; |
| 211 | wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n; |
| 212 | wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n; |
| 213 | |
| 214 | // Burst Length Decode |
| 215 | wire [3:0] burst_length = 1 << (Mode_reg[2:0]); |
| 216 | reg [3:0] read_precharge_truncation; |
| 217 | |
| 218 | // CAS Latency Decode |
| 219 | // wire [2:0] cas_latency_x2 = (Mode_reg[6:4] === 3'o6) ? 5 : 2*Mode_reg[6:4]; |
| 220 | wire [2:0] cas_latency_x2 = 5; |
| 221 | |
| 222 | // DQS Buffer |
| 223 | assign Dqs = Dqs_out; |
| 224 | |
| 225 | // DQ Buffer |
| 226 | assign Dq = Dq_out; |
| 227 | |
| 228 | // Timing Check |
| 229 | time MRD_chk; |
| 230 | time RFC_chk; |
| 231 | time RRD_chk; |
| 232 | time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3; |
| 233 | time RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3; |
| 234 | time RC_chk0, RC_chk1, RC_chk2, RC_chk3; |
| 235 | time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3; |
| 236 | time RP_chk0, RP_chk1, RP_chk2, RP_chk3; |
| 237 | time WR_chk0, WR_chk1, WR_chk2, WR_chk3; |
| 238 | |
| 239 | initial begin |
| 240 | CkeZ = 1'b0; |
| 241 | Sys_clk = 1'b0; |
| 242 | {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000; |
| 243 | {Act_b0, Act_b1, Act_b2, Act_b3} = 4'b1111; |
| 244 | Dqs_int = 1'b0; |
| 245 | Dqs_out = {DQS_BITS{1'bz}}; |
| 246 | Dq_out = {DQ_BITS{1'bz}}; |
| 247 | Data_in_enable = 1'b0; |
| 248 | Data_out_enable = 1'b0; |
| 249 | DLL_enable = 1'b0; |
| 250 | DLL_reset = 1'b0; |
| 251 | DLL_done = 1'b0; |
| 252 | DLL_count = 0; |
| 253 | aref_count = 0; |
| 254 | Prech_count = 0; |
| 255 | power_up_done = 0; |
| 256 | MRD_chk = 0; |
| 257 | RFC_chk = 0; |
| 258 | RRD_chk = 0; |
| 259 | {RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0; |
| 260 | {RAP_chk0, RAP_chk1, RAP_chk2, RAP_chk3} = 0; |
| 261 | {RC_chk0, RC_chk1, RC_chk2, RC_chk3} = 0; |
| 262 | {RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0; |
| 263 | {RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0; |
| 264 | {WR_chk0, WR_chk1, WR_chk2, WR_chk3} = 0; |
| 265 | $timeformat (-9, 3, " ns", 12); |
| 266 | end |
| 267 | |
| 268 | // System Clock |
| 269 | always begin |
| 270 | @ (posedge Clk) begin |
| 271 | Sys_clk = CkeZ; |
| 272 | CkeZ = Cke; |
| 273 | end |
| 274 | @ (negedge Clk) begin |
| 275 | Sys_clk = 1'b0; |
| 276 | end |
| 277 | end |
| 278 | |
| 279 | // Check to make sure that we have a Deselect or NOP command on the bus when CKE is brought high |
| 280 | always @(Cke) begin |
| 281 | if (Cke === 1'b1) begin |
| 282 | if (!((Cs_n) || (~Cs_n & Ras_n & Cas_n & We_n))) begin |
| 283 | $display ("%m: at time %t MEMORY ERROR: You must have a Deselect or NOP command applied", $time); |
| 284 | $display ("%m: when the Clock Enable is brought High."); |
| 285 | end |
| 286 | end |
| 287 | end |
| 288 | |
| 289 | // Check the initialization sequence |
| 290 | initial begin |
| 291 | @ (posedge Cke) begin |
| 292 | @ (posedge DLL_enable) begin |
| 293 | aref_count = 0; |
| 294 | @ (posedge DLL_reset) begin |
| 295 | @ (Prech_count) begin |
| 296 | if (aref_count >= 2) begin |
| 297 | if (Debug) $display ("%m: at time %t MEMORY: Power Up and Initialization Sequence is complete", $time); |
| 298 | power_up_done = 1; |
| 299 | end else begin |
| 300 | aref_count = 0; |
| 301 | @ (aref_count >= 2) begin |
| 302 | if (Debug) $display ("%m: at time %t MEMORY: Power Up and Initialization Sequence is complete", $time); |
| 303 | power_up_done = 1; |
| 304 | end |
| 305 | end |
| 306 | end |
| 307 | end |
| 308 | end |
| 309 | end |
| 310 | end |
| 311 | |
| 312 | // Write Memory |
| 313 | task write_mem; |
| 314 | input [full_mem_bits - 1 : 0] addr; |
| 315 | input [DQ_BITS - 1 : 0] data; |
| 316 | reg [part_mem_bits : 0] i; |
| 317 | begin |
| 318 | `ifdef FULL_MEM |
| 319 | mem_array[addr] = data; |
| 320 | `else |
| 321 | begin : loop |
| 322 | for (i = 0; i < mem_used; i = i + 1) begin |
| 323 | if (addr_array[i] === addr) begin |
| 324 | disable loop; |
| 325 | end |
| 326 | end |
| 327 | end |
| 328 | if (i === mem_used) begin |
| 329 | if (i === (1<<part_mem_bits)) begin |
| 330 | $display ("At time %t ERROR: Memory overflow.\n Write to Address %h with Data %h will be lost.\n You must increase the part_mem_bits parameter or define FULL_MEM.", $time, addr, data); |
| 331 | end else begin |
| 332 | mem_used = mem_used + 1; |
| 333 | addr_array[i] = addr; |
| 334 | end |
| 335 | end |
| 336 | mem_array[i] = data; |
| 337 | `endif |
| 338 | end |
| 339 | endtask |
| 340 | |
| 341 | // Read Memory |
| 342 | task read_mem; |
| 343 | input [full_mem_bits - 1 : 0] addr; |
| 344 | output [DQ_BITS - 1 : 0] data; |
| 345 | reg [part_mem_bits : 0] i; |
| 346 | begin |
| 347 | `ifdef FULL_MEM |
| 348 | data = mem_array[addr]; |
| 349 | `else |
| 350 | begin : loop |
| 351 | for (i = 0; i < mem_used; i = i + 1) begin |
| 352 | if (addr_array[i] === addr) begin |
| 353 | disable loop; |
| 354 | end |
| 355 | end |
| 356 | end |
| 357 | if (i <= mem_used) begin |
| 358 | data = mem_array[i]; |
| 359 | end |
| 360 | `endif |
| 361 | end |
| 362 | endtask |
| 363 | |
| 364 | // Burst Decode |
| 365 | task Burst_Decode; |
| 366 | begin |
| 367 | |
| 368 | // Advance Burst Counter |
| 369 | if (Burst_counter < burst_length) begin |
| 370 | Burst_counter = Burst_counter + 1; |
| 371 | end |
| 372 | |
| 373 | // Burst Type |
| 374 | if (Mode_reg[3] === 1'b0) begin // Sequential Burst |
| 375 | Cols_temp = Cols_addr + 1; |
| 376 | end else if (Mode_reg[3] === 1'b1) begin // Interleaved Burst |
| 377 | Cols_temp[2] = Burst_counter[2] ^ Cols_brst[2]; |
| 378 | Cols_temp[1] = Burst_counter[1] ^ Cols_brst[1]; |
| 379 | Cols_temp[0] = Burst_counter[0] ^ Cols_brst[0]; |
| 380 | end |
| 381 | |
| 382 | // Burst Length |
| 383 | if (burst_length === 2) begin |
| 384 | Cols_addr [0] = Cols_temp [0]; |
| 385 | end else if (burst_length === 4) begin |
| 386 | Cols_addr [1 : 0] = Cols_temp [1 : 0]; |
| 387 | end else if (burst_length === 8) begin |
| 388 | Cols_addr [2 : 0] = Cols_temp [2 : 0]; |
| 389 | end else begin |
| 390 | Cols_addr = Cols_temp; |
| 391 | end |
| 392 | |
| 393 | // Data Counter |
| 394 | if (Burst_counter >= burst_length) begin |
| 395 | Data_in_enable = 1'b0; |
| 396 | Data_out_enable = 1'b0; |
| 397 | read_precharge_truncation = 4'h0; |
| 398 | end |
| 399 | |
| 400 | end |
| 401 | endtask |
| 402 | |
| 403 | // Manual Precharge Pipeline |
| 404 | task Manual_Precharge_Pipeline; |
| 405 | begin |
| 406 | // A10 Precharge Pipeline |
| 407 | A10_precharge[0] = A10_precharge[1]; |
| 408 | A10_precharge[1] = A10_precharge[2]; |
| 409 | A10_precharge[2] = A10_precharge[3]; |
| 410 | A10_precharge[3] = A10_precharge[4]; |
| 411 | A10_precharge[4] = A10_precharge[5]; |
| 412 | A10_precharge[5] = A10_precharge[6]; |
| 413 | A10_precharge[6] = 1'b0; |
| 414 | |
| 415 | // Bank Precharge Pipeline |
| 416 | Bank_precharge[0] = Bank_precharge[1]; |
| 417 | Bank_precharge[1] = Bank_precharge[2]; |
| 418 | Bank_precharge[2] = Bank_precharge[3]; |
| 419 | Bank_precharge[3] = Bank_precharge[4]; |
| 420 | Bank_precharge[4] = Bank_precharge[5]; |
| 421 | Bank_precharge[5] = Bank_precharge[6]; |
| 422 | Bank_precharge[6] = 2'b0; |
| 423 | |
| 424 | // Command Precharge Pipeline |
| 425 | Cmnd_precharge[0] = Cmnd_precharge[1]; |
| 426 | Cmnd_precharge[1] = Cmnd_precharge[2]; |
| 427 | Cmnd_precharge[2] = Cmnd_precharge[3]; |
| 428 | Cmnd_precharge[3] = Cmnd_precharge[4]; |
| 429 | Cmnd_precharge[4] = Cmnd_precharge[5]; |
| 430 | Cmnd_precharge[5] = Cmnd_precharge[6]; |
| 431 | Cmnd_precharge[6] = 1'b0; |
| 432 | |
| 433 | // Terminate a Read if same bank or all banks |
| 434 | if (Cmnd_precharge[0] === 1'b1) begin |
| 435 | if (Bank_precharge[0] === Bank_addr || A10_precharge[0] === 1'b1) begin |
| 436 | if (Data_out_enable === 1'b1) begin |
| 437 | Data_out_enable = 1'b0; |
| 438 | read_precharge_truncation = 4'hF; |
| 439 | end |
| 440 | end |
| 441 | end |
| 442 | end |
| 443 | endtask |
| 444 | |
| 445 | // Burst Terminate Pipeline |
| 446 | task Burst_Terminate_Pipeline; |
| 447 | begin |
| 448 | // Command Precharge Pipeline |
| 449 | Cmnd_bst[0] = Cmnd_bst[1]; |
| 450 | Cmnd_bst[1] = Cmnd_bst[2]; |
| 451 | Cmnd_bst[2] = Cmnd_bst[3]; |
| 452 | Cmnd_bst[3] = Cmnd_bst[4]; |
| 453 | Cmnd_bst[4] = Cmnd_bst[5]; |
| 454 | Cmnd_bst[5] = Cmnd_bst[6]; |
| 455 | Cmnd_bst[6] = 1'b0; |
| 456 | |
| 457 | // Terminate a Read regardless of banks |
| 458 | if (Cmnd_bst[0] === 1'b1 && Data_out_enable === 1'b1) begin |
| 459 | Data_out_enable = 1'b0; |
| 460 | end |
| 461 | end |
| 462 | endtask |
| 463 | |
| 464 | // Dq and Dqs Drivers |
| 465 | task Dq_Dqs_Drivers; |
| 466 | begin |
| 467 | // read command pipeline |
| 468 | Read_cmnd [0] = Read_cmnd [1]; |
| 469 | Read_cmnd [1] = Read_cmnd [2]; |
| 470 | Read_cmnd [2] = Read_cmnd [3]; |
| 471 | Read_cmnd [3] = Read_cmnd [4]; |
| 472 | Read_cmnd [4] = Read_cmnd [5]; |
| 473 | Read_cmnd [5] = Read_cmnd [6]; |
| 474 | Read_cmnd [6] = 1'b0; |
| 475 | |
| 476 | // read bank pipeline |
| 477 | Read_bank [0] = Read_bank [1]; |
| 478 | Read_bank [1] = Read_bank [2]; |
| 479 | Read_bank [2] = Read_bank [3]; |
| 480 | Read_bank [3] = Read_bank [4]; |
| 481 | Read_bank [4] = Read_bank [5]; |
| 482 | Read_bank [5] = Read_bank [6]; |
| 483 | Read_bank [6] = 2'b0; |
| 484 | |
| 485 | // read column pipeline |
| 486 | Read_cols [0] = Read_cols [1]; |
| 487 | Read_cols [1] = Read_cols [2]; |
| 488 | Read_cols [2] = Read_cols [3]; |
| 489 | Read_cols [3] = Read_cols [4]; |
| 490 | Read_cols [4] = Read_cols [5]; |
| 491 | Read_cols [5] = Read_cols [6]; |
| 492 | Read_cols [6] = 0; |
| 493 | |
| 494 | // Initialize Read command |
| 495 | if (Read_cmnd [0] === 1'b1) begin |
| 496 | Data_out_enable = 1'b1; |
| 497 | Bank_addr = Read_bank [0]; |
| 498 | Cols_addr = Read_cols [0]; |
| 499 | Cols_brst = Cols_addr [2 : 0]; |
| 500 | Burst_counter = 0; |
| 501 | |
| 502 | // Row Address Mux |
| 503 | case (Bank_addr) |
| 504 | 2'd0 : Rows_addr = B0_row_addr; |
| 505 | 2'd1 : Rows_addr = B1_row_addr; |
| 506 | 2'd2 : Rows_addr = B2_row_addr; |
| 507 | 2'd3 : Rows_addr = B3_row_addr; |
| 508 | default : $display ("At time %t ERROR: Invalid Bank Address", $time); |
| 509 | endcase |
| 510 | end |
| 511 | |
| 512 | // Toggle Dqs during Read command |
| 513 | if (Data_out_enable === 1'b1) begin |
| 514 | Dqs_int = 1'b0; |
| 515 | if (Dqs_out === {DQS_BITS{1'b0}}) begin |
| 516 | Dqs_out = {DQS_BITS{1'b1}}; |
| 517 | end else if (Dqs_out === {DQS_BITS{1'b1}}) begin |
| 518 | Dqs_out = {DQS_BITS{1'b0}}; |
| 519 | end else begin |
| 520 | Dqs_out = {DQS_BITS{1'b0}}; |
| 521 | end |
| 522 | end else if (Data_out_enable === 1'b0 && Dqs_int === 1'b0) begin |
| 523 | Dqs_out = {DQS_BITS{1'bz}}; |
| 524 | end |
| 525 | |
| 526 | // Initialize dqs for Read command |
| 527 | if (Read_cmnd [2] === 1'b1) begin |
| 528 | if (Data_out_enable === 1'b0) begin |
| 529 | Dqs_int = 1'b1; |
| 530 | Dqs_out = {DQS_BITS{1'b0}}; |
| 531 | end |
| 532 | end |
| 533 | |
| 534 | // Read latch |
| 535 | if (Data_out_enable === 1'b1) begin |
| 536 | // output data |
| 537 | read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_out); |
| 538 | if (Debug) begin |
| 539 | $display ("At time %t READ : Bank = %h, Row = %h, Col = %h, Data = %h", $time, Bank_addr, Rows_addr, Cols_addr, Dq_out); |
| 540 | end |
| 541 | end else begin |
| 542 | Dq_out = {DQ_BITS{1'bz}}; |
| 543 | end |
| 544 | end |
| 545 | endtask |
| 546 | |
| 547 | // Write FIFO and DM Mask Logic |
| 548 | task Write_FIFO_DM_Mask_Logic; |
| 549 | begin |
| 550 | // Write command pipeline |
| 551 | Write_cmnd [0] = Write_cmnd [1]; |
| 552 | Write_cmnd [1] = Write_cmnd [2]; |
| 553 | Write_cmnd [2] = Write_cmnd [3]; |
| 554 | Write_cmnd [3] = 1'b0; |
| 555 | |
| 556 | // Write command pipeline |
| 557 | Write_bank [0] = Write_bank [1]; |
| 558 | Write_bank [1] = Write_bank [2]; |
| 559 | Write_bank [2] = Write_bank [3]; |
| 560 | Write_bank [3] = 2'b0; |
| 561 | |
| 562 | // Write column pipeline |
| 563 | Write_cols [0] = Write_cols [1]; |
| 564 | Write_cols [1] = Write_cols [2]; |
| 565 | Write_cols [2] = Write_cols [3]; |
| 566 | Write_cols [3] = {COL_BITS{1'b0}}; |
| 567 | |
| 568 | // Initialize Write command |
| 569 | if (Write_cmnd [0] === 1'b1) begin |
| 570 | Data_in_enable = 1'b1; |
| 571 | Bank_addr = Write_bank [0]; |
| 572 | Cols_addr = Write_cols [0]; |
| 573 | Cols_brst = Cols_addr [2 : 0]; |
| 574 | Burst_counter = 0; |
| 575 | |
| 576 | // Row address mux |
| 577 | case (Bank_addr) |
| 578 | 2'd0 : Rows_addr = B0_row_addr; |
| 579 | 2'd1 : Rows_addr = B1_row_addr; |
| 580 | 2'd2 : Rows_addr = B2_row_addr; |
| 581 | 2'd3 : Rows_addr = B3_row_addr; |
| 582 | default : $display ("At time %t ERROR: Invalid Row Address", $time); |
| 583 | endcase |
| 584 | end |
| 585 | |
| 586 | // Write data |
| 587 | if (Data_in_enable === 1'b1) begin |
| 588 | |
| 589 | // Data Buffer |
| 590 | read_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf); |
| 591 | |
| 592 | // write negedge Dqs on posedge Sys_clk |
| 593 | if (Sys_clk) begin |
| 594 | if (!dm_fall[0]) begin |
| 595 | Dq_buf [ 7 : 0] = dq_fall [ 7 : 0]; |
| 596 | end |
| 597 | if (!dm_fall[1]) begin |
| 598 | Dq_buf [15 : 8] = dq_fall [15 : 8]; |
| 599 | end |
| 600 | if (~&dm_fall) begin |
| 601 | if (Debug) begin |
| 602 | $display ("At time %t WRITE: Bank = %h, Row = %h, Col = %h, Data = %h", $time, Bank_addr, Rows_addr, Cols_addr, Dq_buf[DQ_BITS-1:0]); |
| 603 | end |
| 604 | end |
| 605 | // write posedge Dqs on negedge Sys_clk |
| 606 | end else begin |
| 607 | if (!dm_rise[0]) begin |
| 608 | Dq_buf [ 7 : 0] = dq_rise [ 7 : 0]; |
| 609 | end |
| 610 | if (!dm_rise[1]) begin |
| 611 | Dq_buf [15 : 8] = dq_rise [15 : 8]; |
| 612 | end |
| 613 | if (~&dm_rise) begin |
| 614 | if (Debug) begin |
| 615 | $display ("At time %t WRITE: Bank = %h, Row = %h, Col = %h, Data = %h", $time, Bank_addr, Rows_addr, Cols_addr, Dq_buf[DQ_BITS-1:0]); |
| 616 | end |
| 617 | end |
| 618 | end |
| 619 | |
| 620 | // Write Data |
| 621 | write_mem({Bank_addr, Rows_addr, Cols_addr}, Dq_buf); |
| 622 | |
| 623 | // tWR start and tWTR check |
| 624 | if (Sys_clk && &dm_pair === 1'b0) begin |
| 625 | case (Bank_addr) |
| 626 | 2'd0 : WR_chk0 = $time; |
| 627 | 2'd1 : WR_chk1 = $time; |
| 628 | 2'd2 : WR_chk2 = $time; |
| 629 | 2'd3 : WR_chk3 = $time; |
| 630 | default : $display ("At time %t ERROR: Invalid Bank Address (tWR)", $time); |
| 631 | endcase |
| 632 | |
| 633 | // tWTR check |
| 634 | if (Read_enable === 1'b1) begin |
| 635 | $display ("At time %t ERROR: tWTR violation during Read", $time); |
| 636 | end |
| 637 | end |
| 638 | end |
| 639 | end |
| 640 | endtask |
| 641 | |
| 642 | // Auto Precharge Calculation |
| 643 | task Auto_Precharge_Calculation; |
| 644 | begin |
| 645 | // Precharge counter |
| 646 | if (Read_precharge [0] === 1'b1 || Write_precharge [0] === 1'b1) begin |
| 647 | Count_precharge [0] = Count_precharge [0] + 1; |
| 648 | end |
| 649 | if (Read_precharge [1] === 1'b1 || Write_precharge [1] === 1'b1) begin |
| 650 | Count_precharge [1] = Count_precharge [1] + 1; |
| 651 | end |
| 652 | if (Read_precharge [2] === 1'b1 || Write_precharge [2] === 1'b1) begin |
| 653 | Count_precharge [2] = Count_precharge [2] + 1; |
| 654 | end |
| 655 | if (Read_precharge [3] === 1'b1 || Write_precharge [3] === 1'b1) begin |
| 656 | Count_precharge [3] = Count_precharge [3] + 1; |
| 657 | end |
| 658 | |
| 659 | // Read with AutoPrecharge Calculation |
| 660 | // The device start internal precharge when: |
| 661 | // 1. Meet tRAS requirement |
| 662 | // 2. BL/2 cycles after command |
| 663 | if ((Read_precharge[0] === 1'b1) && ($time - RAS_chk0 >= tRAS)) begin |
| 664 | if (Count_precharge[0] >= burst_length/2) begin |
| 665 | Pc_b0 = 1'b1; |
| 666 | Act_b0 = 1'b0; |
| 667 | RP_chk0 = $time; |
| 668 | Read_precharge[0] = 1'b0; |
| 669 | end |
| 670 | end |
| 671 | if ((Read_precharge[1] === 1'b1) && ($time - RAS_chk1 >= tRAS)) begin |
| 672 | if (Count_precharge[1] >= burst_length/2) begin |
| 673 | Pc_b1 = 1'b1; |
| 674 | Act_b1 = 1'b0; |
| 675 | RP_chk1 = $time; |
| 676 | Read_precharge[1] = 1'b0; |
| 677 | end |
| 678 | end |
| 679 | if ((Read_precharge[2] === 1'b1) && ($time - RAS_chk2 >= tRAS)) begin |
| 680 | if (Count_precharge[2] >= burst_length/2) begin |
| 681 | Pc_b2 = 1'b1; |
| 682 | Act_b2 = 1'b0; |
| 683 | RP_chk2 = $time; |
| 684 | Read_precharge[2] = 1'b0; |
| 685 | end |
| 686 | end |
| 687 | if ((Read_precharge[3] === 1'b1) && ($time - RAS_chk3 >= tRAS)) begin |
| 688 | if (Count_precharge[3] >= burst_length/2) begin |
| 689 | Pc_b3 = 1'b1; |
| 690 | Act_b3 = 1'b0; |
| 691 | RP_chk3 = $time; |
| 692 | Read_precharge[3] = 1'b0; |
| 693 | end |
| 694 | end |
| 695 | |
| 696 | // Write with AutoPrecharge Calculation |
| 697 | // The device start internal precharge when: |
| 698 | // 1. Meet tRAS requirement |
| 699 | // 2. Write Latency PLUS BL/2 cycles PLUS tWR after Write command |
| 700 | |
| 701 | if ((Write_precharge[0] === 1'b1) && ($time - RAS_chk0 >= tRAS)) begin |
| 702 | if ((Count_precharge[0] >= burst_length/2+1) && ($time - WR_chk0 >= tWR)) begin |
| 703 | Pc_b0 = 1'b1; |
| 704 | Act_b0 = 1'b0; |
| 705 | RP_chk0 = $time; |
| 706 | Write_precharge[0] = 1'b0; |
| 707 | end |
| 708 | end |
| 709 | if ((Write_precharge[1] === 1'b1) && ($time - RAS_chk1 >= tRAS)) begin |
| 710 | if ((Count_precharge[1] >= burst_length/2+1) && ($time - WR_chk1 >= tWR)) begin |
| 711 | Pc_b1 = 1'b1; |
| 712 | Act_b1 = 1'b0; |
| 713 | RP_chk1 = $time; |
| 714 | Write_precharge[1] = 1'b0; |
| 715 | end |
| 716 | end |
| 717 | if ((Write_precharge[2] === 1'b1) && ($time - RAS_chk2 >= tRAS)) begin |
| 718 | if ((Count_precharge[2] >= burst_length/2+1) && ($time - WR_chk2 >= tWR)) begin |
| 719 | Pc_b2 = 1'b1; |
| 720 | Act_b2 = 1'b0; |
| 721 | RP_chk2 = $time; |
| 722 | Write_precharge[2] = 1'b0; |
| 723 | end |
| 724 | end |
| 725 | if ((Write_precharge[3] === 1'b1) && ($time - RAS_chk3 >= tRAS)) begin |
| 726 | if ((Count_precharge[3] >= burst_length/2+1) && ($time - WR_chk3 >= tWR)) begin |
| 727 | Pc_b3 = 1'b1; |
| 728 | Act_b3 = 1'b0; |
| 729 | RP_chk3 = $time; |
| 730 | Write_precharge[3] = 1'b0; |
| 731 | end |
| 732 | end |
| 733 | end |
| 734 | endtask |
| 735 | |
| 736 | // DLL Counter |
| 737 | task DLL_Counter; |
| 738 | begin |
| 739 | if (DLL_reset === 1'b1 && DLL_done === 1'b0) begin |
| 740 | DLL_count = DLL_count + 1; |
| 741 | if (DLL_count >= 200) begin |
| 742 | DLL_done = 1'b1; |
| 743 | end |
| 744 | end |
| 745 | end |
| 746 | endtask |
| 747 | |
| 748 | // Control Logic |
| 749 | task Control_Logic; |
| 750 | begin |
| 751 | // Auto Refresh |
| 752 | if (Aref_enable === 1'b1) begin |
| 753 | // Display Debug Message |
| 754 | if (Debug) begin |
| 755 | $display ("At time %t AREF : Auto Refresh", $time); |
| 756 | end |
| 757 | |
| 758 | // Precharge to Auto Refresh |
| 759 | if (($time - RP_chk0 < tRP) || ($time - RP_chk1 < tRP) || |
| 760 | ($time - RP_chk2 < tRP) || ($time - RP_chk3 < tRP)) begin |
| 761 | $display ("At time %t ERROR: tRP violation during Auto Refresh", $time); |
| 762 | end |
| 763 | |
| 764 | // LMR/EMR to Auto Refresh |
| 765 | if ($time - MRD_chk < tMRD) begin |
| 766 | $display ("At time %t ERROR: tMRD violation during Auto Refresh", $time); |
| 767 | end |
| 768 | |
| 769 | // Auto Refresh to Auto Refresh |
| 770 | if ($time - RFC_chk < tRFC) begin |
| 771 | $display ("At time %t ERROR: tRFC violation during Auto Refresh", $time); |
| 772 | end |
| 773 | |
| 774 | // Precharge to Auto Refresh |
| 775 | if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin |
| 776 | $display ("At time %t ERROR: All banks must be Precharged before Auto Refresh", $time); |
| 777 | if (!no_halt) $stop (0); |
| 778 | end else begin |
| 779 | aref_count = aref_count + 1; |
| 780 | RFC_chk = $time; |
| 781 | end |
| 782 | end |
| 783 | |
| 784 | // Extended Mode Register |
| 785 | if (Ext_mode_enable === 1'b1) begin |
| 786 | if (Debug) begin |
| 787 | $display ("At time %t EMR : Extended Mode Register", $time); |
| 788 | end |
| 789 | |
| 790 | // Precharge to LMR/EMR |
| 791 | if (($time - RP_chk0 < tRP) || ($time - RP_chk1 < tRP) || |
| 792 | ($time - RP_chk2 < tRP) || ($time - RP_chk3 < tRP)) begin |
| 793 | $display ("At time %t ERROR: tRP violation during Extended Mode Register", $time); |
| 794 | end |
| 795 | |
| 796 | // LMR/EMR to LMR/EMR |
| 797 | if ($time - MRD_chk < tMRD) begin |
| 798 | $display ("At time %t ERROR: tMRD violation during Extended Mode Register", $time); |
| 799 | end |
| 800 | |
| 801 | // Auto Refresh to LMR/EMR |
| 802 | if ($time - RFC_chk < tRFC) begin |
| 803 | $display ("At time %t ERROR: tRFC violation during Extended Mode Register", $time); |
| 804 | end |
| 805 | |
| 806 | // Precharge to LMR/EMR |
| 807 | if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin |
| 808 | $display ("At time %t ERROR: all banks must be Precharged before Extended Mode Register", $time); |
| 809 | if (!no_halt) $stop (0); |
| 810 | end else begin |
| 811 | if (Addr[0] === 1'b0) begin |
| 812 | DLL_enable = 1'b1; |
| 813 | if (Debug) begin |
| 814 | $display ("At time %t EMR : Enable DLL", $time); |
| 815 | end |
| 816 | end else begin |
| 817 | DLL_enable = 1'b0; |
| 818 | if (Debug) begin |
| 819 | $display ("At time %t EMR : Disable DLL", $time); |
| 820 | end |
| 821 | end |
| 822 | MRD_chk = $time; |
| 823 | end |
| 824 | end |
| 825 | |
| 826 | // Load Mode Register |
| 827 | if (Mode_reg_enable === 1'b1) begin |
| 828 | if (Debug) begin |
| 829 | $display ("At time %t LMR : Load Mode Register", $time); |
| 830 | end |
| 831 | |
| 832 | // Precharge to LMR/EMR |
| 833 | if (($time - RP_chk0 < tRP) || ($time - RP_chk1 < tRP) || |
| 834 | ($time - RP_chk2 < tRP) || ($time - RP_chk3 < tRP)) begin |
| 835 | $display ("At time %t ERROR: tRP violation during Load Mode Register", $time); |
| 836 | end |
| 837 | |
| 838 | // LMR/EMR to LMR/EMR |
| 839 | if ($time - MRD_chk < tMRD) begin |
| 840 | $display ("At time %t ERROR: tMRD violation during Load Mode Register", $time); |
| 841 | end |
| 842 | |
| 843 | // Auto Refresh to LMR/EMR |
| 844 | if ($time - RFC_chk < tRFC) begin |
| 845 | $display ("At time %t ERROR: tRFC violation during Load Mode Register", $time); |
| 846 | end |
| 847 | |
| 848 | // Precharge to LMR/EMR |
| 849 | if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin |
| 850 | $display ("At time %t ERROR: all banks must be Precharged before Load Mode Register", $time); |
| 851 | end else begin |
| 852 | // Register Mode |
| 853 | Mode_reg = Addr; |
| 854 | |
| 855 | // DLL Reset |
| 856 | if (DLL_enable === 1'b1 && Addr [8] === 1'b1) begin |
| 857 | DLL_reset = 1'b1; |
| 858 | DLL_done = 1'b0; |
| 859 | DLL_count = 0; |
| 860 | end else if (DLL_enable === 1'b1 && DLL_reset === 1'b0 && Addr [8] === 1'b0) begin |
| 861 | $display ("At time %t ERROR: DLL is ENABLE: DLL RESET is required.", $time); |
| 862 | end else if (DLL_enable === 1'b0 && Addr [8] === 1'b1) begin |
| 863 | $display ("At time %t ERROR: DLL is DISABLE: DLL RESET will be ignored.", $time); |
| 864 | end |
| 865 | |
| 866 | // Burst Length |
| 867 | case (Addr [2 : 0]) |
| 868 | 3'b001 : $display ("At time %t LMR : Burst Length = 2", $time); |
| 869 | 3'b010 : $display ("At time %t LMR : Burst Length = 4", $time); |
| 870 | 3'b011 : $display ("At time %t LMR : Burst Length = 8", $time); |
| 871 | default : $display ("At time %t ERROR: Burst Length not supported", $time); |
| 872 | endcase |
| 873 | |
| 874 | // CAS Latency |
| 875 | case (Addr [6 : 4]) |
| 876 | 3'b010 : $display ("At time %t LMR : CAS Latency = 2", $time); |
| 877 | 3'b110 : $display ("At time %t LMR : CAS Latency = 2.5", $time); |
| 878 | 3'b011 : $display ("At time %t LMR : CAS Latency = 3", $time); |
| 879 | default : $display ("At time %t ERROR: CAS Latency not supported", $time); |
| 880 | endcase |
| 881 | |
| 882 | // Record current tMRD time |
| 883 | MRD_chk = $time; |
| 884 | end |
| 885 | end |
| 886 | |
| 887 | // Activate Block |
| 888 | if (Active_enable === 1'b1) begin |
| 889 | if (!(power_up_done)) begin |
| 890 | $display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Activate command", $time); |
| 891 | end |
| 892 | // Display Debug Message |
| 893 | if (Debug) begin |
| 894 | $display ("At time %t ACT : Bank = %h, Row = %h", $time, Ba, Addr); |
| 895 | end |
| 896 | |
| 897 | // Activate to Activate (different bank) |
| 898 | if ((Prev_bank != Ba) && ($time - RRD_chk < tRRD)) begin |
| 899 | $display ("At time %t ERROR: tRRD violation during Activate bank %h", $time, Ba); |
| 900 | end |
| 901 | |
| 902 | // LMR/EMR to Activate |
| 903 | if ($time - MRD_chk < tMRD) begin |
| 904 | $display ("At time %t ERROR: tMRD violation during Activate bank %h", $time, Ba); |
| 905 | end |
| 906 | |
| 907 | // AutoRefresh to Activate |
| 908 | if ($time - RFC_chk < tRFC) begin |
| 909 | $display ("At time %t ERROR: tRFC violation during Activate bank %h", $time, Ba); |
| 910 | end |
| 911 | |
| 912 | // Precharge to Activate |
| 913 | if ((Ba === 2'b00 && Pc_b0 === 1'b0) || (Ba === 2'b01 && Pc_b1 === 1'b0) || |
| 914 | (Ba === 2'b10 && Pc_b2 === 1'b0) || (Ba === 2'b11 && Pc_b3 === 1'b0)) begin |
| 915 | $display ("At time %t ERROR: Bank = %h is already activated - Command Ignored", $time, Ba); |
| 916 | if (!no_halt) $stop (0); |
| 917 | end else begin |
| 918 | // Activate Bank 0 |
| 919 | if (Ba === 2'b00 && Pc_b0 === 1'b1) begin |
| 920 | // Activate to Activate (same bank) |
| 921 | if ($time - RC_chk0 < tRC) begin |
| 922 | $display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba); |
| 923 | end |
| 924 | |
| 925 | // Precharge to Activate |
| 926 | if ($time - RP_chk0 < tRP) begin |
| 927 | $display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba); |
| 928 | end |
| 929 | |
| 930 | // Record variables for checking violation |
| 931 | Act_b0 = 1'b1; |
| 932 | Pc_b0 = 1'b0; |
| 933 | B0_row_addr = Addr; |
| 934 | RC_chk0 = $time; |
| 935 | RCD_chk0 = $time; |
| 936 | RAS_chk0 = $time; |
| 937 | RAP_chk0 = $time; |
| 938 | end |
| 939 | |
| 940 | // Activate Bank 1 |
| 941 | if (Ba === 2'b01 && Pc_b1 === 1'b1) begin |
| 942 | // Activate to Activate (same bank) |
| 943 | if ($time - RC_chk1 < tRC) begin |
| 944 | $display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba); |
| 945 | end |
| 946 | |
| 947 | // Precharge to Activate |
| 948 | if ($time - RP_chk1 < tRP) begin |
| 949 | $display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba); |
| 950 | end |
| 951 | |
| 952 | // Record variables for checking violation |
| 953 | Act_b1 = 1'b1; |
| 954 | Pc_b1 = 1'b0; |
| 955 | B1_row_addr = Addr; |
| 956 | RC_chk1 = $time; |
| 957 | RCD_chk1 = $time; |
| 958 | RAS_chk1 = $time; |
| 959 | RAP_chk1 = $time; |
| 960 | end |
| 961 | |
| 962 | // Activate Bank 2 |
| 963 | if (Ba === 2'b10 && Pc_b2 === 1'b1) begin |
| 964 | // Activate to Activate (same bank) |
| 965 | if ($time - RC_chk2 < tRC) begin |
| 966 | $display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba); |
| 967 | end |
| 968 | |
| 969 | // Precharge to Activate |
| 970 | if ($time - RP_chk2 < tRP) begin |
| 971 | $display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba); |
| 972 | end |
| 973 | |
| 974 | // Record variables for checking violation |
| 975 | Act_b2 = 1'b1; |
| 976 | Pc_b2 = 1'b0; |
| 977 | B2_row_addr = Addr; |
| 978 | RC_chk2 = $time; |
| 979 | RCD_chk2 = $time; |
| 980 | RAS_chk2 = $time; |
| 981 | RAP_chk2 = $time; |
| 982 | end |
| 983 | |
| 984 | // Activate Bank 3 |
| 985 | if (Ba === 2'b11 && Pc_b3 === 1'b1) begin |
| 986 | // Activate to Activate (same bank) |
| 987 | if ($time - RC_chk3 < tRC) begin |
| 988 | $display ("At time %t ERROR: tRC violation during Activate bank %h", $time, Ba); |
| 989 | end |
| 990 | |
| 991 | // Precharge to Activate |
| 992 | if ($time - RP_chk3 < tRP) begin |
| 993 | $display ("At time %t ERROR: tRP violation during Activate bank %h", $time, Ba); |
| 994 | end |
| 995 | |
| 996 | // Record variables for checking violation |
| 997 | Act_b3 = 1'b1; |
| 998 | Pc_b3 = 1'b0; |
| 999 | B3_row_addr = Addr; |
| 1000 | RC_chk3 = $time; |
| 1001 | RCD_chk3 = $time; |
| 1002 | RAS_chk3 = $time; |
| 1003 | RAP_chk3 = $time; |
| 1004 | end |
| 1005 | // Record variable for checking violation |
| 1006 | RRD_chk = $time; |
| 1007 | Prev_bank = Ba; |
| 1008 | read_precharge_truncation[Ba] = 1'b0; |
| 1009 | end |
| 1010 | end |
| 1011 | |
| 1012 | // Precharge Block - consider NOP if bank already precharged or in process of precharging |
| 1013 | if (Prech_enable === 1'b1) begin |
| 1014 | // Display Debug Message |
| 1015 | if (Debug) begin |
| 1016 | $display ("At time %t PRE : Addr[10] = %b, Bank = %b", $time, Addr[10], Ba); |
| 1017 | end |
| 1018 | |
| 1019 | // LMR/EMR to Precharge |
| 1020 | if ($time - MRD_chk < tMRD) begin |
| 1021 | $display ("At time %t ERROR: tMRD violation during Precharge", $time); |
| 1022 | end |
| 1023 | |
| 1024 | // AutoRefresh to Precharge |
| 1025 | if ($time - RFC_chk < tRFC) begin |
| 1026 | $display ("At time %t ERROR: tRFC violation during Precharge", $time); |
| 1027 | end |
| 1028 | |
| 1029 | // Precharge bank 0 |
| 1030 | if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b00)) && Act_b0 === 1'b1) begin |
| 1031 | Act_b0 = 1'b0; |
| 1032 | Pc_b0 = 1'b1; |
| 1033 | RP_chk0 = $time; |
| 1034 | |
| 1035 | // Activate to Precharge Bank |
| 1036 | if ($time - RAS_chk0 < tRAS) begin |
| 1037 | $display ("At time %t ERROR: tRAS violation during Precharge", $time); |
| 1038 | end |
| 1039 | |
| 1040 | // tWR violation check for Write |
| 1041 | if ($time - WR_chk0 < tWR) begin |
| 1042 | $display ("At time %t ERROR: tWR violation during Precharge", $time); |
| 1043 | end |
| 1044 | end |
| 1045 | |
| 1046 | // Precharge bank 1 |
| 1047 | if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b01)) && Act_b1 === 1'b1) begin |
| 1048 | Act_b1 = 1'b0; |
| 1049 | Pc_b1 = 1'b1; |
| 1050 | RP_chk1 = $time; |
| 1051 | |
| 1052 | // Activate to Precharge Bank 1 |
| 1053 | if ($time - RAS_chk1 < tRAS) begin |
| 1054 | $display ("At time %t ERROR: tRAS violation during Precharge", $time); |
| 1055 | end |
| 1056 | |
| 1057 | // tWR violation check for Write |
| 1058 | if ($time - WR_chk1 < tWR) begin |
| 1059 | $display ("At time %t ERROR: tWR violation during Precharge", $time); |
| 1060 | end |
| 1061 | end |
| 1062 | |
| 1063 | // Precharge bank 2 |
| 1064 | if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b10)) && Act_b2 === 1'b1) begin |
| 1065 | Act_b2 = 1'b0; |
| 1066 | Pc_b2 = 1'b1; |
| 1067 | RP_chk2 = $time; |
| 1068 | |
| 1069 | // Activate to Precharge Bank 2 |
| 1070 | if ($time - RAS_chk2 < tRAS) begin |
| 1071 | $display ("At time %t ERROR: tRAS violation during Precharge", $time); |
| 1072 | end |
| 1073 | |
| 1074 | // tWR violation check for Write |
| 1075 | if ($time - WR_chk2 < tWR) begin |
| 1076 | $display ("At time %t ERROR: tWR violation during Precharge", $time); |
| 1077 | end |
| 1078 | end |
| 1079 | |
| 1080 | // Precharge bank 3 |
| 1081 | if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b11)) && Act_b3 === 1'b1) begin |
| 1082 | Act_b3 = 1'b0; |
| 1083 | Pc_b3 = 1'b1; |
| 1084 | RP_chk3 = $time; |
| 1085 | |
| 1086 | // Activate to Precharge Bank 3 |
| 1087 | if ($time - RAS_chk3 < tRAS) begin |
| 1088 | $display ("At time %t ERROR: tRAS violation during Precharge", $time); |
| 1089 | end |
| 1090 | |
| 1091 | // tWR violation check for Write |
| 1092 | if ($time - WR_chk3 < tWR) begin |
| 1093 | $display ("At time %t ERROR: tWR violation during Precharge", $time); |
| 1094 | end |
| 1095 | end |
| 1096 | |
| 1097 | // Prech_count is to make sure we have met part of the initialization sequence |
| 1098 | Prech_count = Prech_count + 1; |
| 1099 | |
| 1100 | // Pipeline for READ |
| 1101 | A10_precharge [cas_latency_x2] = Addr[10]; |
| 1102 | Bank_precharge[cas_latency_x2] = Ba; |
| 1103 | Cmnd_precharge[cas_latency_x2] = 1'b1; |
| 1104 | end |
| 1105 | |
| 1106 | // Burst terminate |
| 1107 | if (Burst_term === 1'b1) begin |
| 1108 | // Display Debug Message |
| 1109 | if (Debug) begin |
| 1110 | $display ("At time %t BST : Burst Terminate",$time); |
| 1111 | end |
| 1112 | |
| 1113 | if (Data_in_enable === 1'b1) begin |
| 1114 | // Illegal to burst terminate a Write |
| 1115 | $display ("At time %t ERROR: It's illegal to burst terminate a Write", $time); |
| 1116 | if (!no_halt) $stop (0); |
| 1117 | end else if (Read_precharge[0] === 1'b1 || Read_precharge[1] === 1'b1 || |
| 1118 | // Illegal to burst terminate a Read with Auto Precharge |
| 1119 | Read_precharge[2] === 1'b1 || Read_precharge[3] === 1'b1) begin |
| 1120 | $display ("At time %t ERROR: It's illegal to burst terminate a Read with Auto Precharge", $time); |
| 1121 | if (!no_halt) $stop (0); |
| 1122 | end else begin |
| 1123 | // Burst Terminate Command Pipeline for Read |
| 1124 | Cmnd_bst[cas_latency_x2] = 1'b1; |
| 1125 | end |
| 1126 | |
| 1127 | end |
| 1128 | |
| 1129 | // Read Command |
| 1130 | if (Read_enable === 1'b1) begin |
| 1131 | if (!(power_up_done)) begin |
| 1132 | $display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Read Command", $time); |
| 1133 | end |
| 1134 | // Check for DLL reset before Read |
| 1135 | if (DLL_reset === 1 && DLL_done === 0) begin |
| 1136 | $display ("%m: at time %t ERROR: You need to wait 200 tCK after DLL Reset Enable to Read, Not %0d clocks.", $time, DLL_count); |
| 1137 | end |
| 1138 | // Display Debug Message |
| 1139 | if (Debug) begin |
| 1140 | $display ("At time %t READ : Bank = %h, Col = %h", $time, Ba, {Addr [11], Addr [9 : 0]}); |
| 1141 | end |
| 1142 | |
| 1143 | // Terminate a Write |
| 1144 | if (Data_in_enable === 1'b1) begin |
| 1145 | Data_in_enable = 1'b0; |
| 1146 | end |
| 1147 | |
| 1148 | // Activate to Read without Auto Precharge |
| 1149 | if ((Addr [10] === 1'b0 && Ba === 2'b00 && $time - RCD_chk0 < tRCD) || |
| 1150 | (Addr [10] === 1'b0 && Ba === 2'b01 && $time - RCD_chk1 < tRCD) || |
| 1151 | (Addr [10] === 1'b0 && Ba === 2'b10 && $time - RCD_chk2 < tRCD) || |
| 1152 | (Addr [10] === 1'b0 && Ba === 2'b11 && $time - RCD_chk3 < tRCD)) begin |
| 1153 | $display("At time %t ERROR: tRCD violation during Read", $time); |
| 1154 | end |
| 1155 | |
| 1156 | // Activate to Read with Auto Precharge |
| 1157 | if ((Addr [10] === 1'b1 && Ba === 2'b00 && $time - RAP_chk0 < tRAP) || |
| 1158 | (Addr [10] === 1'b1 && Ba === 2'b01 && $time - RAP_chk1 < tRAP) || |
| 1159 | (Addr [10] === 1'b1 && Ba === 2'b10 && $time - RAP_chk2 < tRAP) || |
| 1160 | (Addr [10] === 1'b1 && Ba === 2'b11 && $time - RAP_chk3 < tRAP)) begin |
| 1161 | $display ("At time %t ERROR: tRAP violation during Read", $time); |
| 1162 | end |
| 1163 | |
| 1164 | // Interrupt a Read with Auto Precharge (same bank only) |
| 1165 | if (Read_precharge [Ba] === 1'b1) begin |
| 1166 | $display ("At time %t ERROR: It's illegal to interrupt a Read with Auto Precharge", $time); |
| 1167 | if (!no_halt) $stop (0); |
| 1168 | // Cancel Auto Precharge |
| 1169 | if (Addr[10] === 1'b0) begin |
| 1170 | Read_precharge [Ba]= 1'b0; |
| 1171 | end |
| 1172 | end |
| 1173 | // Activate to Read |
| 1174 | if ((Ba === 2'b00 && Pc_b0 === 1'b1) || (Ba === 2'b01 && Pc_b1 === 1'b1) || |
| 1175 | (Ba === 2'b10 && Pc_b2 === 1'b1) || (Ba === 2'b11 && Pc_b3 === 1'b1)) begin |
| 1176 | $display("At time %t ERROR: Bank is not Activated for Read", $time); |
| 1177 | if (!no_halt) $stop (0); |
| 1178 | end else begin |
| 1179 | // CAS Latency pipeline |
| 1180 | Read_cmnd[cas_latency_x2] = 1'b1; |
| 1181 | Read_bank[cas_latency_x2] = Ba; |
| 1182 | Read_cols[cas_latency_x2] = {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]}; |
| 1183 | // Auto Precharge |
| 1184 | if (Addr[10] === 1'b1) begin |
| 1185 | Read_precharge [Ba]= 1'b1; |
| 1186 | Count_precharge [Ba]= 0; |
| 1187 | end |
| 1188 | end |
| 1189 | end |
| 1190 | |
| 1191 | // Write Command |
| 1192 | if (Write_enable === 1'b1) begin |
| 1193 | if (!(power_up_done)) begin |
| 1194 | $display ("%m: at time %t ERROR: Power Up and Initialization Sequence not completed before executing Write Command", $time); |
| 1195 | if (!no_halt) $stop (0); |
| 1196 | end |
| 1197 | // display debug message |
| 1198 | if (Debug) begin |
| 1199 | $display ("At time %t WRITE: Bank = %h, Col = %h", $time, Ba, {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]}); |
| 1200 | end |
| 1201 | |
| 1202 | // Activate to Write |
| 1203 | if ((Ba === 2'b00 && $time - RCD_chk0 < tRCD) || |
| 1204 | (Ba === 2'b01 && $time - RCD_chk1 < tRCD) || |
| 1205 | (Ba === 2'b10 && $time - RCD_chk2 < tRCD) || |
| 1206 | (Ba === 2'b11 && $time - RCD_chk3 < tRCD)) begin |
| 1207 | $display("At time %t ERROR: tRCD violation during Write to Bank %h", $time, Ba); |
| 1208 | end |
| 1209 | |
| 1210 | // Read to Write |
| 1211 | if (Read_cmnd[0] || Read_cmnd[1] || Read_cmnd[2] || Read_cmnd[3] || |
| 1212 | Read_cmnd[4] || Read_cmnd[5] || Read_cmnd[6] || (Burst_counter < burst_length)) begin |
| 1213 | if (Data_out_enable || read_precharge_truncation[Ba]) begin |
| 1214 | $display("At time %t ERROR: Read to Write violation", $time); |
| 1215 | end |
| 1216 | end |
| 1217 | |
| 1218 | // Interrupt a Write with Auto Precharge (same bank only) |
| 1219 | if (Write_precharge [Ba] === 1'b1) begin |
| 1220 | $display ("At time %t ERROR: it's illegal to interrupt a Write with Auto Precharge", $time); |
| 1221 | if (!no_halt) $stop (0); |
| 1222 | // Cancel Auto Precharge |
| 1223 | if (Addr[10] === 1'b0) begin |
| 1224 | Write_precharge [Ba]= 1'b0; |
| 1225 | end |
| 1226 | end |
| 1227 | // Activate to Write |
| 1228 | if ((Ba === 2'b00 && Pc_b0 === 1'b1) || (Ba === 2'b01 && Pc_b1 === 1'b1) || |
| 1229 | (Ba === 2'b10 && Pc_b2 === 1'b1) || (Ba === 2'b11 && Pc_b3 === 1'b1)) begin |
| 1230 | $display("At time %t ERROR: Bank is not Activated for Write", $time); |
| 1231 | if (!no_halt) $stop (0); |
| 1232 | end else begin |
| 1233 | // Pipeline for Write |
| 1234 | Write_cmnd [3] = 1'b1; |
| 1235 | Write_bank [3] = Ba; |
| 1236 | Write_cols [3] = {Addr [ADDR_BITS - 1 : 11], Addr [9 : 0]}; |
| 1237 | // Auto Precharge |
| 1238 | if (Addr[10] === 1'b1) begin |
| 1239 | Write_precharge [Ba]= 1'b1; |
| 1240 | Count_precharge [Ba]= 0; |
| 1241 | end |
| 1242 | end |
| 1243 | end |
| 1244 | end |
| 1245 | endtask |
| 1246 | |
| 1247 | task check_neg_dqs; |
| 1248 | begin |
| 1249 | if (Write_cmnd[2] || Write_cmnd[1] || Data_in_enable) begin |
| 1250 | for (i=0; i<DQS_BITS; i=i+1) begin |
| 1251 | if (expect_neg_dqs[i]) begin |
| 1252 | $display ("At time %t ERROR: Negative DQS[%1d] transition required.", $time, i); |
| 1253 | end |
| 1254 | expect_neg_dqs[i] = 1'b1; |
| 1255 | end |
| 1256 | end else begin |
| 1257 | expect_pos_dqs = 0; |
| 1258 | expect_neg_dqs = 0; |
| 1259 | end |
| 1260 | end |
| 1261 | endtask |
| 1262 | |
| 1263 | task check_pos_dqs; |
| 1264 | begin |
| 1265 | if (Write_cmnd[2] || Write_cmnd[1] || Data_in_enable) begin |
| 1266 | for (i=0; i<DQS_BITS; i=i+1) begin |
| 1267 | if (expect_pos_dqs[i]) begin |
| 1268 | $display ("At time %t ERROR: Positive DQS[%1d] transition required.", $time, i); |
| 1269 | end |
| 1270 | expect_pos_dqs[i] = 1'b1; |
| 1271 | end |
| 1272 | end else begin |
| 1273 | expect_pos_dqs = 0; |
| 1274 | expect_neg_dqs = 0; |
| 1275 | end |
| 1276 | end |
| 1277 | endtask |
| 1278 | |
| 1279 | // Main Logic |
| 1280 | always @ (posedge Sys_clk) begin |
| 1281 | Manual_Precharge_Pipeline; |
| 1282 | Burst_Terminate_Pipeline; |
| 1283 | Dq_Dqs_Drivers; |
| 1284 | Write_FIFO_DM_Mask_Logic; |
| 1285 | Burst_Decode; |
| 1286 | check_neg_dqs; |
| 1287 | Auto_Precharge_Calculation; |
| 1288 | DLL_Counter; |
| 1289 | Control_Logic; |
| 1290 | end |
| 1291 | |
| 1292 | always @ (negedge Sys_clk) begin |
| 1293 | Manual_Precharge_Pipeline; |
| 1294 | Burst_Terminate_Pipeline; |
| 1295 | Dq_Dqs_Drivers; |
| 1296 | Write_FIFO_DM_Mask_Logic; |
| 1297 | Burst_Decode; |
| 1298 | check_pos_dqs; |
| 1299 | end |
| 1300 | |
| 1301 | // Dqs Receiver |
| 1302 | always @ (posedge Dqs_in[0]) begin |
| 1303 | // Latch data at posedge Dqs |
| 1304 | dq_rise[7 : 0] = Dq_in[7 : 0]; |
| 1305 | dm_rise[0] = Dm_in[0]; |
| 1306 | expect_pos_dqs[0] = 0; |
| 1307 | end |
| 1308 | |
| 1309 | always @ (posedge Dqs_in[1]) begin |
| 1310 | // Latch data at posedge Dqs |
| 1311 | dq_rise[15 : 8] = Dq_in[15 : 8]; |
| 1312 | dm_rise[1] = Dm_in [1]; |
| 1313 | expect_pos_dqs[1] = 0; |
| 1314 | end |
| 1315 | |
| 1316 | always @ (negedge Dqs_in[0]) begin |
| 1317 | // Latch data at negedge Dqs |
| 1318 | dq_fall[7 : 0] = Dq_in[7 : 0]; |
| 1319 | dm_fall[0] = Dm_in[0]; |
| 1320 | dm_pair[1:0] = {dm_rise[0], dm_fall[0]}; |
| 1321 | expect_neg_dqs[0] = 0; |
| 1322 | end |
| 1323 | |
| 1324 | always @ (negedge Dqs_in[1]) begin |
| 1325 | // Latch data at negedge Dqs |
| 1326 | dq_fall[15: 8] = Dq_in[15 : 8]; |
| 1327 | dm_fall[1] = Dm_in[1]; |
| 1328 | dm_pair[3:2] = {dm_rise[1], dm_fall[1]}; |
| 1329 | expect_neg_dqs[1] = 0; |
| 1330 | end |
| 1331 | |
| 1332 | specify |
| 1333 | // SYMBOL UNITS DESCRIPTION |
| 1334 | // ------ ----- ----------- |
| 1335 | //`ifdef sg5B // specparams for -5B (CL = 3) |
| 1336 | // specparam tDSS = 1.0; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK |
| 1337 | // specparam tDSH = 1.0; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK |
| 1338 | // specparam tIH = 0.600; // tIH ns Input Hold Time |
| 1339 | // specparam tIS = 0.600; // tIS ns Input Setup Time |
| 1340 | // specparam tDQSH = 1.75; // tDQSH ns DQS input High Pulse Width = 0.35*tCK |
| 1341 | // specparam tDQSL = 1.75; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK |
| 1342 | //`else `ifdef sg6 // specparams for -6 (CL = 2.5) |
| 1343 | specparam tDSS = 1.2; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK |
| 1344 | specparam tDSH = 1.2; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK |
| 1345 | specparam tIH = 0.750; // tIH ns Input Hold Time |
| 1346 | specparam tIS = 0.750; // tIS ns Input Setup Time |
| 1347 | specparam tDQSH = 2.1; // tDQSH ns DQS input High Pulse Width = 0.35*tCK |
| 1348 | specparam tDQSL = 2.1; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK |
| 1349 | //`else `ifdef sg75E // specparams for -75E (CL = 2) |
| 1350 | // specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK |
| 1351 | // specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK |
| 1352 | // specparam tIH = 0.900; // tIH ns Input Hold Time |
| 1353 | // specparam tIS = 0.900; // tIS ns Input Setup Time |
| 1354 | // specparam tDQSH = 2.625; // tDQSH ns DQS input High Pulse Width = 0.35*tCK |
| 1355 | // specparam tDQSL = 2.625; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK |
| 1356 | //`else |
| 1357 | //`define sg75Z // specparams for -75Z (CL = 2) |
| 1358 | // specparam tDSS = 1.5; // tDSS ns DQS falling edge to CLK rising (setup time) = 0.2*tCK |
| 1359 | // specparam tDSH = 1.5; // tDSH ns DQS falling edge from CLK rising (hold time) = 0.2*tCK |
| 1360 | // specparam tIH = 0.900; // tIH ns Input Hold Time |
| 1361 | // specparam tIS = 0.900; // tIS ns Input Setup Time |
| 1362 | // specparam tDQSH = 2.625; // tDQSH ns DQS input High Pulse Width = 0.35*tCK |
| 1363 | // specparam tDQSL = 2.625; // tDQSL ns DQS input Low Pulse Width = 0.35*tCK |
| 1364 | //`endif `endif `endif |
| 1365 | $width (posedge Dqs_in[0] &&& wdqs_valid, tDQSH); |
| 1366 | $width (posedge Dqs_in[1] &&& wdqs_valid, tDQSH); |
| 1367 | $width (negedge Dqs_in[0] &&& wdqs_valid, tDQSL); |
| 1368 | $width (negedge Dqs_in[1] &&& wdqs_valid, tDQSL); |
| 1369 | $setuphold(posedge Clk, Cke, tIS, tIH); |
| 1370 | $setuphold(posedge Clk, Cs_n, tIS, tIH); |
| 1371 | $setuphold(posedge Clk, Cas_n, tIS, tIH); |
| 1372 | $setuphold(posedge Clk, Ras_n, tIS, tIH); |
| 1373 | $setuphold(posedge Clk, We_n, tIS, tIH); |
| 1374 | $setuphold(posedge Clk, Addr, tIS, tIH); |
| 1375 | $setuphold(posedge Clk, Ba, tIS, tIH); |
| 1376 | $setuphold(posedge Clk, negedge Dqs &&& wdqs_valid, tDSS, tDSH); |
| 1377 | endspecify |
| 1378 | |
| 1379 | endmodule |
| 1380 |
Branches:
master
