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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [boards/] [xilinx/] [ml501/] [rtl/] [verilog/] [xilinx_ddr2/] [ddr2_phy_write.v] - Blame information for rev 412

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 412 julius
//*****************************************************************************
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.0
44
//  \   \         Application: MIG
45
//  /   /         Filename: ddr2_phy_write.v
46
// /___/   /\     Date Last Modified: $Date: 2008/12/23 14:26:00 $
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
//*****************************************************************************
60
 
61
`timescale 1ns/1ps
62
 
63
module ddr2_phy_write #
64
  (
65
   // Following parameters are for 72-bit RDIMM design (for ML561 Reference
66
   // board design). Actual values may be different. Actual parameters values
67
   // are passed from design top module ddr2_mig module. Please refer to
68
   // the ddr2_mig module for actual values.
69
   parameter DQ_WIDTH      = 72,
70
   parameter CS_NUM        = 1,
71
   parameter ADDITIVE_LAT  = 0,
72
   parameter CAS_LAT       = 5,
73
   parameter ECC_ENABLE    = 0,
74
   parameter ODT_TYPE      = 1,
75
   parameter REG_ENABLE    = 1,
76
   parameter DDR_TYPE      = 1
77
   )
78
  (
79
   input                       clk0,
80
   input                       clk90,
81
   input                       rst90,
82
   input [(2*DQ_WIDTH)-1:0]    wdf_data,
83
   input [(2*DQ_WIDTH/8)-1:0]  wdf_mask_data,
84
   input                       ctrl_wren,
85
   input                       phy_init_wren,
86
   input                       phy_init_data_sel,
87
   output reg                  dm_ce,
88
   output reg [1:0]            dq_oe_n,
89
   output reg                  dqs_oe_n ,
90
   output reg                  dqs_rst_n ,
91
   output                      wdf_rden,
92
   output reg [CS_NUM-1:0]     odt ,
93
   output [DQ_WIDTH-1:0]       wr_data_rise,
94
   output [DQ_WIDTH-1:0]       wr_data_fall,
95
   output [(DQ_WIDTH/8)-1:0]   mask_data_rise,
96
   output [(DQ_WIDTH/8)-1:0]   mask_data_fall
97
   );
98
 
99
  localparam   MASK_WIDTH               = DQ_WIDTH/8;
100
  localparam   DDR1                     = 0;
101
  localparam   DDR2                     = 1;
102
  localparam   DDR3                     = 2;
103
 
104
  // (MIN,MAX) value of WR_LATENCY for DDR1:
105
  //   REG_ENABLE   = (0,1)
106
  //   ECC_ENABLE   = (0,1)
107
  //   Write latency = 1
108
  //   Total: (1,3)
109
  // (MIN,MAX) value of WR_LATENCY for DDR2:
110
  //   REG_ENABLE   = (0,1)
111
  //   ECC_ENABLE   = (0,1)
112
  //   Write latency = ADDITIVE_CAS + CAS_LAT - 1 = (0,4) + (3,5) - 1 = (2,8)
113
  //     ADDITIVE_LAT = (0,4) (JEDEC79-2B)
114
  //     CAS_LAT      = (3,5) (JEDEC79-2B)
115
  //   Total: (2,10)
116
  localparam WR_LATENCY = (DDR_TYPE == DDR3) ?
117
             (ADDITIVE_LAT + (CAS_LAT) + REG_ENABLE ) :
118
             (DDR_TYPE == DDR2) ?
119
             (ADDITIVE_LAT + (CAS_LAT-1) + REG_ENABLE ) :
120
             (1 + REG_ENABLE );
121
 
122
  // NOTE that ODT timing does not need to be delayed for registered
123
  // DIMM case, since like other control/address signals, it gets
124
  // delayed by one clock cycle at the DIMM
125
  localparam ODT_WR_LATENCY = WR_LATENCY - REG_ENABLE;
126
 
127
  wire                     dm_ce_0;
128
  reg                      dm_ce_r;
129
  wire [1:0]               dq_oe_0;
130
  reg [1:0]                dq_oe_n_90_r1;
131
  reg [1:0]                dq_oe_270;
132
  wire                     dqs_oe_0;
133
  reg                      dqs_oe_270;
134
  reg                      dqs_oe_n_180_r1;
135
  wire                     dqs_rst_0;
136
  reg                      dqs_rst_n_180_r1;
137
  reg                      dqs_rst_270;
138
  reg                      ecc_dm_error_r;
139
  reg                      ecc_dm_error_r1;
140
  reg [(DQ_WIDTH-1):0]     init_data_f;
141
  reg [(DQ_WIDTH-1):0]     init_data_r;
142
  reg [3:0]                init_wdf_cnt_r;
143
  wire                     odt_0;
144
  reg                      rst90_r /* synthesis syn_maxfan = 10 */;
145
  reg [10:0]               wr_stages ;
146
  reg [(2*DQ_WIDTH)-1:0]   wdf_data_r;
147
  reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r;
148
  wire [(2*DQ_WIDTH/8)-1:0] wdf_ecc_mask;
149
 
150
  reg [(2*DQ_WIDTH/8)-1:0] wdf_mask_r1;
151
  wire                     wdf_rden_0;
152
  reg                      calib_rden_90_r;
153
  reg                      wdf_rden_90_r;
154
  reg                      wdf_rden_90_r1;
155
  reg                      wdf_rden_270;
156
 
157
  always @(posedge clk90)
158
      rst90_r <= rst90;
159
 
160
  //***************************************************************************
161
  // Analysis of additional pipeline delays:
162
  //   1. dq_oe (DQ 3-state): 1 CLK90 cyc in IOB 3-state FF
163
  //   2. dqs_oe (DQS 3-state): 1 CLK180 cyc in IOB 3-state FF
164
  //   3. dqs_rst (DQS output value reset): 1 CLK180 cyc in FF + 1 CLK180 cyc
165
  //      in IOB DDR
166
  //   4. odt (ODT control): 1 CLK0 cyc in IOB FF
167
  //   5. write data (output two cyc after wdf_rden - output of RAMB_FIFO w/
168
  //      output register enabled): 2 CLK90 cyc in OSERDES
169
  //***************************************************************************
170
 
171
  // DQS 3-state must be asserted one extra clock cycle due b/c of write
172
  // pre- and post-amble (extra half clock cycle for each)
173
  assign dqs_oe_0 = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
174
 
175
  // same goes for ODT, need to handle both pre- and post-amble (generate
176
  // ODT only for DDR2)
177
  // ODT generation for DDR2 based on write latency. The MIN write
178
  // latency is 2. Based on the write latency ODT is asserted.
179
  generate
180
    if ((DDR_TYPE != DDR1) && (ODT_TYPE > 0))begin: gen_odt_ddr2
181
       if(ODT_WR_LATENCY > 2)
182
         assign odt_0 =
183
                   wr_stages[ODT_WR_LATENCY-1] |
184
                   wr_stages[ODT_WR_LATENCY-2] |
185
                   wr_stages[ODT_WR_LATENCY-3] ;
186
       else
187
         assign odt_0 =
188
                  wr_stages[ODT_WR_LATENCY] |
189
                  wr_stages[ODT_WR_LATENCY-1] |
190
                  wr_stages[ODT_WR_LATENCY-2] ;
191
    end else
192
      assign odt_0 = 1'b0;
193
   endgenerate
194
 
195
  assign dq_oe_0[0]   = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY];
196
  assign dq_oe_0[1]   = wr_stages[WR_LATENCY-1] | wr_stages[WR_LATENCY-2];
197
  assign dqs_rst_0    = ~wr_stages[WR_LATENCY-2];
198
  assign dm_ce_0      = wr_stages[WR_LATENCY] | wr_stages[WR_LATENCY-1]
199
                        | wr_stages[WR_LATENCY-2];
200
 
201
  // write data fifo, read flag assertion
202
  generate
203
    if (DDR_TYPE != DDR1) begin: gen_wdf_ddr2
204
      if (WR_LATENCY > 2)
205
        assign wdf_rden_0 = wr_stages[WR_LATENCY-3];
206
      else
207
        assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
208
    end else begin: gen_wdf_ddr1
209
      assign wdf_rden_0 = wr_stages[WR_LATENCY-2];
210
    end
211
  endgenerate
212
 
213
  // first stage isn't registered
214
  always @(*)
215
    wr_stages[0] = (phy_init_data_sel) ? ctrl_wren : phy_init_wren;
216
 
217
  always @(posedge clk0) begin
218
    wr_stages[1] <= wr_stages[0];
219
    wr_stages[2] <= wr_stages[1];
220
    wr_stages[3] <= wr_stages[2];
221
    wr_stages[4] <= wr_stages[3];
222
    wr_stages[5] <= wr_stages[4];
223
    wr_stages[6] <= wr_stages[5];
224
    wr_stages[7] <= wr_stages[6];
225
    wr_stages[8] <= wr_stages[7];
226
    wr_stages[9] <= wr_stages[8];
227
    wr_stages[10] <= wr_stages[9];
228
  end
229
 
230
  // intermediate synchronization to CLK270
231
  always @(negedge clk90) begin
232
    dq_oe_270         <= dq_oe_0;
233
    dqs_oe_270        <= dqs_oe_0;
234
    dqs_rst_270       <= dqs_rst_0;
235
    wdf_rden_270      <= wdf_rden_0;
236
  end
237
 
238
  // synchronize DQS signals to CLK180
239
  always @(negedge clk0) begin
240
    dqs_oe_n_180_r1  <= ~dqs_oe_270;
241
    dqs_rst_n_180_r1 <= ~dqs_rst_270;
242
  end
243
 
244
  // All write data-related signals synced to CLK90
245
  always @(posedge clk90) begin
246
    dq_oe_n_90_r1  <= ~dq_oe_270;
247
    wdf_rden_90_r  <= wdf_rden_270;
248
  end
249
 
250
  // generate for wdf_rden and calib rden. These signals
251
  // are asserted based on write latency. For write
252
  // latency of 2, the extra register stage is taken out.
253
  generate
254
   if (WR_LATENCY > 2) begin
255
     always @(posedge clk90) begin
256
        // assert wdf rden only for non calibration opertations
257
        wdf_rden_90_r1 <=  wdf_rden_90_r &
258
                           phy_init_data_sel;
259
        // rden for calibration
260
        calib_rden_90_r <= wdf_rden_90_r;
261
     end
262
   end else begin
263
     always @(*) begin
264
        wdf_rden_90_r1 = wdf_rden_90_r
265
                         & phy_init_data_sel;
266
        calib_rden_90_r = wdf_rden_90_r;
267
     end
268
  end // else: !if(WR_LATENCY > 2)
269
  endgenerate
270
 
271
  // dm CE signal to stop dm oscilation
272
  always @(negedge clk90)begin
273
    dm_ce_r <= dm_ce_0;
274
    dm_ce <= dm_ce_r;
275
  end
276
 
277
  // When in ECC mode the upper byte [71:64] will have the
278
  // ECC parity. Mapping the bytes which have valid data
279
  // to the upper byte in ecc mode. Also in ecc mode there
280
  // is an extra register stage to account for timing.
281
 
282
  genvar mask_i;
283
  generate
284
    if(ECC_ENABLE) begin
285
      for (mask_i  = 0; mask_i < (2*DQ_WIDTH)/72;
286
          mask_i = mask_i+1) begin: gen_mask
287
       assign wdf_ecc_mask[((mask_i*9)+9)-1:(mask_i*9)] =
288
                {&wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9],
289
                wdf_mask_data[(mask_i*8)+(7+mask_i):mask_i*9]};
290
      end
291
    end
292
   endgenerate
293
 
294
  generate
295
    if (ECC_ENABLE) begin:gen_ecc_reg
296
       always @(posedge clk90)begin
297
          if(phy_init_data_sel)
298
               wdf_mask_r <= wdf_ecc_mask;
299
          else
300
             wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
301
      end
302
    end else begin
303
      always@(posedge clk90) begin
304
        if (phy_init_data_sel)
305
          wdf_mask_r <= wdf_mask_data;
306
        else
307
          wdf_mask_r <= {(2*DQ_WIDTH/8){1'b0}};
308
      end
309
    end
310
  endgenerate
311
 
312
   always @(posedge clk90) begin
313
      if(phy_init_data_sel)
314
          wdf_data_r <= wdf_data;
315
      else
316
          wdf_data_r <={init_data_f,init_data_r};
317
   end
318
 
319
  // Error generation block during simulation.
320
  // Error will be displayed when all the DM
321
  // bits are not zero. The error will be
322
  // displayed only during the start of the sequence
323
  // for errors that are continous over many cycles.
324
  generate
325
    if (ECC_ENABLE) begin: gen_ecc_error
326
      always @(posedge clk90) begin
327
        //synthesis translate_off
328
        wdf_mask_r1 <= wdf_mask_r;
329
        if(DQ_WIDTH > 72)
330
           ecc_dm_error_r
331
              <= (
332
              (~wdf_mask_r1[35] && (|wdf_mask_r1[34:27])) ||
333
              (~wdf_mask_r1[26] && (|wdf_mask_r1[25:18])) ||
334
              (~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
335
              (~wdf_mask_r1[8] &&  (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
336
         else
337
            ecc_dm_error_r
338
              <= ((~wdf_mask_r1[17] && (|wdf_mask_r1[16:9])) ||
339
              (~wdf_mask_r1[8] &&  (|wdf_mask_r1[7:0]))) && phy_init_data_sel;
340
        ecc_dm_error_r1 <= ecc_dm_error_r ;
341
        if (ecc_dm_error_r && ~ecc_dm_error_r1) // assert the error only once.
342
          $display ("ECC DM ERROR. ");
343
        //synthesis translate_on
344
      end
345
    end
346
  endgenerate
347
 
348
  //***************************************************************************
349
  // State logic to write calibration training patterns
350
  //***************************************************************************
351
 
352
  always @(posedge clk90) begin
353
    if (rst90_r) begin
354
      init_wdf_cnt_r  <= 4'd0;
355
      init_data_r <= {64{1'bx}};
356
      init_data_f <= {64{1'bx}};
357
    end else begin
358
      init_wdf_cnt_r  <= init_wdf_cnt_r + calib_rden_90_r;
359
      casex (init_wdf_cnt_r)
360
        // First stage calibration. Pattern (rise/fall) = 1(r)->0(f)
361
        // The rise data and fall data are already interleaved in the manner
362
        // required for data into the WDF write FIFO
363
        4'b00xx: begin
364
          init_data_r <= {DQ_WIDTH{1'b1}};
365
          init_data_f <= {DQ_WIDTH{1'b0}};
366
        end
367
        // Second stage calibration. Pattern = 1(r)->1(f)->0(r)->0(f)
368
        4'b01x0: begin
369
           init_data_r <= {DQ_WIDTH{1'b1}};
370
           init_data_f <= {DQ_WIDTH{1'b1}};
371
          end
372
        4'b01x1: begin
373
           init_data_r <= {DQ_WIDTH{1'b0}};
374
           init_data_f <= {DQ_WIDTH{1'b0}};
375
        end
376
        // MIG 2.1: Changed Stage 3/4 training pattern
377
        // Third and fourth stage calibration patern = 
378
        //   11(r)->ee(f)->ee(r)->11(f)-11(r)->ee(f)->ee(r)->11(f)
379
        4'b1000: begin
380
          init_data_r <= {DQ_WIDTH/4{4'h1}};
381
          init_data_f <= {DQ_WIDTH/4{4'hE}};
382
        end
383
        4'b1001: begin
384
          init_data_r <= {DQ_WIDTH/4{4'hE}};
385
          init_data_f <= {DQ_WIDTH/4{4'h1}};
386
          end
387
        4'b1010: begin
388
          init_data_r <= {(DQ_WIDTH/4){4'h1}};
389
          init_data_f <= {(DQ_WIDTH/4){4'hE}};
390
        end
391
        4'b1011: begin
392
          init_data_r <= {(DQ_WIDTH/4){4'hE}};
393
          init_data_f <= {(DQ_WIDTH/4){4'h1}};
394
         end
395
        default: begin
396
          init_data_f <= {(2*DQ_WIDTH){1'bx}};
397
          init_data_r <= {(2*DQ_WIDTH){1'bx}};
398
        end
399
      endcase
400
    end
401
  end
402
 
403
  //***************************************************************************
404
 
405
  always @(posedge clk90)
406
    dq_oe_n   <= dq_oe_n_90_r1;
407
 
408
  always @(negedge clk0)
409
    dqs_oe_n  <= dqs_oe_n_180_r1;
410
 
411
  always @(negedge clk0)
412
    dqs_rst_n <= dqs_rst_n_180_r1;
413
 
414
  // generate for odt. odt is asserted based on
415
  //  write latency. For write latency of 2
416
  //  the extra register stage is taken out.
417
  generate
418
    if (ODT_WR_LATENCY > 2) begin
419
      always @(posedge clk0) begin
420
        odt    <= 'b0;
421
        odt[0] <= odt_0;
422
      end
423
    end else begin
424
      always @ (*) begin
425
        odt = 'b0;
426
        odt[0] = odt_0;
427
      end
428
    end
429
  endgenerate
430
 
431
  assign wdf_rden  = wdf_rden_90_r1;
432
 
433
  //***************************************************************************
434
  // Format write data/mask: Data is in format: {fall, rise}
435
  //***************************************************************************
436
 
437
  assign wr_data_rise = wdf_data_r[DQ_WIDTH-1:0];
438
  assign wr_data_fall = wdf_data_r[(2*DQ_WIDTH)-1:DQ_WIDTH];
439
  assign mask_data_rise = wdf_mask_r[MASK_WIDTH-1:0];
440
  assign mask_data_fall = wdf_mask_r[(2*MASK_WIDTH)-1:MASK_WIDTH];
441
 
442
endmodule

powered by: WebSVN 2.1.0

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