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

Subversion Repositories genesys_ddr2

[/] [genesys_ddr2/] [trunk/] [rtl/] [ipcore_dir/] [MEMCtrl/] [user_design/] [rtl/] [ddr2_phy_write.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 oana.bonca
//*****************************************************************************
2
// DISCLAIMER OF LIABILITY
3
//
4
// This file contains proprietary and confidential information of
5
// Xilinx, Inc. ("Xilinx"), that is distributed under a license
6
// from Xilinx, and may be used, copied and/or disclosed only
7
// pursuant to the terms of a valid license agreement with Xilinx.
8
//
9
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
10
// ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
11
// EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
12
// LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
13
// MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
14
// does not warrant that functions included in the Materials will
15
// meet the requirements of Licensee, or that the operation of the
16
// Materials will be uninterrupted or error-free, or that defects
17
// in the Materials will be corrected. Furthermore, Xilinx does
18
// not warrant or make any representations regarding use, or the
19
// results of the use, of the Materials in terms of correctness,
20
// accuracy, reliability or otherwise.
21
//
22
// Xilinx products are not designed or intended to be fail-safe,
23
// or for use in any application requiring fail-safe performance,
24
// such as life-support or safety devices or systems, Class III
25
// medical devices, nuclear facilities, applications related to
26
// the deployment of airbags, or any other applications that could
27
// lead to death, personal injury or severe property or
28
// environmental damage (individually and collectively, "critical
29
// applications"). Customer assumes the sole risk and liability
30
// of any use of Xilinx products in critical applications,
31
// subject only to applicable laws and regulations governing
32
// limitations on product liability.
33
//
34
// Copyright 2006, 2007, 2008 Xilinx, Inc.
35
// All rights reserved.
36
//
37
// This disclaimer and copyright notice must be retained as part
38
// of this file at all times.
39
//*****************************************************************************
40
//   ____  ____
41
//  /   /\/   /
42
// /___/  \  /    Vendor: Xilinx
43
// \   \   \/     Version: 3.6.1
44
//  \   \         Application: MIG
45
//  /   /         Filename: ddr2_phy_write.v
46
// /___/   /\     Date Last Modified: $Date: 2010/11/26 18:26:02 $
47
// \   \  /  \    Date Created: Thu Aug 24 2006
48
//  \___\/\___\
49
//
50
//Device: Virtex-5
51
//Design Name: DDR2
52
//Purpose:
53
//Reference:
54
//   Handles delaying various write control signals appropriately depending
55
//   on CAS latency, additive latency, etc. Also splits the data and mask in
56
//   rise and fall buses.
57
//Revision History:
58
//   Rev 1.1 - For Dual Rank parts support ODT logic corrected. PK. 08/05/08
59
//   Rev 1.2 - Retain current data pattern for stage 4 calibration, and create
60
//             new pattern for stage 4. RC. 09/21/09.
61
//*****************************************************************************
62
 
63
`timescale 1ns/1ps
64
 
65
module ddr2_phy_write #
66
  (
67
   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
68
   // board design). Actual values may be different. Actual parameters values
69
   // are passed from design top module MEMCtrl module. Please refer to
70
   // the MEMCtrl module for actual values.
71
   parameter DQ_WIDTH      = 72,
72
   parameter CS_NUM        = 1,
73
   parameter ADDITIVE_LAT  = 0,
74
   parameter CAS_LAT       = 5,
75
   parameter ECC_ENABLE    = 0,
76
   parameter ODT_TYPE      = 1,
77
   parameter REG_ENABLE    = 1,
78
   parameter DDR_TYPE      = 1
79
   )
80
  (
81
   input                       clk0,
82
   input                       clk90,
83
   input                       rst90,
84
   input [(2*DQ_WIDTH)-1:0]    wdf_data,
85
   input [(2*DQ_WIDTH/8)-1:0]  wdf_mask_data,
86
   input                       ctrl_wren,
87
   input                       phy_init_wren,
88
   input                       phy_init_data_sel,
89
   output reg                  dm_ce,
90
   output reg [1:0]            dq_oe_n,
91
   output reg                  dqs_oe_n ,
92
   output reg                  dqs_rst_n ,
93
   output                      wdf_rden,
94
   output reg [CS_NUM-1:0]     odt ,
95
   output [DQ_WIDTH-1:0]       wr_data_rise,
96
   output [DQ_WIDTH-1:0]       wr_data_fall,
97
   output [(DQ_WIDTH/8)-1:0]   mask_data_rise,
98
   output [(DQ_WIDTH/8)-1:0]   mask_data_fall
99
   );
100
 
101
  localparam   MASK_WIDTH               = DQ_WIDTH/8;
102
  localparam   DDR1                     = 0;
103
  localparam   DDR2                     = 1;
104
  localparam   DDR3                     = 2;
105
 
106
  // (MIN,MAX) value of WR_LATENCY for DDR1:
107
  //   REG_ENABLE   = (0,1)
108
  //   ECC_ENABLE   = (0,1)
109
  //   Write latency = 1
110
  //   Total: (1,3)
111
  // (MIN,MAX) value of WR_LATENCY for DDR2:
112
  //   REG_ENABLE   = (0,1)
113
  //   ECC_ENABLE   = (0,1)
114
  //   Write latency = ADDITIVE_CAS + CAS_LAT - 1 = (0,4) + (3,5) - 1 = (2,8)
115
  //     ADDITIVE_LAT = (0,4) (JEDEC79-2B)
116
  //     CAS_LAT      = (3,5) (JEDEC79-2B)
117
  //   Total: (2,10)
118
  localparam WR_LATENCY = (DDR_TYPE == DDR3) ?
119
             (ADDITIVE_LAT + (CAS_LAT) + REG_ENABLE ) :
120
             (DDR_TYPE == DDR2) ?
121
             (ADDITIVE_LAT + (CAS_LAT-1) + REG_ENABLE ) :
122
             (1 + REG_ENABLE );
123
 
124
  // NOTE that ODT timing does not need to be delayed for registered
125
  // DIMM case, since like other control/address signals, it gets
126
  // delayed by one clock cycle at the DIMM
127
  localparam ODT_WR_LATENCY = WR_LATENCY - REG_ENABLE;
128
 
129
  wire                     dm_ce_0;
130
  reg                      dm_ce_r;
131
  wire [1:0]               dq_oe_0;
132
  reg [1:0]                dq_oe_n_90_r1;
133
  reg [1:0]                dq_oe_270;
134
  wire                     dqs_oe_0;
135
  reg                      dqs_oe_270;
136
  reg                      dqs_oe_n_180_r1;
137
  wire                     dqs_rst_0;
138
  reg                      dqs_rst_n_180_r1;
139
  reg                      dqs_rst_270;
140
  reg                      ecc_dm_error_r;
141
  reg                      ecc_dm_error_r1;
142
  reg [(DQ_WIDTH-1):0]     init_data_f;
143
  reg [(DQ_WIDTH-1):0]     init_data_r;
144
  reg [3:0]                init_wdf_cnt_r;
145
  wire                     odt_0;
146
  reg                      rst90_r /* synthesis syn_maxfan = 10 */;
147
  reg [10:0]               wr_stages ;
148
  reg [(2*DQ_WIDTH)-1:0]   wdf_data_r;
149
  reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r;
150
  wire [(2*DQ_WIDTH/8)-1:0] wdf_ecc_mask;
151
 
152
  reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r1;
153
  wire                     wdf_rden_0;
154
  reg                      calib_rden_90_r;
155
  reg                      wdf_rden_90_r;
156
  reg                      wdf_rden_90_r1;
157
  reg                      wdf_rden_270;
158
 
159
  always @(posedge clk90)
160
      rst90_r <= rst90;
161
 
162
  //***************************************************************************
163
  // Analysis of additional pipeline delays:
164
  //   1. dq_oe (DQ 3-state): 1 CLK90 cyc in IOB 3-state FF
165
  //   2. dqs_oe (DQS 3-state): 1 CLK180 cyc in IOB 3-state FF
166
  //   3. dqs_rst (DQS output value reset): 1 CLK180 cyc in FF + 1 CLK180 cyc
167
  //      in IOB DDR
168
  //   4. odt (ODT control): 1 CLK0 cyc in IOB FF
169
  //   5. write data (output two cyc after wdf_rden - output of RAMB_FIFO w/
170
  //      output register enabled): 2 CLK90 cyc in OSERDES
171
  //***************************************************************************
172
 
173
  // DQS 3-state must be asserted one extra clock cycle due b/c of write
174
  // pre- and post-amble (extra half clock cycle for each)
175
  assign dqs_oe_0 = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
176
 
177
  // same goes for ODT, need to handle both pre- and post-amble (generate
178
  // ODT only for DDR2)
179
  // ODT generation for DDR2 based on write latency. The MIN write
180
  // latency is 2. Based on the write latency ODT is asserted.
181
  generate
182
    if ((DDR_TYPE != DDR1) && (ODT_TYPE > 0))begin: gen_odt_ddr2
183
       if(ODT_WR_LATENCY > 3)
184
         assign odt_0 =
185
                   wr_stages[ODT_WR_LATENCY-2] |
186
                   wr_stages[ODT_WR_LATENCY-3] |
187
                   wr_stages[ODT_WR_LATENCY-4] ;
188
       else if ( ODT_WR_LATENCY == 3)
189
         assign odt_0 =
190
                   wr_stages[ODT_WR_LATENCY-1] |
191
                   wr_stages[ODT_WR_LATENCY-2] |
192
                   wr_stages[ODT_WR_LATENCY-3] ;
193
       else
194
         assign odt_0 =
195
                  wr_stages[ODT_WR_LATENCY] |
196
                  wr_stages[ODT_WR_LATENCY-1] |
197
                  wr_stages[ODT_WR_LATENCY-2] ;
198
    end else
199
      assign odt_0 = 1'b0;
200
   endgenerate
201
 
202
  assign dq_oe_0[0]   = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY];
203
  assign dq_oe_0[1]   = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
204
  assign dqs_rst_0    = ~wr_stages[WR_LATENCY-2];
205
  assign dm_ce_0      = wr_stages[WR_LATENCY] | wr_stages[WR_LATENCY-1]
206
                        | wr_stages[WR_LATENCY-2];
207
 
208
  // write data fifo, read flag assertion
209
  generate
210
    if (DDR_TYPE != DDR1) begin: gen_wdf_ddr2
211
      if (WR_LATENCY > 2)
212
        assign wdf_rden_0 = wr_stages[WR_LATENCY-3];
213
      else
214
        assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
215
    end else begin: gen_wdf_ddr1
216
      assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
217
    end
218
  endgenerate
219
 
220
  // first stage isn't registered
221
  always @(*)
222
    wr_stages[0] = (phy_init_data_sel) ? ctrl_wren : phy_init_wren;
223
 
224
  always @(posedge clk0) begin
225
    wr_stages[1] <= wr_stages[0];
226
    wr_stages[2] <= wr_stages[1];
227
    wr_stages[3] <= wr_stages[2];
228
    wr_stages[4] <= wr_stages[3];
229
    wr_stages[5] <= wr_stages[4];
230
    wr_stages[6] <= wr_stages[5];
231
    wr_stages[7] <= wr_stages[6];
232
    wr_stages[8] <= wr_stages[7];
233
    wr_stages[9] <= wr_stages[8];
234
    wr_stages[10] <= wr_stages[9];
235
  end
236
 
237
  // intermediate synchronization to CLK270
238
  always @(negedge clk90) begin
239
    dq_oe_270         <= dq_oe_0;
240
    dqs_oe_270        <= dqs_oe_0;
241
    dqs_rst_270       <= dqs_rst_0;
242
    wdf_rden_270      <= wdf_rden_0;
243
  end
244
 
245
  // synchronize DQS signals to CLK180
246
  always @(negedge clk0) begin
247
    dqs_oe_n_180_r1  <= ~dqs_oe_270;
248
    dqs_rst_n_180_r1 <= ~dqs_rst_270;
249
  end
250
 
251
  // All write data-related signals synced to CLK90
252
  always @(posedge clk90) begin
253
    dq_oe_n_90_r1  <= ~dq_oe_270;
254
    wdf_rden_90_r  <= wdf_rden_270;
255
  end
256
 
257
  // generate for wdf_rden and calib rden. These signals
258
  // are asserted based on write latency. For write
259
  // latency of 2, the extra register stage is taken out.
260
  generate
261
   if (WR_LATENCY > 2) begin
262
     always @(posedge clk90) begin
263
        // assert wdf rden only for non calibration opertations
264
        wdf_rden_90_r1 <=  wdf_rden_90_r &
265
                           phy_init_data_sel;
266
        // rden for calibration
267
        calib_rden_90_r <= wdf_rden_90_r;
268
     end
269
   end else begin
270
     always @(*) begin
271
        wdf_rden_90_r1 = wdf_rden_90_r
272
                         & phy_init_data_sel;
273
        calib_rden_90_r = wdf_rden_90_r;
274
     end
275
  end // else: !if(WR_LATENCY > 2)
276
  endgenerate
277
 
278
  // dm CE signal to stop dm oscilation
279
  always @(negedge clk90)begin
280
    dm_ce_r <= dm_ce_0;
281
    dm_ce <= dm_ce_r;
282
  end
283
 
284
  // When in ECC mode the upper byte [71:64] will have the
285
  // ECC parity. Mapping the bytes which have valid data
286
  // to the upper byte in ecc mode. Also in ecc mode there
287
  // is an extra register stage to account for timing.
288
 
289
  genvar mask_i;
290
  generate
291
    if(ECC_ENABLE) begin
292
      for (mask_i  = 0; mask_i < (2*DQ_WIDTH)/72;
293
          mask_i = mask_i+1) begin: gen_mask
294
       assign wdf_ecc_mask[((mask_i*9)+9)-1:(mask_i*9)] =
295
                {&wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9],
296
                wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9]};
297
      end
298
    end
299
   endgenerate
300
 
301
  generate
302
    if (ECC_ENABLE) begin:gen_ecc_reg
303
       always @(posedge clk90)begin
304
          if(phy_init_data_sel)
305
               wdf_mask_r <= wdf_ecc_mask;
306
          else
307
             wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
308
      end
309
    end else begin
310
      always@(posedge clk90) begin
311
        if (phy_init_data_sel)
312
          wdf_mask_r <= wdf_mask_data;
313
        else
314
          wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
315
      end
316
    end
317
  endgenerate
318
 
319
   always @(posedge clk90) begin
320
      if(phy_init_data_sel)
321
          wdf_data_r <= wdf_data;
322
      else
323
          wdf_data_r <={init_data_f,init_data_r};
324
   end
325
 
326
  // Error generation block during simulation.
327
  // Error will be displayed when all the DM
328
  // bits are not zero. The error will be
329
  // displayed only during the start of the sequence
330
  // for errors that are continous over many cycles.
331
  generate
332
    if (ECC_ENABLE) begin: gen_ecc_error
333
      always @(posedge clk90) begin
334
        //synthesis translate_off
335
        wdf_mask_r1 <= wdf_mask_r;
336
        if(DQ_WIDTH > 72)
337
           ecc_dm_error_r
338
              <= (
339
              (~wdf_mask_r1[35] && (|wdf_mask_r1[34:27])) ||
340
              (~wdf_mask_r1[26] && (|wdf_mask_r1[25:18])) ||
341
              (~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
342
              (~wdf_mask_r1[8] &&  (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
343
         else
344
            ecc_dm_error_r
345
              <= ((~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
346
              (~wdf_mask_r1[8] &&  (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
347
        ecc_dm_error_r1 <= ecc_dm_error_r ;
348
        if (ecc_dm_error_r && ~ecc_dm_error_r1) // assert the error only once.
349
          $display ("ECC DM ERROR. ");
350
        //synthesis translate_on
351
      end
352
    end
353
  endgenerate
354
 
355
  //***************************************************************************
356
  // State logic to write calibration training patterns
357
  //***************************************************************************
358
 
359
  always @(posedge clk90) begin
360
    if (rst90_r) begin
361
      init_wdf_cnt_r  <= 4'd0;
362
      init_data_r <= {64{1'bx}};
363
      init_data_f <= {64{1'bx}};
364
    end else begin
365
      init_wdf_cnt_r  <= init_wdf_cnt_r + calib_rden_90_r;
366
      casex (init_wdf_cnt_r)
367
        // First stage calibration. Pattern (rise/fall) = 1(r)->0(f)
368
        // The rise data and fall data are already interleaved in the manner
369
        // required for data into the WDF write FIFO
370
        4'b00xx: begin
371
          init_data_r <= {DQ_WIDTH{1'b1}};
372
          init_data_f <= {DQ_WIDTH{1'b0}};
373
        end
374
        // Second stage calibration. Pattern = 1(r)->1(f)->0(r)->0(f)
375
        4'b01x0: begin
376
           init_data_r <= {DQ_WIDTH{1'b1}};
377
           init_data_f <= {DQ_WIDTH{1'b1}};
378
          end
379
        4'b01x1: begin
380
           init_data_r <= {DQ_WIDTH{1'b0}};
381
           init_data_f <= {DQ_WIDTH{1'b0}};
382
        end
383
        // MIG 3.2: Changed Stage 3/4 training pattern
384
        // Third stage calibration patern = 
385
        //   11(r)->ee(f)->ee(r)->11(f)-ee(r)->11(f)->ee(r)->11(f)
386
        4'b1000: begin
387
          init_data_r <= {DQ_WIDTH/4{4'h1}};
388
          init_data_f <= {DQ_WIDTH/4{4'hE}};
389
        end
390
        4'b1001: begin
391
          init_data_r <= {DQ_WIDTH/4{4'hE}};
392
          init_data_f <= {DQ_WIDTH/4{4'h1}};
393
          end
394
        4'b1010: begin
395
          init_data_r <= {(DQ_WIDTH/4){4'hE}};
396
          init_data_f <= {(DQ_WIDTH/4){4'h1}};
397
        end
398
        4'b1011: begin
399
          init_data_r <= {(DQ_WIDTH/4){4'hE}};
400
          init_data_f <= {(DQ_WIDTH/4){4'h1}};
401
        end
402
        // Fourth stage calibration patern = 
403
        //   11(r)->ee(f)->ee(r)->11(f)-11(r)->ee(f)->ee(r)->11(f)
404
        4'b1100: begin
405
          init_data_r <= {DQ_WIDTH/4{4'h1}};
406
          init_data_f <= {DQ_WIDTH/4{4'hE}};
407
        end
408
        4'b1101: begin
409
          init_data_r <= {DQ_WIDTH/4{4'hE}};
410
          init_data_f <= {DQ_WIDTH/4{4'h1}};
411
          end
412
        4'b1110: begin
413
          init_data_r <= {(DQ_WIDTH/4){4'h1}};
414
          init_data_f <= {(DQ_WIDTH/4){4'hE}};
415
        end
416
        4'b1111: begin
417
          // MIG 3.5: Corrected last two writes for stage 4 calibration
418
          // training pattern. Previously MIG 3.3 and MIG 3.4 had the
419
          // incorrect pattern. This can sometimes result in a calibration
420
          // point with small timing margin. 
421
//          init_data_r <= {(DQ_WIDTH/4){4'h1}};
422
//          init_data_f <= {(DQ_WIDTH/4){4'hE}};
423
          init_data_r <= {(DQ_WIDTH/4){4'hE}};
424
          init_data_f <= {(DQ_WIDTH/4){4'h1}};
425
        end
426
      endcase
427
    end
428
  end
429
 
430
  //***************************************************************************
431
 
432
  always @(posedge clk90)
433
    dq_oe_n   <= dq_oe_n_90_r1;
434
 
435
  always @(negedge clk0)
436
    dqs_oe_n  <= dqs_oe_n_180_r1;
437
 
438
  always @(negedge clk0)
439
    dqs_rst_n <= dqs_rst_n_180_r1;
440
 
441
  // generate for odt. odt is asserted based on
442
  //  write latency. For write latency of 2
443
  //  the extra register stage is taken out.
444
  generate
445
    if (ODT_WR_LATENCY > 3) begin
446
      always @(posedge clk0) begin
447
        odt    <= 'b0;
448
        odt[0] <= odt_0;
449
      end
450
    end else begin
451
      always @ (*) begin
452
        odt = 'b0;
453
        odt[0] = odt_0;
454
      end
455
    end
456
  endgenerate
457
 
458
  assign wdf_rden  = wdf_rden_90_r1;
459
 
460
  //***************************************************************************
461
  // Format write data/mask: Data is in format: {fall, rise}
462
  //***************************************************************************
463
 
464
  assign wr_data_rise = wdf_data_r[DQ_WIDTH-1:0];
465
  assign wr_data_fall = wdf_data_r[(2*DQ_WIDTH)-1:DQ_WIDTH];
466
  assign mask_data_rise = wdf_mask_r[MASK_WIDTH-1:0];
467
  assign mask_data_fall = wdf_mask_r[(2*MASK_WIDTH)-1:MASK_WIDTH];
468
 
469
endmodule

powered by: WebSVN 2.1.0

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