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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [boards/] [actel/] [ordb1a3pe1500/] [rtl/] [verilog/] [versatile_mem_ctrl/] [rtl/] [verilog/] [versatile_mem_ctrl_ddr.v] - Blame information for rev 408

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 408 julius
module versatile_mem_ctrl_ddr (
2
  // DDR2 SDRAM side
3
  ck_o, ck_n_o,
4
  dq_io, dqs_io, dqs_n_io,
5
  dm_rdqs_io,
6
  //rdqs_n_i, odt_o, 
7
  // Memory controller side
8
  tx_dat_i, rx_dat_o,
9
  dq_en, dqm_en,
10
  rst, clk_0, clk_90, clk_180, clk_270
11
  );
12
 
13
  output        ck_o;
14
  output        ck_n_o;
15
  inout  [15:0] dq_io;
16
  inout   [1:0] dqs_io;
17
  inout   [1:0] dqs_n_io;
18
  inout   [1:0] dm_rdqs_io;
19
  //input   [1:0] rdqs_n_i;
20
  //output        odt_o;
21
  input  [35:0] tx_dat_i;
22
  output [31:0] rx_dat_o;
23
  input         dq_en;
24
  input         dqm_en;
25
  input         rst;
26
  input         clk_0;
27
  input         clk_90;
28
  input         clk_180;
29
  input         clk_270;
30
 
31
  reg    [31:0] dq_rx_reg;
32
  wire   [31:0] dq_rx;
33
  wire    [1:0] dqs_o, dqs_n_o, dqm_o;
34
  wire   [15:0] dq_o;
35
  wire    [1:0] dqs_delayed, dqs_n_delayed;
36
 
37
  wire   [15:0] dq_iobuf;
38
  wire    [1:0] dqs_iobuf, dqs_n_iobuf;
39
 
40
  genvar        i;
41
 
42
///////////////////////////////////////////////////////////////////////////////
43
// Common for both Xilinx and Altera
44
///////////////////////////////////////////////////////////////////////////////
45
 
46
  // Generate clock with equal delay as data
