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:
parent
5e068f412b
commit
26564ba93c
|
@ -82,6 +82,7 @@ class ECP5DDRPHYInit(Module):
|
||||||
|
|
||||||
class ECP5DDRPHY(Module, AutoCSR):
|
class ECP5DDRPHY(Module, AutoCSR):
|
||||||
def __init__(self, pads, sys_clk_freq=100e6):
|
def __init__(self, pads, sys_clk_freq=100e6):
|
||||||
|
pads = PHYPadsCombiner(pads)
|
||||||
memtype = "DDR3"
|
memtype = "DDR3"
|
||||||
tck = 2/(2*2*sys_clk_freq)
|
tck = 2/(2*2*sys_clk_freq)
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
|
@ -138,61 +139,65 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
|
|
||||||
bl8_sel = Signal()
|
bl8_sel = Signal()
|
||||||
|
|
||||||
# Clock ------------------------------------------------------------------------------------
|
# Iterate on pads groups -------------------------------------------------------------------
|
||||||
for i in range(len(pads.clk_p)):
|
for pads_group in range(len(pads.groups)):
|
||||||
sd_clk_se = Signal()
|
pads.sel_group(pads_group)
|
||||||
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]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Addresses and Commands -------------------------------------------------------------------
|
# Clock ------------------------------------------------------------------------------------
|
||||||
for i in range(addressbits):
|
for i in range(len(pads.clk_p)):
|
||||||
self.specials += Instance("ODDRX2F",
|
sd_clk_se = Signal()
|
||||||
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",
|
self.specials += Instance("ODDRX2F",
|
||||||
i_RST = ResetSignal("sys2x"),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_SCLK = ClockSignal(),
|
i_SCLK = ClockSignal(),
|
||||||
i_D0 = getattr(dfi.phases[0], name)[i],
|
i_D0 = 0,
|
||||||
i_D1 = getattr(dfi.phases[0], name)[i],
|
i_D1 = 1,
|
||||||
i_D2 = getattr(dfi.phases[1], name)[i],
|
i_D2 = 0,
|
||||||
i_D3 = getattr(dfi.phases[1], name)[i],
|
i_D3 = 1,
|
||||||
o_Q = getattr(pads, name)[i]
|
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 ---------------------------------------------------------------------------------------
|
# DQ ---------------------------------------------------------------------------------------
|
||||||
oe_dq = Signal()
|
oe_dq = Signal()
|
||||||
oe_dqs = Signal()
|
oe_dqs = Signal()
|
||||||
|
|
|
@ -18,13 +18,14 @@ from migen import *
|
||||||
from migen.genlib.record import *
|
from migen.genlib.record import *
|
||||||
from migen.fhdl.specials import Tristate
|
from migen.fhdl.specials import Tristate
|
||||||
|
|
||||||
from litedram.common import PhySettings
|
from litedram.common import *
|
||||||
from litedram.phy.dfi import *
|
from litedram.phy.dfi import *
|
||||||
|
|
||||||
# Generic SDR PHY ----------------------------------------------------------------------------------
|
# Generic SDR PHY ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
class GENSDRPHY(Module):
|
class GENSDRPHY(Module):
|
||||||
def __init__(self, pads, cl=2):
|
def __init__(self, pads, cl=2):
|
||||||
|
pads = PHYPadsCombiner(pads)
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
bankbits = len(pads.ba)
|
bankbits = len(pads.ba)
|
||||||
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
||||||
|
@ -52,33 +53,39 @@ class GENSDRPHY(Module):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# Addresses and Commands -------------------------------------------------------------------
|
# Iterate on pads groups -------------------------------------------------------------------
|
||||||
self.sync += [
|
for pads_group in range(len(pads.groups)):
|
||||||
pads.a.eq(dfi.p0.address),
|
pads.sel_group(pads_group)
|
||||||
pads.ba.eq(dfi.p0.bank),
|
|
||||||
pads.cas_n.eq(dfi.p0.cas_n),
|
# Addresses and Commands ---------------------------------------------------------------
|
||||||
pads.ras_n.eq(dfi.p0.ras_n),
|
self.sync += [
|
||||||
pads.we_n.eq(dfi.p0.we_n)
|
pads.a.eq(dfi.p0.address),
|
||||||
]
|
pads.ba.eq(dfi.p0.bank),
|
||||||
if hasattr(pads, "cke"):
|
pads.cas_n.eq(dfi.p0.cas_n),
|
||||||
self.sync += pads.cke.eq(dfi.p0.cke)
|
pads.ras_n.eq(dfi.p0.ras_n),
|
||||||
if hasattr(pads, "cs_n"):
|
pads.we_n.eq(dfi.p0.we_n)
|
||||||
self.sync += pads.cs_n.eq(dfi.p0.cs_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/DQS/DM Data ---------------------------------------------------------------------------
|
||||||
dq_o = Signal(databits)
|
dq_o = Signal(databits)
|
||||||
dq_oe = Signal()
|
dq_oe = Signal()
|
||||||
dq_i = Signal(databits)
|
dq_i = Signal(databits)
|
||||||
self.sync += dq_o.eq(dfi.p0.wrdata)
|
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"):
|
if hasattr(pads, "dm"):
|
||||||
assert len(pads.dm)*8 == databits
|
assert len(pads.dm)*8 == databits
|
||||||
self.sync += \
|
for i in range(len(pads.dm)):
|
||||||
If(dfi.p0.wrdata_en,
|
self.sync += \
|
||||||
pads.dm.eq(dfi.p0.wrdata_mask)
|
If(dfi.p0.wrdata_en,
|
||||||
).Else(
|
pads.dm[i].eq(dfi.p0.wrdata_mask)
|
||||||
pads.dm.eq(0)
|
).Else(
|
||||||
)
|
pads.dm[i].eq(0)
|
||||||
|
)
|
||||||
dq_in = Signal(databits)
|
dq_in = Signal(databits)
|
||||||
self.sync.sys_ps += dq_in.eq(dq_i)
|
self.sync.sys_ps += dq_in.eq(dq_i)
|
||||||
self.sync += dfi.p0.rddata.eq(dq_in)
|
self.sync += dfi.p0.rddata.eq(dq_in)
|
||||||
|
|
|
@ -27,12 +27,13 @@ from migen import *
|
||||||
from migen.genlib.record import *
|
from migen.genlib.record import *
|
||||||
from migen.fhdl.decorators import ClockDomainsRenamer
|
from migen.fhdl.decorators import ClockDomainsRenamer
|
||||||
|
|
||||||
from litedram.common import PhySettings
|
from litedram.common import *
|
||||||
from litedram.phy.dfi import *
|
from litedram.phy.dfi import *
|
||||||
|
|
||||||
|
|
||||||
class S6HalfRateDDRPHY(Module):
|
class S6HalfRateDDRPHY(Module):
|
||||||
def __init__(self, pads, memtype, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
|
def __init__(self, pads, memtype, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
|
||||||
|
pads = PHYPadsCombiner(pads)
|
||||||
if memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
|
if memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
|
||||||
raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
|
raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
|
@ -130,19 +131,23 @@ class S6HalfRateDDRPHY(Module):
|
||||||
r_dfi[n].we_n.eq(phase.we_n)
|
r_dfi[n].we_n.eq(phase.we_n)
|
||||||
]
|
]
|
||||||
|
|
||||||
# output cmds
|
# Iterate on pads groups -------------------------------------------------------------------
|
||||||
sd_sdram_half += [
|
for pads_group in range(len(pads.groups)):
|
||||||
pads.a.eq(r_dfi[phase_sel].address),
|
pads.sel_group(pads_group)
|
||||||
pads.ba.eq(r_dfi[phase_sel].bank),
|
|
||||||
pads.cke.eq(r_dfi[phase_sel].cke),
|
# output cmds
|
||||||
pads.ras_n.eq(r_dfi[phase_sel].ras_n),
|
sd_sdram_half += [
|
||||||
pads.cas_n.eq(r_dfi[phase_sel].cas_n),
|
pads.a.eq(r_dfi[phase_sel].address),
|
||||||
pads.we_n.eq(r_dfi[phase_sel].we_n)
|
pads.ba.eq(r_dfi[phase_sel].bank),
|
||||||
]
|
pads.cke.eq(r_dfi[phase_sel].cke),
|
||||||
# optional pads
|
pads.ras_n.eq(r_dfi[phase_sel].ras_n),
|
||||||
for name in "reset_n", "cs_n", "odt":
|
pads.cas_n.eq(r_dfi[phase_sel].cas_n),
|
||||||
if hasattr(pads, name):
|
pads.we_n.eq(r_dfi[phase_sel].we_n)
|
||||||
sd_sdram_half += getattr(pads, name).eq(getattr(r_dfi[phase_sel], name))
|
]
|
||||||
|
# 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 ----------------------------------------------------------------------------------
|
||||||
bitslip_cnt = Signal(4)
|
bitslip_cnt = Signal(4)
|
||||||
|
@ -406,6 +411,7 @@ class S6HalfRateDDRPHY(Module):
|
||||||
|
|
||||||
class S6QuarterRateDDRPHY(Module):
|
class S6QuarterRateDDRPHY(Module):
|
||||||
def __init__(self, pads, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
|
def __init__(self, pads, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
|
||||||
|
pads = PHYPadsCombiner(pads)
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
bankbits = len(pads.ba)
|
bankbits = len(pads.ba)
|
||||||
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
||||||
|
|
|
@ -25,6 +25,7 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
iodelay_clk_freq = 200e6,
|
iodelay_clk_freq = 200e6,
|
||||||
cmd_latency = 0):
|
cmd_latency = 0):
|
||||||
assert not (memtype == "DDR3" and nphases == 2) # FIXME: Needs BL8 support for nphases=2
|
assert not (memtype == "DDR3" and nphases == 2) # FIXME: Needs BL8 support for nphases=2
|
||||||
|
pads = PHYPadsCombiner(pads)
|
||||||
tck = 2/(2*nphases*sys_clk_freq)
|
tck = 2/(2*nphases*sys_clk_freq)
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
bankbits = len(pads.ba)
|
bankbits = len(pads.ba)
|
||||||
|
@ -93,144 +94,15 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# Clock ------------------------------------------------------------------------------------
|
# Iterate on pads groups -------------------------------------------------------------------
|
||||||
ddr_clk = "sys2x" if nphases == 2 else "sys4x"
|
for pads_group in range(len(pads.groups)):
|
||||||
for i in range(len(pads.clk_p)):
|
pads.sel_group(pads_group)
|
||||||
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]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Addresses and Commands -------------------------------------------------------------------
|
# Clock --------------------------------------------------------------------------------
|
||||||
for i in range(addressbits):
|
ddr_clk = "sys2x" if nphases == 2 else "sys4x"
|
||||||
address = Signal()
|
for i in range(len(pads.clk_p)):
|
||||||
self.specials += Instance("OSERDESE2",
|
sd_clk_se_nodelay = Signal()
|
||||||
p_SERDES_MODE = "MASTER",
|
sd_clk_se_delayed = Signal()
|
||||||
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()
|
|
||||||
self.specials += Instance("OSERDESE2",
|
self.specials += Instance("OSERDESE2",
|
||||||
p_SERDES_MODE = "MASTER",
|
p_SERDES_MODE = "MASTER",
|
||||||
p_DATA_WIDTH = 2*nphases,
|
p_DATA_WIDTH = 2*nphases,
|
||||||
|
@ -240,16 +112,63 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
i_RST = ResetSignal(),
|
i_RST = ResetSignal(),
|
||||||
i_CLK = ClockSignal(ddr_clk),
|
i_CLK = ClockSignal(ddr_clk),
|
||||||
i_CLKDIV = ClockSignal(),
|
i_CLKDIV = ClockSignal(),
|
||||||
i_D1 = getattr(dfi.phases[0], name)[i],
|
i_D1 = 0,
|
||||||
i_D2 = getattr(dfi.phases[0], name)[i],
|
i_D2 = 1,
|
||||||
i_D3 = getattr(dfi.phases[1], name)[i],
|
i_D3 = 0,
|
||||||
i_D4 = getattr(dfi.phases[1], name)[i],
|
i_D4 = 1,
|
||||||
i_D5 = getattr(dfi.phases[2], name)[i],
|
i_D5 = 0,
|
||||||
i_D6 = getattr(dfi.phases[2], name)[i],
|
i_D6 = 1,
|
||||||
i_D7 = getattr(dfi.phases[3], name)[i],
|
i_D7 = 0,
|
||||||
i_D8 = getattr(dfi.phases[3], name)[i],
|
i_D8 = 1,
|
||||||
|
o_OQ = sd_clk_se_nodelay,
|
||||||
i_OCE = 1,
|
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:
|
if with_odelay:
|
||||||
self.specials += Instance("ODELAYE2",
|
self.specials += Instance("ODELAYE2",
|
||||||
|
@ -266,9 +185,95 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
i_LDPIPEEN = 0,
|
i_LDPIPEEN = 0,
|
||||||
i_CE = self._cdly_inc.re,
|
i_CE = self._cdly_inc.re,
|
||||||
i_INC = 1,
|
i_INC = 1,
|
||||||
o_ODATAIN = cmd,
|
o_ODATAIN = address,
|
||||||
o_DATAOUT = getattr(pads, name)[i],
|
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 -------------------------------------------------------------------------------
|
# DQS and DM -------------------------------------------------------------------------------
|
||||||
oe_dqs = Signal()
|
oe_dqs = Signal()
|
||||||
|
|
|
@ -24,6 +24,7 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
iodelay_clk_freq = 200e6,
|
iodelay_clk_freq = 200e6,
|
||||||
cmd_latency = 0,
|
cmd_latency = 0,
|
||||||
sim_device = "ULTRASCALE"):
|
sim_device = "ULTRASCALE"):
|
||||||
|
pads = PHYPadsCombiner(pads)
|
||||||
tck = 2/(2*4*sys_clk_freq)
|
tck = 2/(2*4*sys_clk_freq)
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
if memtype == "DDR4":
|
if memtype == "DDR4":
|
||||||
|
@ -93,49 +94,13 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# Clock ------------------------------------------------------------------------------------
|
# Iterate on pads groups -------------------------------------------------------------------
|
||||||
clk_o_nodelay = Signal()
|
for pads_group in range(len(pads.groups)):
|
||||||
clk_o_delayed = Signal()
|
pads.sel_group(pads_group)
|
||||||
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,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Addresses and Commands -------------------------------------------------------------------
|
# Clock ------------------------------------------------------------------------------------
|
||||||
for i in range(addressbits if memtype=="DDR3" else addressbits-3):
|
clk_o_nodelay = Signal()
|
||||||
a_o_nodelay = Signal()
|
clk_o_delayed = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("OSERDESE3",
|
Instance("OSERDESE3",
|
||||||
p_SIM_DEVICE = sim_device,
|
p_SIM_DEVICE = sim_device,
|
||||||
|
@ -147,11 +112,8 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
i_RST = ResetSignal(),
|
i_RST = ResetSignal(),
|
||||||
i_CLK = ClockSignal("sys4x"),
|
i_CLK = ClockSignal("sys4x"),
|
||||||
i_CLKDIV = ClockSignal(),
|
i_CLKDIV = ClockSignal(),
|
||||||
i_D = Cat(dfi.phases[0].address[i], dfi.phases[0].address[i],
|
i_D = 0b10101010,
|
||||||
dfi.phases[1].address[i], dfi.phases[1].address[i],
|
o_OQ = clk_o_nodelay,
|
||||||
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",
|
Instance("ODELAYE3",
|
||||||
p_SIM_DEVICE = sim_device,
|
p_SIM_DEVICE = sim_device,
|
||||||
|
@ -166,99 +128,142 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
i_EN_VTC = self._en_vtc.storage,
|
i_EN_VTC = self._en_vtc.storage,
|
||||||
i_CE = self._cdly_inc.re,
|
i_CE = self._cdly_inc.re,
|
||||||
i_INC = 1,
|
i_INC = 1,
|
||||||
i_ODATAIN = a_o_nodelay,
|
i_ODATAIN = clk_o_nodelay,
|
||||||
o_DATAOUT = pads.a[i],
|
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)
|
# Addresses and Commands -------------------------------------------------------------------
|
||||||
if memtype == "DDR3":
|
for i in range(addressbits if memtype=="DDR3" else addressbits-3):
|
||||||
self.comb += pads.ba.eq(pads_ba)
|
a_o_nodelay = Signal()
|
||||||
else:
|
self.specials += [
|
||||||
self.comb += pads.ba.eq(pads_ba[:len(pads.ba)])
|
Instance("OSERDESE3",
|
||||||
self.comb += pads.bg.eq(pads_ba[len(pads.ba):])
|
p_SIM_DEVICE = sim_device,
|
||||||
for i in range(bankbits):
|
p_DATA_WIDTH = 8,
|
||||||
ba_o_nodelay = Signal()
|
p_INIT = 0,
|
||||||
self.specials += [
|
p_IS_RST_INVERTED = 0,
|
||||||
Instance("OSERDESE3",
|
p_IS_CLK_INVERTED = 0,
|
||||||
p_SIM_DEVICE = sim_device,
|
p_IS_CLKDIV_INVERTED = 0,
|
||||||
p_DATA_WIDTH = 8,
|
i_RST = ResetSignal(),
|
||||||
p_INIT = 0,
|
i_CLK = ClockSignal("sys4x"),
|
||||||
p_IS_RST_INVERTED = 0,
|
i_CLKDIV = ClockSignal(),
|
||||||
p_IS_CLK_INVERTED = 0,
|
i_D = Cat(dfi.phases[0].address[i], dfi.phases[0].address[i],
|
||||||
p_IS_CLKDIV_INVERTED = 0,
|
dfi.phases[1].address[i], dfi.phases[1].address[i],
|
||||||
i_RST = ResetSignal(),
|
dfi.phases[2].address[i], dfi.phases[2].address[i],
|
||||||
i_CLK = ClockSignal("sys4x"),
|
dfi.phases[3].address[i], dfi.phases[3].address[i]),
|
||||||
i_CLKDIV = ClockSignal(),
|
o_OQ = a_o_nodelay,
|
||||||
i_D = Cat(
|
),
|
||||||
dfi.phases[0].bank[i], dfi.phases[0].bank[i],
|
Instance("ODELAYE3",
|
||||||
dfi.phases[1].bank[i], dfi.phases[1].bank[i],
|
p_SIM_DEVICE = sim_device,
|
||||||
dfi.phases[2].bank[i], dfi.phases[2].bank[i],
|
p_CASCADE = "NONE",
|
||||||
dfi.phases[3].bank[i], dfi.phases[3].bank[i]),
|
p_UPDATE_MODE = "ASYNC",
|
||||||
o_OQ = ba_o_nodelay,
|
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
|
||||||
),
|
p_DELAY_FORMAT = "TIME",
|
||||||
Instance("ODELAYE3",
|
p_DELAY_TYPE = "VARIABLE",
|
||||||
p_SIM_DEVICE = sim_device,
|
p_DELAY_VALUE = 0,
|
||||||
p_CASCADE = "NONE",
|
i_RST = self._cdly_rst.re,
|
||||||
p_UPDATE_MODE = "ASYNC",
|
i_CLK = ClockSignal(),
|
||||||
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
|
i_EN_VTC = self._en_vtc.storage,
|
||||||
p_DELAY_FORMAT = "TIME",
|
i_CE = self._cdly_inc.re,
|
||||||
p_DELAY_TYPE = "VARIABLE",
|
i_INC = 1,
|
||||||
p_DELAY_VALUE = 0,
|
i_ODATAIN = a_o_nodelay,
|
||||||
i_RST = self._cdly_rst.re,
|
o_DATAOUT = pads.a[i],
|
||||||
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"]
|
pads_ba = Signal(bankbits)
|
||||||
if hasattr(pads, "reset_n"):
|
if memtype == "DDR3":
|
||||||
controls.append("reset_n")
|
self.comb += pads.ba.eq(pads_ba)
|
||||||
if hasattr(pads, "cs_n"):
|
else:
|
||||||
controls.append("cs_n")
|
self.comb += pads.ba.eq(pads_ba[:len(pads.ba)])
|
||||||
if hasattr(pads, "act_n"):
|
self.comb += pads.bg.eq(pads_ba[len(pads.ba):])
|
||||||
controls.append("act_n")
|
for i in range(bankbits):
|
||||||
for name in controls:
|
ba_o_nodelay = Signal()
|
||||||
x_o_nodelay = Signal()
|
self.specials += [
|
||||||
self.specials += [
|
Instance("OSERDESE3",
|
||||||
Instance("OSERDESE3",
|
p_SIM_DEVICE = sim_device,
|
||||||
p_SIM_DEVICE = sim_device,
|
p_DATA_WIDTH = 8,
|
||||||
p_DATA_WIDTH = 8,
|
p_INIT = 0,
|
||||||
p_INIT = 0,
|
p_IS_RST_INVERTED = 0,
|
||||||
p_IS_RST_INVERTED = 0,
|
p_IS_CLK_INVERTED = 0,
|
||||||
p_IS_CLK_INVERTED = 0,
|
p_IS_CLKDIV_INVERTED = 0,
|
||||||
p_IS_CLKDIV_INVERTED = 0,
|
i_RST = ResetSignal(),
|
||||||
i_RST = ResetSignal(),
|
i_CLK = ClockSignal("sys4x"),
|
||||||
i_CLK = ClockSignal("sys4x"),
|
i_CLKDIV = ClockSignal(),
|
||||||
i_CLKDIV = ClockSignal(),
|
i_D = Cat(
|
||||||
i_D = Cat(
|
dfi.phases[0].bank[i], dfi.phases[0].bank[i],
|
||||||
getattr(dfi.phases[0], name), getattr(dfi.phases[0], name),
|
dfi.phases[1].bank[i], dfi.phases[1].bank[i],
|
||||||
getattr(dfi.phases[1], name), getattr(dfi.phases[1], name),
|
dfi.phases[2].bank[i], dfi.phases[2].bank[i],
|
||||||
getattr(dfi.phases[2], name), getattr(dfi.phases[2], name),
|
dfi.phases[3].bank[i], dfi.phases[3].bank[i]),
|
||||||
getattr(dfi.phases[3], name), getattr(dfi.phases[3], name)),
|
o_OQ = ba_o_nodelay,
|
||||||
o_OQ = x_o_nodelay,
|
),
|
||||||
),
|
Instance("ODELAYE3",
|
||||||
Instance("ODELAYE3",
|
p_SIM_DEVICE = sim_device,
|
||||||
p_SIM_DEVICE = sim_device,
|
p_CASCADE = "NONE",
|
||||||
p_CASCADE = "NONE",
|
p_UPDATE_MODE = "ASYNC",
|
||||||
p_UPDATE_MODE = "ASYNC",
|
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
|
||||||
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
|
p_DELAY_FORMAT = "TIME",
|
||||||
p_DELAY_FORMAT = "TIME",
|
p_DELAY_TYPE = "VARIABLE",
|
||||||
p_DELAY_TYPE = "VARIABLE",
|
p_DELAY_VALUE = 0,
|
||||||
p_DELAY_VALUE = 0,
|
i_RST = self._cdly_rst.re,
|
||||||
i_RST = self._cdly_rst.re,
|
i_CLK = ClockSignal(),
|
||||||
i_CLK = ClockSignal(),
|
i_EN_VTC = self._en_vtc.storage,
|
||||||
i_EN_VTC = self._en_vtc.storage,
|
i_CE = self._cdly_inc.re,
|
||||||
i_CE = self._cdly_inc.re,
|
i_INC = 1,
|
||||||
i_INC = 1,
|
i_ODATAIN = ba_o_nodelay,
|
||||||
i_ODATAIN = x_o_nodelay,
|
o_DATAOUT = pads_ba[i],
|
||||||
o_DATAOUT = getattr(pads, name),
|
)
|
||||||
)
|
]
|
||||||
]
|
|
||||||
|
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 -------------------------------------------------------------------------------
|
# DQS and DM -------------------------------------------------------------------------------
|
||||||
oe_dqs = Signal()
|
oe_dqs = Signal()
|
||||||
|
|
Loading…
Reference in New Issue