2 # 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for
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.
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.
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.
20 # - use CSR for bitslip?
22 from migen
.fhdl
.std
import *
23 from migen
.bus
.dfi
import *
24 from migen
.genlib
.record
import *
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")
34 nphases
= phy_settings
.nphases
35 self
.phy_settings
= phy_settings
37 self
.dfi
= Interface(a
, ba
, nphases
*d
, nphases
)
38 self
.clk4x_wr_strb
= Signal()
39 self
.clk4x_rd_strb
= Signal()
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")
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")
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
))
68 If(sys_clk
& ~sys_clk_d
, phase_sel
.eq(0)
69 ).Else(phase_sel
.eq(phase_sel
+1)),
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
):
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
)
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
)
101 bitslip_cnt
= Signal(4)
102 bitslip_inc
= Signal()
105 If(bitslip_cnt
==bitslip
,
108 bitslip_cnt
.eq(bitslip_cnt
+1),
116 sdram_half_clk_n
= Signal()
117 self
.comb
+= sdram_half_clk_n
.eq(~sdram_half_clk
)
128 dqs_t_d0
.eq(~
(drive_dqs | postamble
)),
129 dqs_t_d1
.eq(~drive_dqs
),
132 for i
in range(d
//8):
134 self
.specials
+= Instance("ODDR2",
135 Instance
.Parameter("DDR_ALIGNMENT", "C1"),
136 Instance
.Parameter("INIT", 0),
137 Instance
.Parameter("SRTYPE", "ASYNC"),
139 Instance
.Input("C0", sdram_half_clk
),
140 Instance
.Input("C1", sdram_half_clk_n
),
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),
148 Instance
.Output("Q", dqs_o
[i
])
152 self
.specials
+= Instance("ODDR2",
153 Instance
.Parameter("DDR_ALIGNMENT", "C1"),
154 Instance
.Parameter("INIT", 0),
155 Instance
.Parameter("SRTYPE", "ASYNC"),
157 Instance
.Input("C0", sdram_half_clk
),
158 Instance
.Input("C1", sdram_half_clk_n
),
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),
166 Instance
.Output("Q", dqs_t
[i
])
169 # DQS tristate buffer
170 self
.specials
+= Instance("OBUFT",
171 Instance
.Input("I", dqs_o
[i
]),
172 Instance
.Input("T", dqs_t
[i
]),
174 Instance
.Output("O", pads
.dqs
[i
])
177 sd_sdram_half
+= postamble
.eq(drive_dqs
)
179 d_dfi
= [Record(phase_wrdata_description(nphases
*d
)+phase_rddata_description(nphases
*d
))
180 for i
in range(2*nphases
)]
182 for n
, phase
in enumerate(self
.dfi
.phases
):
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
),
190 d_dfi
[nphases
+n
].wrdata
.eq(phase
.wrdata
),
191 d_dfi
[nphases
+n
].wrdata_mask
.eq(phase
.wrdata_mask
)
196 drive_dq_n
= Signal()
197 d_drive_dq
= Signal()
198 d_drive_dq_n
= Signal()
200 drive_dq_n
.eq(~drive_dq
),
201 d_drive_dq_n
.eq(~d_drive_dq
)
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"),
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
),
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),
241 Instance
.Output("SHIFTOUT1"),
242 Instance
.Output("SHIFTOUT2"),
243 Instance
.Output("SHIFTOUT3"),
244 Instance
.Output("SHIFTOUT4"),
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"),
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"),
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
]),
271 Instance
.Output("DFB"),
272 Instance
.Output("CFB0"),
273 Instance
.Output("CFB1"),
274 Instance
.Output("VALID"),
275 Instance
.Output("INCDEC"),
276 Instance
.Output("SHIFTOUT")
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
])
287 for i
in range(d
//8):
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"),
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
),
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),
320 Instance
.Output("SHIFTOUT1"),
321 Instance
.Output("SHIFTOUT2"),
322 Instance
.Output("SHIFTOUT3"),
323 Instance
.Output("SHIFTOUT4"),
330 self
.comb
+= drive_dq
.eq(d_dfi
[phy_settings
.wrphase
].wrdata_en
)
331 sd_sys
+= d_drive_dq
.eq(drive_dq
)
333 d_dfi_wrdata_en
= Signal()
334 sd_sys
+= d_dfi_wrdata_en
.eq(d_dfi
[phy_settings
.wrphase
].wrdata_en
)
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]))
339 self
.comb
+= drive_dqs
.eq(r_dfi_wrdata_en
[1])
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
))
344 for n
, phase
in enumerate(self
.dfi
.phases
):
346 phase
.rddata
.eq(d_dfi
[n
].rddata
),
347 phase
.rddata_valid
.eq(rddata_sr
[0]),