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.14/] [memfifo.srcs/] [sources_1/] [ip/] [mig_7series_0/] [mig_7series_0/] [user_design/] [rtl/] [ui/] [mig_7series_v2_3_ui_rd_data.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              : ui_rd_data.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
// User interface read buffer.  Re orders read data returned from the
67
// memory controller back to the request order.
68
//
69
// Consists of a large buffer for the data, a status RAM and two counters.
70
//
71
// The large buffer is implemented with distributed RAM in 6 bit wide,
72
// 1 read, 1 write mode.  The status RAM is implemented with a distributed
73
// RAM configured as 2 bits wide 1 read/write, 1 read mode.
74
//
75
// As read requests are received from the application, the data_buf_addr
76
// counter supplies the data_buf_addr sent into the memory controller.
77
// With each read request, the counter is incremented, eventually rolling
78
// over.  This mechanism labels each read request with an incrementing number.
79
//
80
// When the memory controller returns read data, it echos the original
81
// data_buf_addr with the read data.
82
//
83
// The status RAM is indexed with the same address as the data buffer
84
// RAM.  Each word of the data buffer RAM has an associated status bit
85
// and "end" bit.  Requests of size 1 return a data burst on two consecutive
86
// states.  Requests of size zero return with a single assertion of rd_data_en.
87
//
88
// Upon returning data, the status and end bits are updated for each
89
// corresponding location in the status RAM indexed by the data_buf_addr
90
// echoed on the rd_data_addr field.
91
//
92
// The other side of the status and data RAMs is indexed by the rd_buf_indx.
93
// The rd_buf_indx constantly monitors the status bit it is currently
94
// pointing to.  When the status becomes set to the proper state (more on
95
// this later) read data is returned to the application, and the rd_buf_indx
96
// is incremented.
97
//
98
// At rst the rd_buf_indx is initialized to zero.  Data will not have been
99
// returned from the memory controller yet, so there is nothing to return
100
// to the application. Evenutally, read requests will be made, and the
101
// memory controller will return the corresponding data.  The memory
102
// controller may not return this data in the request order.  In which
103
// case, the status bit at location zero, will not indicate
104
// the data for request zero is ready.  Eventually, the memory controller
105
// will return data for request zero.  The data is forwarded on to the
106
// application, and rd_buf_indx is incremented to point to the next status
107
// bits and data in the buffers.  The status bit will be examined, and if
108
// data is valid, this data will be returned as well.  This process
109
// continues until the status bit indexed by rd_buf_indx indicates data
110
// is not ready.  This may be because the rd_data_buf
111
// is empty, or that some data was returned out of order.   Since rd_buf_indx
112
// always increments sequentially, data is always returned to the application
113
// in request order.
114
//
115
// Some further discussion of the status bit is in order.  The rd_data_buf
116
// is a circular buffer.  The status bit is a single bit.  Distributed RAM
117
// supports only a single write port.  The write port is consumed by
118
// memory controller read data updates.  If a simple '1' were used to
119
// indicate the status, when rd_data_indx rolled over it would immediately
120
// encounter a one for a request that may not be ready.
121
//
122
// This problem is solved by causing read data returns to flip the
123
// status bit, and adding hi order bit beyond the size required to
124
// index the rd_data_buf.  Data is considered ready when the status bit
125
// and this hi order bit are equal.
126
//
127
// The status RAM needs to be initialized to zero after reset.  This is
128
// accomplished by cycling through all rd_buf_indx valus and writing a
129
// zero to the status bits directly following deassertion of reset.  This
130
// mechanism is used for similar purposes
131
// for the wr_data_buf.
132
//
133
// When ORDERING == "STRICT", read data reordering is unnecessary.  For thi
134
// case, most of the logic in the block is not generated.
135
 
136
`timescale 1 ps / 1 ps
137
 
138
// User interface read data.
139
 
140
module mig_7series_v2_3_ui_rd_data #
141
  (
142
   parameter TCQ = 100,
143
   parameter APP_DATA_WIDTH       = 256,
144
   parameter DATA_BUF_ADDR_WIDTH  = 5,
145
   parameter ECC                  = "OFF",
146
   parameter nCK_PER_CLK          = 2 ,
147
   parameter ORDERING             = "NORM"
148
  )
149
  (/*AUTOARG*/
150
  // Outputs
151
  ram_init_done_r, ram_init_addr, app_rd_data_valid, app_rd_data_end,
152
  app_rd_data, app_ecc_multiple_err, rd_buf_full, rd_data_buf_addr_r,
153
  // Inputs
154
  rst, clk, rd_data_en, rd_data_addr, rd_data_offset, rd_data_end,
155
  rd_data, ecc_multiple, rd_accepted
156
  );
157
 
158
  input rst;
159
  input clk;
160
 
161
  output wire ram_init_done_r;
162
  output wire [3:0] ram_init_addr;
163
 
164
// rd_buf_indx points to the status and data storage rams for
165
// reading data out to the app.
166
  reg [5:0] rd_buf_indx_r;
167
  reg ram_init_done_r_lcl /* synthesis syn_maxfan = 10 */;
168
  assign ram_init_done_r = ram_init_done_r_lcl;
169
  wire app_rd_data_valid_ns;
170
  wire single_data;
171
  reg [5:0] rd_buf_indx_ns;
172
  generate begin : rd_buf_indx
173
      wire upd_rd_buf_indx = ~ram_init_done_r_lcl || app_rd_data_valid_ns;
174
// Loop through all status write addresses once after rst.  Initializes
175
// the status and pointer RAMs.
176
      wire ram_init_done_ns =
177
            ~rst && (ram_init_done_r_lcl || (rd_buf_indx_r[4:0] == 5'h1f));
178
      always @(posedge clk) ram_init_done_r_lcl <= #TCQ ram_init_done_ns;
179
 
180
      always @(/*AS*/rd_buf_indx_r or rst or single_data
181
               or upd_rd_buf_indx) begin
182
        rd_buf_indx_ns = rd_buf_indx_r;
183
        if (rst) rd_buf_indx_ns = 6'b0;
184
        else if (upd_rd_buf_indx) rd_buf_indx_ns =
185
          // need to use every slot of RAMB32 if all address bits are used
186
          rd_buf_indx_r + 6'h1 + (DATA_BUF_ADDR_WIDTH == 5 ? 0 : single_data);
187
      end
188
      always @(posedge clk) rd_buf_indx_r <= #TCQ rd_buf_indx_ns;
189
    end
190
  endgenerate
191
  assign ram_init_addr = rd_buf_indx_r[3:0];
192
 
193
  input rd_data_en;
194
  input [DATA_BUF_ADDR_WIDTH-1:0] rd_data_addr;
195
  input rd_data_offset;
196
  input rd_data_end;
197
  input [APP_DATA_WIDTH-1:0] rd_data;
198
  output reg app_rd_data_valid /* synthesis syn_maxfan = 10 */;
199
  output reg app_rd_data_end;
200
  output reg [APP_DATA_WIDTH-1:0] app_rd_data;
201
  input [3:0] ecc_multiple;
202
  reg [2*nCK_PER_CLK-1:0] app_ecc_multiple_err_r = 'b0;
203
  output wire [2*nCK_PER_CLK-1:0] app_ecc_multiple_err;
204
  assign app_ecc_multiple_err = app_ecc_multiple_err_r;
205
  input rd_accepted;
206
  output wire rd_buf_full;
207
  output wire [DATA_BUF_ADDR_WIDTH-1:0] rd_data_buf_addr_r;
208
 
209
// Compute dimensions of read data buffer.  Depending on width of
210
// DQ bus and DRAM CK
211
// to fabric ratio, number of RAM32Ms is variable.  RAM32Ms are used in
212
// single write, single read, 6 bit wide mode.
213
  localparam RD_BUF_WIDTH = APP_DATA_WIDTH + (ECC == "OFF" ? 0 : 2*nCK_PER_CLK);
214
  localparam FULL_RAM_CNT = (RD_BUF_WIDTH/6);
215
  localparam REMAINDER = RD_BUF_WIDTH % 6;
216
  localparam RAM_CNT = FULL_RAM_CNT + ((REMAINDER == 0 ) ? 0 : 1);
217
  localparam RAM_WIDTH = (RAM_CNT*6);
218
  generate
219
    if (ORDERING == "STRICT") begin : strict_mode
220
      assign app_rd_data_valid_ns = 1'b0;
221
      assign single_data = 1'b0;
222
      assign rd_buf_full = 1'b0;
223
      reg [DATA_BUF_ADDR_WIDTH-1:0] rd_data_buf_addr_r_lcl;
224
      wire [DATA_BUF_ADDR_WIDTH-1:0] rd_data_buf_addr_ns =
225
                   rst
226
                    ? 0
227
                    : rd_data_buf_addr_r_lcl + rd_accepted;
228
      always @(posedge clk) rd_data_buf_addr_r_lcl <=
229
                                #TCQ rd_data_buf_addr_ns;
230
      assign rd_data_buf_addr_r = rd_data_buf_addr_ns;
231
// app_* signals required to be registered.      
232
      if (ECC == "OFF") begin : ecc_off
233
        always @(/*AS*/rd_data) app_rd_data = rd_data;
234
        always @(/*AS*/rd_data_en) app_rd_data_valid = rd_data_en;
235
        always @(/*AS*/rd_data_end) app_rd_data_end = rd_data_end;
236
      end
237
      else begin : ecc_on
238
        always @(posedge clk) app_rd_data <= #TCQ rd_data;
239
        always @(posedge clk) app_rd_data_valid <= #TCQ rd_data_en;
240
        always @(posedge clk) app_rd_data_end <= #TCQ rd_data_end;
241
        always @(posedge clk) app_ecc_multiple_err_r <= #TCQ ecc_multiple;
242
      end
243
    end
244
    else begin : not_strict_mode
245
 wire rd_buf_we = ~ram_init_done_r_lcl || rd_data_en /* synthesis syn_maxfan = 10 */;
246
      // In configurations where read data is returned in a single fabric cycle
247
      // the offset is always zero and we can use the bit to get a deeper
248
      // FIFO. The RAMB32 has 5 address bits, so when the DATA_BUF_ADDR_WIDTH
249
      // is set to use them all, discard the offset. Otherwise, include the
250
      // offset.
251
      wire [4:0] rd_buf_wr_addr = DATA_BUF_ADDR_WIDTH == 5 ?
252
                                    rd_data_addr :
253
                                    {rd_data_addr, rd_data_offset};
254
      wire [1:0] rd_status;
255
// Instantiate status RAM.  One bit for status and one for "end".
256
      begin : status_ram
257
// Turns out read to write back status is a timing path.  Update
258
// the status in the ram on the state following the read.  Bypass
259
// the write data into the status read path.
260
        wire [4:0] status_ram_wr_addr_ns = ram_init_done_r_lcl
261
                                           ? rd_buf_wr_addr
262
                                           : rd_buf_indx_r[4:0];
263
        reg [4:0] status_ram_wr_addr_r;
264
        always @(posedge clk) status_ram_wr_addr_r <=
265
                             #TCQ status_ram_wr_addr_ns;
266
        wire [1:0] wr_status;
267
// Not guaranteed to write second status bit.  If it is written, always
268
// copy in the first status bit.
269
        reg wr_status_r1;
270
        always @(posedge clk) wr_status_r1 <= #TCQ wr_status[0];
271
        wire [1:0] status_ram_wr_data_ns =
272
                         ram_init_done_r_lcl
273
                           ? {rd_data_end, ~(rd_data_offset
274
                                              ? wr_status_r1
275
                                              : wr_status[0])}
276
                           : 2'b0;
277
        reg [1:0] status_ram_wr_data_r;
278
        always @(posedge clk) status_ram_wr_data_r <=
279
                              #TCQ status_ram_wr_data_ns;
280
        reg rd_buf_we_r1;
281
        always @(posedge clk) rd_buf_we_r1 <= #TCQ rd_buf_we;
282
        RAM32M
283
          #(.INIT_A(64'h0000000000000000),
284
            .INIT_B(64'h0000000000000000),
285
            .INIT_C(64'h0000000000000000),
286
            .INIT_D(64'h0000000000000000)
287
           ) RAM32M0 (
288
            .DOA(rd_status),
289
            .DOB(),
290
            .DOC(wr_status),
291
            .DOD(),
292
            .DIA(status_ram_wr_data_r),
293
            .DIB(2'b0),
294
            .DIC(status_ram_wr_data_r),
295
            .DID(status_ram_wr_data_r),
296
            .ADDRA(rd_buf_indx_r[4:0]),
297
            .ADDRB(5'b0),
298
            .ADDRC(status_ram_wr_addr_ns),
299
            .ADDRD(status_ram_wr_addr_r),
300
            .WE(rd_buf_we_r1),
301
            .WCLK(clk)
302
           );
303
      end // block: status_ram
304
 
305
      wire [RAM_WIDTH-1:0] rd_buf_out_data;
306
      begin : rd_buf
307
        wire [RAM_WIDTH-1:0] rd_buf_in_data;
308
        if (REMAINDER == 0)
309
          if (ECC == "OFF")
310
            assign rd_buf_in_data = rd_data;
311
          else
312
            assign rd_buf_in_data = {ecc_multiple, rd_data};
313
        else
314
          if (ECC == "OFF")
315
            assign rd_buf_in_data = {{6-REMAINDER{1'b0}}, rd_data};
316
          else
317
            assign rd_buf_in_data =
318
              {{6-REMAINDER{1'b0}}, ecc_multiple, rd_data};
319
 
320
        // Dedicated copy for driving distributed RAM.
321
        (* keep = "true" *) reg [4:0] rd_buf_indx_copy_r /* synthesis syn_keep = 1 */;
322
        always @(posedge clk) rd_buf_indx_copy_r <= #TCQ rd_buf_indx_ns[4:0];
323
 
324
        genvar i;
325
        for (i=0; i<RAM_CNT; i=i+1) begin : rd_buffer_ram
326
          RAM32M
327
            #(.INIT_A(64'h0000000000000000),
328
              .INIT_B(64'h0000000000000000),
329
              .INIT_C(64'h0000000000000000),
330
              .INIT_D(64'h0000000000000000)
331
          ) RAM32M0 (
332
              .DOA(rd_buf_out_data[((i*6)+4)+:2]),
333
              .DOB(rd_buf_out_data[((i*6)+2)+:2]),
334
              .DOC(rd_buf_out_data[((i*6)+0)+:2]),
335
              .DOD(),
336
              .DIA(rd_buf_in_data[((i*6)+4)+:2]),
337
              .DIB(rd_buf_in_data[((i*6)+2)+:2]),
338
              .DIC(rd_buf_in_data[((i*6)+0)+:2]),
339
              .DID(2'b0),
340
              .ADDRA(rd_buf_indx_copy_r[4:0]),
341
              .ADDRB(rd_buf_indx_copy_r[4:0]),
342
              .ADDRC(rd_buf_indx_copy_r[4:0]),
343
              .ADDRD(rd_buf_wr_addr),
344
              .WE(rd_buf_we),
345
              .WCLK(clk)
346
             );
347
        end // block: rd_buffer_ram
348
      end
349
 
350
      wire rd_data_rdy = (rd_status[0] == rd_buf_indx_r[5]);
351
 wire bypass = rd_data_en && (rd_buf_wr_addr[4:0] == rd_buf_indx_r[4:0]) /* synthesis syn_maxfan = 10 */;
352
      assign app_rd_data_valid_ns =
353
              ram_init_done_r_lcl && (bypass || rd_data_rdy);
354
      wire app_rd_data_end_ns = bypass ? rd_data_end : rd_status[1];
355
      always @(posedge clk) app_rd_data_valid <= #TCQ app_rd_data_valid_ns;
356
      always @(posedge clk) app_rd_data_end <= #TCQ app_rd_data_end_ns;
357
 
358
      assign single_data =
359
          app_rd_data_valid_ns && app_rd_data_end_ns && ~rd_buf_indx_r[0];
360
 
361
      wire [APP_DATA_WIDTH-1:0] app_rd_data_ns =
362
                              bypass
363
                                ? rd_data
364
                                : rd_buf_out_data[APP_DATA_WIDTH-1:0];
365
      always @(posedge clk) app_rd_data <= #TCQ app_rd_data_ns;
366
      if (ECC != "OFF") begin : assign_app_ecc_multiple
367
        wire [3:0] app_ecc_multiple_err_ns =
368
                              bypass
369
                                ? ecc_multiple
370
                                : rd_buf_out_data[APP_DATA_WIDTH+:4];
371
        always @(posedge clk) app_ecc_multiple_err_r <=
372
                                #TCQ app_ecc_multiple_err_ns;
373
      end
374
 
375
      //Added to fix timing. The signal app_rd_data_valid has 
376
      //a very high fanout. So making a dedicated copy for usage
377
      //with the occ_cnt counter.
378
      (* equivalent_register_removal = "no" *)
379
      reg app_rd_data_valid_copy;
380
      always @(posedge clk) app_rd_data_valid_copy <= #TCQ app_rd_data_valid_ns;
381
// Keep track of how many entries in the queue hold data.
382
      wire free_rd_buf = app_rd_data_valid_copy && app_rd_data_end; //changed to use registered version
383
                                                                    //of the signals in ordered to fix timing
384
      reg [DATA_BUF_ADDR_WIDTH:0] occ_cnt_r;
385
      wire [DATA_BUF_ADDR_WIDTH:0] occ_minus_one = occ_cnt_r - 1;
386
      wire [DATA_BUF_ADDR_WIDTH:0] occ_plus_one = occ_cnt_r + 1;
387
      begin : occupied_counter
388
        reg [DATA_BUF_ADDR_WIDTH:0] occ_cnt_ns;
389
        always @(/*AS*/free_rd_buf or occ_cnt_r or rd_accepted or rst or occ_minus_one or occ_plus_one) begin
390
          occ_cnt_ns = occ_cnt_r;
391
          if (rst) occ_cnt_ns = 0;
392
          else case ({rd_accepted, free_rd_buf})
393
                 2'b01 : occ_cnt_ns = occ_minus_one;
394
                 2'b10 : occ_cnt_ns = occ_plus_one;
395
          endcase // case ({wr_data_end, new_rd_data})
396
        end
397
        always @(posedge clk) occ_cnt_r <= #TCQ occ_cnt_ns;
398
        assign rd_buf_full = occ_cnt_ns[DATA_BUF_ADDR_WIDTH];
399
 
400
`ifdef MC_SVA
401
  rd_data_buffer_full: cover property (@(posedge clk) (~rst && rd_buf_full));
402
  rd_data_buffer_inc_dec_15: cover property (@(posedge clk)
403
         (~rst && rd_accepted && free_rd_buf && (occ_cnt_r == 'hf)));
404
  rd_data_underflow: assert property (@(posedge clk)
405
         (rst || !((occ_cnt_r == 'b0) && (occ_cnt_ns == 'h1f))));
406
  rd_data_overflow: assert property (@(posedge clk)
407
         (rst || !((occ_cnt_r == 'h10) && (occ_cnt_ns == 'h11))));
408
`endif
409
    end // block: occupied_counter
410
 
411
 
412
// Generate the data_buf_address written into the memory controller
413
// for reads.  Increment with each accepted read, and rollover at 0xf.
414
      reg [DATA_BUF_ADDR_WIDTH-1:0] rd_data_buf_addr_r_lcl;
415
      assign rd_data_buf_addr_r = rd_data_buf_addr_r_lcl;
416
      begin : data_buf_addr
417
        reg [DATA_BUF_ADDR_WIDTH-1:0] rd_data_buf_addr_ns;
418
        always @(/*AS*/rd_accepted or rd_data_buf_addr_r_lcl or rst) begin
419
          rd_data_buf_addr_ns = rd_data_buf_addr_r_lcl;
420
          if (rst) rd_data_buf_addr_ns = 0;
421
          else if (rd_accepted) rd_data_buf_addr_ns =
422
                                  rd_data_buf_addr_r_lcl + 1;
423
        end
424
        always @(posedge clk) rd_data_buf_addr_r_lcl <=
425
                                #TCQ rd_data_buf_addr_ns;
426
      end // block: data_buf_addr
427
    end // block: not_strict_mode
428
  endgenerate
429
 
430
endmodule // ui_rd_data
431
 
432
// Local Variables:
433
// verilog-library-directories:(".")
434
// End:

powered by: WebSVN 2.1.0

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