Xué video camera
Sign in or create your account | Project List | Help
Xué video camera Git Source Tree
Root/
| 1 | /**************************************************************************************** |
| 2 | * |
| 3 | * File Name: tb.v |
| 4 | * |
| 5 | * Dependencies: ddr2.v, ddr2_parameters.vh |
| 6 | * |
| 7 | * Description: Micron SDRAM DDR2 (Double Data Rate 2) test bench |
| 8 | * |
| 9 | * Note: -Set simulator resolution to "ps" accuracy |
| 10 | * -Set Debug = 0 to disable $display messages |
| 11 | * |
| 12 | * Disclaimer This software code and all associated documentation, comments or other |
| 13 | * of Warranty: information (collectively "Software") is provided "AS IS" without |
| 14 | * warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY |
| 15 | * DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
| 16 | * TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES |
| 17 | * OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT |
| 18 | * WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE |
| 19 | * OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. |
| 20 | * FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR |
| 21 | * THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, |
| 22 | * ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE |
| 23 | * OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, |
| 24 | * ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, |
| 25 | * INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, |
| 26 | * WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, |
| 27 | * OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE |
| 28 | * THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 29 | * DAMAGES. Because some jurisdictions prohibit the exclusion or |
| 30 | * limitation of liability for consequential or incidental damages, the |
| 31 | * above limitation may not apply to you. |
| 32 | * |
| 33 | * Copyright 2003 Micron Technology, Inc. All rights reserved. |
| 34 | * |
| 35 | ****************************************************************************************/ |
| 36 | |
| 37 | // DO NOT CHANGE THE TIMESCALE |
| 38 | |
| 39 | `timescale 1ps / 1ps |
| 40 | |
| 41 | module tb; |
| 42 | |
| 43 | `include "ddr2_parameters.vh" |
| 44 | |
| 45 | // ports |
| 46 | reg ck; |
| 47 | wire ck_n = ~ck; |
| 48 | reg cke; |
| 49 | reg cs_n; |
| 50 | reg ras_n; |
| 51 | reg cas_n; |
| 52 | reg we_n; |
| 53 | reg [BA_BITS-1:0] ba; |
| 54 | reg [ADDR_BITS-1:0] a; |
| 55 | wire [DM_BITS-1:0] dm; |
| 56 | wire [DQ_BITS-1:0] dq; |
| 57 | wire [DQS_BITS-1:0] dqs; |
| 58 | wire [DQS_BITS-1:0] dqs_n; |
| 59 | wire [DQS_BITS-1:0] rdqs_n; |
| 60 | reg odt; |
| 61 | |
| 62 | // mode registers |
| 63 | reg [ADDR_BITS-1:0] mode_reg0; //Mode Register |
| 64 | reg [ADDR_BITS-1:0] mode_reg1; //Extended Mode Register |
| 65 | wire [2:0] cl = mode_reg0[6:4]; //CAS Latency |
| 66 | wire bo = mode_reg0[3]; //Burst Order |
| 67 | wire [7:0] bl = (1<<mode_reg0[2:0]); //Burst Length |
| 68 | wire rdqs_en = mode_reg1[11]; //RDQS Enable |
| 69 | wire dqs_n_en = ~mode_reg1[10]; //dqs# Enable |
| 70 | wire [2:0] al = mode_reg1[5:3]; //Additive Latency |
| 71 | wire [3:0] rl = al + cl; //Read Latency |
| 72 | wire [3:0] wl = al + cl-1'b1; //Write Latency |
| 73 | |
| 74 | // dq transmit |
| 75 | reg dq_en; |
| 76 | reg [DM_BITS-1:0] dm_out; |
| 77 | reg [DQ_BITS-1:0] dq_out; |
| 78 | reg dqs_en; |
| 79 | reg [DQS_BITS-1:0] dqs_out; |
| 80 | assign dm = dq_en ? dm_out : {DM_BITS{1'bz}}; |
| 81 | assign dq = dq_en ? dq_out : {DQ_BITS{1'bz}}; |
| 82 | assign dqs = dqs_en ? dqs_out : {DQS_BITS{1'bz}}; |
| 83 | assign dqs_n = (dqs_en & dqs_n_en) ? ~dqs_out : {DQS_BITS{1'bz}}; |
| 84 | |
| 85 | // dq receive |
| 86 | reg [DM_BITS-1:0] dm_fifo [2*(AL_MAX+CL_MAX)+BL_MAX:0]; |
| 87 | reg [DQ_BITS-1:0] dq_fifo [2*(AL_MAX+CL_MAX)+BL_MAX:0]; |
| 88 | wire [DQ_BITS-1:0] q0, q1, q2, q3; |
| 89 | reg [1:0] burst_cntr; |
| 90 | assign rdqs_n = {DQS_BITS{1'bz}}; |
| 91 | |
| 92 | // timing definition in tCK units |
| 93 | real tck; |
| 94 | wire [11:0] taa = ceil(CL_TIME/tck); |
| 95 | wire [11:0] tanpd = TANPD; |
| 96 | wire [11:0] taond = TAOND; |
| 97 | wire [11:0] taofd = ceil(TAOFD); |
| 98 | wire [11:0] taxpd = TAXPD; |
| 99 | wire [11:0] tccd = TCCD; |
| 100 | wire [11:0] tcke = TCKE; |
| 101 | wire [11:0] tdllk = TDLLK; |
| 102 | wire [11:0] tfaw = ceil(TFAW/tck); |
| 103 | wire [11:0] tmod = ceil(TMOD/tck); |
| 104 | wire [11:0] tmrd = TMRD; |
| 105 | wire [11:0] tras = ceil(TRAS_MIN/tck); |
| 106 | wire [11:0] trc = TRC; |
| 107 | wire [11:0] trcd = ceil(TRCD/tck); |
| 108 | wire [11:0] trfc = ceil(TRFC_MIN/tck); |
| 109 | wire [11:0] trp = ceil(TRP/tck); |
| 110 | wire [11:0] trrd = ceil(TRRD/tck); |
| 111 | wire [11:0] trtp = ceil(TRTP/tck); |
| 112 | wire [11:0] twr = ceil(TWR/tck); |
| 113 | wire [11:0] twtr = ceil(TWTR/tck); |
| 114 | wire [11:0] txard = TXARD; |
| 115 | wire [11:0] txards = TXARDS; |
| 116 | wire [11:0] txp = TXP; |
| 117 | wire [11:0] txsnr = ceil(TXSNR/tck); |
| 118 | wire [11:0] txsrd = TXSRD; |
| 119 | |
| 120 | initial begin |
| 121 | $timeformat (-9, 1, " ns", 1); |
| 122 | `ifdef period |
| 123 | tck <= `period; |
| 124 | `else |
| 125 | tck <= TCK_MIN; |
| 126 | `endif |
| 127 | ck <= 1'b1; |
| 128 | end |
| 129 | |
| 130 | // component instantiation |
| 131 | ddr2 sdramddr2 ( |
| 132 | ck, |
| 133 | ck_n, |
| 134 | cke, |
| 135 | cs_n, |
| 136 | ras_n, |
| 137 | cas_n, |
| 138 | we_n, |
| 139 | dm, |
| 140 | ba, |
| 141 | a, |
| 142 | dq, |
| 143 | dqs, |
| 144 | dqs_n, |
| 145 | rdqs_n, |
| 146 | odt |
| 147 | ); |
| 148 | |
| 149 | // clock generator |
| 150 | always @(posedge ck) begin |
| 151 | ck <= #(tck/2) 1'b0; |
| 152 | ck <= #(tck) 1'b1; |
| 153 | end |
| 154 | |
| 155 | function integer ceil; |
| 156 | input number; |
| 157 | real number; |
| 158 | if (number > $rtoi(number)) |
| 159 | ceil = $rtoi(number) + 1; |
| 160 | else |
| 161 | ceil = number; |
| 162 | endfunction |
| 163 | |
| 164 | function integer max; |
| 165 | input arg1; |
| 166 | input arg2; |
| 167 | integer arg1; |
| 168 | integer arg2; |
| 169 | if (arg1 > arg2) |
| 170 | max = arg1; |
| 171 | else |
| 172 | max = arg2; |
| 173 | endfunction |
| 174 | |
| 175 | task power_up; |
| 176 | begin |
| 177 | cke <= 1'b0; |
| 178 | odt <= 1'b0; |
| 179 | repeat(10) @(negedge ck); |
| 180 | cke <= 1'b1; |
| 181 | nop (400000/tck+1); |
| 182 | end |
| 183 | endtask |
| 184 | |
| 185 | task load_mode; |
| 186 | input [BA_BITS-1:0] bank; |
| 187 | input [ADDR_BITS-1:0] addr; |
| 188 | begin |
| 189 | case (bank) |
| 190 | 0: mode_reg0 = addr; |
| 191 | 1: mode_reg1 = addr; |
| 192 | endcase |
| 193 | cke <= 1'b1; |
| 194 | cs_n <= 1'b0; |
| 195 | ras_n <= 1'b0; |
| 196 | cas_n <= 1'b0; |
| 197 | we_n <= 1'b0; |
| 198 | ba <= bank; |
| 199 | a <= addr; |
| 200 | @(negedge ck); |
| 201 | end |
| 202 | endtask |
| 203 | |
| 204 | task refresh; |
| 205 | begin |
| 206 | cke <= 1'b1; |
| 207 | cs_n <= 1'b0; |
| 208 | ras_n <= 1'b0; |
| 209 | cas_n <= 1'b0; |
| 210 | we_n <= 1'b1; |
| 211 | @(negedge ck); |
| 212 | end |
| 213 | endtask |
| 214 | |
| 215 | task precharge; |
| 216 | input [BA_BITS-1:0] bank; |
| 217 | input ap; //precharge all |
| 218 | begin |
| 219 | cke <= 1'b1; |
| 220 | cs_n <= 1'b0; |
| 221 | ras_n <= 1'b0; |
| 222 | cas_n <= 1'b1; |
| 223 | we_n <= 1'b0; |
| 224 | ba <= bank; |
| 225 | a <= (ap<<10); |
| 226 | @(negedge ck); |
| 227 | end |
| 228 | endtask |
| 229 | |
| 230 | task activate; |
| 231 | input [BA_BITS-1:0] bank; |
| 232 | input [ROW_BITS-1:0] row; |
| 233 | begin |
| 234 | cke <= 1'b1; |
| 235 | cs_n <= 1'b0; |
| 236 | ras_n <= 1'b0; |
| 237 | cas_n <= 1'b1; |
| 238 | we_n <= 1'b1; |
| 239 | ba <= bank; |
| 240 | a <= row; |
| 241 | @(negedge ck); |
| 242 | end |
| 243 | endtask |
| 244 | |
| 245 | //write task supports burst lengths <= 8 |
| 246 | task write; |
| 247 | input [BA_BITS-1:0] bank; |
| 248 | input [COL_BITS-1:0] col; |
| 249 | input ap; //Auto Precharge |
| 250 | input [8*DM_BITS-1:0] dm; |
| 251 | input [8*DQ_BITS-1:0] dq; |
| 252 | reg [ADDR_BITS-1:0] atemp [1:0]; |
| 253 | integer i; |
| 254 | begin |
| 255 | cke <= 1'b1; |
| 256 | cs_n <= 1'b0; |
| 257 | ras_n <= 1'b1; |
| 258 | cas_n <= 1'b0; |
| 259 | we_n <= 1'b0; |
| 260 | ba <= bank; |
| 261 | atemp[0] = col & 10'h3ff; //addr[ 9: 0] = COL[ 9: 0] |
| 262 | atemp[1] = (col>>10)<<11; //addr[ N:11] = COL[ N:10] |
| 263 | a <= atemp[0] | atemp[1] | (ap<<10); |
| 264 | for (i=0; i<=bl; i=i+1) begin |
| 265 | |
| 266 | dqs_en <= #(wl*tck + i*tck/2) 1'b1; |
| 267 | if (i%2 == 0) begin |
| 268 | dqs_out <= #(wl*tck + i*tck/2) {DQS_BITS{1'b0}}; |
| 269 | end else begin |
| 270 | dqs_out <= #(wl*tck + i*tck/2) {DQS_BITS{1'b1}}; |
| 271 | end |
| 272 | |
| 273 | dq_en <= #(wl*tck + i*tck/2 + tck/4) 1'b1; |
| 274 | dm_out <= #(wl*tck + i*tck/2 + tck/4) dm>>i*DM_BITS; |
| 275 | dq_out <= #(wl*tck + i*tck/2 + tck/4) dq>>i*DQ_BITS; |
| 276 | end |
| 277 | dqs_en <= #(wl*tck + bl*tck/2 + tck/2) 1'b0; |
| 278 | dq_en <= #(wl*tck + bl*tck/2 + tck/4) 1'b0; |
| 279 | @(negedge ck); |
| 280 | end |
| 281 | endtask |
| 282 | |
| 283 | // read without data verification |
| 284 | task read; |
| 285 | input [BA_BITS-1:0] bank; |
| 286 | input [COL_BITS-1:0] col; |
| 287 | input ap; //Auto Precharge |
| 288 | reg [ADDR_BITS-1:0] atemp [1:0]; |
| 289 | begin |
| 290 | cke <= 1'b1; |
| 291 | cs_n <= 1'b0; |
| 292 | ras_n <= 1'b1; |
| 293 | cas_n <= 1'b0; |
| 294 | we_n <= 1'b1; |
| 295 | ba <= bank; |
| 296 | atemp[0] = col & 10'h3ff; //addr[ 9: 0] = COL[ 9: 0] |
| 297 | atemp[1] = (col>>10)<<11; //addr[ N:11] = COL[ N:10] |
| 298 | a <= atemp[0] | atemp[1] | (ap<<10); |
| 299 | @(negedge ck); |
| 300 | end |
| 301 | endtask |
| 302 | |
| 303 | task nop; |
| 304 | input [31:0] count; |
| 305 | begin |
| 306 | cke <= 1'b1; |
| 307 | cs_n <= 1'b0; |
| 308 | ras_n <= 1'b1; |
| 309 | cas_n <= 1'b1; |
| 310 | we_n <= 1'b1; |
| 311 | repeat(count) @(negedge ck); |
| 312 | end |
| 313 | endtask |
| 314 | |
| 315 | task deselect; |
| 316 | input [31:0] count; |
| 317 | begin |
| 318 | cke <= 1'b1; |
| 319 | cs_n <= 1'b1; |
| 320 | ras_n <= 1'b1; |
| 321 | cas_n <= 1'b1; |
| 322 | we_n <= 1'b1; |
| 323 | repeat(count) @(negedge ck); |
| 324 | end |
| 325 | endtask |
| 326 | |
| 327 | task power_down; |
| 328 | input [31:0] count; |
| 329 | begin |
| 330 | cke <= 1'b0; |
| 331 | cs_n <= 1'b1; |
| 332 | ras_n <= 1'b1; |
| 333 | cas_n <= 1'b1; |
| 334 | we_n <= 1'b1; |
| 335 | repeat(count) @(negedge ck); |
| 336 | end |
| 337 | endtask |
| 338 | |
| 339 | task self_refresh; |
| 340 | input [31:0] count; |
| 341 | begin |
| 342 | cke <= 1'b0; |
| 343 | cs_n <= 1'b0; |
| 344 | ras_n <= 1'b0; |
| 345 | cas_n <= 1'b0; |
| 346 | we_n <= 1'b1; |
| 347 | cs_n <= #(tck) 1'b1; |
| 348 | ras_n <= #(tck) 1'b1; |
| 349 | cas_n <= #(tck) 1'b1; |
| 350 | we_n <= #(tck) 1'b1; |
| 351 | repeat(count) @(negedge ck); |
| 352 | end |
| 353 | endtask |
| 354 | |
| 355 | // read with data verification |
| 356 | task read_verify; |
| 357 | input [BA_BITS-1:0] bank; |
| 358 | input [COL_BITS-1:0] col; |
| 359 | input ap; //Auto Precharge |
| 360 | input [8*DM_BITS-1:0] dm; //Expected Data Mask |
| 361 | input [8*DQ_BITS-1:0] dq; //Expected Data |
| 362 | integer i; |
| 363 | begin |
| 364 | read (bank, col, ap); |
| 365 | for (i=0; i<bl; i=i+1) begin |
| 366 | dm_fifo[2*rl + i] = dm >> (i*DM_BITS); |
| 367 | dq_fifo[2*rl + i] = dq >> (i*DQ_BITS); |
| 368 | end |
| 369 | end |
| 370 | endtask |
| 371 | |
| 372 | // receiver(s) for data_verify process |
| 373 | dqrx dqrx[DQS_BITS-1:0] (dqs, dq, q0, q1, q2, q3); |
| 374 | |
| 375 | // perform data verification as a result of read_verify task call |
| 376 | always @(ck) begin:data_verify |
| 377 | integer i; |
| 378 | integer j; |
| 379 | reg [DQ_BITS-1:0] bit_mask; |
| 380 | reg [DM_BITS-1:0] dm_temp; |
| 381 | reg [DQ_BITS-1:0] dq_temp; |
| 382 | |
| 383 | for (i = !ck; (i < 2/(2.0 - !ck)); i=i+1) begin |
| 384 | if (dm_fifo[i] === {DM_BITS{1'bx}}) begin |
| 385 | burst_cntr = 0; |
| 386 | end else begin |
| 387 | |
| 388 | dm_temp = dm_fifo[i]; |
| 389 | for (j=0; j<DQ_BITS; j=j+1) begin |
| 390 | bit_mask[j] = !dm_temp[j/8]; |
| 391 | end |
| 392 | |
| 393 | case (burst_cntr) |
| 394 | 0: dq_temp = q0; |
| 395 | 1: dq_temp = q1; |
| 396 | 2: dq_temp = q2; |
| 397 | 3: dq_temp = q3; |
| 398 | endcase |
| 399 | //if ( ((dq_temp & bit_mask) === (dq_fifo[i] & bit_mask))) |
| 400 | // $display ("%m at time %t: INFO: Successful read data compare. Expected = %h, Actual = %h, Mask = %h, i = %d", $time, dq_fifo[i], dq_temp, bit_mask, burst_cntr); |
| 401 | if ((dq_temp & bit_mask) !== (dq_fifo[i] & bit_mask)) |
| 402 | $display ("%m at time %t: ERROR: Read data miscompare. Expected = %h, Actual = %h, Mask = %h, i = %d", $time, dq_fifo[i], dq_temp, bit_mask, burst_cntr); |
| 403 | |
| 404 | burst_cntr = burst_cntr + 1; |
| 405 | end |
| 406 | end |
| 407 | |
| 408 | if (ck) begin |
| 409 | if (dm_fifo[2] === {DM_BITS{1'bx}}) begin |
| 410 | dqrx[0%DQS_BITS].ptr <= 0; // v2k syntax |
| 411 | dqrx[1%DQS_BITS].ptr <= 0; // v2k syntax |
| 412 | dqrx[2%DQS_BITS].ptr <= 0; // v2k syntax |
| 413 | dqrx[3%DQS_BITS].ptr <= 0; // v2k syntax |
| 414 | end |
| 415 | end else begin |
| 416 | for (i=0; i<=(2*(AL_MAX+CL_MAX)+BL_MAX); i=i+1) begin |
| 417 | dm_fifo[i] = dm_fifo[i+2]; |
| 418 | dq_fifo[i] = dq_fifo[i+2]; |
| 419 | end |
| 420 | end |
| 421 | end |
| 422 | |
| 423 | // End-of-test triggered in 'subtest.vh' |
| 424 | task test_done; |
| 425 | begin |
| 426 | $display ("%m at time %t: INFO: Simulation is Complete", $time); |
| 427 | $stop(0); |
| 428 | end |
| 429 | endtask |
| 430 | |
| 431 | // Test included from external file |
| 432 | `include "subtest.vh" |
| 433 | |
| 434 | endmodule |
| 435 | |
| 436 | module dqrx ( |
| 437 | dqs, dq, q0, q1, q2, q3 |
| 438 | ); |
| 439 | |
| 440 | `include "ddr2_parameters.vh" |
| 441 | |
| 442 | input dqs; |
| 443 | input [DQ_BITS/DQS_BITS-1:0] dq; |
| 444 | output [DQ_BITS/DQS_BITS-1:0] q0; |
| 445 | output [DQ_BITS/DQS_BITS-1:0] q1; |
| 446 | output [DQ_BITS/DQS_BITS-1:0] q2; |
| 447 | output [DQ_BITS/DQS_BITS-1:0] q3; |
| 448 | |
| 449 | reg [DQ_BITS/DQS_BITS-1:0] q [3:0]; |
| 450 | |
| 451 | assign q0 = q[0]; |
| 452 | assign q1 = q[1]; |
| 453 | assign q2 = q[2]; |
| 454 | assign q3 = q[3]; |
| 455 | |
| 456 | reg [1:0] ptr; |
| 457 | reg dqs_q; |
| 458 | |
| 459 | always @(dqs) begin |
| 460 | if (dqs ^ dqs_q) begin |
| 461 | #(TDQSQ + 1); |
| 462 | q[ptr] <= dq; |
| 463 | ptr <= (ptr + 1)%4; |
| 464 | end |
| 465 | dqs_q <= dqs; |
| 466 | end |
| 467 | |
| 468 | endmodule |
| 469 |
Branches:
master
