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]
|
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()
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue