add DDR2 controller, generated via MIG
[fleet.git] / src / edu / berkeley / fleet / fpga / ddr2 / ddr2_phy_dqs_iob.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_phy_dqs_iob.v
50 // /___/   /\     Date Last Modified: $Date: 2008/07/22 15:41:06 $
51 // \   \  /  \    Date Created: Wed Aug 16 2006
52 //  \___\/\___\
53 //
54 //Device: Virtex-5
55 //Design Name: DDR2
56 //Purpose:
57 //   This module places the data strobes in the IOBs.
58 //Reference:
59 //Revision History:
60 //*****************************************************************************
61
62 `timescale 1ns/1ps
63
64 module ddr2_phy_dqs_iob #
65   (
66    parameter DDR_TYPE              = 1,
67    parameter HIGH_PERFORMANCE_MODE = "TRUE"
68    )
69   (
70    input        clk0,
71    input        clkdiv0,
72    input        rst0,
73    input        dlyinc_dqs,
74    input        dlyce_dqs,
75    input        dlyrst_dqs,
76    input        dlyinc_gate,
77    input        dlyce_gate,
78    input        dlyrst_gate,
79    input        dqs_oe_n,
80    input        dqs_rst_n,
81    input        en_dqs,
82    inout        ddr_dqs,
83    inout        ddr_dqs_n,
84    output       dq_ce,
85    output       delayed_dqs
86    );
87
88   wire                     clk180;
89   wire                     dqs_bufio;
90
91   wire                     dqs_ibuf;
92   wire                     dqs_idelay;
93   wire                     dqs_oe_n_delay;
94   wire                     dqs_oe_n_r;
95   wire                     dqs_rst_n_delay;
96   reg                      dqs_rst_n_r /* synthesis syn_preserve = 1*/;
97   wire                     dqs_out;
98   wire                     en_dqs_sync /* synthesis syn_keep = 1 */;
99
100   // for simulation only. Synthesis should ignore this delay
101   localparam    DQS_NET_DELAY = 0.8;
102
103   assign        clk180 = ~clk0;
104
105   // add delta delay to inputs clocked by clk180 to avoid delta-delay
106   // simulation issues
107   assign dqs_rst_n_delay = dqs_rst_n;
108   assign dqs_oe_n_delay  = dqs_oe_n;
109
110   //***************************************************************************
111   // DQS input-side resources:
112   //  - IODELAY (pad -> IDELAY)
113   //  - BUFIO (IDELAY -> BUFIO)
114   //***************************************************************************
115
116   // Route DQS from PAD to IDELAY
117   IODELAY #
118     (
119      .DELAY_SRC("I"),
120      .IDELAY_TYPE("VARIABLE"),
121      .HIGH_PERFORMANCE_MODE(HIGH_PERFORMANCE_MODE),
122      .IDELAY_VALUE(0),
123      .ODELAY_VALUE(0)
124      )
125     u_idelay_dqs
126       (
127        .DATAOUT (dqs_idelay),
128        .C       (clkdiv0),
129        .CE      (dlyce_dqs),
130        .DATAIN  (),
131        .IDATAIN (dqs_ibuf),
132        .INC     (dlyinc_dqs),
133        .ODATAIN (),
134        .RST     (dlyrst_dqs),
135        .T       ()
136        );
137
138   // From IDELAY to BUFIO
139   BUFIO u_bufio_dqs
140     (
141      .I  (dqs_idelay),
142      .O  (dqs_bufio)
143      );
144
145   // To model additional delay of DQS BUFIO + gating network
146   // for behavioral simulation. Make sure to select a delay number smaller
147   // than half clock cycle (otherwise output will not track input changes
148   // because of inertial delay). Duplicate to avoid delta delay issues.
149   assign #(DQS_NET_DELAY) i_delayed_dqs = dqs_bufio;
150   assign #(DQS_NET_DELAY) delayed_dqs   = dqs_bufio;
151
152   //***************************************************************************
153   // DQS gate circuit (not supported for all controllers)
154   //***************************************************************************
155
156   // Gate routing:
157   //   en_dqs -> IDELAY -> en_dqs_sync -> IDDR.S -> dq_ce ->
158   //   capture IDDR.CE
159
160   // Delay CE control so that it's in phase with delayed DQS
161   IODELAY #
162     (
163      .DELAY_SRC             ("DATAIN"),
164      .IDELAY_TYPE           ("VARIABLE"),
165      .HIGH_PERFORMANCE_MODE (HIGH_PERFORMANCE_MODE),
166      .IDELAY_VALUE          (0),
167      .ODELAY_VALUE          (0)
168      )
169     u_iodelay_dq_ce
170       (
171        .DATAOUT (en_dqs_sync),
172        .C       (clkdiv0),
173        .CE      (dlyce_gate),
174        .DATAIN  (en_dqs),
175        .IDATAIN (),
176        .INC     (dlyinc_gate),
177        .ODATAIN (),
178        .RST     (dlyrst_gate),
179        .T       ()
180        );
181
182   // Generate sync'ed CE to DQ IDDR's using an IDDR clocked by DQS
183   // We could also instantiate a negative-edge SDR flop here
184   IDDR #
185     (
186      .DDR_CLK_EDGE ("OPPOSITE_EDGE"),
187      .INIT_Q1      (1'b0),
188      .INIT_Q2      (1'b0),
189      .SRTYPE       ("ASYNC")
190      )
191     u_iddr_dq_ce
192       (
193        .Q1 (),
194        .Q2 (dq_ce),           // output on falling edge
195        .C  (i_delayed_dqs),
196        .CE (1'b1),
197        .D  (en_dqs_sync),
198        .R  (1'b0),
199        .S  (en_dqs_sync)
200        );
201
202   //***************************************************************************
203   // DQS output-side resources
204   //***************************************************************************
205
206   // synthesis attribute keep of dqs_rst_n_r is "true"
207   always @(posedge clk180)
208     dqs_rst_n_r <= dqs_rst_n_delay;
209
210   ODDR #
211     (
212      .SRTYPE("SYNC"),
213      .DDR_CLK_EDGE("OPPOSITE_EDGE")
214      )
215     u_oddr_dqs
216       (
217        .Q  (dqs_out),
218        .C  (clk180),
219        .CE (1'b1),
220        .D1 (dqs_rst_n_r),      // keep output deasserted for write preamble
221        .D2 (1'b0),
222        .R  (1'b0),
223        .S  (1'b0)
224        );
225
226   (* IOB = "TRUE" *) FDP u_tri_state_dqs
227     (
228      .D   (dqs_oe_n_delay),
229      .Q   (dqs_oe_n_r),
230      .C   (clk180),
231      .PRE (rst0)
232      ) /* synthesis syn_useioff = 1 */;
233
234   //***************************************************************************
235
236   // use either single-ended (for DDR1) or differential (for DDR2) DQS input
237
238   generate
239     if (DDR_TYPE > 0) begin: gen_dqs_iob_ddr2
240       IOBUFDS u_iobuf_dqs
241         (
242          .O   (dqs_ibuf),
243          .IO  (ddr_dqs),
244          .IOB (ddr_dqs_n),
245          .I   (dqs_out),
246          .T   (dqs_oe_n_r)
247          );
248     end else begin: gen_dqs_iob_ddr1
249       IOBUF u_iobuf_dqs
250         (
251          .O   (dqs_ibuf),
252          .IO  (ddr_dqs),
253          .I   (dqs_out),
254          .T   (dqs_oe_n_r)
255          );
256     end
257   endgenerate
258
259 endmodule