Merge marina project in subdirectory marina/
[fleet.git] / src / edu / berkeley / fleet / fpga / ddr2 / 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 users 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 ECC_WIDTH     = 72,
76    parameter ECC_ENABLE    = 0
77    )
78   (
79    input                                    clk0,
80    input                                    rst0,
81    input [(DQS_WIDTH*DQ_PER_DQS)-1:0]       rd_data_in_rise,
82    input [(DQS_WIDTH*DQ_PER_DQS)-1:0]       rd_data_in_fall,
83    input [DQS_WIDTH-1:0]                    ctrl_rden,
84    input [DQS_WIDTH-1:0]                    ctrl_rden_sel,
85    output reg [1:0]                         rd_ecc_error,
86    output                                   rd_data_valid,
87    output reg [(APPDATA_WIDTH/2)-1:0]       rd_data_out_rise,
88    output reg [(APPDATA_WIDTH/2)-1:0]       rd_data_out_fall
89    );
90
91   // determine number of FIFO72's to use based on data width
92   localparam RDF_FIFO_NUM = ((APPDATA_WIDTH/2)+63)/64;
93
94   reg [DQS_WIDTH-1:0]               ctrl_rden_r;
95   wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] fall_data;
96   reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rd_data_in_fall_r;
97   reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rd_data_in_rise_r;
98   wire                              rden;
99   reg [DQS_WIDTH-1:0]               rden_sel_r
100                                     /* synthesis syn_preserve=1 */;
101   wire [DQS_WIDTH-1:0]              rden_sel_mux;
102   wire [(DQS_WIDTH*DQ_PER_DQS)-1:0] rise_data;
103
104   // ECC specific signals
105   wire [((RDF_FIFO_NUM -1) *2)+1:0] db_ecc_error;
106   reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  fall_data_r;
107   reg                               fifo_rden_r0;
108   reg                               fifo_rden_r1;
109   reg                               fifo_rden_r2;
110   reg                               fifo_rden_r3;
111   reg                               fifo_rden_r4;
112   reg                               fifo_rden_r5;
113   reg                               fifo_rden_r6;
114   wire [(APPDATA_WIDTH/2)-1:0]      rd_data_out_fall_temp;
115   wire [(APPDATA_WIDTH/2)-1:0]      rd_data_out_rise_temp;
116   reg                               rst_r;
117   reg [(DQS_WIDTH*DQ_PER_DQS)-1:0]  rise_data_r;
118   wire [((RDF_FIFO_NUM -1) *2)+1:0] sb_ecc_error;
119
120
121   //***************************************************************************
122
123   always @(posedge clk0) begin
124     rden_sel_r        <= ctrl_rden_sel;
125     ctrl_rden_r       <= ctrl_rden;
126     rd_data_in_rise_r <= rd_data_in_rise;
127     rd_data_in_fall_r <= rd_data_in_fall;
128   end
129
130   // Instantiate primitive to allow this flop to be attached to multicycle
131   // path constraint in UCF. Multicycle path allowed for data from read FIFO.
132   // This is the same signal as RDEN_SEL_R, but is only used to select data
133   // (does not affect control signals)
134   genvar rd_i;
135   generate
136     for (rd_i = 0; rd_i < DQS_WIDTH; rd_i = rd_i+1) begin: gen_rden_sel_mux
137       FDRSE u_ff_rden_sel_mux
138         (
139          .Q   (rden_sel_mux[rd_i]),
140          .C   (clk0),
141          .CE  (1'b1),
142          .D   (ctrl_rden_sel[rd_i]),
143          .R   (1'b0),
144          .S   (1'b0)
145          ) /* synthesis syn_preserve=1 */;
146     end
147   endgenerate
148
149   // determine correct read data valid signal timing
150   assign rden = (rden_sel_r[0]) ? ctrl_rden[0] : ctrl_rden_r[0];
151
152   // assign data based on the skew
153   genvar data_i;
154   generate
155     for(data_i = 0; data_i < DQS_WIDTH; data_i = data_i+1) begin: gen_data
156       assign rise_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
157                        (data_i*DQ_PER_DQS)]
158                = (rden_sel_mux[data_i]) ?
159                  rd_data_in_rise[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1) :
160                                  (data_i*DQ_PER_DQS)] :
161                  rd_data_in_rise_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
162                                    (data_i*DQ_PER_DQS)];
163        assign fall_data[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
164                         (data_i*DQ_PER_DQS)]
165                 = (rden_sel_mux[data_i]) ?
166                   rd_data_in_fall[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
167                                   (data_i*DQ_PER_DQS)] :
168                   rd_data_in_fall_r[(data_i*DQ_PER_DQS)+(DQ_PER_DQS-1):
169                                     (data_i*DQ_PER_DQS)];
170     end
171   endgenerate
172
173   // Generate RST for FIFO reset AND for read/write enable:
174   // ECC FIFO always being read from and written to
175   always @(posedge clk0)
176     rst_r <= rst0;
177
178   genvar rdf_i;
179   generate
180     if (ECC_ENABLE) begin
181       always @(posedge clk0) begin
182         rd_ecc_error[0]   <= (|sb_ecc_error) & fifo_rden_r5;
183         rd_ecc_error[1]   <= (|db_ecc_error) & fifo_rden_r5;
184         rd_data_out_rise  <= rd_data_out_rise_temp;
185         rd_data_out_fall  <= rd_data_out_fall_temp;
186         rise_data_r       <= rise_data;
187         fall_data_r       <= fall_data;
188       end
189
190       // can use any of the read valids, they're all delayed by same amount
191       assign rd_data_valid = fifo_rden_r6;
192
193       // delay read valid to take into account max delay difference btw
194       // the read enable coming from the different DQS groups
195       always @(posedge clk0) begin
196         if (rst0) begin
197           fifo_rden_r0 <= 1'b0;
198           fifo_rden_r1 <= 1'b0;
199           fifo_rden_r2 <= 1'b0;
200           fifo_rden_r3 <= 1'b0;
201           fifo_rden_r4 <= 1'b0;
202           fifo_rden_r5 <= 1'b0;
203           fifo_rden_r6 <= 1'b0;
204         end else begin
205           fifo_rden_r0 <= rden;
206           fifo_rden_r1 <= fifo_rden_r0;
207           fifo_rden_r2 <= fifo_rden_r1;
208           fifo_rden_r3 <= fifo_rden_r2;
209           fifo_rden_r4 <= fifo_rden_r3;
210           fifo_rden_r5 <= fifo_rden_r4;
211           fifo_rden_r6 <= fifo_rden_r5;
212         end
213       end
214
215       for (rdf_i = 0; rdf_i < RDF_FIFO_NUM; rdf_i = rdf_i + 1) begin: gen_rdf
216
217         FIFO36_72  # // rise fifo
218           (
219            .ALMOST_EMPTY_OFFSET     (9'h007),
220            .ALMOST_FULL_OFFSET      (9'h00F),
221            .DO_REG                  (1),          // extra CC output delay
222            .EN_ECC_WRITE            ("FALSE"),
223            .EN_ECC_READ             ("TRUE"),
224            .EN_SYN                  ("FALSE"),
225            .FIRST_WORD_FALL_THROUGH ("FALSE")
226            )
227           u_rdf
228             (
229              .ALMOSTEMPTY (),
230              .ALMOSTFULL  (),
231              .DBITERR     (db_ecc_error[rdf_i + rdf_i]),
232              .DO          (rd_data_out_rise_temp[(64*(rdf_i+1))-1:
233                                                  (64 *rdf_i)]),
234              .DOP         (),
235              .ECCPARITY   (),
236              .EMPTY       (),
237              .FULL        (),
238              .RDCOUNT     (),
239              .RDERR       (),
240              .SBITERR     (sb_ecc_error[rdf_i + rdf_i]),
241              .WRCOUNT     (),
242              .WRERR       (),
243              .DI          (rise_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
244                                        (64 *rdf_i)+(rdf_i*8)]),
245              .DIP         (rise_data_r[(72*(rdf_i+1))-1:
246                                        (64*(rdf_i+1))+ (8*rdf_i)]),
247              .RDCLK       (clk0),
248              .RDEN        (~rst_r),
249              .RST         (rst_r),
250              .WRCLK       (clk0),
251              .WREN        (~rst_r)
252              );
253
254         FIFO36_72  # // fall_fifo
255           (
256            .ALMOST_EMPTY_OFFSET     (9'h007),
257            .ALMOST_FULL_OFFSET      (9'h00F),
258            .DO_REG                  (1),          // extra CC output delay
259            .EN_ECC_WRITE            ("FALSE"),
260            .EN_ECC_READ             ("TRUE"),
261            .EN_SYN                  ("FALSE"),
262            .FIRST_WORD_FALL_THROUGH ("FALSE")
263            )
264           u_rdf1
265             (
266              .ALMOSTEMPTY (),
267              .ALMOSTFULL  (),
268              .DBITERR     (db_ecc_error[(rdf_i+1) + rdf_i]),
269              .DO          (rd_data_out_fall_temp[(64*(rdf_i+1))-1:
270                                                  (64 *rdf_i)]),
271              .DOP         (),
272              .ECCPARITY   (),
273              .EMPTY       (),
274              .FULL        (),
275              .RDCOUNT     (),
276              .RDERR       (),
277              .SBITERR     (sb_ecc_error[(rdf_i+1) + rdf_i]),
278              .WRCOUNT     (),
279              .WRERR       (),
280              .DI          (fall_data_r[((64*(rdf_i+1)) + (rdf_i*8))-1:
281                                        (64*rdf_i)+(rdf_i*8)]),
282              .DIP         (fall_data_r[(72*(rdf_i+1))-1:
283                                        (64*(rdf_i+1))+ (8*rdf_i)]),
284              .RDCLK       (clk0),
285              .RDEN        (~rst_r),
286              .RST         (rst_r),          // or can use rst0
287              .WRCLK       (clk0),
288              .WREN        (~rst_r)
289              );
290       end
291     end else begin
292       assign rd_data_valid = fifo_rden_r0;
293       always @(posedge clk0) begin
294         rd_data_out_rise <= rise_data;
295         rd_data_out_fall <= fall_data;
296         fifo_rden_r0 <= rden;
297       end
298     end
299   endgenerate
300
301 endmodule