phy/ecp5/s7/usddrphy: separate DQS/DM to improve readability.

This commit is contained in:
Florent Kermarrec 2020-09-29 19:23:34 +02:00
parent 5aaffb7c16
commit c2d1cf358b
3 changed files with 124 additions and 118 deletions

View File

@ -207,12 +207,8 @@ class ECP5DDRPHY(Module, AutoCSR):
o_Q = getattr(pads, name)[i] o_Q = getattr(pads, name)[i]
) )
# DQ --------------------------------------------------------------------------------------- # DQS/DM/DQ --------------------------------------------------------------------------------
dq_oe = Signal()
dqs_re = Signal() dqs_re = Signal()
dqs_oe = Signal()
dqs_postamble = Signal()
dqs_preamble = Signal()
for i in range(databits//8): for i in range(databits//8):
# DQSBUFM # DQSBUFM
dqs_i = Signal() dqs_i = Signal()
@ -276,7 +272,37 @@ class ECP5DDRPHY(Module, AutoCSR):
If(burstdet & ~burstdet_d, self._burstdet_seen.status[i].eq(1)), If(burstdet & ~burstdet_d, self._burstdet_seen.status[i].eq(1)),
] ]
# DQS and DM --------------------------------------------------------------------------- # DQS ----------------------------------------------------------------------------------
dqs = Signal()
dqs_oe = Signal()
dqs_oe_n = Signal()
dqs_postamble = Signal()
dqs_preamble = Signal()
self.specials += [
Instance("ODDRX2DQSB",
i_RST = ResetSignal("sys"),
i_SCLK = ClockSignal("sys"),
i_ECLK = ClockSignal("sys2x"),
i_DQSW = dqsw,
i_D0 = 0,
i_D1 = 1,
i_D2 = 0,
i_D3 = 1,
o_Q = dqs
),
Instance("TSHX2DQSA",
i_RST = ResetSignal("sys"),
i_SCLK = ClockSignal("sys"),
i_ECLK = ClockSignal("sys2x"),
i_DQSW = dqsw,
i_T0 = ~(dqs_oe | dqs_postamble),
i_T1 = ~(dqs_oe | dqs_preamble),
o_Q = dqs_oe_n
),
Tristate(pads.dqs_p[i], dqs, ~dqs_oe_n, dqs_i)
]
# DM -----------------------------------------------------------------------------------
dm_o_data = Signal(8) dm_o_data = Signal(8)
dm_o_data_d = Signal(8) dm_o_data_d = Signal(8)
dm_o_data_muxed = Signal(4) dm_o_data_muxed = Signal(4)
@ -308,32 +334,8 @@ class ECP5DDRPHY(Module, AutoCSR):
o_Q = pads.dm[i] o_Q = pads.dm[i]
) )
dqs = Signal() # DQ -----------------------------------------------------------------------------------
dqs_oe_n = Signal() dq_oe = Signal()
self.specials += [
Instance("ODDRX2DQSB",
i_RST = ResetSignal("sys"),
i_SCLK = ClockSignal("sys"),
i_ECLK = ClockSignal("sys2x"),
i_DQSW = dqsw,
i_D0 = 0,
i_D1 = 1,
i_D2 = 0,
i_D3 = 1,
o_Q = dqs
),
Instance("TSHX2DQSA",
i_RST = ResetSignal("sys"),
i_SCLK = ClockSignal("sys"),
i_ECLK = ClockSignal("sys2x"),
i_DQSW = dqsw,
i_T0 = ~(dqs_oe | dqs_postamble),
i_T1 = ~(dqs_oe | dqs_preamble),
o_Q = dqs_oe_n
),
Tristate(pads.dqs_p[i], dqs, ~dqs_oe_n, dqs_i)
]
for j in range(8*i, 8*(i+1)): for j in range(8*i, 8*(i+1)):
dq_o = Signal() dq_o = Signal()
dq_i = Signal() dq_i = Signal()

View File

