s6ddrphy: style and other minor fixes
[litex.git] / milkymist / s6ddrphy / __init__.py
1 #
2 # 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for
3 # Spartan-6
4 #
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 # CL + 2 cycles later, along with the assertion
12 # of dfi_rddata_valid.
13 #
14 # This PHY supports configurable CAS Latency.
15 # Read commands must be sent on phase RDPHASE.
16 # Write commands must be sent on phase WRPHASE.
17 #/
18
19 # Todo:
20 # - use CSR for bitslip?
21
22 from migen.fhdl.std import *
23 from migen.bus.dfi import *
24 from migen.genlib.record import *
25
26 class S6DDRPHY(Module):
27 def __init__(self, pads, phy_settings, bitslip):
28 if phy_settings.type not in ["DDR", "LPDDR", "DDR2"]:
29 raise NotImplementedError("S6DDRPHY only supports DDR, LPDDR and DDR2")
30
31 a = flen(pads.a)
32 ba = flen(pads.ba)
33 d = flen(pads.dq)
34 nphases = phy_settings.nphases
35 self.phy_settings = phy_settings
36
37 self.dfi = Interface(a, ba, nphases*d, nphases)
38 self.clk4x_wr_strb = Signal()
39 self.clk4x_rd_strb = Signal()
40
41 ###
42
43 # sys_clk : system clk, used for dfi interface
44 # sdram_half_clk : half rate sdram clk
45 # sdram_full_wr_clk : full rate sdram write clk
46 # sdram_full_rd_clk : full rate sdram write clk
47 sd_sys = getattr(self.sync, "sys")
48 sd_sdram_half = getattr(self.sync, "sdram_half")
49
50 sys_clk = ClockSignal("sys")
51 sdram_half_clk = ClockSignal("sdram_half")
52 sdram_full_wr_clk = ClockSignal("sdram_full_wr")
53 sdram_full_rd_clk = ClockSignal("sdram_full_rd")
54
55 #
56 # Command/address
57 #
58
59 # select active phase
60 # sys_clk ____----____----
61 # phase_sel(nphases=1) 0 0
62 # phase_sel(nphases=2) 0 1 0 1
63 # phase_sel(nphases=4) 0 1 2 3 0 1 2 3
64 phase_sel = Signal(log2_int(nphases))
65 sys_clk_d = Signal()
66
67 sd_sdram_half += [
68 If(sys_clk & ~sys_clk_d, phase_sel.eq(0)
69 ).Else(phase_sel.eq(phase_sel+1)),
70 sys_clk_d.eq(sys_clk)
71 ]
72
73 # register dfi cmds on half_rate clk
74 r_dfi = Array(Record(phase_cmd_description(a, ba)) for i in range(nphases))
75 for n, phase in enumerate(self.dfi.phases):
76 sd_sdram_half +=[
77 r_dfi[n].address.eq(phase.address),
78 r_dfi[n].bank.eq(phase.bank),
79 r_dfi[n].cs_n.eq(phase.cs_n),
80 r_dfi[n].cke.eq(phase.cke),
81 r_dfi[n].cas_n.eq(phase.cas_n),
82 r_dfi[n].ras_n.eq(phase.ras_n),
83 r_dfi[n].we_n.eq(phase.we_n)
84 ]
85
86 # output cmds
87 sd_sdram_half += [
88 pads.a.eq(r_dfi[phase_sel].address),
89 pads.ba.eq(r_dfi[phase_sel].bank),
90 pads.cs_n.eq(r_dfi[phase_sel].cs_n),
91 pads.cke.eq(r_dfi[phase_sel].cke),
92 pads.ras_n.eq(r_dfi[phase_sel].ras_n),
93 pads.cas_n.eq(r_dfi[phase_sel].cas_n),
94 pads.we_n.eq(r_dfi[phase_sel].we_n)
95 ]
96
97
98 #
99 # Bitslip
100 #
101 bitslip_cnt = Signal(4)
102 bitslip_inc = Signal()
103
104 sd_sys += [
105 If(bitslip_cnt==bitslip,
106 bitslip_inc.eq(0)
107 ).Else(
108 bitslip_cnt.eq(bitslip_cnt+1),
109 bitslip_inc.eq(1)
110 )
111 ]
112
113 #
114 # DQ/DQS/DM data
115 #
116 sdram_half_clk_n = Signal()
117 self.comb += sdram_half_clk_n.eq(~sdram_half_clk)
118
119 postamble = Signal()
120 drive_dqs = Signal()
121 dqs_t_d0 = Signal()
122 dqs_t_d1 = Signal()
123
124 dqs_o = Signal(d//8)
125 dqs_t = Signal(d//8)
126
127 self.comb += [
128 dqs_t_d0.eq(~(drive_dqs | postamble)),
129 dqs_t_d1.eq(~drive_dqs),
130 ]
131
132 for i in range(d//8):
133 # DQS output
134 self.specials += Instance("ODDR2",
135 Instance.Parameter("DDR_ALIGNMENT", "C1"),
136 Instance.Parameter("INIT", 0),
137 Instance.Parameter("SRTYPE", "ASYNC"),
138
139 Instance.Input("C0", sdram_half_clk),
140 Instance.Input("C1", sdram_half_clk_n),
141
142 Instance.Input("CE", 1),
143 Instance.Input("D0", 0),
144 Instance.Input("D1", 1),
145 Instance.Input("R", 0),
146 Instance.Input("S", 0),
147
148 Instance.Output("Q", dqs_o[i])
149 )
150
151 # DQS tristate cmd
152 self.specials += Instance("ODDR2",
153 Instance.Parameter("DDR_ALIGNMENT", "C1"),
154 Instance.Parameter("INIT", 0),
155 Instance.Parameter("SRTYPE", "ASYNC"),
156
157 Instance.Input("C0", sdram_half_clk),
158 Instance.Input("C1", sdram_half_clk_n),
159
160 Instance.Input("CE", 1),
161 Instance.Input("D0", dqs_t_d0),
162 Instance.Input("D1", dqs_t_d1),
163 Instance.Input("R", 0),
164 Instance.Input("S", 0),
165
166 Instance.Output("Q", dqs_t[i])
167 )
168
169 # DQS tristate buffer
170 self.specials += Instance("OBUFT",
171 Instance.Input("I", dqs_o[i]),
172 Instance.Input("T", dqs_t[i]),
173
174 Instance.Output("O", pads.dqs[i])
175 )
176
177 sd_sdram_half += postamble.eq(drive_dqs)
178
179 d_dfi = [Record(phase_wrdata_description(nphases*d)+phase_rddata_description(nphases*d))
180 for i in range(2*nphases)]
181
182 for n, phase in enumerate(self.dfi.phases):
183 self.comb += [
184 d_dfi[n].wrdata.eq(phase.wrdata),
185 d_dfi[n].wrdata_mask.eq(phase.wrdata_mask),
186 d_dfi[n].wrdata_en.eq(phase.wrdata_en),
187 d_dfi[n].rddata_en.eq(phase.rddata_en),
188 ]
189 sd_sys += [
190 d_dfi[nphases+n].wrdata.eq(phase.wrdata),
191 d_dfi[nphases+n].wrdata_mask.eq(phase.wrdata_mask)
192 ]
193
194
195 drive_dq = Signal()
196 drive_dq_n = Signal()
197 d_drive_dq = Signal()
198 d_drive_dq_n = Signal()
199 self.comb += [
200 drive_dq_n.eq(~drive_dq),
201 d_drive_dq_n.eq(~d_drive_dq)
202 ]
203
204 dq_t = Signal(d)
205 dq_o = Signal(d)
206 dq_i = Signal(d)
207
208 for i in range(d):
209 # Data serializer
210 self.specials += Instance("OSERDES2",
211 Instance.Parameter("DATA_WIDTH", 4),
212 Instance.Parameter("DATA_RATE_OQ", "SDR"),
213 Instance.Parameter("DATA_RATE_OT", "SDR"),
214 Instance.Parameter("SERDES_MODE", "NONE"),
215 Instance.Parameter("OUTPUT_MODE", "SINGLE_ENDED"),
216
217 Instance.Output("OQ", dq_o[i]),
218 Instance.Input("OCE", 1),
219 Instance.Input("CLK0", sdram_full_wr_clk),
220 Instance.Input("CLK1", 0),
221 Instance.Input("IOCE", self.clk4x_wr_strb),
222 Instance.Input("RST", 0),
223 Instance.Input("CLKDIV", sys_clk),
224
225 Instance.Input("D1", d_dfi[1*nphases+0].wrdata[i]),
226 Instance.Input("D2", d_dfi[1*nphases+1].wrdata[i+d]),
227 Instance.Input("D3", d_dfi[1*nphases+1].wrdata[i]),
228 Instance.Input("D4", d_dfi[0*nphases+0].wrdata[i+d]),
229 Instance.Output("TQ", dq_t[i]),
230 Instance.Input("T1", d_drive_dq_n),
231 Instance.Input("T2", d_drive_dq_n),
232 Instance.Input("T3", d_drive_dq_n),
233 Instance.Input("T4", drive_dq_n),
234 Instance.Input("TRAIN", 0),
235 Instance.Input("TCE", 1),
236 Instance.Input("SHIFTIN1", 0),
237 Instance.Input("SHIFTIN2", 0),
238 Instance.Input("SHIFTIN3", 0),
239 Instance.Input("SHIFTIN4", 0),
240
241 Instance.Output("SHIFTOUT1"),
242 Instance.Output("SHIFTOUT2"),
243 Instance.Output("SHIFTOUT3"),
244 Instance.Output("SHIFTOUT4"),
245 )
246
247 # Data deserializer
248 self.specials += Instance("ISERDES2",
249 Instance.Parameter("DATA_WIDTH", 4),
250 Instance.Parameter("DATA_RATE", "SDR"),
251 Instance.Parameter("BITSLIP_ENABLE", "TRUE"),
252 Instance.Parameter("SERDES_MODE", "NONE"),
253 Instance.Parameter("INTERFACE_TYPE", "RETIMED"),
254
255 Instance.Input("D", dq_i[i]),
256 Instance.Input("CE0", 1),
257 Instance.Input("CLK0", sdram_full_rd_clk),
258 Instance.Input("CLK1", 0),
259 Instance.Input("IOCE", self.clk4x_rd_strb),
260 Instance.Input("RST", ResetSignal()),
261 Instance.Input("CLKDIV", sys_clk),
262 Instance.Output("SHIFTIN"),
263 Instance.Input("BITSLIP", bitslip_inc),
264 Instance.Output("FABRICOUT"),
265
266 Instance.Output("Q1", d_dfi[0*nphases+0].rddata[i+d]),
267 Instance.Output("Q2", d_dfi[0*nphases+0].rddata[i]),
268 Instance.Output("Q3", d_dfi[0*nphases+1].rddata[i+d]),
269 Instance.Output("Q4", d_dfi[0*nphases+1].rddata[i]),
270
271 Instance.Output("DFB"),
272 Instance.Output("CFB0"),
273 Instance.Output("CFB1"),
274 Instance.Output("VALID"),
275 Instance.Output("INCDEC"),
276 Instance.Output("SHIFTOUT")
277 )
278
279 # Data buffer
280 self.specials += Instance("IOBUF",
281 Instance.Input("I", dq_o[i]),
282 Instance.Output("O", dq_i[i]),
283 Instance.Input("T", dq_t[i]),
284 Instance.InOut("IO", pads.dq[i])
285 )
286
287 for i in range(d//8):
288 # Mask serializer
289 self.specials += Instance("OSERDES2",
290 Instance.Parameter("DATA_WIDTH", 4),
291 Instance.Parameter("DATA_RATE_OQ", "SDR"),
292 Instance.Parameter("DATA_RATE_OT", "SDR"),
293 Instance.Parameter("SERDES_MODE", "NONE"),
294 Instance.Parameter("OUTPUT_MODE", "SINGLE_ENDED"),
295
296 Instance.Output("OQ", pads.dm[i]),
297 Instance.Input("OCE", 1),
298 Instance.Input("CLK0", sdram_full_wr_clk),
299 Instance.Input("CLK1", 0),
300 Instance.Input("IOCE", self.clk4x_wr_strb),
301 Instance.Input("RST", 0),
302 Instance.Input("CLKDIV", sys_clk),
303
304 Instance.Input("D1", d_dfi[1*nphases+0].wrdata_mask[i]),
305 Instance.Input("D2", d_dfi[1*nphases+1].wrdata_mask[i+d//8]),
306 Instance.Input("D3", d_dfi[1*nphases+1].wrdata_mask[i]),
307 Instance.Input("D4", d_dfi[0*nphases+0].wrdata_mask[i+d//8]),
308 Instance.Output("TQ"),
309 Instance.Input("T1"),
310 Instance.Input("T2"),
311 Instance.Input("T3"),
312 Instance.Input("T4"),
313 Instance.Input("TRAIN", 0),
314 Instance.Input("TCE", 0),
315 Instance.Input("SHIFTIN1", 0),
316 Instance.Input("SHIFTIN2", 0),
317 Instance.Input("SHIFTIN3", 0),
318 Instance.Input("SHIFTIN4", 0),
319
320 Instance.Output("SHIFTOUT1"),
321 Instance.Output("SHIFTOUT2"),
322 Instance.Output("SHIFTOUT3"),
323 Instance.Output("SHIFTOUT4"),
324 )
325
326
327 #
328 # DQ/DQS/DM control
329 #
330 self.comb += drive_dq.eq(d_dfi[phy_settings.wrphase].wrdata_en)
331 sd_sys += d_drive_dq.eq(drive_dq)
332
333 d_dfi_wrdata_en = Signal()
334 sd_sys += d_dfi_wrdata_en.eq(d_dfi[phy_settings.wrphase].wrdata_en)
335
336 r_dfi_wrdata_en = Signal(2)
337 sd_sdram_half += r_dfi_wrdata_en.eq(Cat(d_dfi_wrdata_en, r_dfi_wrdata_en[0]))
338
339 self.comb += drive_dqs.eq(r_dfi_wrdata_en[1])
340
341 rddata_sr = Signal(phy_settings.cl+2)
342 sd_sys += rddata_sr.eq(Cat(rddata_sr[1:phy_settings.cl+2], d_dfi[phy_settings.rdphase].rddata_en))
343
344 for n, phase in enumerate(self.dfi.phases):
345 self.comb += [
346 phase.rddata.eq(d_dfi[n].rddata),
347 phase.rddata_valid.eq(rddata_sr[0]),
348 ]