c1ceec7a91eb25c59f9778ad2fce1d800e151fc7
[fleet.git] / src / edu / berkeley / fleet / fpga / greg / ddr2_usr_rd.v
1 //*****************************************************************************
2 // DISCLAIMER OF LIABILITY
3 // 
4 // This text/file contains proprietary, confidential
5 // information of Xilinx, Inc., is distributed under license
6 // from Xilinx, Inc., and may be used, copied and/or
7 // disclosed only pursuant to the terms of a valid license
8 // agreement with Xilinx, Inc. Xilinx hereby grants you a 
9 // license to use this text/file solely for design, simulation, 
10 // implementation and creation of design files limited 
11 // to Xilinx devices or technologies. Use with non-Xilinx 
12 // devices or technologies is expressly prohibited and 
13 // immediately terminates your license unless covered by
14 // a separate agreement.
15 //
16 // Xilinx is providing this design, code, or information 
17 // "as-is" solely for use in developing programs and 
18 // solutions for Xilinx devices, with no obligation on the 
19 // part of Xilinx to provide support. By providing this design, 
20 // code, or information as one possible implementation of 
21 // this feature, application or standard, Xilinx is making no 
22 // representation that this implementation is free from any 
23 // claims of infringement. You are responsible for 
24 // obtaining any rights you may require for your implementation. 
25 // Xilinx expressly disclaims any warranty whatsoever with 
26 // respect to the adequacy of the implementation, including 
27 // but not limited to any warranties or representations that this
28 // implementation is free from claims of infringement, implied 
29 // warranties of merchantability or fitness for a particular 
30 // purpose.
31 //
32 // Xilinx products are not intended for use in life support
33 // appliances, devices, or systems. Use in such applications is
34 // expressly prohibited.
35 //
36 // Any modifications that are made to the Source Code are 
37 // done at the user�s sole risk and will be unsupported.
38 //
39 // Copyright (c) 2006-2007 Xilinx, Inc. All rights reserved.
40 //
41 // This copyright and support notice must be retained as part 
42 // of this text at all times. 
43 //*****************************************************************************
44 //   ____  ____
45 //  /   /\/   /
46 // /___/  \  /    Vendor: Xilinx
47 // \   \   \/     Version: 2.3
48 //  \   \         Application: MIG
49 //  /   /         Filename: ddr2_usr_rd.v
50 // /___/   /\     Date Last Modified: $Date: 2008/07/02 14:03:08 $
51 // \   \  /  \    Date Created: Tue Aug 29 2006
52 //  \___\/\___\
53 //
54 //Device: Virtex-5
55 //Design Name: DDR2
56 //Purpose:
57 //   The delay between the read data with respect to the command issued is
58 //   calculted in terms of no. of clocks. This data is then stored into the
59 //   FIFOs and then read back and given as the ouput for comparison.
60 //Reference:
61 //Revision History:
62 //*****************************************************************************
63
64 `timescale 1ns/1ps
65
66 module ddr2_usr_rd #
67   (
68    // Following parameters are for 72-bit RDIMM design (for ML561 Reference 
69    // board design). Actual values may be different. Actual parameters values 
70    // are passed from design top module ddr2_sdram module. Please refer to
71    // the ddr2_sdram module for actual values.
72    parameter DQ_PER_DQS    = 8,
73    parameter DQS_WIDTH     = 9,
74    parameter APPDATA_WIDTH = 144,
75    parameter APPDATA_BURST_LEN = 2,
76    parameter APPDATA_BURST_BITS = 1,
77    parameter ECC_WIDTH     = 72,
78    parameter ECC_ENABLE    = 0,
79    parameter EN_SYN        = "FALSE"
80    )
81   (
82    input                                    clk0,               //read buffer write clock
83    input                                    rst0,
84    //new ports by xtan & gdgib
85    input                                    rb_clk,             //read buffer read clock
86    input                                    rb_rst,             //read buffer read reset
87    output                                   rb_full,            //read buffer is full (error)
88    //end new signals by xtan & gdgib
89    input [(DQS_WIDTH*DQ_PER_DQS)-1:0]       rd_data_in_rise,
90    input [(DQS_WIDTH*DQ_PER_DQS)-1:0]       rd_data_in_fall,
91    input [DQS_WIDTH-1:0]                    ctrl_rden,
92    input [DQS_WIDTH-1:0]                    ctrl_rden_sel,
93    output reg [1:0]                         rd_ecc_error,
94    output reg                               rd_data_valid,
95    input                                    rd_data_rden,
96    output reg [(APPDATA_WIDTH/2)-1:0]       rd_data_out_rise,
97    output reg [(APPDATA_WIDTH/2)-1:0]       rd_data_out_fall,
98    output                                                                       rd_fifo_clear
99    );
100
101   // determine number of FIFO72's to use based on data width
102   localparam RDF_FIFO_NUM = ((APPDATA_WIDTH/2)+63)/64;
103
104   reg [DQS_WIDTH-1:0]               ctrl_rden_r;
105   wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data;
106   reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rd_data_in_fall_r;
107   reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rd_data_in_rise_r;
108   wire                              rden;
109   reg [DQS_WIDTH-1:0]               rden_sel_r
110                                     /* synthesis syn_preserve=1 */;
111   wire [DQS_WIDTH-1:0]              rden_sel_mux;
112   wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data;
113
114   // ECC specific signals
115   wire [((RDF_FIFO_NUM -1) *2)+1:0] db_ecc_error;
116   reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  fall_data_r;
117   reg                               rden_r;
118   wire [(APPDATA_WIDTH/2)-1:0]      rd_data_out_fall_temp;
119   wire [(APPDATA_WIDTH/2)-1:0]      rd_data_out_rise_temp;
120   reg                               rst_r;
121   reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rise_data_r;
122   wire [((RDF_FIFO_NUM -1) *2)+1:0] sb_ecc_error;
123   wire [RDF_FIFO_NUM-1:0]           rdf_empty;
124   wire                                                          fifo_read, fifo_preread;
125
126   reg  [1:0]                        rd_data_valid_pre;
127   wire [RDF_FIFO_NUM-1:0]               w_rb_full;              //added by xtan
128
129         //***************************************************************************
130   
131   reg   [APPDATA_BURST_BITS-1:0] blfifo_readcount, blfifo_writecount;
132   wire                                                  blfifo_readterminal, blfifo_writeterminal;
133   wire                                                  blfifo_read, blfifo_write;
134   wire                                                  blfifo_empty, blfifo_full;
135   
136   asyncfifo_dmem_1b blfifo (
137         .din(1'b0), 
138         .rd_clk(rb_clk),
139         .rd_en(blfifo_read),
140         .rst(rst_r | rb_rst),
141         .wr_clk(clk0),
142         .wr_en(blfifo_write),
143         .dout(), 
144         .empty(blfifo_empty),
145         .full(blfifo_full));
146         assign rd_fifo_clear = ~blfifo_full;
147         
148         always @ (posedge rb_clk) begin
149                 if (rb_rst) blfifo_readcount <= 0;
150                 else if (fifo_read & ~rdf_empty[0]) begin
151                         if (blfifo_readterminal) blfifo_readcount <= 0;
152                         else blfifo_readcount <= blfifo_readcount + 1;
153                 end
154         end
155         
156         always @ (posedge clk0) begin
157                 if (rst_r | rst0) blfifo_writecount <= 0;
158                 else if (rden_r) begin
159                         if (blfifo_writeterminal) blfifo_writecount <= 0;
160                         else blfifo_writecount <= blfifo_writecount + 1;
161                 end
162         end
163         
164         assign  blfifo_readterminal = (blfifo_readcount == (APPDATA_BURST_LEN - 1));
165         assign  blfifo_writeterminal = (blfifo_writecount == (APPDATA_BURST_LEN - 1));
166         assign  blfifo_read = (~|blfifo_readcount) & (fifo_read & rd_data_valid);
167         assign  blfifo_write = blfifo_writeterminal & rden_r;
168
169   //***************************************************************************
170
171   always @(posedge clk0) begin
172     rden_sel_r        <= ctrl_rden_sel;
173     ctrl_rden_r       <= ctrl_rden;
174     rd_data_in_rise_r <= rd_data_in_rise;
175     rd_data_in_fall_r <= rd_data_in_fall;
176   end
177
178   // Instantiate primitive to allow this flop to be attached to multicycle
179   // path constraint in UCF. Multicycle path allowed for data from read FIFO.
180   // This is the same signal as RDEN_SEL_R, but is only used to select data
181   // (does not affect control signals)
182   genvar rd_i;
183   generate
184     for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rden_sel_mux
185       FDRSE u_ff_rden_sel_mux
186         (
187          .Q   (rden_sel_mux[rd_i]),
188          .C   (clk0),
189          .CE  (1'b1),
190          .D   (ctrl_rden_sel[rd_i]),
191          .R   (1'b0),
192          .S   (1'b0)
193          ) /* synthesis syn_preserve=1 */;
194     end
195   endgenerate
196
197   // determine correct read data valid signal timing
198   assign rden = (rden_sel_r[0]) ? ctrl_rden[0] : ctrl_rden_r[0];
199
200   // assign data based on the skew
201   genvar data_i;
202   generate
203     for(data_i = 0; data_i < DQS_WIDTH; data_i = data_i+1) begin: gen_data
204       assign rise_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
205                        (data_i*DQ_PER_DQS)]
206                = (rden_sel_mux[data_i]) ?
207                  rd_data_in_rise[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1) :
208                                  (data_i*DQ_PER_DQS)] :
209                  rd_data_in_rise_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
210                                    (data_i*DQ_PER_DQS)];
211        assign fall_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
212                         (data_i*DQ_PER_DQS)]
213                 = (rden_sel_mux[data_i]) ?
214                   rd_data_in_fall[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
215                                   (data_i*DQ_PER_DQS)] :
216                   rd_data_in_fall_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
217                                     (data_i*DQ_PER_DQS)];
218     end
219   endgenerate
220
221   assign rb_full = w_rb_full[0];
222   
223   // Generate RST for FIFO reset AND for read/write enable:
224   // ECC FIFO always being read from and written to
225   always @(posedge clk0)
226     rst_r <= rst0;
227   
228   always @(posedge clk0) begin
229         rise_data_r       <= rise_data;
230         fall_data_r       <= fall_data;
231   end
232   
233   // delay read valid to take into account max delay difference btw
234   // the read enable coming from the different DQS groups
235   always @(posedge clk0) begin
236     if (rst0) rden_r <= 1'b0;
237     else rden_r <= rden;
238   end
239
240   always @(posedge rb_clk) begin
241         if (fifo_read) begin
242           rd_data_out_rise  <= rd_data_out_rise_temp;
243           rd_data_out_fall  <= rd_data_out_fall_temp;
244         end
245         
246         if (rb_rst) rd_data_valid <= 1'b0;
247     else if (fifo_read) rd_data_valid <= rd_data_valid_pre[1];
248         
249     if (rb_rst) begin
250         rd_data_valid_pre <= 2'b00;
251     end else begin
252         rd_data_valid_pre[0] <= fifo_preread & ~rdf_empty[0];
253         rd_data_valid_pre[1] <= rd_data_valid_pre[0] | (fifo_preread ? 1'b0 : rd_data_valid_pre[1]);
254     end
255   end
256   
257   assign fifo_preread = (~|rd_data_valid_pre | (fifo_read & ^rd_data_valid_pre)) & ~(rst0 | rst_r | rb_rst);
258   assign fifo_read = (~rd_data_valid | rd_data_rden) & ~(rst0 | rst_r | rb_rst);
259
260   genvar rdf_i;
261   generate
262     if (ECC_ENABLE) begin
263       always @(posedge rb_clk) begin
264         if (fifo_preread) begin
265               rd_ecc_error[0]   <= |sb_ecc_error;
266               rd_ecc_error[1]   <= |db_ecc_error;
267             end
268       end
269
270       for (rdf_i = 0; rdf_i < RDF_FIFO_NUM; rdf_i = rdf_i + 1) begin: gen_rdf
271
272         FIFO36_72  # // rise fifo
273           (
274            .ALMOST_EMPTY_OFFSET     (9'h007),
275            .ALMOST_FULL_OFFSET      (9'h00F),
276            .DO_REG                  (1),          // extra CC output delay
277            .EN_ECC_WRITE            ("FALSE"),
278            .EN_ECC_READ             ("TRUE"),
279            .EN_SYN                  (EN_SYN),
280            .FIRST_WORD_FALL_THROUGH ("FALSE")
281            )
282           u_rdf
283             (
284              .ALMOSTEMPTY (),
285              .ALMOSTFULL  (),
286              .DBITERR     (db_ecc_error[rdf_i + rdf_i]),
287              .DO          (rd_data_out_rise_temp[(64*(rdf_i+1))-1:
288                                                  (64 *rdf_i)]),
289              .DOP         (),
290              .ECCPARITY   (),
291              .EMPTY       (rdf_empty[rdf_i]),
292              .FULL        (w_rb_full[rdf_i]),
293              .RDCOUNT     (),
294              .RDERR       (),
295              .SBITERR     (sb_ecc_error[rdf_i + rdf_i]),
296              .WRCOUNT     (),
297              .WRERR       (),
298              .DI          (rise_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
299                                        (64 *rdf_i)+(rdf_i*8)]),
300              .DIP         (rise_data_r[(72*(rdf_i+1))-1:
301                                        (64*(rdf_i+1))+ (8*rdf_i)]),
302              .RDCLK       (rb_clk),
303              .RDEN        (fifo_preread),
304              .RST         (rst_r | rb_rst),
305              .WRCLK       (clk0),
306              .WREN        (rden_r)
307              );
308
309         FIFO36_72  # // fall_fifo
310           (
311            .ALMOST_EMPTY_OFFSET     (9'h007),
312            .ALMOST_FULL_OFFSET      (9'h00F),
313            .DO_REG                  (1),          // extra CC output delay
314            .EN_ECC_WRITE            ("FALSE"),
315            .EN_ECC_READ             ("TRUE"),
316            .EN_SYN                  (EN_SYN),
317            .FIRST_WORD_FALL_THROUGH ("FALSE")
318            )
319           u_rdf1
320             (
321              .ALMOSTEMPTY (),
322              .ALMOSTFULL  (),
323              .DBITERR     (db_ecc_error[(rdf_i+1) + rdf_i]),
324              .DO          (rd_data_out_fall_temp[(64*(rdf_i+1))-1:
325                                                  (64 *rdf_i)]),
326              .DOP         (),
327              .ECCPARITY   (),
328              .EMPTY       (),
329              .FULL        (),
330              .RDCOUNT     (),
331              .RDERR       (),
332              .SBITERR     (sb_ecc_error[(rdf_i+1) + rdf_i]),
333              .WRCOUNT     (),
334              .WRERR       (),
335              .DI          (fall_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
336                                        (64*rdf_i)+(rdf_i*8)]),
337              .DIP         (fall_data_r[(72*(rdf_i+1))-1:
338                                        (64*(rdf_i+1))+ (8*rdf_i)]),
339              .RDCLK       (rb_clk),
340              .RDEN        (fifo_preread),
341              .RST         (rst_r | rb_rst),          // or can use rst0
342              .WRCLK       (clk0),
343              .WREN        (rden_r)
344              );
345       end
346     end else begin
347       for (rdf_i = 0; rdf_i < RDF_FIFO_NUM; rdf_i = rdf_i + 1) begin: gen_rdf
348
349         FIFO36_72  # // rise fifo
350           (
351            .ALMOST_EMPTY_OFFSET     (9'h007),
352            .ALMOST_FULL_OFFSET      (9'h00F),
353            .DO_REG                  (1),          // extra CC output delay
354            .EN_ECC_WRITE            ("FALSE"),
355            .EN_ECC_READ             ("FALSE"),
356            .EN_SYN                  (EN_SYN),
357            .FIRST_WORD_FALL_THROUGH ("FALSE")
358            )
359           u_rdf
360             (
361              .ALMOSTEMPTY (),
362              .ALMOSTFULL  (),
363              .DBITERR     (),
364              .DO          (rd_data_out_rise_temp[(64*(rdf_i+1))-1:
365                                                  (64 *rdf_i)]),
366              .DOP         (),
367              .ECCPARITY   (),
368              .EMPTY       (rdf_empty[rdf_i]),
369              .FULL        (w_rb_full[rdf_i]),
370              .RDCOUNT     (),
371              .RDERR       (),
372              .SBITERR     (),
373              .WRCOUNT     (),
374              .WRERR       (),
375              .DI          (rise_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
376                                        (64 *rdf_i)+(rdf_i*8)]),
377              .DIP         (),
378              .RDCLK       (rb_clk),
379              .RDEN        (fifo_preread),
380              .RST         (rst_r | rb_rst),
381              .WRCLK       (clk0),
382              .WREN        (rden_r)
383              );
384
385         FIFO36_72  # // fall_fifo
386           (
387            .ALMOST_EMPTY_OFFSET     (9'h007),
388            .ALMOST_FULL_OFFSET      (9'h00F),
389            .DO_REG                  (1),          // extra CC output delay
390            .EN_ECC_WRITE            ("FALSE"),
391            .EN_ECC_READ             ("FALSE"),
392            .EN_SYN                  (EN_SYN),
393            .FIRST_WORD_FALL_THROUGH ("FALSE")
394            )
395           u_rdf1
396             (
397              .ALMOSTEMPTY (),
398              .ALMOSTFULL  (),
399              .DBITERR     (),
400              .DO          (rd_data_out_fall_temp[(64*(rdf_i+1))-1:
401                                                  (64 *rdf_i)]),
402              .DOP         (),
403              .ECCPARITY   (),
404              .EMPTY       (),
405              .FULL        (),
406              .RDCOUNT     (),
407              .RDERR       (),
408              .SBITERR     (),
409              .WRCOUNT     (),
410              .WRERR       (),
411              .DI          (fall_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
412                                        (64*rdf_i)+(rdf_i*8)]),
413              .DIP         (),
414              .RDCLK       (rb_clk),
415              .RDEN        (fifo_preread),
416              .RST         (rst_r | rb_rst),          // or can use rst0
417              .WRCLK       (clk0),
418              .WREN        (rden_r)
419              );
420       end
421     end
422   endgenerate
423
424 endmodule