class ECP5DDRPHYInit(Elaboratable):
- def __init__(self, eclk_cd):
+ def __init__(self):
self.pause = Signal()
self.stop = Signal()
self.delay = Signal()
- self._eclk_cd = eclk_cd
+ self.reset = Signal()
def elaborate(self, platform):
m = Module()
new_lock = Signal()
update = Signal()
- stop = Signal()
freeze = Signal()
- pause = Signal()
- reset = Signal()
# DDRDLLA instance -------------------------------------------------------------------------
_lock = Signal()
delay = Signal()
m.submodules += Instance("DDRDLLA",
i_CLK=ClockSignal("sync2x"),
- i_RST=ResetSignal(),
+ i_RST=ResetSignal("init"),
i_UDDCNTLN=~update,
i_FREEZE=freeze,
o_DDRDEL=delay,
)
lock = Signal()
lock_d = Signal()
- m.submodules += FFSynchronizer(_lock, lock)
- m.d.sync += lock_d.eq(lock)
+ m.submodules += FFSynchronizer(_lock, lock, o_domain="init")
+ m.d.init += lock_d.eq(lock)
m.d.sync += new_lock.eq(lock & ~lock_d)
# DDRDLLA/DDQBUFM/ECLK initialization sequence ---------------------------------------------
t = 8 # in cycles
tl = Timeline([
(1*t, [freeze.eq(1)]), # Freeze DDRDLLA
- (2*t, [stop.eq(1)]), # Stop ECLK domain
- (3*t, [reset.eq(1)]), # Reset ECLK domain
- (4*t, [reset.eq(0)]), # Release ECLK domain reset
- (5*t, [stop.eq(0)]), # Release ECLK domain stop
+ (2*t, [self.stop.eq(1)]), # Stop ECLK domain
+ (3*t, [self.reset.eq(1)]), # Reset ECLK domain
+ (4*t, [self.reset.eq(0)]), # Release ECLK domain reset
+ (5*t, [self.stop.eq(0)]), # Release ECLK domain stop
(6*t, [freeze.eq(0)]), # Release DDRDLLA freeze
- (7*t, [pause.eq(1)]), # Pause DQSBUFM
+ (7*t, [self.pause.eq(1)]), # Pause DQSBUFM
(8*t, [update.eq(1)]), # Update DDRDLLA
(9*t, [update.eq(0)]), # Release DDRDMMA update
- (10*t, [pause.eq(0)]), # Release DQSBUFM pause
+ (10*t, [self.pause.eq(0)]), # Release DQSBUFM pause
])
m.submodules += tl
# Wait DDRDLLA Lock
m.d.comb += tl.trigger.eq(new_lock)
- # ------------------------------------------------------------------------------------------
- m.d.comb += [
- self.pause.eq(pause),
- self.stop.eq(stop),
- self.delay.eq(delay),
- ResetSignal(self._eclk_cd).eq(reset)
- ]
+ m.d.comb += self.delay.eq(delay)
return m
class ECP5DDRPHY(Peripheral, Elaboratable):
def __init__(self, pads, sys_clk_freq=100e6):
- super().__init__()
+ super().__init__(name="phy")
- #self.pads = PHYPadsCombiner(pads)
self.pads = pads
self._sys_clk_freq = sys_clk_freq
- databits = len(self.pads.dq.o)
+ databits = len(self.pads.dq.io)
assert databits % 8 == 0
# CSR
self._burstdet_clr = bank.csr(1, "rw")
self._burstdet_seen = bank.csr(databits//8, "r")
- self._zero_ev = self.event(mode="rise")
-
self._bridge = self.bridge(data_width=32, granularity=8, alignment=2)
self.bus = self._bridge.bus
- self.irq = self._bridge.irq
- addressbits = len(self.pads.a.o)
- bankbits = len(self.pads.ba.o)
- nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n)
- databits = len(self.pads.dq.o)
+ addressbits = len(self.pads.a.o0)
+ bankbits = len(self.pads.ba.o0)
+ nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n.o)
+ databits = len(self.pads.dq.io)
self.dfi = Interface(addressbits, bankbits, nranks, 4*databits, 4)
# PHY settings -----------------------------------------------------------------------------
tck = 2/(2*2*self._sys_clk_freq)
nphases = 2
- databits = len(self.pads.dq.o)
- nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n)
- addressbits = len(self.pads.a.o)
- bankbits = len(self.pads.ba.o)
+ databits = len(self.pads.dq.io)
+ nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n.o)
cl, cwl = get_cl_cw("DDR3", tck)
cl_sys_latency = get_sys_latency(nphases, cl)
cwl_sys_latency = get_sys_latency(nphases, cwl)
tck = 2/(2*2*self._sys_clk_freq)
nphases = 2
- databits = len(self.pads.dq.o)
- nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n)
- addressbits = len(self.pads.a.o)
- bankbits = len(self.pads.ba.o)
+ databits = len(self.pads.dq.io)
# Init -------------------------------------------------------------------------------------
- m.submodules.init = init = DomainRenamer("init")(ECP5DDRPHYInit("sync2x"))
+ m.submodules.init = init = ECP5DDRPHYInit()
# Parameters -------------------------------------------------------------------------------
cl, cwl = get_cl_cw("DDR3", tck)
rddata_en = Signal(self.settings.read_latency)
# Clock --------------------------------------------------------------------------------
- for i in range(len(self.pads.clk.o)):
- sd_clk_se = Signal()
- m.submodules += Instance("ODDRX2F",
- i_RST=ResetSignal("sync2x"),
- i_ECLK=ClockSignal("sync2x"),
- i_SCLK=ClockSignal(),
- i_D0=0,
- i_D1=1,
- i_D2=0,
- i_D3=1,
- o_Q=self.pads.clk.o[i]
- )
+ m.d.comb += [
+ self.pads.clk.o_clk.eq(ClockSignal("dramsync")),
+ self.pads.clk.o_fclk.eq(ClockSignal("sync2x")),
+ ]
+ for i in range(len(self.pads.clk.o0)):
+ m.d.comb += [
+ self.pads.clk.o0[i].eq(0),
+ self.pads.clk.o1[i].eq(1),
+ self.pads.clk.o2[i].eq(0),
+ self.pads.clk.o3[i].eq(1),
+ ]
# Addresses and Commands ---------------------------------------------------------------
- for i in range(addressbits):
- m.submodules += Instance("ODDRX2F",
- i_RST=ResetSignal("sync2x"),
- i_ECLK=ClockSignal("sync2x"),
- 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=self.pads.a.o[i]
- )
- for i in range(bankbits):
- m.submodules += Instance("ODDRX2F",
- i_RST=ResetSignal("sync2x"),
- i_ECLK=ClockSignal("sync2x"),
- 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=self.pads.ba.o[i]
- )
- controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
+ m.d.comb += [
+ self.pads.a.o_clk.eq(ClockSignal("dramsync")),
+ self.pads.a.o_fclk.eq(ClockSignal("sync2x")),
+ self.pads.ba.o_clk.eq(ClockSignal("dramsync")),
+ self.pads.ba.o_fclk.eq(ClockSignal("sync2x")),
+ ]
+ for i in range(len(self.pads.a.o0)):
+ m.d.comb += [
+ self.pads.a.o0[i].eq(dfi.phases[0].address[i]),
+ self.pads.a.o1[i].eq(dfi.phases[0].address[i]),
+ self.pads.a.o2[i].eq(dfi.phases[1].address[i]),
+ self.pads.a.o3[i].eq(dfi.phases[1].address[i]),
+ ]
+ for i in range(len(self.pads.ba.o0)):
+ m.d.comb += [
+ self.pads.ba.o0[i].eq(dfi.phases[0].bank[i]),
+ self.pads.ba.o1[i].eq(dfi.phases[0].bank[i]),
+ self.pads.ba.o2[i].eq(dfi.phases[1].bank[i]),
+ self.pads.ba.o3[i].eq(dfi.phases[1].bank[i]),
+ ]
+
+ controls = ["ras_n", "cas_n", "we_n", "clk_en", "odt"]
if hasattr(self.pads, "reset_n"):
controls.append("reset_n")
if hasattr(self.pads, "cs_n"):
controls.append("cs_n")
for name in controls:
- for i in range(len(getattr(self.pads, name))):
- m.submodules += Instance("ODDRX2F",
- i_RST=ResetSignal("sync2x"),
- i_ECLK=ClockSignal("sync2x"),
- 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(self.pads, name)[i]
- )
+ m.d.comb += [
+ getattr(self.pads, name).o_clk.eq(ClockSignal("dramsync")),
+ getattr(self.pads, name).o_fclk.eq(ClockSignal("sync2x")),
+ ]
+ for i in range(len(getattr(self.pads, name).o0)):
+ m.d.comb += [
+ getattr(self.pads, name).o0[i].eq(getattr(dfi.phases[0], name)[i]),
+ getattr(self.pads, name).o1[i].eq(getattr(dfi.phases[0], name)[i]),
+ getattr(self.pads, name).o2[i].eq(getattr(dfi.phases[1], name)[i]),
+ getattr(self.pads, name).o3[i].eq(getattr(dfi.phases[1], name)[i]),
+ ]
# DQ ---------------------------------------------------------------------------------------
dq_oe = Signal()
with m.Switch(dqs_bitslip):
for j, b in enumerate(range(-2, 2)):
with m.Case(j):
- m.d.sync += dqs_read.eq(rddata_en[cl_sys_latency + b:cl_sys_latency + b + 2] != 0)
+ m.d.sync += dqs_read.eq(1)
m.submodules += Instance("DQSBUFM",
p_DQS_LI_DEL_ADJ="MINUS",
p_DQS_LI_DEL_VAL=1,
p_DQS_LO_DEL_ADJ="MINUS",
p_DQS_LO_DEL_VAL=4,
+
+ # Delay
+ i_DYNDELAY0=0,
+ i_DYNDELAY1=0,
+ i_DYNDELAY2=0,
+ i_DYNDELAY3=0,
+ i_DYNDELAY4=0,
+ i_DYNDELAY5=0,
+ i_DYNDELAY6=0,
+ i_DYNDELAY7=0,
+
# Clocks / Reset
i_SCLK=ClockSignal("sync"),
i_ECLK=ClockSignal("sync2x"),
- i_RST=ResetSignal("sync2x"),
+ i_RST=ResetSignal("dramsync"),
i_DDRDEL=init.delay,
i_PAUSE=init.pause | self._dly_sel.w_data[i],
dfi.phases[1].wrdata_mask[3*databits//8+i]),
)
m.d.sync += dm_o_data_d.eq(dm_o_data)
- dm_bl8_cases = {}
- dm_bl8_cases[0] = dm_o_data_muxed.eq(dm_o_data[:4])
- dm_bl8_cases[1] = dm_o_data_muxed.eq(dm_o_data_d[4:])
- m.d.sync += Case(bl8_chunk, dm_bl8_cases) # FIXME: use self.comb?
+ with m.Switch(bl8_chunk):
+ with m.Case(0):
+ m.d.sync += dm_o_data_muxed.eq(dm_o_data[:4])
+ with m.Case(1):
+ m.d.sync += dm_o_data_muxed.eq(dm_o_data_d[4:])
m.submodules += Instance("ODDRX2DQA",
- i_RST=ResetSignal("sync2x"),
+ i_RST=ResetSignal("dramsync"),
i_ECLK=ClockSignal("sync2x"),
- i_SCLK=ClockSignal(),
+ i_SCLK=ClockSignal("dramsync"),
i_DQSW270=dqsw270,
i_D0=dm_o_data_muxed[0],
i_D1=dm_o_data_muxed[1],
i_D2=dm_o_data_muxed[2],
i_D3=dm_o_data_muxed[3],
- o_Q=pads.dm[i]
+ o_Q=self.pads.dm.o[i]
)
dqs = Signal()
dqs_oe_n = Signal()
m.submodules += [
Instance("ODDRX2DQSB",
- i_RST=ResetSignal("sync2x"),
+ i_RST=ResetSignal("dramsync"),
i_ECLK=ClockSignal("sync2x"),
i_SCLK=ClockSignal(),
i_DQSW=dqsw,
o_Q=dqs
),
Instance("TSHX2DQSA",
- i_RST=ResetSignal("sync2x"),
+ i_RST=ResetSignal("dramsync"),
i_ECLK=ClockSignal("sync2x"),
i_SCLK=ClockSignal(),
i_DQSW=dqsw,
dqs_pattern.postamble),
o_Q=dqs_oe_n
),
- Tristate(pads.dqs_p[i], dqs, ~dqs_oe_n, dqs_i)
+ Instance("BB",
+ i_I=dqs,
+ i_T=dqs_oe_n,
+ o_O=dqs_i,
+ io_B=self.pads.dqs.io[i]
+ )
]
for j in range(8*i, 8*(i+1)):
dfi.phases[1].wrdata[3*databits+j])
)
m.d.sync += dq_o_data_d.eq(dq_o_data)
- dq_bl8_cases = {}
- dq_bl8_cases[0] = dq_o_data_muxed.eq(dq_o_data[:4])
- dq_bl8_cases[1] = dq_o_data_muxed.eq(dq_o_data_d[4:])
# FIXME: use self.comb?
- m.d.sync += Case(bl8_chunk, dq_bl8_cases)
+ with m.Switch(bl8_chunk):
+ with m.Case(0):
+ m.d.sync += dq_o_data_muxed.eq(dq_o_data[:4])
+ with m.Case(1):
+ m.d.sync += dq_o_data_muxed.eq(dq_o_data_d[4:])
_dq_i_data = Signal(4)
m.submodules += [
Instance("ODDRX2DQA",
- i_RST=ResetSignal("sync2x"),
+ i_RST=ResetSignal("dramsync"),
i_ECLK=ClockSignal("sync2x"),
i_SCLK=ClockSignal(),
i_DQSW270=dqsw270,
o_Z=dq_i_delayed
),
Instance("IDDRX2DQA",
- i_RST=ResetSignal("sync2x"),
+ i_RST=ResetSignal("dramsync"),
i_ECLK=ClockSignal("sync2x"),
i_SCLK=ClockSignal(),
i_DQSR90=dqsr90,
]
m.d.sync += dq_i_data[:4].eq(dq_i_data[4:])
m.d.sync += dq_i_data[4:].eq(_dq_i_data)
- m.d.comb += [
+ m.d.sync += [
dfi.phases[0].rddata[0*databits+j].eq(dq_i_data[0]),
dfi.phases[0].rddata[1*databits+j].eq(dq_i_data[1]),
dfi.phases[0].rddata[2*databits+j].eq(dq_i_data[2]),
]
m.submodules += [
Instance("TSHX2DQA",
- i_RST=ResetSignal("sync2x"),
+ i_RST=ResetSignal("dramsync"),
i_ECLK=ClockSignal("sync2x"),
i_SCLK=ClockSignal(),
i_DQSW270=dqsw270,
dqs_pattern.postamble),
o_Q=dq_oe_n,
),
- Tristate(pads.dq[j], dq_o, ~dq_oe_n, dq_i)
+ Instance("BB",
+ i_I=dq_o,
+ i_T=dq_oe_n,
+ o_O=dq_i,
+ io_B=self.pads.dq.io[j]
+ )
]
# Read Control Path ------------------------------------------------------------------------
# The read data valid is asserted for 1 sys_clk cycle when the data is available on the DFI
# interface, the latency is the sum of the ODDRX2DQA, CAS, IDDRX2DQA latencies.
rddata_en_last = Signal.like(rddata_en)
- m.d.comb += rddata_en.eq(
- Cat(dfi.phases[self.settings.rdphase].rddata_en, rddata_en_last))
+ m.d.comb += rddata_en.eq(Cat(dfi.phases[self.settings.rdphase].rddata_en, rddata_en_last))
m.d.sync += rddata_en_last.eq(rddata_en)
m.d.sync += [phase.rddata_valid.eq(rddata_en[-1])
for phase in dfi.phases]