diff --git a/litedram/phy/ecp5ddrphy.py b/litedram/phy/ecp5ddrphy.py index fb59b0e..5c55697 100644 --- a/litedram/phy/ecp5ddrphy.py +++ b/litedram/phy/ecp5ddrphy.py @@ -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() diff --git a/litedram/phy/s7ddrphy.py b/litedram/phy/s7ddrphy.py index 95403de..4a7871f 100644 --- a/litedram/phy/s7ddrphy.py +++ b/litedram/phy/s7ddrphy.py @@ -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. diff --git a/litedram/phy/usddrphy.py b/litedram/phy/usddrphy.py index 0416cca..2f0e345 100644 --- a/litedram/phy/usddrphy.py +++ b/litedram/phy/usddrphy.py @@ -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.