OpenCores
URL https://opencores.org/ocsvn/versatile_mem_ctrl/versatile_mem_ctrl/trunk

Subversion Repositories versatile_mem_ctrl

[/] [versatile_mem_ctrl/] [trunk/] [bench/] [ddr/] [tb.v] - Blame information for rev 31

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 11 mikaeljf
/****************************************************************************************
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.