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

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [examples/] [memfifo/] [fpga-2.18/] [memfifo.srcs/] [sources_1/] [ip/] [mig_7series_0/] [mig_7series_0/] [user_design/] [rtl/] [controller/] [mig_7series_v2_3_col_mach.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ZTEX
//*****************************************************************************
2
// (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
3
//
4
// This file contains confidential and proprietary information
5
// of Xilinx, Inc. and is protected under U.S. and
6
// international copyright and other intellectual property
7
// laws.
8
//
9
// DISCLAIMER
10
// This disclaimer is not a license and does not grant any
11
// rights to the materials distributed herewith. Except as
12
// otherwise provided in a valid license issued to you by
13
// Xilinx, and to the maximum extent permitted by applicable
14
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
15
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
16
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
17
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
18
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
19
// (2) Xilinx shall not be liable (whether in contract or tort,
20
// including negligence, or under any other theory of
21
// liability) for any loss or damage of any kind or nature
22
// related to, arising under or in connection with these
23
// materials, including for any direct, or any indirect,
24
// special, incidental, or consequential loss or damage
25
// (including loss of data, profits, goodwill, or any type of
26
// loss or damage suffered as a result of any action brought
27
// by a third party) even if such damage or loss was
28
// reasonably foreseeable or Xilinx had been advised of the
29
// possibility of the same.
30
//
31
// CRITICAL APPLICATIONS
32
// Xilinx products are not designed or intended to be fail-
33
// safe, or for use in any application requiring fail-safe
34
// performance, such as life-support or safety devices or
35
// systems, Class III medical devices, nuclear facilities,
36
// applications related to the deployment of airbags, or any
37
// other applications that could lead to death, personal
38
// injury, or severe property or environmental damage
39
// (individually and collectively, "Critical
40
// Applications"). Customer assumes the sole risk and
41
// liability of any use of Xilinx products in Critical
42
// Applications, subject only to applicable laws and
43
// regulations governing limitations on product liability.
44
//
45
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
46
// PART OF THIS FILE AT ALL TIMES.
47
//
48
//*****************************************************************************
49
//   ____  ____
50
//  /   /\/   /
51
// /___/  \  /    Vendor                : Xilinx
52
// \   \   \/     Version               : %version
53
//  \   \         Application           : MIG
54
//  /   /         Filename              : col_mach.v
55
// /___/   /\     Date Last Modified    : $date$
56
// \   \  /  \    Date Created          : Tue Jun 30 2009
57
//  \___\/\___\
58
//
59
//Device            : 7-Series
60
//Design Name       : DDR3 SDRAM
61
//Purpose           :
62
//Reference         :
63
//Revision History  :
64
//*****************************************************************************
65
 
66
// The column machine manages the dq bus.  Since there is a single DQ
67
// bus, and the column part of the DRAM is tightly coupled to this DQ
68
// bus, conceptually, the DQ bus and all of the column hardware in
69
// a multi rank DRAM array are managed as a single unit.
70
//
71
//
72
// The column machine does not "enforce" the column timing directly.
73
// It generates information and sends it to the bank machines.  If the
74
// bank machines incorrectly make a request, the column machine will
75
// simply overwrite the existing request with the new request even
76
// if this would result in a timing or protocol violation.
77
//
78
// The column machine
79
// hosts the block that controls read and write data transfer
80
// to and from the dq bus.
81
//
82
// And if configured, there is provision for tracking the address
83
// of a command as it moves through the column pipeline.  This
84
// address will be logged for detected ECC errors.
85
 
86
`timescale 1 ps / 1 ps
87
 
88
module mig_7series_v2_3_col_mach #
89
  (
90
   parameter TCQ = 100,
91
   parameter BANK_WIDTH               = 3,
92
   parameter BURST_MODE               = "8",
93
   parameter COL_WIDTH                = 12,
94
   parameter CS_WIDTH                 = 4,
95
   parameter DATA_BUF_ADDR_WIDTH      = 8,
96
   parameter DATA_BUF_OFFSET_WIDTH    = 1,
97
   parameter DELAY_WR_DATA_CNTRL      = 0,
98
   parameter DQS_WIDTH                = 8,
99
   parameter DRAM_TYPE                = "DDR3",
100
   parameter EARLY_WR_DATA_ADDR       = "OFF",
101
   parameter ECC                      = "OFF",
102
   parameter MC_ERR_ADDR_WIDTH        = 31,
103
   parameter nCK_PER_CLK              = 2,
104
   parameter nPHY_WRLAT               = 0,
105
   parameter RANK_WIDTH               = 2,
106
   parameter ROW_WIDTH                = 16
107
  )
108
  (/*AUTOARG*/
109
  // Outputs
110
  dq_busy_data, wr_data_offset, mc_wrdata_en, wr_data_en,
111
  wr_data_addr, rd_rmw, ecc_err_addr, ecc_status_valid, wr_ecc_buf, rd_data_end,
112
  rd_data_addr, rd_data_offset, rd_data_en, col_read_fifo_empty,
113
  // Inputs
114
  clk, rst, sent_col, col_size, col_wr_data_buf_addr,
115
  phy_rddata_valid, col_periodic_rd, col_data_buf_addr, col_rmw,
116
  col_rd_wr, col_ra, col_ba, col_row, col_a
117
  );
118
 
119
  input clk;
120
  input rst;
121
 
122
  input sent_col;
123
  input col_rd_wr;
124
 
125
  output reg dq_busy_data = 1'b0;
126
 
127
// The following generates a column command disable based mostly on the type
128
// of DRAM and the fabric to DRAM CK ratio.
129
  generate
130
    if ((nCK_PER_CLK == 1) && ((BURST_MODE == "8") || (DRAM_TYPE == "DDR3")))
131
    begin : three_bumps
132
      reg [1:0] granted_col_d_r;
133
      wire [1:0] granted_col_d_ns = {sent_col, granted_col_d_r[1]};
134
      always @(posedge clk) granted_col_d_r <= #TCQ granted_col_d_ns;
135
      always @(/*AS*/granted_col_d_r or sent_col)
136
                dq_busy_data = sent_col || |granted_col_d_r;
137
    end
138
    if (((nCK_PER_CLK == 2) && ((BURST_MODE == "8") || (DRAM_TYPE == "DDR3")))
139
    || ((nCK_PER_CLK == 1) && ((BURST_MODE == "4") || (DRAM_TYPE == "DDR2"))))
140
    begin : one_bump
141
       always @(/*AS*/sent_col) dq_busy_data = sent_col;
142
    end
143
  endgenerate
144
 
145
// This generates a data offset based on fabric clock to DRAM CK ratio and
146
// the size bit.  Note that this is different that the dq_busy_data signal
147
// generated above.
148
  reg [1:0] offset_r = 2'b0;
149
  reg [1:0] offset_ns = 2'b0;
150
 
151
  input col_size;
152
  wire data_end;
153
  generate
154
 
155
    if(nCK_PER_CLK == 4) begin : data_valid_4_1
156
 
157
      // For 4:1 mode all data is transfered in a single beat so the default
158
      // values of 0 for offset_r/offset_ns suffice - just tie off data_end
159
      assign data_end = 1'b1;
160
 
161
    end
162
 
163
    else begin
164
 
165
      if(DATA_BUF_OFFSET_WIDTH == 2) begin : data_valid_1_1
166
 
167
        always @(col_size or offset_r or rst or sent_col) begin
168
          if (rst) offset_ns = 2'b0;
169
          else begin
170
            offset_ns = offset_r;
171
            if (sent_col) offset_ns = 2'b1;
172
            else if (|offset_r && (offset_r != {col_size, 1'b1}))
173
              offset_ns = offset_r + 2'b1;
174
            else offset_ns = 2'b0;
175
          end
176
 
177
        end
178
 
179
        always @(posedge clk) offset_r <= #TCQ offset_ns;
180
        assign data_end = col_size ? (offset_r == 2'b11) : offset_r[0];
181
 
182
      end
183
 
184
      else begin : data_valid_2_1
185
 
186
        always @(col_size or rst or sent_col)
187
          offset_ns[0] = rst ? 1'b0 : sent_col && col_size;
188
        always @(posedge clk) offset_r[0] <= #TCQ offset_ns[0];
189
        assign data_end = col_size ? offset_r[0] : 1'b1;
190
 
191
      end
192
 
193
    end
194
 
195
  endgenerate
196
 
197
  reg [DATA_BUF_OFFSET_WIDTH-1:0] offset_r1 = {DATA_BUF_OFFSET_WIDTH{1'b0}};
198
  reg [DATA_BUF_OFFSET_WIDTH-1:0] offset_r2 = {DATA_BUF_OFFSET_WIDTH{1'b0}};
199
  reg col_rd_wr_r1;
200
  reg col_rd_wr_r2;
201
  generate
202
    if ((nPHY_WRLAT >= 1) || (DELAY_WR_DATA_CNTRL == 1)) begin : offset_pipe_0
203
      always @(posedge clk) offset_r1 <=
204
                              #TCQ offset_r[DATA_BUF_OFFSET_WIDTH-1:0];
205
      always @(posedge clk) col_rd_wr_r1 <= #TCQ col_rd_wr;
206
    end
207
    if(nPHY_WRLAT == 2) begin : offset_pipe_1
208
      always @(posedge clk) offset_r2 <=
209
                              #TCQ offset_r1[DATA_BUF_OFFSET_WIDTH-1:0];
210
      always @(posedge clk) col_rd_wr_r2 <= #TCQ col_rd_wr_r1;
211
    end
212
  endgenerate
213
 
214
  output wire [DATA_BUF_OFFSET_WIDTH-1:0] wr_data_offset;
215
  assign wr_data_offset = (DELAY_WR_DATA_CNTRL == 1)
216
                            ? offset_r1[DATA_BUF_OFFSET_WIDTH-1:0]
217
                            : (EARLY_WR_DATA_ADDR == "OFF")
218
                              ? offset_r[DATA_BUF_OFFSET_WIDTH-1:0]
219
                              : offset_ns[DATA_BUF_OFFSET_WIDTH-1:0];
220
 
221
  reg sent_col_r1;
222
  reg sent_col_r2;
223
  always @(posedge clk) sent_col_r1 <= #TCQ sent_col;
224
  always @(posedge clk) sent_col_r2 <= #TCQ sent_col_r1;
225
 
226
  wire wrdata_en =  (nPHY_WRLAT == 0) ?
227
                      (sent_col || |offset_r) & ~col_rd_wr :
228
                    (nPHY_WRLAT == 1) ?
229
                      (sent_col_r1 || |offset_r1) & ~col_rd_wr_r1 :
230
                  //(nPHY_WRLAT >= 2) ?
231
                      (sent_col_r2 || |offset_r2) & ~col_rd_wr_r2;
232
 
233
  output wire mc_wrdata_en;
234
  assign mc_wrdata_en = wrdata_en;
235
 
236
  output wire wr_data_en;
237
  assign wr_data_en = (DELAY_WR_DATA_CNTRL == 1)
238
                              ? ((sent_col_r1 || |offset_r1) && ~col_rd_wr_r1)
239
                              : ((sent_col || |offset_r) && ~col_rd_wr);
240
 
241
 
242
  input [DATA_BUF_ADDR_WIDTH-1:0] col_wr_data_buf_addr;
243
  output wire [DATA_BUF_ADDR_WIDTH-1:0] wr_data_addr;
244
  generate
245
    if (DELAY_WR_DATA_CNTRL == 1) begin : delay_wr_data_cntrl_eq_1
246
      reg [DATA_BUF_ADDR_WIDTH-1:0] col_wr_data_buf_addr_r;
247
      always @(posedge clk) col_wr_data_buf_addr_r <=
248
                              #TCQ col_wr_data_buf_addr;
249
      assign wr_data_addr = col_wr_data_buf_addr_r;
250
    end
251
    else begin : delay_wr_data_cntrl_ne_1
252
      assign wr_data_addr = col_wr_data_buf_addr;
253
    end
254
  endgenerate
255
 
256
// CAS-RD to mc_rddata_en
257
 
258
  wire read_data_valid = (sent_col || |offset_r) && col_rd_wr;
259
 
260
function integer clogb2 (input integer size); // ceiling logb2
261
    begin
262
    size = size - 1;
263
    for (clogb2=1; size>1; clogb2=clogb2+1)
264
            size = size >> 1;
265
  end
266
endfunction // clogb2
267
 
268
// Implement FIFO that records reads as they are sent to the DRAM.
269
// When phy_rddata_valid is returned some unknown time later, the 
270
// FIFO output is used to control how the data is interpreted.
271
 
272
  input phy_rddata_valid;
273
  output wire rd_rmw;
274
  output reg [MC_ERR_ADDR_WIDTH-1:0] ecc_err_addr;
275
  output reg ecc_status_valid;
276
  output reg wr_ecc_buf;
277
  output reg rd_data_end;
278
  output reg [DATA_BUF_ADDR_WIDTH-1:0] rd_data_addr;
279
  output reg [DATA_BUF_OFFSET_WIDTH-1:0] rd_data_offset;
280
  output reg rd_data_en /* synthesis syn_maxfan = 10 */;
281
  output col_read_fifo_empty;
282
 
283
  input col_periodic_rd;
284
  input [DATA_BUF_ADDR_WIDTH-1:0] col_data_buf_addr;
285
  input col_rmw;
286
  input [RANK_WIDTH-1:0] col_ra;
287
  input [BANK_WIDTH-1:0] col_ba;
288
  input [ROW_WIDTH-1:0] col_row;
289
  input [ROW_WIDTH-1:0] col_a;
290
 
291
  // Real column address (skip A10/AP and A12/BC#). The maximum width is 12;
292
  // the width will be tailored for the target DRAM downstream.
293
  wire [11:0] col_a_full;
294
 
295
  // Minimum row width is 12; take remaining 11 bits after omitting A10/AP
296
  assign col_a_full[10:0] = {col_a[11], col_a[9:0]};
297
 
298
  // Get the 12th bit when row address width accommodates it; omit A12/BC#
299
  generate
300
     if (ROW_WIDTH >= 14) begin : COL_A_FULL_11_1
301
        assign col_a_full[11] = col_a[13];
302
     end else begin : COL_A_FULL_11_0
303
        assign col_a_full[11] = 0;
304
     end
305
  endgenerate
306
 
307
  // Extract only the width of the target DRAM
308
  wire [COL_WIDTH-1:0] col_a_extracted = col_a_full[COL_WIDTH-1:0];
309
 
310
  localparam MC_ERR_LINE_WIDTH = MC_ERR_ADDR_WIDTH-DATA_BUF_OFFSET_WIDTH;
311
  localparam FIFO_WIDTH = 1 /*data_end*/ +
312
                          1 /*periodic_rd*/ +
313
                          DATA_BUF_ADDR_WIDTH +
314
                          DATA_BUF_OFFSET_WIDTH +
315
                          ((ECC == "OFF") ? 0 : 1+MC_ERR_LINE_WIDTH);
316
  localparam FULL_RAM_CNT = (FIFO_WIDTH/6);
317
  localparam REMAINDER = FIFO_WIDTH % 6;
318
  localparam RAM_CNT = FULL_RAM_CNT + ((REMAINDER == 0 ) ? 0 : 1);
319
  localparam RAM_WIDTH = (RAM_CNT*6);
320
 
321
  generate
322
    begin : read_fifo
323
 
324
      wire [MC_ERR_LINE_WIDTH:0] ecc_line;
325
      if (CS_WIDTH == 1)
326
        assign ecc_line = {col_rmw, col_ba, col_row, col_a_extracted};
327
      else
328
        assign ecc_line = {col_rmw,
329
                           col_ra,
330
                           col_ba,
331
                           col_row,
332
                           col_a_extracted};
333
 
334
      wire [FIFO_WIDTH-1:0] real_fifo_data;
335
      if (ECC == "OFF")
336
         assign real_fifo_data = {data_end,
337
                                  col_periodic_rd,
338
                                  col_data_buf_addr,
339
                                  offset_r[DATA_BUF_OFFSET_WIDTH-1:0]};
340
      else
341
         assign real_fifo_data = {data_end,
342
                                  col_periodic_rd,
343
                                  col_data_buf_addr,
344
                                  offset_r[DATA_BUF_OFFSET_WIDTH-1:0],
345
                                  ecc_line};
346
 
347
      wire [RAM_WIDTH-1:0] fifo_in_data;
348
      if (REMAINDER == 0)
349
        assign fifo_in_data = real_fifo_data;
350
      else
351
        assign fifo_in_data = {{6-REMAINDER{1'b0}}, real_fifo_data};
352
 
353
      wire [RAM_WIDTH-1:0] fifo_out_data_ns;
354
 
355
      reg [4:0] head_r;
356
      wire [4:0] head_ns = rst ? 5'b0 : read_data_valid
357
                                          ? (head_r + 5'b1)
358
                                          : head_r;
359
      always @(posedge clk) head_r <= #TCQ head_ns;
360
 
361
 
362
      reg [4:0] tail_r;
363
      wire [4:0] tail_ns = rst ? 5'b0 : phy_rddata_valid
364
                                          ? (tail_r + 5'b1)
365
                                          : tail_r;
366
      always @(posedge clk) tail_r <= #TCQ tail_ns;
367
 
368
      assign col_read_fifo_empty = head_r == tail_r ? 1'b1 : 1'b0;
369
 
370
      genvar i;
371
      for (i=0; i<RAM_CNT; i=i+1) begin : fifo_ram
372
        RAM32M
373
          #(.INIT_A(64'h0000000000000000),
374
            .INIT_B(64'h0000000000000000),
375
            .INIT_C(64'h0000000000000000),
376
            .INIT_D(64'h0000000000000000)
377
          ) RAM32M0 (
378
            .DOA(fifo_out_data_ns[((i*6)+4)+:2]),
379
            .DOB(fifo_out_data_ns[((i*6)+2)+:2]),
380
            .DOC(fifo_out_data_ns[((i*6)+0)+:2]),
381
            .DOD(),
382
            .DIA(fifo_in_data[((i*6)+4)+:2]),
383
            .DIB(fifo_in_data[((i*6)+2)+:2]),
384
            .DIC(fifo_in_data[((i*6)+0)+:2]),
385
            .DID(2'b0),
386
            .ADDRA(tail_ns),
387
            .ADDRB(tail_ns),
388
            .ADDRC(tail_ns),
389
            .ADDRD(head_r),
390
            .WE(1'b1),
391
            .WCLK(clk)
392
           );
393
      end // block: fifo_ram
394
 
395
      reg [RAM_WIDTH-1:0] fifo_out_data_r;
396
      always @(posedge clk) fifo_out_data_r <= #TCQ fifo_out_data_ns;
397
 
398
// When ECC is ON, most of the FIFO output is delayed
399
// by one state.
400
      if (ECC == "OFF") begin
401
        reg periodic_rd;
402
        always @(/*AS*/phy_rddata_valid or fifo_out_data_r) begin
403
          {rd_data_end,
404
           periodic_rd,
405
           rd_data_addr,
406
           rd_data_offset} = fifo_out_data_r[FIFO_WIDTH-1:0];
407
          ecc_err_addr = {MC_ERR_ADDR_WIDTH{1'b0}};
408
          rd_data_en = phy_rddata_valid && ~periodic_rd;
409
          ecc_status_valid = 1'b0;
410
          wr_ecc_buf = 1'b0;
411
        end
412
        assign rd_rmw = 1'b0;
413
      end
414
      else begin
415
        wire rd_data_end_ns;
416
        wire periodic_rd;
417
        wire [DATA_BUF_ADDR_WIDTH-1:0] rd_data_addr_ns;
418
        wire [DATA_BUF_OFFSET_WIDTH-1:0] rd_data_offset_ns;
419
        wire [MC_ERR_ADDR_WIDTH-1:0] ecc_err_addr_ns;
420
        assign {rd_data_end_ns,
421
                periodic_rd,
422
                rd_data_addr_ns,
423
                rd_data_offset_ns,
424
                rd_rmw,
425
                ecc_err_addr_ns[DATA_BUF_OFFSET_WIDTH+:MC_ERR_LINE_WIDTH]} =
426
                  {fifo_out_data_r[FIFO_WIDTH-1:0]};
427
        assign ecc_err_addr_ns[0+:DATA_BUF_OFFSET_WIDTH] = rd_data_offset_ns;
428
        always @(posedge clk) rd_data_end <= #TCQ rd_data_end_ns;
429
        always @(posedge clk) rd_data_addr <= #TCQ rd_data_addr_ns;
430
        always @(posedge clk) rd_data_offset <= #TCQ rd_data_offset_ns;
431
        always @(posedge clk) ecc_err_addr <= #TCQ ecc_err_addr_ns;
432
        wire rd_data_en_ns = phy_rddata_valid && ~(periodic_rd || rd_rmw);
433
        always @(posedge clk) rd_data_en <= rd_data_en_ns;
434
        wire ecc_status_valid_ns = phy_rddata_valid && ~periodic_rd;
435
        always @(posedge clk) ecc_status_valid <= #TCQ ecc_status_valid_ns;
436
        wire wr_ecc_buf_ns = phy_rddata_valid && ~periodic_rd && rd_rmw;
437
        always @(posedge clk) wr_ecc_buf <= #TCQ wr_ecc_buf_ns;
438
      end
439
    end
440
  endgenerate
441
 
442
endmodule

powered by: WebSVN 2.1.0

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