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

Subversion Repositories m1_core

[/] [m1_core/] [trunk/] [hdl/] [behav/] [ddr_model/] [ddr.v] - Blame information for rev 58

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

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

powered by: WebSVN 2.1.0

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