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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 412 julius
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  Xilinx DDR2 controller Wishbone Interface                   ////
4
////                                                              ////
5
////  Description                                                 ////
6
////  Simple interface to the Xilinx MIG generated DDR2 controller////
7
////                                                              ////
8
////  To Do:                                                      ////
9
////   Increase usage of cache BRAM to maximum (currently only    ////
10
////   256 bytes out of about 8192)                               ////
11
////   Make this a Wishbone B3 registered feedback burst friendly ////
12
////   server.                                                    ////
13
////                                                              ////
14
////  Author(s):                                                  ////
15
////      - Julius Baxter, julius.baxter@orsoc.se                 ////
16
////                                                              ////
17
////                                                              ////
18
//////////////////////////////////////////////////////////////////////
19
////                                                              ////
20
//// Copyright (C) 2010 Authors and OPENCORES.ORG                 ////
21
////                                                              ////
22
//// This source file may be used and distributed without         ////
23
//// restriction provided that this copyright statement is not    ////
24
//// removed from the file and that any derivative work contains  ////
25
//// the original copyright notice and the associated disclaimer. ////
26
////                                                              ////
27
//// This source file is free software; you can redistribute it   ////
28
//// and/or modify it under the terms of the GNU Lesser General   ////
29
//// Public License as published by the Free Software Foundation; ////
30
//// either version 2.1 of the License, or (at your option) any   ////
31
//// later version.                                               ////
32
////                                                              ////
33
//// This source is distributed in the hope that it will be       ////
34
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
35
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
36
//// PURPOSE.  See the GNU Lesser General Public License for more ////
37
//// details.                                                     ////
38
////                                                              ////
39
//// You should have received a copy of the GNU Lesser General    ////
40
//// Public License along with this source; if not, download it   ////
41
//// from http://www.opencores.org/lgpl.shtml                     ////
42
////                                                              ////
43
//////////////////////////////////////////////////////////////////////
44
/*
45
 * The controller is design to stream lots of data out at the DDR2 controller's
46
 * rate. All we implement here is enough to do the simplest accesses into a
47
 * small cache, which eases the domain crossing headaches.
48
 *
49
 * This was originally written to handle a DDR2 part which is doing burst length
50
 * of 4 as a minimum via a databus which is 64-bits wide.
51
 *
52
 * This means the smallest accesses is 4*64=256-bits or 32-bytes.
53
 *
54
 * We are bridging to a 32-bit wide system bus, so this means we must handle
55
 * accesses in 8-word lots.
56
 *
57
 * A simple cache mechanism has been implemented, meaning we check if the cached
58
 * data has been written to, and therefore needs writing back to the main memory
59
 * before any other access can occur.
60
 *
61
 * Cache memory:
62
 * The cache memory is a core-generated module, instantiating something out
63
 * of the XilinxCoreLib. The reason is because an arrangement or RAMB36s with
64
 * different sized A and B data in/out ports can't be instantiated directly
65
 * for some reason.
66
 * What we have is side A with 32-bits, and side B with 128-bits wide.
67
 *
68
 * TODO:
69
 * This only supports 8-words for now but can easily be expanded, although
70
 * multiple way/associativity caching will require some extra work to handle
71
 * multiple cached addresses.
72
 *
73
 * But it should be easy enough to make this thing cache as much as its RAMB
74
 * resources allow (4-RAMB16s becuase due to the 128-bit DDR2-side interface)
75
 * which is about 8Kbyte.
76
 *
77
 * Multi-cycle paths:
78
 * Write:
79
 * To indicate that a writeback is occuring, a system-bus domain (wishbone, in
80
 * this case) signal is set, and then sampled in the controller domain whenever
81
 * a system-bus domain clock edge is detected. This register is "do_writeback"
82
 * and then the controller domain register "ddr2_write_done" is asserted when
83
 * the data has been written out of the RAMs and into the controller's fifos.
84
 * "ddr2_write_done" is then sampled by the system-bus domain and "do_writeback"
85
 * So there are paths between:
86
 * ( register -> (sampled by) -> register )
87
 * wb_clk:do_writeback -> ddr2_clk:do_writeback_ddr2_shifter
88
 * wb_clk:do_writeback -> ddr2_clk:ddr2_write_done
89
 * ddr2_clk:ddr2_write_done -> wb_clk:do_writeback
90
 *
91
 * Read:
92
 * The only signal crossing we have here is the one indicating the read data
93
 * has arrived into the cache RAM from the controller. The controller domain
94
 * register "ddr2_read_done" is set, and sampled in the system-bus domain by the
95
 * logic controlling the "do_readfrom" register. "ddr2_read_done" is cleared
96
 * when the controller domain sees that "do_readfrom" has been de-asserted.
97
 * So there are paths between:
98
 * ( register -> (sampled by) -> register )
99
 * ddr2_clk:ddr2_read_done -> wb_clk:do_readfrom
100
 * wb_clk:do_readfrom -> ddr2_clk:ddr2_read_done
101
 *
102
 */
