phy/usddrphy: simplify tCK reference by using a specific ODELAYE3 in FIXED mode and keep the PHY in reset by default.

Keeping the PHY in reset by default was not possible previously due to the ODELAYE3 configuration
that was lost on reset. Using a specific ODELAYE3 in FIXED mode allow keeping the PHY in reset at
startup.
This commit is contained in:
Florent Kermarrec 2021-01-21 18:18:39 +01:00
parent a91883db23
commit 0127937215
1 changed files with 13 additions and 15 deletions

View File

@ -59,7 +59,7 @@ class USDDRPHY(Module, AutoCSR):
wrphase = get_sys_phase(nphases, cwl_sys_latency, cwl + cmd_latency) wrphase = get_sys_phase(nphases, cwl_sys_latency, cwl + cmd_latency)
# Registers -------------------------------------------------------------------------------- # Registers --------------------------------------------------------------------------------
self._rst = CSRStorage() self._rst = CSRStorage(reset=1)
self._en_vtc = CSRStorage(reset=1) self._en_vtc = CSRStorage(reset=1)
@ -126,6 +126,18 @@ class USDDRPHY(Module, AutoCSR):
# # # # # #
# tCK reference ----------------------------------------------------------------------------
self.specials += Instance("ODELAYE3",
p_SIM_DEVICE = device,
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "FIXED",
p_DELAY_VALUE = int(tck*1e12/4),
i_CLK = ClockSignal(),
i_EN_VTC = self._en_vtc.storage,
o_CNTVALUEOUT = self._half_sys8x_taps.status,
)
# Iterate on pads groups ------------------------------------------------------------------- # Iterate on pads groups -------------------------------------------------------------------
for pads_group in range(len(pads.groups)): for pads_group in range(len(pads.groups)):
pads.sel_group(pads_group) pads.sel_group(pads_group)
@ -241,18 +253,6 @@ class USDDRPHY(Module, AutoCSR):
self.submodules += dqs_oe_delay, dqs_pattern self.submodules += dqs_oe_delay, dqs_pattern
self.comb += dqs_oe_delay.input.eq(dqs_preamble | dqs_oe | dqs_postamble) self.comb += dqs_oe_delay.input.eq(dqs_preamble | dqs_oe | dqs_postamble)
for i in range(databits//8): for i in range(databits//8):
if i == 0:
# Store initial DQS DELAY_VALUE (in taps) to be able to reload DELAY_VALUE after reset.
dqs_taps = Signal(9)
dqs_taps_timer = WaitTimer(2**16)
dqs_taps_done = Signal()
self.submodules += dqs_taps_timer
self.comb += dqs_taps_timer.wait.eq(~dqs_taps_done)
self.sync += \
If(dqs_taps_timer.done,
dqs_taps_done.eq(1),
self._half_sys8x_taps.status.eq(dqs_taps)
)
dqs_bitslip = BitSlip(8, dqs_bitslip = BitSlip(8,
i = dqs_pattern.o, i = dqs_pattern.o,
rst = (self._dly_sel.storage[i] & self._wdly_dq_bitslip_rst.re) | self._rst.storage, rst = (self._dly_sel.storage[i] & self._wdly_dq_bitslip_rst.re) | self._rst.storage,
@ -282,7 +282,6 @@ class USDDRPHY(Module, AutoCSR):
i_D = dqs_bitslip.o, i_D = dqs_bitslip.o,
o_OQ = dqs_nodelay, o_OQ = dqs_nodelay,
o_T_OUT = dqs_t, o_T_OUT = dqs_t,
), ),
Instance("ODELAYE3", Instance("ODELAYE3",
p_SIM_DEVICE = device, p_SIM_DEVICE = device,
@ -299,7 +298,6 @@ class USDDRPHY(Module, AutoCSR):
i_EN_VTC = self._en_vtc.storage, i_EN_VTC = self._en_vtc.storage,
i_CE = self._dly_sel.storage[i] & self._wdly_dqs_inc.re, i_CE = self._dly_sel.storage[i] & self._wdly_dqs_inc.re,
i_INC = 1, i_INC = 1,
o_CNTVALUEOUT = Signal(9) if i != 0 or j != 0 else dqs_taps,
i_ODATAIN = dqs_nodelay, i_ODATAIN = dqs_nodelay,
o_DATAOUT = dqs_delayed, o_DATAOUT = dqs_delayed,
), ),