phy/ecp5ddrphy: improve presentation/readability
This commit is contained in:
parent
bb1b431184
commit
e0966e2ed3
|
@ -1,5 +1,5 @@
|
||||||
# This file is Copyright (c) 2019 David Shah <dave@ds0.me>
|
# This file is Copyright (c) 2019 David Shah <dave@ds0.me>
|
||||||
# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
# This file is Copyright (c) 2019-2020 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
# 1:2 frequency-ratio DDR3 PHY for Lattice's ECP5
|
# 1:2 frequency-ratio DDR3 PHY for Lattice's ECP5
|
||||||
|
@ -23,7 +23,7 @@ from litedram.phy.dfi import *
|
||||||
class ECP5DDRPHYInit(Module):
|
class ECP5DDRPHYInit(Module):
|
||||||
def __init__(self, eclk_cd):
|
def __init__(self, eclk_cd):
|
||||||
self.pause = Signal()
|
self.pause = Signal()
|
||||||
self.stop = Signal()
|
self.stop = Signal()
|
||||||
self.delay = Signal()
|
self.delay = Signal()
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
@ -39,14 +39,14 @@ class ECP5DDRPHYInit(Module):
|
||||||
_lock = Signal()
|
_lock = Signal()
|
||||||
delay = Signal()
|
delay = Signal()
|
||||||
self.specials += Instance("DDRDLLA",
|
self.specials += Instance("DDRDLLA",
|
||||||
i_CLK=ClockSignal("sys2x"),
|
i_CLK = ClockSignal("sys2x"),
|
||||||
i_RST=ResetSignal(),
|
i_RST = ResetSignal(),
|
||||||
i_UDDCNTLN=~update,
|
i_UDDCNTLN = ~update,
|
||||||
i_FREEZE=freeze,
|
i_FREEZE = freeze,
|
||||||
o_DDRDEL=delay,
|
o_DDRDEL = delay,
|
||||||
o_LOCK=_lock
|
o_LOCK = _lock
|
||||||
)
|
)
|
||||||
lock = Signal()
|
lock = Signal()
|
||||||
lock_d = Signal()
|
lock_d = Signal()
|
||||||
self.specials += MultiReg(_lock, lock)
|
self.specials += MultiReg(_lock, lock)
|
||||||
self.sync += lock_d.eq(lock)
|
self.sync += lock_d.eq(lock)
|
||||||
|
@ -82,13 +82,13 @@ 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):
|
||||||
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)
|
||||||
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)
|
||||||
databits = len(pads.dq)
|
databits = len(pads.dq)
|
||||||
nphases = 2
|
nphases = 2
|
||||||
assert databits%8 == 0
|
assert databits%8 == 0
|
||||||
|
|
||||||
# Init -------------------------------------------------------------------------------------
|
# Init -------------------------------------------------------------------------------------
|
||||||
|
@ -97,20 +97,20 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
# Registers --------------------------------------------------------------------------------
|
# Registers --------------------------------------------------------------------------------
|
||||||
self._dly_sel = CSRStorage(databits//8)
|
self._dly_sel = CSRStorage(databits//8)
|
||||||
|
|
||||||
self._rdly_dq_rst = CSR()
|
self._rdly_dq_rst = CSR()
|
||||||
self._rdly_dq_inc = CSR()
|
self._rdly_dq_inc = CSR()
|
||||||
self._rdly_dq_bitslip_rst = CSR()
|
self._rdly_dq_bitslip_rst = CSR()
|
||||||
self._rdly_dq_bitslip = CSR()
|
self._rdly_dq_bitslip = CSR()
|
||||||
|
|
||||||
self._burstdet_clr = CSR()
|
self._burstdet_clr = CSR()
|
||||||
self._burstdet_seen = CSRStatus(databits//8)
|
self._burstdet_seen = CSRStatus(databits//8)
|
||||||
|
|
||||||
# Observation
|
# Observation
|
||||||
self.datavalid = Signal(databits//8)
|
self.datavalid = Signal(databits//8)
|
||||||
|
|
||||||
# PHY settings -----------------------------------------------------------------------------
|
# PHY settings -----------------------------------------------------------------------------
|
||||||
cl, cwl = get_cl_cw(memtype, tck)
|
cl, cwl = get_cl_cw(memtype, tck)
|
||||||
cl_sys_latency = get_sys_latency(nphases, cl)
|
cl_sys_latency = get_sys_latency(nphases, cl)
|
||||||
cwl_sys_latency = get_sys_latency(nphases, cwl)
|
cwl_sys_latency = get_sys_latency(nphases, cwl)
|
||||||
|
|
||||||
rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
|
rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
|
||||||
|
@ -141,44 +141,40 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
# Clock ------------------------------------------------------------------------------------
|
# Clock ------------------------------------------------------------------------------------
|
||||||
for i in range(len(pads.clk_p)):
|
for i in range(len(pads.clk_p)):
|
||||||
sd_clk_se = Signal()
|
sd_clk_se = Signal()
|
||||||
self.specials += [
|
self.specials += Instance("ODDRX2F",
|
||||||
Instance("ODDRX2F",
|
i_D0 = 0,
|
||||||
i_D0=0,
|
i_D1 = 1,
|
||||||
i_D1=1,
|
i_D2 = 0,
|
||||||
i_D2=0,
|
i_D3 = 1,
|
||||||
i_D3=1,
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_SCLK = ClockSignal(),
|
||||||
i_SCLK=ClockSignal(),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_RST=ResetSignal("sys2x"),
|
o_Q = pads.clk_p[i]
|
||||||
o_Q=pads.clk_p[i]
|
)
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Addresses and Commands -------------------------------------------------------------------
|
# Addresses and Commands -------------------------------------------------------------------
|
||||||
for i in range(addressbits):
|
for i in range(addressbits):
|
||||||
self.specials += \
|
self.specials += Instance("ODDRX2F",
|
||||||
Instance("ODDRX2F",
|
i_D0 = dfi.phases[0].address[i],
|
||||||
i_D0=dfi.phases[0].address[i],
|
i_D1 = dfi.phases[0].address[i],
|
||||||
i_D1=dfi.phases[0].address[i],
|
i_D2 = dfi.phases[1].address[i],
|
||||||
i_D2=dfi.phases[1].address[i],
|
i_D3 = dfi.phases[1].address[i],
|
||||||
i_D3=dfi.phases[1].address[i],
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_SCLK = ClockSignal(),
|
||||||
i_SCLK=ClockSignal(),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_RST=ResetSignal("sys2x"),
|
o_Q = pads.a[i]
|
||||||
o_Q=pads.a[i]
|
)
|
||||||
)
|
|
||||||
for i in range(bankbits):
|
for i in range(bankbits):
|
||||||
self.specials += \
|
self.specials += Instance("ODDRX2F",
|
||||||
Instance("ODDRX2F",
|
i_D0 = dfi.phases[0].bank[i],
|
||||||
i_D0=dfi.phases[0].bank[i],
|
i_D1 = dfi.phases[0].bank[i],
|
||||||
i_D1=dfi.phases[0].bank[i],
|
i_D2 = dfi.phases[1].bank[i],
|
||||||
i_D2=dfi.phases[1].bank[i],
|
i_D3 = dfi.phases[1].bank[i],
|
||||||
i_D3=dfi.phases[1].bank[i],
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_SCLK = ClockSignal(),
|
||||||
i_SCLK=ClockSignal(),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_RST=ResetSignal("sys2x"),
|
o_Q = pads.ba[i]
|
||||||
o_Q=pads.ba[i]
|
)
|
||||||
)
|
|
||||||
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
|
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
|
||||||
if hasattr(pads, "reset_n"):
|
if hasattr(pads, "reset_n"):
|
||||||
controls.append("reset_n")
|
controls.append("reset_n")
|
||||||
|
@ -186,33 +182,32 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
controls.append("cs_n")
|
controls.append("cs_n")
|
||||||
for name in controls:
|
for name in controls:
|
||||||
for i in range(len(getattr(pads, name))):
|
for i in range(len(getattr(pads, name))):
|
||||||
self.specials += \
|
self.specials += Instance("ODDRX2F",
|
||||||
Instance("ODDRX2F",
|
i_D0 = getattr(dfi.phases[0], name)[i],
|
||||||
i_D0=getattr(dfi.phases[0], name)[i],
|
i_D1 = getattr(dfi.phases[0], name)[i],
|
||||||
i_D1=getattr(dfi.phases[0], name)[i],
|
i_D2 = getattr(dfi.phases[1], name)[i],
|
||||||
i_D2=getattr(dfi.phases[1], name)[i],
|
i_D3 = getattr(dfi.phases[1], name)[i],
|
||||||
i_D3=getattr(dfi.phases[1], name)[i],
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_SCLK = ClockSignal(),
|
||||||
i_SCLK=ClockSignal(),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_RST=ResetSignal("sys2x"),
|
o_Q = getattr(pads, name)[i]
|
||||||
o_Q=getattr(pads, name)[i]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# DQ ---------------------------------------------------------------------------------------
|
# DQ ---------------------------------------------------------------------------------------
|
||||||
oe_dq = Signal()
|
oe_dq = Signal()
|
||||||
oe_dqs = Signal()
|
oe_dqs = Signal()
|
||||||
dqs_postamble = Signal()
|
dqs_postamble = Signal()
|
||||||
dqs_preamble = Signal()
|
dqs_preamble = Signal()
|
||||||
dqs_read = Signal()
|
dqs_read = Signal()
|
||||||
for i in range(databits//8):
|
for i in range(databits//8):
|
||||||
# DQSBUFM
|
# DQSBUFM
|
||||||
dqs_i = Signal()
|
dqs_i = Signal()
|
||||||
dqsr90 = Signal()
|
dqsr90 = Signal()
|
||||||
dqsw270 = Signal()
|
dqsw270 = Signal()
|
||||||
dqsw = Signal()
|
dqsw = Signal()
|
||||||
rdpntr = Signal(3)
|
rdpntr = Signal(3)
|
||||||
wrpntr = Signal(3)
|
wrpntr = Signal(3)
|
||||||
rdly = Signal(7)
|
rdly = Signal(7)
|
||||||
self.sync += \
|
self.sync += \
|
||||||
If(self._dly_sel.storage[i],
|
If(self._dly_sel.storage[i],
|
||||||
If(self._rdly_dq_rst.re,
|
If(self._rdly_dq_rst.re,
|
||||||
|
@ -222,48 +217,48 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
datavalid = Signal()
|
datavalid = Signal()
|
||||||
burstdet = Signal()
|
burstdet = Signal()
|
||||||
self.specials += Instance("DQSBUFM",
|
self.specials += Instance("DQSBUFM",
|
||||||
p_DQS_LI_DEL_ADJ="MINUS",
|
p_DQS_LI_DEL_ADJ = "MINUS",
|
||||||
p_DQS_LI_DEL_VAL=1,
|
p_DQS_LI_DEL_VAL = 1,
|
||||||
p_DQS_LO_DEL_ADJ="MINUS",
|
p_DQS_LO_DEL_ADJ = "MINUS",
|
||||||
p_DQS_LO_DEL_VAL=4,
|
p_DQS_LO_DEL_VAL = 4,
|
||||||
# Clocks / Reset
|
# Clocks / Reset
|
||||||
i_SCLK=ClockSignal("sys"),
|
i_SCLK = ClockSignal("sys"),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_RST=ResetSignal("sys2x"),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_DDRDEL=self.init.delay,
|
i_DDRDEL = self.init.delay,
|
||||||
i_PAUSE=self.init.pause | self._dly_sel.storage[i],
|
i_PAUSE = self.init.pause | self._dly_sel.storage[i],
|
||||||
|
|
||||||
# Control
|
# Control
|
||||||
# Assert LOADNs to use DDRDEL control
|
# Assert LOADNs to use DDRDEL control
|
||||||
i_RDLOADN=0,
|
i_RDLOADN = 0,
|
||||||
i_RDMOVE=0,
|
i_RDMOVE = 0,
|
||||||
i_RDDIRECTION=1,
|
i_RDDIRECTION = 1,
|
||||||
i_WRLOADN=0,
|
i_WRLOADN = 0,
|
||||||
i_WRMOVE=0,
|
i_WRMOVE = 0,
|
||||||
i_WRDIRECTION=1,
|
i_WRDIRECTION = 1,
|
||||||
|
|
||||||
# Reads (generate shifted DQS clock for reads)
|
# Reads (generate shifted DQS clock for reads)
|
||||||
i_READ0=dqs_read,
|
i_READ0 = dqs_read,
|
||||||
i_READ1=dqs_read,
|
i_READ1 = dqs_read,
|
||||||
i_READCLKSEL0=rdly[0],
|
i_READCLKSEL0 = rdly[0],
|
||||||
i_READCLKSEL1=rdly[1],
|
i_READCLKSEL1 = rdly[1],
|
||||||
i_READCLKSEL2=rdly[2],
|
i_READCLKSEL2 = rdly[2],
|
||||||
i_DQSI=dqs_i,
|
i_DQSI = dqs_i,
|
||||||
o_DQSR90=dqsr90,
|
o_DQSR90 = dqsr90,
|
||||||
o_RDPNTR0=rdpntr[0],
|
o_RDPNTR0 = rdpntr[0],
|
||||||
o_RDPNTR1=rdpntr[1],
|
o_RDPNTR1 = rdpntr[1],
|
||||||
o_RDPNTR2=rdpntr[2],
|
o_RDPNTR2 = rdpntr[2],
|
||||||
o_WRPNTR0=wrpntr[0],
|
o_WRPNTR0 = wrpntr[0],
|
||||||
o_WRPNTR1=wrpntr[1],
|
o_WRPNTR1 = wrpntr[1],
|
||||||
o_WRPNTR2=wrpntr[2],
|
o_WRPNTR2 = wrpntr[2],
|
||||||
o_DATAVALID=self.datavalid[i],
|
o_DATAVALID = self.datavalid[i],
|
||||||
o_BURSTDET=burstdet,
|
o_BURSTDET = burstdet,
|
||||||
|
|
||||||
# Writes (generate shifted ECLK clock for writes)
|
# Writes (generate shifted ECLK clock for writes)
|
||||||
o_DQSW270=dqsw270,
|
o_DQSW270 = dqsw270,
|
||||||
o_DQSW=dqsw
|
o_DQSW = dqsw
|
||||||
)
|
)
|
||||||
burstdet_d = Signal()
|
burstdet_d = Signal()
|
||||||
self.sync += [
|
self.sync += [
|
||||||
|
@ -277,9 +272,9 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
|
|
||||||
# DQS and DM ---------------------------------------------------------------------------
|
# DQS and DM ---------------------------------------------------------------------------
|
||||||
dqs_serdes_pattern = Signal(8, reset=0b1010)
|
dqs_serdes_pattern = Signal(8, reset=0b1010)
|
||||||
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)
|
||||||
self.comb += dm_o_data.eq(Cat(
|
self.comb += dm_o_data.eq(Cat(
|
||||||
dfi.phases[0].wrdata_mask[0*databits//8+i], dfi.phases[0].wrdata_mask[1*databits//8+i],
|
dfi.phases[0].wrdata_mask[0*databits//8+i], dfi.phases[0].wrdata_mask[1*databits//8+i],
|
||||||
dfi.phases[0].wrdata_mask[2*databits//8+i], dfi.phases[0].wrdata_mask[3*databits//8+i],
|
dfi.phases[0].wrdata_mask[2*databits//8+i], dfi.phases[0].wrdata_mask[3*databits//8+i],
|
||||||
|
@ -293,53 +288,52 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
).Else(
|
).Else(
|
||||||
dm_o_data_muxed.eq(dm_o_data[:4])
|
dm_o_data_muxed.eq(dm_o_data[:4])
|
||||||
)
|
)
|
||||||
self.specials += \
|
self.specials += Instance("ODDRX2DQA",
|
||||||
Instance("ODDRX2DQA",
|
i_D0 = dm_o_data_muxed[0],
|
||||||
i_D0=dm_o_data_muxed[0],
|
i_D1 = dm_o_data_muxed[1],
|
||||||
i_D1=dm_o_data_muxed[1],
|
i_D2 = dm_o_data_muxed[2],
|
||||||
i_D2=dm_o_data_muxed[2],
|
i_D3 = dm_o_data_muxed[3],
|
||||||
i_D3=dm_o_data_muxed[3],
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_RST=ResetSignal("sys2x"),
|
i_DQSW270 = dqsw270,
|
||||||
i_DQSW270=dqsw270,
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_SCLK = ClockSignal(),
|
||||||
i_SCLK=ClockSignal(),
|
o_Q = pads.dm[i]
|
||||||
o_Q=pads.dm[i]
|
)
|
||||||
)
|
|
||||||
|
|
||||||
dqs = Signal()
|
dqs = Signal()
|
||||||
dqs_oe_n = Signal()
|
dqs_oe_n = Signal()
|
||||||
self.specials += \
|
self.specials += [
|
||||||
Instance("ODDRX2DQSB",
|
Instance("ODDRX2DQSB",
|
||||||
i_D0=dqs_serdes_pattern[0],
|
i_D0 = dqs_serdes_pattern[0],
|
||||||
i_D1=dqs_serdes_pattern[1],
|
i_D1 = dqs_serdes_pattern[1],
|
||||||
i_D2=dqs_serdes_pattern[2],
|
i_D2 = dqs_serdes_pattern[2],
|
||||||
i_D3=dqs_serdes_pattern[3],
|
i_D3 = dqs_serdes_pattern[3],
|
||||||
i_RST=ResetSignal("sys2x"),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_DQSW=dqsw,
|
i_DQSW = dqsw,
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_SCLK=ClockSignal(),
|
i_SCLK = ClockSignal(),
|
||||||
o_Q=dqs
|
o_Q = dqs
|
||||||
)
|
),
|
||||||
self.specials += \
|
|
||||||
Instance("TSHX2DQSA",
|
Instance("TSHX2DQSA",
|
||||||
i_T0=~(oe_dqs|dqs_postamble),
|
i_T0 = ~(oe_dqs|dqs_postamble),
|
||||||
i_T1=~(oe_dqs|dqs_preamble),
|
i_T1 = ~(oe_dqs|dqs_preamble),
|
||||||
i_SCLK=ClockSignal(),
|
i_SCLK = ClockSignal(),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_DQSW=dqsw,
|
i_DQSW = dqsw,
|
||||||
i_RST=ResetSignal("sys2x"),
|
i_RST = ResetSignal("sys2x"),
|
||||||
o_Q=dqs_oe_n,
|
o_Q = dqs_oe_n,
|
||||||
)
|
),
|
||||||
self.specials += Tristate(pads.dqs_p[i], dqs, ~dqs_oe_n, dqs_i)
|
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()
|
||||||
dq_oe_n = Signal()
|
dq_oe_n = Signal()
|
||||||
dq_i_delayed = Signal()
|
dq_i_delayed = Signal()
|
||||||
dq_i_data = Signal(4)
|
dq_i_data = Signal(4)
|
||||||
dq_o_data = Signal(8)
|
dq_o_data = Signal(8)
|
||||||
dq_o_data_d = Signal(8)
|
dq_o_data_d = Signal(8)
|
||||||
dq_o_data_muxed = Signal(4)
|
dq_o_data_muxed = Signal(4)
|
||||||
self.comb += dq_o_data.eq(Cat(
|
self.comb += dq_o_data.eq(Cat(
|
||||||
dfi.phases[0].wrdata[0*databits+j], dfi.phases[0].wrdata[1*databits+j],
|
dfi.phases[0].wrdata[0*databits+j], dfi.phases[0].wrdata[1*databits+j],
|
||||||
|
@ -354,45 +348,44 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
).Else(
|
).Else(
|
||||||
dq_o_data_muxed.eq(dq_o_data[:4])
|
dq_o_data_muxed.eq(dq_o_data[:4])
|
||||||
)
|
)
|
||||||
self.specials += \
|
self.specials += [
|
||||||
Instance("ODDRX2DQA",
|
Instance("ODDRX2DQA",
|
||||||
i_D0=dq_o_data_muxed[0],
|
i_D0 = dq_o_data_muxed[0],
|
||||||
i_D1=dq_o_data_muxed[1],
|
i_D1 = dq_o_data_muxed[1],
|
||||||
i_D2=dq_o_data_muxed[2],
|
i_D2 = dq_o_data_muxed[2],
|
||||||
i_D3=dq_o_data_muxed[3],
|
i_D3 = dq_o_data_muxed[3],
|
||||||
i_RST=ResetSignal("sys2x"),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_DQSW270=dqsw270,
|
i_DQSW270 = dqsw270,
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_SCLK=ClockSignal(),
|
i_SCLK = ClockSignal(),
|
||||||
o_Q=dq_o
|
o_Q = dq_o
|
||||||
)
|
),
|
||||||
self.specials += \
|
|
||||||
Instance("DELAYF",
|
Instance("DELAYF",
|
||||||
i_A=dq_i,
|
i_A = dq_i,
|
||||||
i_LOADN=1,
|
i_LOADN = 1,
|
||||||
i_MOVE=0,
|
i_MOVE = 0,
|
||||||
i_DIRECTION=0,
|
i_DIRECTION = 0,
|
||||||
o_Z=dq_i_delayed,
|
o_Z = dq_i_delayed,
|
||||||
p_DEL_MODE="DQS_ALIGNED_X2"
|
p_DEL_MODE = "DQS_ALIGNED_X2"
|
||||||
)
|
),
|
||||||
self.specials += \
|
|
||||||
Instance("IDDRX2DQA",
|
Instance("IDDRX2DQA",
|
||||||
i_D=dq_i_delayed,
|
i_D = dq_i_delayed,
|
||||||
i_RST=ResetSignal("sys2x"),
|
i_RST = ResetSignal("sys2x"),
|
||||||
i_DQSR90=dqsr90,
|
i_DQSR90 = dqsr90,
|
||||||
i_SCLK=ClockSignal(),
|
i_SCLK = ClockSignal(),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_RDPNTR0=rdpntr[0],
|
i_RDPNTR0 = rdpntr[0],
|
||||||
i_RDPNTR1=rdpntr[1],
|
i_RDPNTR1 = rdpntr[1],
|
||||||
i_RDPNTR2=rdpntr[2],
|
i_RDPNTR2 = rdpntr[2],
|
||||||
i_WRPNTR0=wrpntr[0],
|
i_WRPNTR0 = wrpntr[0],
|
||||||
i_WRPNTR1=wrpntr[1],
|
i_WRPNTR1 = wrpntr[1],
|
||||||
i_WRPNTR2=wrpntr[2],
|
i_WRPNTR2 = wrpntr[2],
|
||||||
o_Q0=dq_i_data[0],
|
o_Q0 = dq_i_data[0],
|
||||||
o_Q1=dq_i_data[1],
|
o_Q1 = dq_i_data[1],
|
||||||
o_Q2=dq_i_data[2],
|
o_Q2 = dq_i_data[2],
|
||||||
o_Q3=dq_i_data[3],
|
o_Q3 = dq_i_data[3],
|
||||||
)
|
)
|
||||||
|
]
|
||||||
dq_bitslip = BitSlip(4)
|
dq_bitslip = BitSlip(4)
|
||||||
self.comb += dq_bitslip.i.eq(dq_i_data)
|
self.comb += dq_bitslip.i.eq(dq_i_data)
|
||||||
self.sync += \
|
self.sync += \
|
||||||
|
@ -412,17 +405,18 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
dfi.phases[1].rddata[0*databits+j].eq(dq_bitslip.o[0]), dfi.phases[1].rddata[1*databits+j].eq(dq_bitslip.o[1]),
|
dfi.phases[1].rddata[0*databits+j].eq(dq_bitslip.o[0]), dfi.phases[1].rddata[1*databits+j].eq(dq_bitslip.o[1]),
|
||||||
dfi.phases[1].rddata[2*databits+j].eq(dq_bitslip.o[2]), dfi.phases[1].rddata[3*databits+j].eq(dq_bitslip.o[3]),
|
dfi.phases[1].rddata[2*databits+j].eq(dq_bitslip.o[2]), dfi.phases[1].rddata[3*databits+j].eq(dq_bitslip.o[3]),
|
||||||
]
|
]
|
||||||
self.specials += \
|
self.specials += [
|
||||||
Instance("TSHX2DQA",
|
Instance("TSHX2DQA",
|
||||||
i_T0=~oe_dq,
|
i_T0 = ~oe_dq,
|
||||||
i_T1=~oe_dq,
|
i_T1 = ~oe_dq,
|
||||||
i_SCLK=ClockSignal(),
|
i_SCLK = ClockSignal(),
|
||||||
i_ECLK=ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_DQSW270=dqsw270,
|
i_DQSW270 = dqsw270,
|
||||||
i_RST=ResetSignal("sys2x"),
|
i_RST = ResetSignal("sys2x"),
|
||||||
o_Q=dq_oe_n,
|
o_Q = dq_oe_n,
|
||||||
)
|
),
|
||||||
self.specials += Tristate(pads.dq[j], dq_o, ~dq_oe_n, dq_i)
|
Tristate(pads.dq[j], dq_o, ~dq_oe_n, dq_i)
|
||||||
|
]
|
||||||
|
|
||||||
# Flow control -----------------------------------------------------------------------------
|
# Flow control -----------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
@ -430,7 +424,7 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
# ODDRX2DQA latency
|
# ODDRX2DQA latency
|
||||||
# cl_sys_latency
|
# cl_sys_latency
|
||||||
# IDDRX2DQA latency
|
# IDDRX2DQA latency
|
||||||
rddata_en = dfi.phases[self.settings.rdphase].rddata_en
|
rddata_en = dfi.phases[self.settings.rdphase].rddata_en
|
||||||
rddata_ens = Array([Signal() for i in range(self.settings.read_latency-1)])
|
rddata_ens = Array([Signal() for i in range(self.settings.read_latency-1)])
|
||||||
for i in range(self.settings.read_latency-1):
|
for i in range(self.settings.read_latency-1):
|
||||||
n_rddata_en = Signal()
|
n_rddata_en = Signal()
|
||||||
|
|
Loading…
Reference in New Issue