phy/ecp5/s7/usddrphy: separate DQS/DM to improve readability.
This commit is contained in:
parent
5aaffb7c16
commit
c2d1cf358b
|
@ -207,12 +207,8 @@ class ECP5DDRPHY(Module, AutoCSR):
|
|||
o_Q = getattr(pads, name)[i]
|
||||
)
|
||||
|
||||
# DQ ---------------------------------------------------------------------------------------
|
||||
dq_oe = Signal()
|
||||
# DQS/DM/DQ --------------------------------------------------------------------------------
|
||||
dqs_re = Signal()
|
||||
dqs_oe = Signal()
|
||||
dqs_postamble = Signal()
|
||||
dqs_preamble = Signal()
|
||||
for i in range(databits//8):
|
||||
# DQSBUFM
|
||||
dqs_i = Signal()
|
||||
|
@ -276,7 +272,37 @@ class ECP5DDRPHY(Module, AutoCSR):
|
|||
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_d = Signal(8)
|
||||
dm_o_data_muxed = Signal(4)
|
||||
|
@ -308,32 +334,8 @@ class ECP5DDRPHY(Module, AutoCSR):
|
|||
o_Q = pads.dm[i]
|
||||
)
|
||||
|
||||
dqs = Signal()
|
||||
dqs_oe_n = 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)
|
||||
]
|
||||
|
||||
# DQ -----------------------------------------------------------------------------------
|
||||
dq_oe = Signal()
|
||||
for j in range(8*i, 8*(i+1)):
|
||||
dq_o = Signal()
|
||||
dq_i = Signal()
|
||||
|
|
|
@ -161,7 +161,7 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
o_OB = pads.clk_n[i]
|
||||
)
|
||||
|
||||
# Addresses and Commands -------------------------------------------------------------------
|
||||
# Addresses and Commands ---------------------------------------------------------------
|
||||
for i in range(addressbits):
|
||||
address = Signal()
|
||||
self.specials += Instance("OSERDESE2",
|
||||
|
@ -289,7 +289,7 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
o_DATAOUT = getattr(pads, name)[i],
|
||||
)
|
||||
|
||||
# DQS and DM -------------------------------------------------------------------------------
|
||||
# DQS --------------------------------------------------------------------------------------
|
||||
dqs_oe = Signal()
|
||||
dqs_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed.
|
||||
dqs_pattern = DQSPattern(
|
||||
|
@ -298,47 +298,6 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
register = not with_odelay)
|
||||
self.submodules += dqs_pattern
|
||||
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):
|
||||
dqs_o_no_delay = Signal()
|
||||
dqs_o_delayed = Signal()
|
||||
|
@ -392,6 +351,49 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
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_oe = Signal()
|
||||
dq_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed.
|
||||
|
|
|
@ -124,7 +124,7 @@ class USDDRPHY(Module, AutoCSR):
|
|||
for pads_group in range(len(pads.groups)):
|
||||
pads.sel_group(pads_group)
|
||||
|
||||
# Clock ------------------------------------------------------------------------------------
|
||||
# Clock --------------------------------------------------------------------------------
|
||||
clk_o_nodelay = Signal()
|
||||
clk_o_delayed = Signal()
|
||||
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):
|
||||
a_o_nodelay = Signal()
|
||||
self.specials += [
|
||||
|
@ -295,7 +295,7 @@ class USDDRPHY(Module, AutoCSR):
|
|||
if hasattr(pads, "ten"):
|
||||
self.comb += pads.ten.eq(0)
|
||||
|
||||
# DQS and DM -------------------------------------------------------------------------------
|
||||
# DQS --------------------------------------------------------------------------------------
|
||||
dqs_oe = Signal()
|
||||
dqs_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed.
|
||||
dqs_pattern = DQSPattern(
|
||||
|
@ -304,46 +304,6 @@ class USDDRPHY(Module, AutoCSR):
|
|||
self.submodules += dqs_pattern
|
||||
self.sync += dqs_oe_delayed.eq(dqs_pattern.preamble | dqs_oe | dqs_pattern.postamble)
|
||||
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:
|
||||
# Store initial DQS DELAY_VALUE (in taps) to be able to reload DELAY_VALUE after reset.
|
||||
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_oe = Signal()
|
||||
dq_oe_delayed = Signal() # Tristate control is asynchronous, needs to be delayed.
|
||||
|
|
Loading…
Reference in New Issue