47
  ddr_ff_out ddr_ff_out_ck (
48
    .Q(ck_o),
49
    .C0(clk_0),
50
    .C1(clk_180),
51
    .CE(1'b1),
52
    .D0(1'b1),
53
    .D1(1'b0),
54
    .R(1'b0),
55
    .S(1'b0));
56
 
57
  ddr_ff_out ddr_ff_out_ck_n (
58
    .Q(ck_n_o),
59
    .C0(clk_0),
60
    .C1(clk_180),
61
    .CE(1'b1),
62
    .D0(1'b0),
63
    .D1(1'b1),
64
    .R(wb_rst),
65
    .S(1'b0));
66
 
67
  // Generate strobe with equal delay as data
68
  generate
69
    for (i=0; i<2; i=i+1) begin:dqs_oddr
70
      ddr_ff_out ddr_ff_out_dqs (
71
        .Q(dqs_o[i]),
72
        .C0(clk_0),
73
        .C1(clk_180),
74
        .CE(1'b1),
75
        .D0(1'b1),
76
        .D1(1'b0),
77
        .R(1'b0),
78
        .S(1'b0));
79
    end
80
  endgenerate
81
 
82
  generate
83
    for (i=0; i<2; i=i+1) begin:dqs_n_oddr
84
      ddr_ff_out ddr_ff_out_dqs_n (
85
        .Q(dqs_n_o[i]),
86
        .C0(clk_0),
87
        .C1(clk_180),
88
        .CE(1'b1),
89
        .D0(1'b0),
90
        .D1(1'b1),
91
        .R(wb_rst),
92
        .S(1'b0));
93
    end
94
  endgenerate
95
 
96
 
97
 
98
///////////////////////////////////////////////////////////////////////////////
99
// Xilinx
100
///////////////////////////////////////////////////////////////////////////////
101
 
102
`ifdef XILINX
103
 
104
  reg  [15:0] dq_tx_reg;
105
  wire [15:0] dq_tx;
106
  reg   [3:0] dqm_tx_reg;
107
  wire  [3:0] dqm_tx;
108
 
109
  // IO BUFFER
110
  // DDR data to/from DDR2 SDRAM
111
  generate
112
    for (i=0; i<16; i=i+1) begin:iobuf_dq
113
      IOBUF u_iobuf_dq (
114
        .I(dq_o[i]),
115
        .T(!dq_en),
116
        .IO(dq_io[i]),
117
        .O(dq_iobuf[i]));
118
    end
119
  endgenerate
120
 
121
  // DQS strobe to/from DDR2 SDRAM
122
  generate
123
    for (i=0; i<2; i=i+1) begin:iobuf_dqs
124
      IOBUF u_iobuf_dqs (
125
        .I(dqs_o[i]),
126
        .T(!dq_en),
127
        .IO(dqs_io[i]),
128
        .O(dqs_iobuf[i]));
129
    end
130
  endgenerate
131
 
132
  // DQS strobe to/from DDR2 SDRAM
133
  generate
134
    for (i=0; i<2; i=i+1) begin:iobuf_dqs_n
135
      IOBUF u_iobuf_dqs_n (
136
        .I(dqs_n_o[i]),
137
        .T(!dq_en),
138
        .IO(dqs_n_io[i]),
139
        .O(dqs_n_iobuf[i]));
140
    end
141
  endgenerate
142
 
143
 
144
  // Data from Tx FIFO
145
  always @ (posedge clk_270 or posedge wb_rst)
146
    if (wb_rst)
147
      dq_tx_reg[15:0] <= 16'h0;
148
    else
149
      if (dqm_en)
150
        dq_tx_reg[15:0] <= tx_dat_i[19:4];
151
      else
152
        dq_tx_reg[15:0] <= tx_dat_i[19:4];
153
 
154
  assign dq_tx[15:0] = tx_dat_i[35:20];
155
 
156
  // Output Data DDR flip-flops
157
  generate
158
    for (i=0; i<16; i=i+1) begin:data_out_oddr
159
      ddr_ff_out ddr_ff_out_inst_0 (
160
        .Q(dq_o[i]),
161
        .C0(clk_270),
162
        .C1(clk_90),
163
        .CE(dq_en),
164
        .D0(dq_tx[i]),
165
        .D1(dq_tx_reg[i]),
166
        .R(wb_rst),
167
        .S(1'b0));
168
    end
169
  endgenerate
170
 
171
  // Data mask from Tx FIFO
172
  always @ (posedge clk_270 or posedge wb_rst)
173
    if (wb_rst)
174
      dqm_tx_reg[1:0] <= 2'b00;
175
    else
176
      if (dqm_en)
177
        dqm_tx_reg[1:0] <= 2'b00;
178
      else
179
        dqm_tx_reg[1:0] <= tx_dat_i[1:0];
180
 
181
  always @ (posedge clk_180 or posedge wb_rst)
182
    if (wb_rst)
183
      dqm_tx_reg[3:2] <= 2'b00;
184
    else
185
      if (dqm_en)
186
        dqm_tx_reg[3:2] <= 2'b00;
187
      else
188
        dqm_tx_reg[3:2] <= tx_dat_i[3:2];
189
 
190
  assign dqm_tx[1:0] = (dqm_en) ? 2'b00 : tx_dat_i[3:2];
191
 
192
  // Mask output DDR flip-flops
193
  generate
194
    for (i=0; i<2; i=i+1) begin:data_mask_oddr
195
      ddr_ff_out ddr_ff_out_inst_1 (
196
        .Q(dqm_o[i]),
197
        .C0(clk_270),
198
        .C1(clk_90),
199
        .CE(dq_en),
200
        .D0(!dqm_tx[i]),
201
        .D1(!dqm_tx_reg[i]),
202
        .R(wb_rst),
203
        .S(1'b0));
204
    end
205
  endgenerate
206
 
207
  // Data mask to DDR2 SDRAM
208
  generate
209
    for (i=0; i<2; i=i+1) begin:iobuf_dqm
210
      IOBUF u_iobuf_dqm (
211
        .I(dqm_o[i]),
212
        .T(!dq_en),
213
        .IO(dm_rdqs_io[i]),
214
        .O());
215
    end
216
  endgenerate
217
 
218
 
219
`ifdef INT_CLOCKED_DATA_CAPTURE
220
  // Data in
221
  // DDR flip-flops
222
  generate
223
    for (i=0; i<16; i=i+1) begin:iddr2gen
224
      ddr_ff_in ddr_ff_in_inst_0 (
225
        .Q0(dq_rx[i]),
226
        .Q1(dq_rx[i+16]),
227
        .C0(clk_270),
228
        .C1(clk_90),
229
        .CE(1'b1),
230
        .D(dq_io[i]),
231
        .R(wb_rst),
232
        .S(1'b0));
233
    end
234
  endgenerate
235
 
236
  // Data to Rx FIFO
237
  always @ (posedge clk_0 or posedge wb_rst)
238
    if (wb_rst)
239
      dq_rx_reg[31:16] <= 16'h0;
240
    else
241
      dq_rx_reg[31:16] <= dq_rx[31:16];
242
 
243
  always @ (posedge clk_180 or posedge wb_rst)
244
    if (wb_rst)
245
      dq_rx_reg[15:0] <= 16'h0;
246
    else
247
      dq_rx_reg[15:0] <= dq_rx[15:0];
248
 
249
  assign rx_dat_o = dq_rx_reg;
250
`endif   // INT_CLOCKED_DATA_CAPTURE
251
 
252
 
253
`ifdef DEL_DQS_DATA_CAPTURE_1
254
 
255
  wire  [1:0] dqs_iodelay, dqs_n_iodelay;
256
 
257
  // Delay DQS
258
  assign # 2 dqs_iodelay   = dqs_iobuf;
259
  assign # 2 dqs_n_iodelay = dqs_n_iobuf;
260
 
261
  // IDDR FF
262
  generate
263
    for (i=0; i<16; i=i+1) begin:iddr_dq
264
      ddr_ff_in ddr_ff_in_inst_0 (
265
        .Q0(dq_rx[i]),
266
        .Q1(dq_rx[i+16]),
267
        .C0(dqs_iodelay[0]),
268
        .C1(dqs_n_iodelay[0]),
269
        .CE(1'b1),
270
        .D(dq_iobuf[i]),
271
        .R(wb_rst),
272
        .S(1'b0));
273
    end
274
  endgenerate
275
 
276
  // Data to Rx FIFO
277
  always @ (posedge clk_0 or posedge wb_rst)
278
    if (wb_rst)
279
      dq_rx_reg[31:16] <= 16'h0;
280
    else
281
      dq_rx_reg[31:16] <= dq_rx[31:16];
282
 
283
  always @ (posedge clk_0 or posedge wb_rst)
284
    if (wb_rst)
285
      dq_rx_reg[15:0] <= 16'h0;
286
    else
287
      dq_rx_reg[15:0] <= dq_rx[15:0];
288
 
289
  assign rx_dat_o = dq_rx_reg;
290
 
291
`endif   // DEL_DQS_DATA_CAPTURE_1
292
 
293
 
294
`ifdef DEL_DQS_DATA_CAPTURE_2
295
 
296
  wire [15:0] dq_iodelay;
297
  wire  [1:0] dqs_iodelay, dqs_n_iodelay;
298
  wire [15:0] dq_iddr_fall, dq_iddr_rise;
299
  reg  [15:0] dq_fall_1, dq_rise_1;
300
  reg  [15:0] dq_fall_2, dq_rise_2;
301
  reg  [15:0] dq_fall_3, dq_rise_3;
302
 
303
 
304
  // Delay data
305
  // IODELAY is available in the Xilinx Virtex FPGAs
306
  /*IODELAY # (
307
    .DELAY_SRC(),
308
    .IDELAY_TYPE(),
309
    .HIGH_PERFORMANCE_MODE(),
310
    .IDELAY_VALUE(),
311
    .ODELAY_VALUE())
312
   u_idelay_dq (
313
      .DATAOUT(),
314
      .C(),
315
      .CE(),
316
      .DATAIN(),
317
      .IDATAIN(),
318
      .INC(),
319
      .ODATAIN(),
320
      .RST(),
321
      .T());*/
322
  // IODELAY is NOT available in the Xilinx Spartan FPGAs, 
323
  // equivalent delay can be implemented using a chain of LUT
324
  /*lut_delay lut_delay_dq (
325
    .clk_i(),
326
    .d_i(dq_iobuf),
327
    .d_o(dq_iodelay));*/
328
 
329
  // IDDR FF
330
  generate
331
    for (i=0; i<16; i=i+1) begin:iddr_dq
332
      ddr_ff_in ddr_ff_in_inst_0 (
333
        .Q0(dq_iddr_fall[i]),
334
        .Q1(dq_iddr_rise[i]),
335
        .C0(dqs_iodelay[0]),
336
        .C1(dqs_n_iodelay[0]),
337
        .CE(1'b1),
338
        .D(dq_iobuf[i]),
339
        .R(wb_rst),
340
        .S(1'b0));
341
    end
342
  endgenerate
343
 
344
  // Rise & fall clocked FF
345
  always @ (posedge clk_0 or posedge wb_rst)
346
    if (wb_rst) begin
347
      dq_fall_1 <= 16'h0;
348
      dq_rise_1 <= 16'h0;
349
    end else begin
350
      dq_fall_1 <= dq_iddr_fall;
351
      dq_rise_1 <= dq_iddr_rise;
352
    end
353
 
354
  always @ (posedge clk_180 or posedge wb_rst)
355
    if (wb_rst) begin
356
      dq_fall_2 <= 16'h0;
357
      dq_rise_2 <= 16'h0;
358
    end else begin
359
      dq_fall_2 <= dq_iddr_fall;
360
      dq_rise_2 <= dq_iddr_rise;
361
    end
362
 
363
  // Fall sync FF
364
  always @ (posedge clk_0 or posedge wb_rst)
365
    if (wb_rst) begin
366
      dq_fall_3 <= 16'h0;
367
      dq_rise_3 <= 16'h0;
368
    end else begin
369
      dq_fall_3 <= dq_fall_2;
370
      dq_rise_3 <= dq_rise_2;
371
    end
372
 
373
  // Mux
374
  assign rx_dat_o[31:16] = dq_fall_1;
375
  assign rx_dat_o[15:0]  = dq_rise_1;
376
 
377
  // DDR DQS to IODUFDS
378
  // Delay DQS
379
  // IODELAY is NOT available in the Xilinx Spartan FPGAs, 
380
  // equivalent delay can be implemented using a chain of LUTs
381
/*
382
  generate
383
    for (i=0; i<2; i=i+1) begin:lut_delay_dqs
384
      lut_delay lut_delay_dqs (
385
        .d_i(dqs_iobuf[i]),
386
        .d_o(dqs_iodelay[i]));
387
    end
388
  endgenerate
389
  generate
390
    for (i=0; i<2; i=i+1) begin:lut_delay_dqs_n
391
      lut_delay lut_delay_dqs_n (
392
        .d_i(dqs_n_iobuf[i]),
393
        .d_o(dqs_n_iodelay[i]));
394
    end
395
  endgenerate
396
*/
397
 
398
  assign # 2 dqs_iodelay   = dqs_iobuf;
399
  assign # 2 dqs_n_iodelay = dqs_n_iobuf;
400
 
401
 
402
  // BUFIO (?)
403
`endif   // DEL_DQS_DATA_CAPTURE_2
404
 
405
`endif   // XILINX
406
 
407
 
408
///////////////////////////////////////////////////////////////////////////////
409
// Altera
410
///////////////////////////////////////////////////////////////////////////////
411
 
412
`ifdef ALTERA
413
 
414
  wire  [3:0] dqm_tx;
415
 
416
  // Data out
417
  // DDR flip-flops
418
  generate
419
    for (i=0; i<16; i=i+1) begin:data_out_oddr
420
      ddr_ff_out ddr_ff_out_inst_0 (
421
        .Q(dq_o[i]),
422
        .C0(clk_270),
423
        .C1(clk_90),
424
        .CE(dq_en),
425
        .D0(tx_dat_i[i+16+4]),
426
        .D1(tx_dat_i[i+4]),
427
        .R(wb_rst),
428
        .S(1'b0));
429
    end
430
  endgenerate
431
 
432
  // Assign outport
433
  assign dq_io = dq_en ? dq_o : {16{1'bz}};
434
 
435
  // Data mask
436
  // Data mask from Tx FIFO
437
  assign dqm_tx = dqm_en ? {4{1'b0}} : tx_dat_i[3:0];
438
 
439
  // DDR flip-flops
440
  generate
441
    for (i=0; i<2; i=i+1) begin:data_mask_oddr
442
      ddr_ff_out ddr_ff_out_inst_1 (
443
        .Q(dqm_o[i]),
444
        .C0(clk_270),
445
        .C1(clk_90),
446
        .CE(dq_en),
447
        .D0(!dqm_tx[i+2]),
448
        .D1(!dqm_tx[i]),
449
        .R(wb_rst),
450
        .S(1'b0));
451
    end
452
  endgenerate
453
 
454
  // Assign outport
455
  assign dm_rdqs_io = dq_en ? dqm_o : 2'bzz;
456
 
457
 
458
  // Data in
459
`ifdef INT_CLOCKED_DATA_CAPTURE
460
  // DDR flip-flops
461
  generate
462
    for (i=0; i<16; i=i+1) begin:iddr2gen
463
      ddr_ff_in ddr_ff_in_inst_0 (
464
        .Q0(dq_rx[i]),
465
        .Q1(dq_rx[i+16]),
466
        .C0(clk_270),
467
        .C1(clk_90),
468
        .CE(1'b1),
469
        .D(dq_io[i]),
470
        .R(wb_rst),
471
        .S(1'b0));
472
    end
473
  endgenerate
474
 
475
  // Data to Rx FIFO
476
  always @ (posedge clk_180 or posedge wb_rst)
477
    if (wb_rst)
478
      dq_rx_reg <= 32'h0;
479
    else
480
      dq_rx_reg <= dq_rx;
481
 
482
  assign rx_dat_o = dq_rx_reg;
483
`endif   // INT_CLOCKED_DATA_CAPTURE
484
 
485
`ifdef DEL_DQS_DATA_CAPTURE_1
486
   // Delay DQS
487
   // DDR FF
488
`endif   // DEL_DQS_DATA_CAPTURE_1
489
 
490
`ifdef DEL_DQS_DATA_CAPTURE_2
491
   // DDR data to IOBUFFER
492
   // Delay data (?)
493
   // DDR FF
494
   // Rise & fall clocked FF
495
   // Fall sync FF
496
   // Mux
497
   // DDR DQS to IODUFDS
498
   // Delay DQS
499
   // BUFIO (?)
500
`endif   // DEL_DQS_DATA_CAPTURE_2
501
 
502
`endif   // ALTERA
503
 
504
 
505
endmodule   // versatile_mem_ctrl_ddr
506
 
507
 

powered by: WebSVN 2.1.0

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