@ -161,7 +161,7 @@ class S7DDRPHY(Module, AutoCSR):
o_OB = pads.clk_n[i] o_OB = pads.clk_n[i]
) )
# Addresses and Commands ------------------------------------------------------------------- # Addresses and Commands ---------------------------------------------------------------
for i in range(addressbits): for i in range(addressbits):
address = Signal() address = Signal()
self.specials += Instance("OSERDESE2", self.specials += Instance("OSERDESE2",
@ -289,7 +289,7 @@ class S7DDRPHY(Module, AutoCSR):
o_DATAOUT = getattr(pads, name)[i], o_DATAOUT = getattr(pads, name)[i],
) )
# DQS and DM ------------------------------------------------------------------------------- # DQS --------------------------------------------------------------------------------------
dqs_oe = Signal() dqs_oe = Signal()
dqs_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed. dqs_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed.
dqs_pattern = DQSPattern( dqs_pattern = DQSPattern(
@ -298,47 +298,6 @@ class S7DDRPHY(Module, AutoCSR):
register = not with_odelay) register = not with_odelay)
self.submodules += dqs_pattern self.submodules += dqs_pattern
self.sync += dqs_oe_delayed.eq(dqs_pattern.preamble | dqs_oe | dqs_pattern.postamble) self.sync += dqs_oe_delayed.eq(dqs_pattern.preamble | dqs_oe | dqs_pattern.postamble)
for i in range(databits//8):
dm_o_nodelay = Signal()
self.specials += Instance("OSERDESE2",
p_SERDES_MODE = "MASTER",
p_DATA_WIDTH = 2*nphases,
p_TRISTATE_WIDTH = 1,
p_DATA_RATE_OQ = "DDR",
p_DATA_RATE_TQ = "BUF",
i_RST = ResetSignal() | self._rst.storage,
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = dfi.phases[0].wrdata_mask[i],
i_D2 = dfi.phases[0].wrdata_mask[databits//8+i],
i_D3 = dfi.phases[1].wrdata_mask[i],
i_D4 = dfi.phases[1].wrdata_mask[databits//8+i],
i_D5 = dfi.phases[2].wrdata_mask[i],
i_D6 = dfi.phases[2].wrdata_mask[databits//8+i],
i_D7 = dfi.phases[3].wrdata_mask[i],
i_D8 = dfi.phases[3].wrdata_mask[databits//8+i],
i_OCE = 1,
o_OQ = dm_o_nodelay if with_odelay else pads.dm[i],
)
if with_odelay:
self.specials += Instance("ODELAYE2",
p_SIGNAL_PATTERN = "DATA",
p_DELAY_SRC = "ODATAIN",
p_CINVCTRL_SEL = "FALSE",
p_HIGH_PERFORMANCE_MODE = "TRUE",
p_PIPE_SEL = "FALSE",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_ODELAY_TYPE = "VARIABLE",
p_ODELAY_VALUE = 0,
i_C = ClockSignal(),
i_LD = (self._dly_sel.storage[i] & self._wdly_dq_rst.re) | self._rst.storage,
i_LDPIPEEN = 0,
i_CE = self._dly_sel.storage[i] & self._wdly_dq_inc.re,
i_INC = 1,
o_ODATAIN = dm_o_nodelay,
o_DATAOUT = pads.dm[i],
)
for i in range(databits//8): for i in range(databits//8):
dqs_o_no_delay = Signal() dqs_o_no_delay = Signal()
dqs_o_delayed = Signal() dqs_o_delayed = Signal()
@ -392,6 +351,49 @@ class S7DDRPHY(Module, AutoCSR):
io_IOB = pads.dqs_n[i], io_IOB = pads.dqs_n[i],
) )
# DM ---------------------------------------------------------------------------------------
for i in range(databits//8):
dm_o_nodelay = Signal()
self.specials += Instance("OSERDESE2",
p_SERDES_MODE = "MASTER",
p_DATA_WIDTH = 2*nphases,
p_TRISTATE_WIDTH = 1,
p_DATA_RATE_OQ = "DDR",
p_DATA_RATE_TQ = "BUF",
i_RST = ResetSignal() | self._rst.storage,
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = dfi.phases[0].wrdata_mask[i],
i_D2 = dfi.phases[0].wrdata_mask[databits//8+i],
i_D3 = dfi.phases[1].wrdata_mask[i],
i_D4 = dfi.phases[1].wrdata_mask[databits//8+i],
i_D5 = dfi.phases[2].wrdata_mask[i],
i_D6 = dfi.phases[2].wrdata_mask[databits//8+i],
i_D7 = dfi.phases[3].wrdata_mask[i],
i_D8 = dfi.phases[3].wrdata_mask[databits//8+i],
i_OCE = 1,
o_OQ = dm_o_nodelay if with_odelay else pads.dm[i],
)
if with_odelay:
self.specials += Instance("ODELAYE2",
p_SIGNAL_PATTERN = "DATA",
p_DELAY_SRC = "ODATAIN",
p_CINVCTRL_SEL = "FALSE",
p_HIGH_PERFORMANCE_MODE = "TRUE",
p_PIPE_SEL = "FALSE",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_ODELAY_TYPE = "VARIABLE",
p_ODELAY_VALUE = 0,
i_C = ClockSignal(),
i_LD = (self._dly_sel.storage[i] & self._wdly_dq_rst.re) | self._rst.storage,
i_LDPIPEEN = 0,
i_CE = self._dly_sel.storage[i] & self._wdly_dq_inc.re,
i_INC = 1,
o_ODATAIN = dm_o_nodelay,
o_DATAOUT = pads.dm[i],
)
# DQ --------------------------------------------------------------------------------------- # DQ ---------------------------------------------------------------------------------------
dq_oe = Signal() dq_oe = Signal()
dq_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed. dq_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed.

View File

@ -124,7 +124,7 @@ class USDDRPHY(Module, AutoCSR):
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)
# Clock ------------------------------------------------------------------------------------ # Clock --------------------------------------------------------------------------------
clk_o_nodelay = Signal() clk_o_nodelay = Signal()
clk_o_delayed = Signal() clk_o_delayed = Signal()
self.specials += [ self.specials += [
@ -165,7 +165,7 @@ class USDDRPHY(Module, AutoCSR):
) )
] ]
# Addresses and Commands ------------------------------------------------------------------- # Addresses and Commands ---------------------------------------------------------------
for i in range(addressbits if memtype=="DDR3" else addressbits-3): for i in range(addressbits if memtype=="DDR3" else addressbits-3):
a_o_nodelay = Signal() a_o_nodelay = Signal()
self.specials += [ self.specials += [
@ -295,7 +295,7 @@ class USDDRPHY(Module, AutoCSR):
if hasattr(pads, "ten"): if hasattr(pads, "ten"):
self.comb += pads.ten.eq(0) self.comb += pads.ten.eq(0)
# DQS and DM ------------------------------------------------------------------------------- # DQS --------------------------------------------------------------------------------------
dqs_oe = Signal() dqs_oe = Signal()
dqs_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed. dqs_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed.
dqs_pattern = DQSPattern( dqs_pattern = DQSPattern(
@ -304,46 +304,6 @@ class USDDRPHY(Module, AutoCSR):
self.submodules += dqs_pattern self.submodules += dqs_pattern
self.sync += dqs_oe_delayed.eq(dqs_pattern.preamble | dqs_oe | dqs_pattern.postamble) self.sync += dqs_oe_delayed.eq(dqs_pattern.preamble | dqs_oe | dqs_pattern.postamble)
for i in range(databits//8): for i in range(databits//8):
if hasattr(pads, "dm"):
dm_o_nodelay = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = device,
p_DATA_WIDTH = 8,
p_INIT = 0,
p_IS_RST_INVERTED = 0,
p_IS_CLK_INVERTED = 0,
p_IS_CLKDIV_INVERTED = 0,
i_RST = ResetSignal() | self._rst.storage,
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = Cat(
dfi.phases[0].wrdata_mask[i], dfi.phases[0].wrdata_mask[databits//8+i],
dfi.phases[1].wrdata_mask[i], dfi.phases[1].wrdata_mask[databits//8+i],
dfi.phases[2].wrdata_mask[i], dfi.phases[2].wrdata_mask[databits//8+i],
dfi.phases[3].wrdata_mask[i], dfi.phases[3].wrdata_mask[databits//8+i]),
o_OQ = dm_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = device,
p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_IS_CLK_INVERTED = 0,
p_IS_RST_INVERTED = 0,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "VARIABLE",
p_DELAY_VALUE = 0,
i_RST = (self._dly_sel.storage[i] & self._wdly_dq_rst.re) | self._rst.storage,
i_EN_VTC = self._en_vtc.storage,
i_CLK = ClockSignal(),
i_CE = self._dly_sel.storage[i] & self._wdly_dq_inc.re,
i_INC = 1,
i_ODATAIN = dm_o_nodelay,
o_DATAOUT = pads.dm[i],
)
]
if i == 0: if i == 0:
# Store initial DQS DELAY_VALUE (in taps) to be able to reload DELAY_VALUE after reset. # Store initial DQS DELAY_VALUE (in taps) to be able to reload DELAY_VALUE after reset.
dqs_taps = Signal(9) dqs_taps = Signal(9)
@ -412,6 +372,48 @@ class USDDRPHY(Module, AutoCSR):
) )
] ]
# DM ---------------------------------------------------------------------------------------
for i in range(databits//8):
if hasattr(pads, "dm"):
dm_o_nodelay = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = device,
p_DATA_WIDTH = 8,
p_INIT = 0,
p_IS_RST_INVERTED = 0,
p_IS_CLK_INVERTED = 0,
p_IS_CLKDIV_INVERTED = 0,
i_RST = ResetSignal() | self._rst.storage,
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = Cat(
dfi.phases[0].wrdata_mask[i], dfi.phases[0].wrdata_mask[databits//8+i],
dfi.phases[1].wrdata_mask[i], dfi.phases[1].wrdata_mask[databits//8+i],
dfi.phases[2].wrdata_mask[i], dfi.phases[2].wrdata_mask[databits//8+i],
dfi.phases[3].wrdata_mask[i], dfi.phases[3].wrdata_mask[databits//8+i]),
o_OQ = dm_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = device,
p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_IS_CLK_INVERTED = 0,
p_IS_RST_INVERTED = 0,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "VARIABLE",
p_DELAY_VALUE = 0,
i_RST = (self._dly_sel.storage[i] & self._wdly_dq_rst.re) | self._rst.storage,
i_EN_VTC = self._en_vtc.storage,
i_CLK = ClockSignal(),
i_CE = self._dly_sel.storage[i] & self._wdly_dq_inc.re,
i_INC = 1,
i_ODATAIN = dm_o_nodelay,
o_DATAOUT = pads.dm[i],
)
]
# DQ --------------------------------------------------------------------------------------- # DQ ---------------------------------------------------------------------------------------
dq_oe = Signal() dq_oe = Signal()
dq_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed. dq_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed.