phys: integrate PHYPadsCombiner.

pads can now be passed to the PHY as:

# DRAM Chips with common command/address lines (traditional):
pads = platform.request("ddram")

# DRAM Chips with dissociated command/address lines:
pads = [platform.request("ddram", 0), platform.request("ddram", 1)]

LiteDRAM controller will automatically adapts itself to this combined pads.
This commit is contained in:
Florent Kermarrec 2020-03-06 18:56:28 +01:00
parent 5e068f412b
commit 26564ba93c
5 changed files with 396 additions and 368 deletions

View File

@ -82,6 +82,7 @@ class ECP5DDRPHYInit(Module):
class ECP5DDRPHY(Module, AutoCSR):
def __init__(self, pads, sys_clk_freq=100e6):
pads = PHYPadsCombiner(pads)
memtype = "DDR3"
tck = 2/(2*2*sys_clk_freq)
addressbits = len(pads.a)
@ -138,61 +139,65 @@ class ECP5DDRPHY(Module, AutoCSR):
bl8_sel = Signal()
# Clock ------------------------------------------------------------------------------------
for i in range(len(pads.clk_p)):
sd_clk_se = Signal()
self.specials += Instance("ODDRX2F",
i_RST = ResetSignal("sys2x"),
i_ECLK = ClockSignal("sys2x"),
i_SCLK = ClockSignal(),
i_D0 = 0,
i_D1 = 1,
i_D2 = 0,
i_D3 = 1,
o_Q = pads.clk_p[i]
)
# Iterate on pads groups -------------------------------------------------------------------
for pads_group in range(len(pads.groups)):
pads.sel_group(pads_group)
# Addresses and Commands -------------------------------------------------------------------
for i in range(addressbits):
self.specials += Instance("ODDRX2F",
i_RST = ResetSignal("sys2x"),
i_ECLK = ClockSignal("sys2x"),
i_SCLK = ClockSignal(),
i_D0 = dfi.phases[0].address[i],
i_D1 = dfi.phases[0].address[i],
i_D2 = dfi.phases[1].address[i],
i_D3 = dfi.phases[1].address[i],
o_Q = pads.a[i]
)
for i in range(bankbits):
self.specials += Instance("ODDRX2F",
i_RST = ResetSignal("sys2x"),
i_ECLK = ClockSignal("sys2x"),
i_SCLK = ClockSignal(),
i_D0 = dfi.phases[0].bank[i],
i_D1 = dfi.phases[0].bank[i],
i_D2 = dfi.phases[1].bank[i],
i_D3 = dfi.phases[1].bank[i],
o_Q = pads.ba[i]
)
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
if hasattr(pads, "reset_n"):
controls.append("reset_n")
if hasattr(pads, "cs_n"):
controls.append("cs_n")
for name in controls:
for i in range(len(getattr(pads, name))):
# Clock ------------------------------------------------------------------------------------
for i in range(len(pads.clk_p)):
sd_clk_se = Signal()
self.specials += Instance("ODDRX2F",
i_RST = ResetSignal("sys2x"),
i_ECLK = ClockSignal("sys2x"),
i_SCLK = ClockSignal(),
i_D0 = getattr(dfi.phases[0], name)[i],
i_D1 = getattr(dfi.phases[0], name)[i],
i_D2 = getattr(dfi.phases[1], name)[i],
i_D3 = getattr(dfi.phases[1], name)[i],
o_Q = getattr(pads, name)[i]
i_D0 = 0,
i_D1 = 1,
i_D2 = 0,
i_D3 = 1,
o_Q = pads.clk_p[i]
)
# Addresses and Commands -------------------------------------------------------------------
for i in range(addressbits):
self.specials += Instance("ODDRX2F",
i_RST = ResetSignal("sys2x"),
i_ECLK = ClockSignal("sys2x"),
i_SCLK = ClockSignal(),
i_D0 = dfi.phases[0].address[i],
i_D1 = dfi.phases[0].address[i],
i_D2 = dfi.phases[1].address[i],
i_D3 = dfi.phases[1].address[i],
o_Q = pads.a[i]
)
for i in range(bankbits):
self.specials += Instance("ODDRX2F",
i_RST = ResetSignal("sys2x"),
i_ECLK = ClockSignal("sys2x"),
i_SCLK = ClockSignal(),
i_D0 = dfi.phases[0].bank[i],
i_D1 = dfi.phases[0].bank[i],
i_D2 = dfi.phases[1].bank[i],
i_D3 = dfi.phases[1].bank[i],
o_Q = pads.ba[i]
)
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
if hasattr(pads, "reset_n"):
controls.append("reset_n")
if hasattr(pads, "cs_n"):
controls.append("cs_n")
for name in controls:
for i in range(len(getattr(pads, name))):
self.specials += Instance("ODDRX2F",
i_RST = ResetSignal("sys2x"),
i_ECLK = ClockSignal("sys2x"),
i_SCLK = ClockSignal(),
i_D0 = getattr(dfi.phases[0], name)[i],
i_D1 = getattr(dfi.phases[0], name)[i],
i_D2 = getattr(dfi.phases[1], name)[i],
i_D3 = getattr(dfi.phases[1], name)[i],
o_Q = getattr(pads, name)[i]
)
# DQ ---------------------------------------------------------------------------------------
oe_dq = Signal()
oe_dqs = Signal()

View File

@ -18,13 +18,14 @@ from migen import *
from migen.genlib.record import *
from migen.fhdl.specials import Tristate
from litedram.common import PhySettings
from litedram.common import *
from litedram.phy.dfi import *
# Generic SDR PHY ----------------------------------------------------------------------------------
class GENSDRPHY(Module):
def __init__(self, pads, cl=2):
pads = PHYPadsCombiner(pads)
addressbits = len(pads.a)
bankbits = len(pads.ba)
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
@ -52,33 +53,39 @@ class GENSDRPHY(Module):
# # #
# Addresses and Commands -------------------------------------------------------------------
self.sync += [
pads.a.eq(dfi.p0.address),
pads.ba.eq(dfi.p0.bank),
pads.cas_n.eq(dfi.p0.cas_n),
pads.ras_n.eq(dfi.p0.ras_n),
pads.we_n.eq(dfi.p0.we_n)
]
if hasattr(pads, "cke"):
self.sync += pads.cke.eq(dfi.p0.cke)
if hasattr(pads, "cs_n"):
self.sync += pads.cs_n.eq(dfi.p0.cs_n)
# Iterate on pads groups -------------------------------------------------------------------
for pads_group in range(len(pads.groups)):
pads.sel_group(pads_group)
# Addresses and Commands ---------------------------------------------------------------
self.sync += [
pads.a.eq(dfi.p0.address),
pads.ba.eq(dfi.p0.bank),
pads.cas_n.eq(dfi.p0.cas_n),
pads.ras_n.eq(dfi.p0.ras_n),
pads.we_n.eq(dfi.p0.we_n)
]
if hasattr(pads, "cke"):
self.sync += pads.cke.eq(dfi.p0.cke)
if hasattr(pads, "cs_n"):
self.sync += pads.cs_n.eq(dfi.p0.cs_n)
# DQ/DQS/DM Data ---------------------------------------------------------------------------
dq_o = Signal(databits)
dq_o = Signal(databits)
dq_oe = Signal()
dq_i = Signal(databits)
dq_i = Signal(databits)
self.sync += dq_o.eq(dfi.p0.wrdata)
self.specials += Tristate(pads.dq, dq_o, dq_oe, dq_i)
for i in range(len(pads.dq)):
self.specials += Tristate(pads.dq[i], dq_o[i], dq_oe, dq_i[i])
if hasattr(pads, "dm"):
assert len(pads.dm)*8 == databits
self.sync += \
If(dfi.p0.wrdata_en,
pads.dm.eq(dfi.p0.wrdata_mask)
).Else(
pads.dm.eq(0)
)
for i in range(len(pads.dm)):
self.sync += \
If(dfi.p0.wrdata_en,
pads.dm[i].eq(dfi.p0.wrdata_mask)
).Else(
pads.dm[i].eq(0)
)
dq_in = Signal(databits)
self.sync.sys_ps += dq_in.eq(dq_i)
self.sync += dfi.p0.rddata.eq(dq_in)

View File

@ -27,12 +27,13 @@ from migen import *
from migen.genlib.record import *
from migen.fhdl.decorators import ClockDomainsRenamer
from litedram.common import PhySettings
from litedram.common import *
from litedram.phy.dfi import *
class S6HalfRateDDRPHY(Module):
def __init__(self, pads, memtype, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
pads = PHYPadsCombiner(pads)
if memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
addressbits = len(pads.a)
@ -130,19 +131,23 @@ class S6HalfRateDDRPHY(Module):
r_dfi[n].we_n.eq(phase.we_n)
]
# output cmds
sd_sdram_half += [
pads.a.eq(r_dfi[phase_sel].address),
pads.ba.eq(r_dfi[phase_sel].bank),
pads.cke.eq(r_dfi[phase_sel].cke),
pads.ras_n.eq(r_dfi[phase_sel].ras_n),
pads.cas_n.eq(r_dfi[phase_sel].cas_n),
pads.we_n.eq(r_dfi[phase_sel].we_n)
]
# optional pads
for name in "reset_n", "cs_n", "odt":
if hasattr(pads, name):
sd_sdram_half += getattr(pads, name).eq(getattr(r_dfi[phase_sel], name))
# Iterate on pads groups -------------------------------------------------------------------
for pads_group in range(len(pads.groups)):
pads.sel_group(pads_group)
# output cmds
sd_sdram_half += [
pads.a.eq(r_dfi[phase_sel].address),
pads.ba.eq(r_dfi[phase_sel].bank),
pads.cke.eq(r_dfi[phase_sel].cke),
pads.ras_n.eq(r_dfi[phase_sel].ras_n),
pads.cas_n.eq(r_dfi[phase_sel].cas_n),
pads.we_n.eq(r_dfi[phase_sel].we_n)
]
# optional pads
for name in "reset_n", "cs_n", "odt":
if hasattr(pads, name):
sd_sdram_half += getattr(pads, name).eq(getattr(r_dfi[phase_sel], name))
# Bitslip ----------------------------------------------------------------------------------
bitslip_cnt = Signal(4)
@ -406,6 +411,7 @@ class S6HalfRateDDRPHY(Module):
class S6QuarterRateDDRPHY(Module):
def __init__(self, pads, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
pads = PHYPadsCombiner(pads)
addressbits = len(pads.a)
bankbits = len(pads.ba)
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)

View File

@ -25,6 +25,7 @@ class S7DDRPHY(Module, AutoCSR):
iodelay_clk_freq = 200e6,
cmd_latency = 0):
assert not (memtype == "DDR3" and nphases == 2) # FIXME: Needs BL8 support for nphases=2
pads = PHYPadsCombiner(pads)
tck = 2/(2*nphases*sys_clk_freq)
addressbits = len(pads.a)
bankbits = len(pads.ba)
@ -93,144 +94,15 @@ class S7DDRPHY(Module, AutoCSR):
# # #
# Clock ------------------------------------------------------------------------------------
ddr_clk = "sys2x" if nphases == 2 else "sys4x"
for i in range(len(pads.clk_p)):
sd_clk_se_nodelay = Signal()
sd_clk_se_delayed = 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(),
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = 0,
i_D2 = 1,
i_D3 = 0,
i_D4 = 1,
i_D5 = 0,
i_D6 = 1,
i_D7 = 0,
i_D8 = 1,
o_OQ = sd_clk_se_nodelay,
i_OCE = 1,
)
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._cdly_rst.re,
i_LDPIPEEN = 0,
i_CE = self._cdly_inc.re,
i_INC = 1,
o_ODATAIN = sd_clk_se_nodelay,
o_DATAOUT = sd_clk_se_delayed,
)
self.specials += Instance("OBUFDS",
i_I = sd_clk_se_delayed if with_odelay else sd_clk_se_nodelay,
o_O = pads.clk_p[i],
o_OB = pads.clk_n[i]
)
# Iterate on pads groups -------------------------------------------------------------------
for pads_group in range(len(pads.groups)):
pads.sel_group(pads_group)
# Addresses and Commands -------------------------------------------------------------------
for i in range(addressbits):
address = 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(),
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = dfi.phases[0].address[i],
i_D2 = dfi.phases[0].address[i],
i_D3 = dfi.phases[1].address[i],
i_D4 = dfi.phases[1].address[i],
i_D5 = dfi.phases[2].address[i],
i_D6 = dfi.phases[2].address[i],
i_D7 = dfi.phases[3].address[i],
i_D8 = dfi.phases[3].address[i],
i_OCE = 1,
o_OQ = address if with_odelay else pads.a[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._cdly_rst.re,
i_LDPIPEEN = 0,
i_CE = self._cdly_inc.re,
i_INC = 1,
o_ODATAIN = address,
o_DATAOUT = pads.a[i],
)
for i in range(bankbits):
bank = 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(),
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = dfi.phases[0].bank[i],
i_D2 = dfi.phases[0].bank[i],
i_D3 = dfi.phases[1].bank[i],
i_D4 = dfi.phases[1].bank[i],
i_D5 = dfi.phases[2].bank[i],
i_D6 = dfi.phases[2].bank[i],
i_D7 = dfi.phases[3].bank[i],
i_D8 = dfi.phases[3].bank[i],
i_OCE = 1,
o_OQ = bank if with_odelay else pads.ba[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._cdly_rst.re,
i_LDPIPEEN = 0,
i_CE = self._cdly_inc.re,
i_INC = 1,
o_ODATAIN = bank,
o_DATAOUT = pads.ba[i],
)
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
if hasattr(pads, "reset_n"):
controls.append("reset_n")
if hasattr(pads, "cs_n"):
controls.append("cs_n")
for name in controls:
for i in range(len(getattr(pads, name))):
cmd = Signal()
# Clock --------------------------------------------------------------------------------
ddr_clk = "sys2x" if nphases == 2 else "sys4x"
for i in range(len(pads.clk_p)):
sd_clk_se_nodelay = Signal()
sd_clk_se_delayed = Signal()
self.specials += Instance("OSERDESE2",
p_SERDES_MODE = "MASTER",
p_DATA_WIDTH = 2*nphases,
@ -240,16 +112,63 @@ class S7DDRPHY(Module, AutoCSR):
i_RST = ResetSignal(),
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = getattr(dfi.phases[0], name)[i],
i_D2 = getattr(dfi.phases[0], name)[i],
i_D3 = getattr(dfi.phases[1], name)[i],
i_D4 = getattr(dfi.phases[1], name)[i],
i_D5 = getattr(dfi.phases[2], name)[i],
i_D6 = getattr(dfi.phases[2], name)[i],
i_D7 = getattr(dfi.phases[3], name)[i],
i_D8 = getattr(dfi.phases[3], name)[i],
i_D1 = 0,
i_D2 = 1,
i_D3 = 0,
i_D4 = 1,
i_D5 = 0,
i_D6 = 1,
i_D7 = 0,
i_D8 = 1,
o_OQ = sd_clk_se_nodelay,
i_OCE = 1,
o_OQ = cmd if with_odelay else getattr(pads, name)[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._cdly_rst.re,
i_LDPIPEEN = 0,
i_CE = self._cdly_inc.re,
i_INC = 1,
o_ODATAIN = sd_clk_se_nodelay,
o_DATAOUT = sd_clk_se_delayed,
)
self.specials += Instance("OBUFDS",
i_I = sd_clk_se_delayed if with_odelay else sd_clk_se_nodelay,
o_O = pads.clk_p[i],
o_OB = pads.clk_n[i]
)
# Addresses and Commands -------------------------------------------------------------------
for i in range(addressbits):
address = 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(),
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = dfi.phases[0].address[i],
i_D2 = dfi.phases[0].address[i],
i_D3 = dfi.phases[1].address[i],
i_D4 = dfi.phases[1].address[i],
i_D5 = dfi.phases[2].address[i],
i_D6 = dfi.phases[2].address[i],
i_D7 = dfi.phases[3].address[i],
i_D8 = dfi.phases[3].address[i],
i_OCE = 1,
o_OQ = address if with_odelay else pads.a[i],
)
if with_odelay:
self.specials += Instance("ODELAYE2",
@ -266,9 +185,95 @@ class S7DDRPHY(Module, AutoCSR):
i_LDPIPEEN = 0,
i_CE = self._cdly_inc.re,
i_INC = 1,
o_ODATAIN = cmd,
o_DATAOUT = getattr(pads, name)[i],
o_ODATAIN = address,
o_DATAOUT = pads.a[i],
)
for i in range(bankbits):
bank = 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(),
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = dfi.phases[0].bank[i],
i_D2 = dfi.phases[0].bank[i],
i_D3 = dfi.phases[1].bank[i],
i_D4 = dfi.phases[1].bank[i],
i_D5 = dfi.phases[2].bank[i],
i_D6 = dfi.phases[2].bank[i],
i_D7 = dfi.phases[3].bank[i],
i_D8 = dfi.phases[3].bank[i],
i_OCE = 1,
o_OQ = bank if with_odelay else pads.ba[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._cdly_rst.re,
i_LDPIPEEN = 0,
i_CE = self._cdly_inc.re,
i_INC = 1,
o_ODATAIN = bank,
o_DATAOUT = pads.ba[i],
)
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
if hasattr(pads, "reset_n"):
controls.append("reset_n")
if hasattr(pads, "cs_n"):
controls.append("cs_n")
for name in controls:
for i in range(len(getattr(pads, name))):
cmd = 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(),
i_CLK = ClockSignal(ddr_clk),
i_CLKDIV = ClockSignal(),
i_D1 = getattr(dfi.phases[0], name)[i],
i_D2 = getattr(dfi.phases[0], name)[i],
i_D3 = getattr(dfi.phases[1], name)[i],
i_D4 = getattr(dfi.phases[1], name)[i],
i_D5 = getattr(dfi.phases[2], name)[i],
i_D6 = getattr(dfi.phases[2], name)[i],
i_D7 = getattr(dfi.phases[3], name)[i],
i_D8 = getattr(dfi.phases[3], name)[i],
i_OCE = 1,
o_OQ = cmd if with_odelay else getattr(pads, name)[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._cdly_rst.re,
i_LDPIPEEN = 0,
i_CE = self._cdly_inc.re,
i_INC = 1,
o_ODATAIN = cmd,
o_DATAOUT = getattr(pads, name)[i],
)
# DQS and DM -------------------------------------------------------------------------------
oe_dqs = Signal()

View File

@ -24,6 +24,7 @@ class USDDRPHY(Module, AutoCSR):
iodelay_clk_freq = 200e6,
cmd_latency = 0,
sim_device = "ULTRASCALE"):
pads = PHYPadsCombiner(pads)
tck = 2/(2*4*sys_clk_freq)
addressbits = len(pads.a)
if memtype == "DDR4":
@ -93,49 +94,13 @@ class USDDRPHY(Module, AutoCSR):
# # #
# Clock ------------------------------------------------------------------------------------
clk_o_nodelay = Signal()
clk_o_delayed = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = sim_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(),
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = 0b10101010,
o_OQ = clk_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "VARIABLE",
p_DELAY_VALUE = 0,
i_RST = self._cdly_rst.re,
i_CLK = ClockSignal(),
i_EN_VTC = self._en_vtc.storage,
i_CE = self._cdly_inc.re,
i_INC = 1,
i_ODATAIN = clk_o_nodelay,
o_DATAOUT = clk_o_delayed,
),
Instance("OBUFDS",
i_I = clk_o_delayed,
o_O = pads.clk_p,
o_OB = pads.clk_n,
)
]
# Iterate on pads groups -------------------------------------------------------------------
for pads_group in range(len(pads.groups)):
pads.sel_group(pads_group)
# Addresses and Commands -------------------------------------------------------------------
for i in range(addressbits if memtype=="DDR3" else addressbits-3):
a_o_nodelay = Signal()
# Clock ------------------------------------------------------------------------------------
clk_o_nodelay = Signal()
clk_o_delayed = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = sim_device,
@ -147,11 +112,8 @@ class USDDRPHY(Module, AutoCSR):
i_RST = ResetSignal(),
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = Cat(dfi.phases[0].address[i], dfi.phases[0].address[i],
dfi.phases[1].address[i], dfi.phases[1].address[i],
dfi.phases[2].address[i], dfi.phases[2].address[i],
dfi.phases[3].address[i], dfi.phases[3].address[i]),
o_OQ = a_o_nodelay,
i_D = 0b10101010,
o_OQ = clk_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
@ -166,99 +128,142 @@ class USDDRPHY(Module, AutoCSR):
i_EN_VTC = self._en_vtc.storage,
i_CE = self._cdly_inc.re,
i_INC = 1,
i_ODATAIN = a_o_nodelay,
o_DATAOUT = pads.a[i],
i_ODATAIN = clk_o_nodelay,
o_DATAOUT = clk_o_delayed,
),
Instance("OBUFDS",
i_I = clk_o_delayed,
o_O = pads.clk_p,
o_OB = pads.clk_n,
)
]
pads_ba = Signal(bankbits)
if memtype == "DDR3":
self.comb += pads.ba.eq(pads_ba)
else:
self.comb += pads.ba.eq(pads_ba[:len(pads.ba)])
self.comb += pads.bg.eq(pads_ba[len(pads.ba):])
for i in range(bankbits):
ba_o_nodelay = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = sim_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(),
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = Cat(
dfi.phases[0].bank[i], dfi.phases[0].bank[i],
dfi.phases[1].bank[i], dfi.phases[1].bank[i],
dfi.phases[2].bank[i], dfi.phases[2].bank[i],
dfi.phases[3].bank[i], dfi.phases[3].bank[i]),
o_OQ = ba_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "VARIABLE",
p_DELAY_VALUE = 0,
i_RST = self._cdly_rst.re,
i_CLK = ClockSignal(),
i_EN_VTC = self._en_vtc.storage,
i_CE = self._cdly_inc.re,
i_INC = 1,
i_ODATAIN = ba_o_nodelay,
o_DATAOUT = pads_ba[i],
)
]
# Addresses and Commands -------------------------------------------------------------------
for i in range(addressbits if memtype=="DDR3" else addressbits-3):
a_o_nodelay = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = sim_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(),
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = Cat(dfi.phases[0].address[i], dfi.phases[0].address[i],
dfi.phases[1].address[i], dfi.phases[1].address[i],
dfi.phases[2].address[i], dfi.phases[2].address[i],
dfi.phases[3].address[i], dfi.phases[3].address[i]),
o_OQ = a_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "VARIABLE",
p_DELAY_VALUE = 0,
i_RST = self._cdly_rst.re,
i_CLK = ClockSignal(),
i_EN_VTC = self._en_vtc.storage,
i_CE = self._cdly_inc.re,
i_INC = 1,
i_ODATAIN = a_o_nodelay,
o_DATAOUT = pads.a[i],
)
]
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
if hasattr(pads, "reset_n"):
controls.append("reset_n")
if hasattr(pads, "cs_n"):
controls.append("cs_n")
if hasattr(pads, "act_n"):
controls.append("act_n")
for name in controls:
x_o_nodelay = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = sim_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(),
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = Cat(
getattr(dfi.phases[0], name), getattr(dfi.phases[0], name),
getattr(dfi.phases[1], name), getattr(dfi.phases[1], name),
getattr(dfi.phases[2], name), getattr(dfi.phases[2], name),
getattr(dfi.phases[3], name), getattr(dfi.phases[3], name)),
o_OQ = x_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "VARIABLE",
p_DELAY_VALUE = 0,
i_RST = self._cdly_rst.re,
i_CLK = ClockSignal(),
i_EN_VTC = self._en_vtc.storage,
i_CE = self._cdly_inc.re,
i_INC = 1,
i_ODATAIN = x_o_nodelay,
o_DATAOUT = getattr(pads, name),
)
]
pads_ba = Signal(bankbits)
if memtype == "DDR3":
self.comb += pads.ba.eq(pads_ba)
else:
self.comb += pads.ba.eq(pads_ba[:len(pads.ba)])
self.comb += pads.bg.eq(pads_ba[len(pads.ba):])
for i in range(bankbits):
ba_o_nodelay = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = sim_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(),
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = Cat(
dfi.phases[0].bank[i], dfi.phases[0].bank[i],
dfi.phases[1].bank[i], dfi.phases[1].bank[i],
dfi.phases[2].bank[i], dfi.phases[2].bank[i],
dfi.phases[3].bank[i], dfi.phases[3].bank[i]),
o_OQ = ba_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "VARIABLE",
p_DELAY_VALUE = 0,
i_RST = self._cdly_rst.re,
i_CLK = ClockSignal(),
i_EN_VTC = self._en_vtc.storage,
i_CE = self._cdly_inc.re,
i_INC = 1,
i_ODATAIN = ba_o_nodelay,
o_DATAOUT = pads_ba[i],
)
]
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
if hasattr(pads, "reset_n"):
controls.append("reset_n")
if hasattr(pads, "cs_n"):
controls.append("cs_n")
if hasattr(pads, "act_n"):
controls.append("act_n")
for name in controls:
x_o_nodelay = Signal()
self.specials += [
Instance("OSERDESE3",
p_SIM_DEVICE = sim_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(),
i_CLK = ClockSignal("sys4x"),
i_CLKDIV = ClockSignal(),
i_D = Cat(
getattr(dfi.phases[0], name), getattr(dfi.phases[0], name),
getattr(dfi.phases[1], name), getattr(dfi.phases[1], name),
getattr(dfi.phases[2], name), getattr(dfi.phases[2], name),
getattr(dfi.phases[3], name), getattr(dfi.phases[3], name)),
o_OQ = x_o_nodelay,
),
Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
p_DELAY_FORMAT = "TIME",
p_DELAY_TYPE = "VARIABLE",
p_DELAY_VALUE = 0,
i_RST = self._cdly_rst.re,
i_CLK = ClockSignal(),
i_EN_VTC = self._en_vtc.storage,
i_CE = self._cdly_inc.re,
i_INC = 1,
i_ODATAIN = x_o_nodelay,
o_DATAOUT = getattr(pads, name),
)
]
# DQS and DM -------------------------------------------------------------------------------
oe_dqs = Signal()