103
module xilinx_ddr2_if (
104
    input [31:0]       wb_adr_i,
105
    input              wb_stb_i,
106
    input              wb_cyc_i,
107
    input              wb_we_i,
108
    input [3:0]        wb_sel_i,
109
    input [31:0]       wb_dat_i,
110
    output [31:0]      wb_dat_o,
111
    output reg         wb_ack_o,
112
 
113
    output [12:0]      ddr2_a,
114
    output [1:0]       ddr2_ba,
115
    output             ddr2_ras_n,
116
    output             ddr2_cas_n,
117
    output             ddr2_we_n,
118
    output [1:0]       ddr2_cs_n,
119
    output [1:0]       ddr2_odt,
120
    output [1:0]       ddr2_cke,
121
    output [7:0]       ddr2_dm,
122
 
123
    inout [63:0]       ddr2_dq,
124
    inout [7:0]        ddr2_dqs,
125
    inout [7:0]        ddr2_dqs_n,
126
    output [1:0]       ddr2_ck,
127
    output [1:0]       ddr2_ck_n,
128
 
129
    input              ddr2_if_clk,
130
    input              ddr2_if_rst,
131
    input              idly_clk_200,
132
    input              wb_clk,
133
    input              wb_rst);
134
 
135
`include "xilinx_ddr2_params.v"
136
 
137
   wire                ddr2_clk; // DDR2 iface domain clock.
138
   wire                ddr2_rst; // reset from the ddr2 module
139
 
140
   wire                wb_req;
141
   reg                 wb_req_r;
142
   reg                 wb_ack_o_r;
143
 
144
   wire                wb_req_new;
145
   reg                 wb_req_new_r;
146
 
147
   reg                 wb_req_addr_hit;
148
 
149
   reg                 cached_addr_valid;
150
 
151
   reg [31:6]          cached_addr;
152
 
153
   wire                cache_hit;
154
 
155
   reg                 cache_dirty;
156
 
157
   reg [2:0]            wb_req_cache_word_addr;
158
 
159
   wire                wb_cache_en;
160
 
161
   reg                 do_writeback, do_writeback_r;
162
   wire                do_writeback_start, do_writeback_finished;
163
   wire                doing_writeback;
164
 
165
   reg                 do_readfrom, do_readfrom_r;
166
   wire                do_readfrom_start, do_readfrom_finished;
167
   wire                doing_readfrom;
168
 
169
 
170
   // Domain crossing logic
171
   reg                 wb_clk_r;
172
   reg                 wb_clk_in_ddr2_clk;
173
 
174
   reg                 wb_clk_in_ddr2_clk_r;
175
   wire                wb_clk_edge;
176
   reg [2:0]            ddr2_clk_phase;
177
   // Sample when clk phase is 0
178
   reg [7:0]            do_writeback_ddr2_shifter;
179
   reg [7:0]            do_writeback_ddr2_shifter_r;
180
   reg                 do_writeback_ddr2_fifo_we;
181
   reg                 ddr2_write_done;
182
 
183
   // Currently, ddr2-side of cache is address is a single bit
184
   reg [1:0]            ddr2_cache_addr;
185
   wire [127:0]        ddr2_cache_data_o;
186
   reg                 rd_data_valid_r;
187
   reg                 ddr2_read_done;
188
 
189
   // DDR2 MIG interface wires
190
   wire                app_af_afull;
191
   wire                app_wdf_afull;
192
   wire                app_wdf_wren;
193
   wire                app_af_wren;
194
   wire [30:0]          app_af_addr;
195
   wire [2:0]           app_af_cmd;
196
   wire [(APPDATA_WIDTH)-1:0] app_wdf_data;
197
   wire [(APPDATA_WIDTH/8)-1:0] app_wdf_mask_data;
198
   wire                         rd_data_valid;
199
   wire [(APPDATA_WIDTH)-1:0]    rd_data_fifo_out;
200
   wire                         phy_init_done;
201
 
202
 
203
   assign cache_hit = (cached_addr ==  wb_adr_i[31:6]) & cached_addr_valid;
204
 
205
   // Wishbone request detection
206
   assign wb_req = wb_stb_i & wb_cyc_i & phy_init_done;
207
 
208
   always @(posedge wb_clk)
209
     wb_req_r <= wb_req;
210
 
211
   assign wb_req_new = wb_req & !wb_req_r;
212
 
213
   always @(posedge wb_clk)
214
     wb_req_new_r <= wb_req_new;
215
 
216
   // Register whether it's a hit or not
217
   // As more lines are added, add them to this check.
218
   always @(posedge wb_clk)
219
     if (wb_rst)
220
       wb_req_addr_hit <= 0;
221
     else
222
       wb_req_addr_hit <= wb_req & cache_hit & cached_addr_valid;
223
 
224
   always @(posedge wb_clk)
225
     if (wb_rst)
226
       wb_ack_o <= 0;
227
     else
228
       wb_ack_o <= wb_req_addr_hit & !wb_ack_o & !wb_ack_o_r;
229
 
230
   always @(posedge wb_clk)
231
     wb_ack_o_r <= wb_ack_o;
232
 
233
   // Address valid logic
234
   always @(posedge wb_clk)
235
     if (wb_rst)
236
       cached_addr_valid <= 0;
237
     else if (do_readfrom_finished)
238
       cached_addr_valid <= 1;
239
     else if ( do_writeback_finished ) // Data written back, cache not valid
240
       cached_addr_valid <= 0;
241
     else if (wb_req & !cache_hit & cached_addr_valid & !cache_dirty)
242
       // Invalidate cache so a readfrom begins
243
       cached_addr_valid <= 0;
244
 
245
   // Address cacheing
246
   always @(posedge wb_clk)
247
     if (wb_rst)
248
       cached_addr <= 0;
249
     else if (do_readfrom_start)
250
       cached_addr <= wb_adr_i[31:6];
251
 
252
   // Cache dirty signal
253
   always @(posedge wb_clk)
254
     if (wb_rst)
255
       cache_dirty <= 0;
256
     else if (wb_req & wb_we_i & wb_req_addr_hit & wb_ack_o)
257
       cache_dirty <= 1;
258
     else if (!cached_addr_valid & cache_dirty)
259
       cache_dirty <= 0;
260
 
261
   // Wishbone side of cache enable. Important!
262
   // 1. Enable on first access, if it's not a write
263
   // 2. Enable if we've just refreshed the cache
264
   // 3. Enable on ACK'ing for a write
265
   assign wb_cache_en = (wb_req_new & !wb_we_i) | do_readfrom_finished |
266
                        (wb_req_addr_hit & wb_stb_i & !wb_we_i & !wb_ack_o) |
267
                        (wb_ack_o & wb_we_i);
268
 
269
   // Writeback detect logic
270
   always @(posedge wb_clk)
271
     if (wb_rst)
272
       do_writeback <= 0;
273
     else if (ddr2_write_done) // DDR2 domain signal
274
       do_writeback <= 0;
275
     else if (wb_req & !cache_hit & cached_addr_valid & !doing_writeback & cache_dirty)
276
       do_writeback <= 1;
277
 
278
 
279
   always @(posedge wb_clk)
280
     do_writeback_r <= do_writeback;
281
 
282
   assign do_writeback_start = do_writeback & !do_writeback_r;
283
   assign do_writeback_finished = !do_writeback & do_writeback_r;
284
   assign doing_writeback = do_writeback | do_writeback_r;
285
 
286
   // DDR2 Read detect logic
287
   always @(posedge wb_clk)
288
     if (wb_rst)
289
       do_readfrom <= 0;
290
     else if (ddr2_read_done) // DDR2 domain signal
291
       do_readfrom <= 0;
292
     else if (wb_req & !cache_hit & !cached_addr_valid & !doing_readfrom & !cache_dirty)
293
       do_readfrom <= 1;
294
 
295
   always @(posedge wb_clk)
296
     do_readfrom_r <= do_readfrom;
297
 
298
   assign do_readfrom_start = do_readfrom & !do_readfrom_r;
299
   assign do_readfrom_finished = !do_readfrom & do_readfrom_r;
300
   assign doing_readfrom = do_readfrom | do_readfrom_r;
301
 
302
   // Address fifo signals
303
   assign app_af_wren = (do_writeback_finished | do_readfrom_start);
304
   assign app_af_cmd[0] = do_readfrom_start; // 1 - read, 0 - write
305
   assign app_af_cmd[2:1] = 0;
306
   assign app_af_addr = do_readfrom_start ?  {2'd0, wb_adr_i[31:6],3'd0} :
307
                        {2'd0,cached_addr,3'd0};
308
 
309
   assign app_wdf_wren = do_writeback_ddr2_fifo_we;
310
   assign app_wdf_data = ddr2_cache_data_o;
311
   assign app_wdf_mask_data = 0;
312
 
313
   always @(posedge wb_clk) if (wb_rst) wb_clk_r <= 0; else wb_clk_r <= ~wb_clk_r;
314
   always @(posedge ddr2_clk) wb_clk_in_ddr2_clk <= wb_clk_r;
315
   always @(posedge ddr2_clk) wb_clk_in_ddr2_clk_r <= wb_clk_in_ddr2_clk;
316
 
317
   assign wb_clk_edge = wb_clk_in_ddr2_clk & !wb_clk_in_ddr2_clk_r;
318
 
319
   always @(posedge ddr2_clk)
320
     if (ddr2_rst)
321
       ddr2_clk_phase <= 0;
322
     else if (wb_clk_edge)
323
       ddr2_clk_phase <= 0;
324
     else
325
       ddr2_clk_phase <= ddr2_clk_phase + 1;
326
 
327
   always @(posedge ddr2_clk)
328
     do_writeback_ddr2_fifo_we <= (do_writeback_ddr2_shifter_r[0]) |
329
                                  (do_writeback_ddr2_shifter_r[2]) |
330
                                  (do_writeback_ddr2_shifter_r[4]) |
331
                                  (do_writeback_ddr2_shifter_r[6]);
332
 
333
   // Kick off counting when we see that the wb_clk domain is
334
   // doing a writeback.
335
   always @(posedge ddr2_clk)
336
     if (ddr2_rst)
337
       do_writeback_ddr2_shifter <= 4'h0;
338
     else if  (|do_writeback_ddr2_shifter)
339
       do_writeback_ddr2_shifter <= {do_writeback_ddr2_shifter[6:0], 1'b0};
340
     else if (!(|ddr2_clk_phase) & do_writeback & !ddr2_write_done) // sample WB domain
341
       do_writeback_ddr2_shifter <= 1;
342
 
343
 
344
 
345
   always @(posedge ddr2_clk)
346
     do_writeback_ddr2_shifter_r <= do_writeback_ddr2_shifter;
347
 
348
   always @(posedge ddr2_clk)
349
     if (ddr2_rst)
350
       ddr2_write_done <= 0;
351
     else if (do_writeback_ddr2_shifter[7])
352
       ddr2_write_done <= 1;
353
     else if ((!(|ddr2_clk_phase)) & !do_writeback) // sample WB domain
354
       ddr2_write_done <= 0;
355
 
356
   always @(posedge ddr2_clk)
357
     if (ddr2_rst)
358
       ddr2_cache_addr <= 0;
359
     else if (rd_data_valid | do_writeback_ddr2_fifo_we)
360
       ddr2_cache_addr <= ddr2_cache_addr + 1;
361
 
362
   always @(posedge ddr2_clk)
363
     rd_data_valid_r <= rd_data_valid;
364
 
365
   // Read done signaling to WB domain
366
   always @(posedge ddr2_clk)
367
     if (ddr2_rst)
368
       ddr2_read_done <= 0;
369
     else if (!rd_data_valid & rd_data_valid_r) // Detect read data valid falling edge
370
       ddr2_read_done <= 1;
371
     else if (!(|ddr2_clk_phase) & !do_readfrom) // Read WB domain
372
       ddr2_read_done <= 0;
373
 
374
   wire [3:0]                    wb_cache_adr;
375
   assign wb_cache_adr = wb_adr_i[5:2];
376
   wire [3:0]                    wb_cache_sel_we;
377
   assign wb_cache_sel_we = {4{wb_we_i}} & wb_sel_i;
378
   wire                         ddr2_cache_en;
379
   wire [15:0]                   ddr2_cache_we;
380
   assign ddr2_cache_en = rd_data_valid | (|do_writeback_ddr2_shifter);
381
   assign ddr2_cache_we = {16{rd_data_valid}};
382
 
383
 
384
   // Xilinx Coregen true dual-port RAMB array.
385
   // Wishbone side : 32-bit
386
   // DDR2 side : 128-bit
387
   xilinx_ddr2_if_cache cache_mem0
388
     (
389
      // Wishbone side
390
      .clka(wb_clk),
391
      .ena(wb_cache_en),
392
      .wea(wb_cache_sel_we),
393
      .addra({8'd0,wb_cache_adr}),
394
      .dina(wb_dat_i),
395
      .douta(wb_dat_o),
396
 
397
      // DDR2 controller side
398
      .clkb(ddr2_clk),
399
      .enb(ddr2_cache_en),
400
      .web(ddr2_cache_we),
401
      .addrb({8'd0,ddr2_cache_addr}),
402
      .dinb(rd_data_fifo_out),
403
      .doutb(ddr2_cache_data_o));
404
 
405
   ddr2_mig #
406
     (
407
      .BANK_WIDTH            (BANK_WIDTH),
408
      .CKE_WIDTH             (CKE_WIDTH),
409
      .CLK_WIDTH             (CLK_WIDTH),
410
      .COL_WIDTH             (COL_WIDTH),
411
      .CS_NUM                (CS_NUM),
412
      .CS_WIDTH              (CS_WIDTH),
413
      .CS_BITS               (CS_BITS),
414
      .DM_WIDTH              (DM_WIDTH),
415
      .DQ_WIDTH              (DQ_WIDTH),
416
      .DQ_PER_DQS            (DQ_PER_DQS),
417
      .DQ_BITS               (DQ_BITS),
418
      .DQS_WIDTH             (DQS_WIDTH),
419
      .DQS_BITS              (DQS_BITS),
420
      .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
421
      .ODT_WIDTH             (ODT_WIDTH),
422
      .ROW_WIDTH             (ROW_WIDTH),
423
      .APPDATA_WIDTH         (APPDATA_WIDTH),
424
      .ADDITIVE_LAT          (ADDITIVE_LAT),
425
      .BURST_LEN             (BURST_LEN),
426
      .BURST_TYPE            (BURST_TYPE),
427
      .CAS_LAT               (CAS_LAT),
428
      .ECC_ENABLE            (ECC_ENABLE),
429
      .MULTI_BANK_EN         (MULTI_BANK_EN),
430
      .ODT_TYPE              (ODT_TYPE),
431
      .REDUCE_DRV            (REDUCE_DRV),
432
      .REG_ENABLE            (REG_ENABLE),
433
      .TREFI_NS              (TREFI_NS),
434
      .TRAS                  (TRAS),
435
      .TRCD                  (TRCD),
436
      .TRFC                  (TRFC),
437
      .TRP                   (TRP),
438
      .TRTP                  (TRTP),
439
      .TWR                   (TWR),
440
      .TWTR                  (TWTR),
441
      .SIM_ONLY              (SIM_ONLY),
442
      .RST_ACT_LOW           (RST_ACT_LOW),
443
      .CLK_TYPE              (CLK_TYPE),
444
      .DLL_FREQ_MODE         (DLL_FREQ_MODE),
445
      .CLK_PERIOD            (CLK_PERIOD)
446
      )
447
   ddr2_mig0
448
     (
449
      .sys_clk           (ddr2_if_clk),
450
      .idly_clk_200      (idly_clk_200),
451
      .sys_rst_n         (ddr2_if_rst), // Act. high, sync. to ddr2_if_clk
452
      .ddr2_ras_n        (ddr2_ras_n),
453
      .ddr2_cas_n        (ddr2_cas_n),
454
      .ddr2_we_n         (ddr2_we_n),
455
      .ddr2_cs_n         (ddr2_cs_n),
456
      .ddr2_cke          (ddr2_cke),
457
      .ddr2_odt          (ddr2_odt),
458
      .ddr2_dm           (ddr2_dm),
459
      .ddr2_dq           (ddr2_dq),
460
      .ddr2_dqs          (ddr2_dqs),
461
      .ddr2_dqs_n        (ddr2_dqs_n),
462
      .ddr2_ck           (ddr2_ck),
463
      .ddr2_ck_n         (ddr2_ck_n),
464
      .ddr2_ba           (ddr2_ba),
465
      .ddr2_a            (ddr2_a),
466
 
467
      .clk0_tb           (ddr2_clk),
468
      .rst0_tb           (ddr2_rst),
469
      .usr_clk           (wb_clk),
470
      .app_af_afull      (app_af_afull),
471
      .app_wdf_afull     (app_wdf_afull),
472
      .rd_data_valid     (rd_data_valid),
473
      .rd_data_fifo_out  (rd_data_fifo_out),
474
      .app_af_wren       (app_af_wren),
475
      .app_af_cmd        (app_af_cmd),
476
      .app_af_addr       (app_af_addr),
477
      .app_wdf_wren      (app_wdf_wren),
478
      .app_wdf_data      (app_wdf_data),
479
      .app_wdf_mask_data (app_wdf_mask_data),
480
      .phy_init_done     (phy_init_done)
481
      );
482
 
483
 
484
endmodule // ml501_ddr2_if
485
// Local Variables:
486
// verilog-library-directories:("." "ddr2_mig")
487
// verilog-library-extensions:(".v" ".h")
488
// End:

powered by: WebSVN 2.1.0

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