ddrphy: working on hardware, simulation a bit messed up
[litex.git] / verilog / s6ddrphy / s6ddrphy.v
1 /*
2 * 1:2 frequency-ratio DDR PHY for Spartan-6
3 *
4 ************* DATAPATH SIGNALS ***********
5 * Assert dfi_wrdata_en and present the data
6 * on dfi_wrdata_mask/dfi_wrdata in the same
7 * cycle as the write command.
8 *
9 * Assert dfi_rddata_en in the same cycle as the read
10 * command. The data will come back on dfi_rddata
11 * 4 cycles later, along with the assertion of
12 * dfi_rddata_valid.
13 *
14 * This PHY only supports CAS Latency 3.
15 * Read commands must be sent on phase 0.
16 * Write commands must be sent on phase 1.
17 */
18
19 module s6ddrphy #(
20 parameter NUM_AD = 0,
21 parameter NUM_BA = 0,
22 parameter NUM_D = 0 /* < number of data lines per DFI phase */
23 ) (
24 /* Clocks */
25 input sys_clk,
26 input clk2x_270,
27 input clk4x_wr,
28 input clk4x_wr_strb,
29 input clk4x_rd,
30 input clk4x_rd_strb,
31
32 /* DFI phase 0 */
33 input [NUM_AD-1:0] dfi_address_p0,
34 input [NUM_BA-1:0] dfi_bank_p0,
35 input dfi_cs_n_p0,
36 input dfi_cke_p0,
37 input dfi_ras_n_p0,
38 input dfi_cas_n_p0,
39 input dfi_we_n_p0,
40 input dfi_wrdata_en_p0,
41 input [NUM_D/8-1:0] dfi_wrdata_mask_p0,
42 input [NUM_D-1:0] dfi_wrdata_p0,
43 input dfi_rddata_en_p0,
44 output [NUM_D-1:0] dfi_rddata_w0,
45 output dfi_rddata_valid_w0,
46
47 /* DFI phase 1 */
48 input [NUM_AD-1:0] dfi_address_p1,
49 input [NUM_BA-1:0] dfi_bank_p1,
50 input dfi_cs_n_p1,
51 input dfi_cke_p1,
52 input dfi_ras_n_p1,
53 input dfi_cas_n_p1,
54 input dfi_we_n_p1,
55 input dfi_wrdata_en_p1,
56 input [NUM_D/8-1:0] dfi_wrdata_mask_p1,
57 input [NUM_D-1:0] dfi_wrdata_p1,
58 input dfi_rddata_en_p1,
59 output [NUM_D-1:0] dfi_rddata_w1,
60 output dfi_rddata_valid_w1,
61
62 /* DDR SDRAM pads */
63 output sd_clk_out_p,
64 output sd_clk_out_n,
65 output reg [NUM_AD-1:0] sd_a,
66 output reg [NUM_BA-1:0] sd_ba,
67 output reg sd_cs_n,
68 output reg sd_cke,
69 output reg sd_ras_n,
70 output reg sd_cas_n,
71 output reg sd_we_n,
72 inout [NUM_D/2-1:0] sd_dq,
73 output [NUM_D/16-1:0] sd_dm,
74 inout [NUM_D/16-1:0] sd_dqs
75 );
76
77 /*
78 * SDRAM clock
79 */
80 ODDR2 #(
81 .DDR_ALIGNMENT("NONE"),
82 .INIT(1'b0),
83 .SRTYPE("SYNC")
84 ) sd_clk_forward_p (
85 .Q(sd_clk_out_p),
86 .C0(clk2x_270),
87 .C1(~clk2x_270),
88 .CE(1'b1),
89 .D0(1'b1),
90 .D1(1'b0),
91 .R(1'b0),
92 .S(1'b0)
93 );
94 ODDR2 #(
95 .DDR_ALIGNMENT("NONE"),
96 .INIT(1'b0),
97 .SRTYPE("SYNC")
98 ) sd_clk_forward_n (
99 .Q(sd_clk_out_n),
100 .C0(clk2x_270),
101 .C1(~clk2x_270),
102 .CE(1'b1),
103 .D0(1'b0),
104 .D1(1'b1),
105 .R(1'b0),
106 .S(1'b0)
107 );
108
109 /*
110 * Command/address
111 */
112
113 reg phase_sel;
114 always @(posedge clk2x_270)
115 phase_sel <= sys_clk;
116
117 reg [NUM_AD-1:0] r_dfi_address_p0;
118 reg [NUM_BA-1:0] r_dfi_bank_p0;
119 reg r_dfi_cs_n_p0;
120 reg r_dfi_cke_p0;
121 reg r_dfi_ras_n_p0;
122 reg r_dfi_cas_n_p0;
123 reg r_dfi_we_n_p0;
124 reg [NUM_AD-1:0] r_dfi_address_p1;
125 reg [NUM_BA-1:0] r_dfi_bank_p1;
126 reg r_dfi_cs_n_p1;
127 reg r_dfi_cke_p1;
128 reg r_dfi_ras_n_p1;
129 reg r_dfi_cas_n_p1;
130 reg r_dfi_we_n_p1;
131
132 always @(posedge clk2x_270) begin
133 r_dfi_address_p0 <= dfi_address_p0;
134 r_dfi_bank_p0 <= dfi_bank_p0;
135 r_dfi_cs_n_p0 <= dfi_cs_n_p0;
136 r_dfi_cke_p0 <= dfi_cke_p0;
137 r_dfi_ras_n_p0 <= dfi_ras_n_p0;
138 r_dfi_cas_n_p0 <= dfi_cas_n_p0;
139 r_dfi_we_n_p0 <= dfi_we_n_p0;
140
141 r_dfi_address_p1 <= dfi_address_p1;
142 r_dfi_bank_p1 <= dfi_bank_p1;
143 r_dfi_cs_n_p1 <= dfi_cs_n_p1;
144 r_dfi_cke_p1 <= dfi_cke_p1;
145 r_dfi_ras_n_p1 <= dfi_ras_n_p1;
146 r_dfi_cas_n_p1 <= dfi_cas_n_p1;
147 r_dfi_we_n_p1 <= dfi_we_n_p1;
148 end
149
150 always @(posedge clk2x_270) begin
151 if(phase_sel) begin
152 sd_a <= r_dfi_address_p0;
153 sd_ba <= r_dfi_bank_p0;
154 sd_cs_n <= r_dfi_cs_n_p0;
155 sd_cke <= r_dfi_cke_p0;
156 sd_ras_n <= r_dfi_ras_n_p0;
157 sd_cas_n <= r_dfi_cas_n_p0;
158 sd_we_n <= r_dfi_we_n_p0;
159 end else begin
160 sd_a <= r_dfi_address_p1;
161 sd_ba <= r_dfi_bank_p1;
162 sd_cs_n <= r_dfi_cs_n_p1;
163 sd_cke <= r_dfi_cke_p1;
164 sd_ras_n <= r_dfi_ras_n_p1;
165 sd_cas_n <= r_dfi_cas_n_p1;
166 sd_we_n <= r_dfi_we_n_p1;
167 end
168 end
169
170 /*
171 * DQ/DQS/DM data
172 */
173
174 genvar i;
175
176 wire drive_dqs;
177 wire [NUM_D/16-1:0] dqs_o;
178 wire [NUM_D/16-1:0] dqs_t;
179 reg postamble;
180 generate
181 for(i=0;i<NUM_D/16;i=i+1)
182 begin: gen_dqs
183 ODDR2 #(
184 .DDR_ALIGNMENT("C1"),
185 .INIT(1'b0),
186 .SRTYPE("ASYNC")
187 ) dqs_o_oddr (
188 .Q(dqs_o[i]),
189 .C0(clk2x_270),
190 .C1(~clk2x_270),
191 .CE(1'b1),
192 .D0(1'b0),
193 .D1(1'b1),
194 .R(1'b0),
195 .S(1'b0)
196 );
197 ODDR2 #(
198 .DDR_ALIGNMENT("C1"),
199 .INIT(1'b0),
200 .SRTYPE("ASYNC")
201 ) dqs_t_oddr (
202 .Q(dqs_t[i]),
203 .C0(clk2x_270),
204 .C1(~clk2x_270),
205 .CE(1'b1),
206 .D0(~(drive_dqs | postamble)),
207 .D1(~drive_dqs),
208 .R(1'b0),
209 .S(1'b0)
210 );
211 OBUFT dqs_obuft(
212 .I(dqs_o[i]),
213 .T(dqs_t[i]),
214 .O(sd_dqs[i])
215 );
216 end
217 endgenerate
218 always @(posedge clk2x_270)
219 postamble <= drive_dqs;
220
221 reg [NUM_D-1:0] d_dfi_wrdata_p0;
222 reg [NUM_D-1:0] d_dfi_wrdata_p1;
223 reg [NUM_D/8-1:0] d_dfi_wrdata_mask_p0;
224 reg [NUM_D/8-1:0] d_dfi_wrdata_mask_p1;
225 always @(posedge sys_clk) begin
226 d_dfi_wrdata_p0 <= dfi_wrdata_p0;
227 d_dfi_wrdata_p1 <= dfi_wrdata_p1;
228 d_dfi_wrdata_mask_p0 <= dfi_wrdata_mask_p0;
229 d_dfi_wrdata_mask_p1 <= dfi_wrdata_mask_p1;
230 end
231
232 wire drive_dq;
233 wire d_drive_dq;
234 wire [NUM_D/2-1:0] dq_i;
235 wire [NUM_D/2-1:0] dq_o;
236 wire [NUM_D/2-1:0] dq_t;
237 generate
238 for(i=0;i<NUM_D/2;i=i+1)
239 begin: gen_dq
240 OSERDES2 #(
241 .DATA_WIDTH(4),
242 .DATA_RATE_OQ("SDR"),
243 .DATA_RATE_OT("SDR"),
244 .SERDES_MODE("NONE"),
245 .OUTPUT_MODE("SINGLE_ENDED")
246 ) dq_oserdes (
247 .OQ(dq_o[i]),
248 .OCE(1'b1),
249 .CLK0(clk4x_wr),
250 .CLK1(1'b0),
251 .IOCE(clk4x_wr_strb),
252 .RST(1'b0),
253 .CLKDIV(sys_clk),
254 .D1(d_dfi_wrdata_p0[i]),
255 .D2(d_dfi_wrdata_p1[i+NUM_D/2]),
256 .D3(d_dfi_wrdata_p1[i]),
257 .D4(dfi_wrdata_p0[i+NUM_D/2]),
258 .TQ(dq_t[i]),
259 .T1(~d_drive_dq),
260 .T2(~d_drive_dq),
261 .T3(~d_drive_dq),
262 .T4(~drive_dq),
263 .TRAIN(1'b0),
264 .TCE(1'b1),
265 .SHIFTIN1(1'b0),
266 .SHIFTIN2(1'b0),
267 .SHIFTIN3(1'b0),
268 .SHIFTIN4(1'b0),
269 .SHIFTOUT1(),
270 .SHIFTOUT2(),
271 .SHIFTOUT3(),
272 .SHIFTOUT4()
273 );
274 ISERDES2 #(
275 .DATA_WIDTH(4),
276 .DATA_RATE("SDR"),
277 .BITSLIP_ENABLE("FALSE"),
278 .SERDES_MODE("NONE"),
279 .INTERFACE_TYPE("RETIMED")
280 ) dq_iserdes (
281 .D(dq_i[i]),
282 .CE0(1'b1),
283 .CLK0(clk4x_rd),
284 .CLK1(1'b0),
285 .IOCE(clk4x_rd_strb),
286 .RST(1'b0),
287 .CLKDIV(sys_clk),
288 .SHIFTIN(),
289 .BITSLIP(1'b0),
290 .FABRICOUT(),
291 .Q1(dfi_rddata_w0[i+NUM_D/2]),
292 .Q2(dfi_rddata_w0[i]),
293 .Q3(dfi_rddata_w1[i+NUM_D/2]),
294 .Q4(dfi_rddata_w1[i]),
295 .DFB(),
296 .CFB0(),
297 .CFB1(),
298 .VALID(),
299 .INCDEC(),
300 .SHIFTOUT()
301 );
302 IOBUF dq_iobuf(
303 .I(dq_o[i]),
304 .O(dq_i[i]),
305 .T(dq_t[i]),
306 .IO(sd_dq[i])
307 );
308 end
309 endgenerate
310
311 generate
312 for(i=0;i<NUM_D/16;i=i+1)
313 begin: gen_dm_oserdes
314 OSERDES2 #(
315 .DATA_WIDTH(4),
316 .DATA_RATE_OQ("SDR"),
317 .DATA_RATE_OT("SDR"),
318 .SERDES_MODE("NONE"),
319 .OUTPUT_MODE("SINGLE_ENDED")
320 ) dm_oserdes (
321 .OQ(sd_dm[i]),
322 .OCE(1'b1),
323 .CLK0(clk4x_wr),
324 .CLK1(1'b0),
325 .IOCE(clk4x_wr_strb),
326 .RST(1'b0),
327 .CLKDIV(sys_clk),
328 .D1(d_dfi_wrdata_mask_p0[i]),
329 .D2(d_dfi_wrdata_mask_p1[i+NUM_D/16]),
330 .D3(d_dfi_wrdata_mask_p1[i]),
331 .D4(dfi_wrdata_mask_p0[i+NUM_D/16]),
332 .TQ(),
333 .T1(),
334 .T2(),
335 .T3(),
336 .T4(),
337 .TRAIN(1'b0),
338 .TCE(1'b0),
339 .SHIFTIN1(1'b0),
340 .SHIFTIN2(1'b0),
341 .SHIFTIN3(1'b0),
342 .SHIFTIN4(1'b0),
343 .SHIFTOUT1(),
344 .SHIFTOUT2(),
345 .SHIFTOUT3(),
346 .SHIFTOUT4()
347 );
348 end
349 endgenerate
350
351 /*
352 * DQ/DQS/DM control
353 */
354
355 reg d_dfi_wrdata_en_p1;
356 always @(posedge sys_clk)
357 d_dfi_wrdata_en_p1 <= dfi_wrdata_en_p1;
358
359 assign drive_dq = dfi_wrdata_en_p1;
360 assign d_drive_dq = d_dfi_wrdata_en_p1;
361
362 reg r_dfi_wrdata_en;
363 reg r2_dfi_wrdata_en;
364 always @(posedge clk2x_270) begin
365 r_dfi_wrdata_en <= d_dfi_wrdata_en_p1;
366 r2_dfi_wrdata_en <= r_dfi_wrdata_en;
367 end
368
369 assign drive_dqs = r2_dfi_wrdata_en;
370
371 wire rddata_valid;
372 reg [4:0] rddata_sr;
373 assign dfi_rddata_valid_w0 = rddata_sr[0];
374 assign dfi_rddata_valid_w1 = rddata_sr[0];
375 always @(posedge sys_clk)
376 rddata_sr <= {dfi_rddata_en_p0, rddata_sr[4:1]};
377
378 endmodule