class ECP5CRG(Elaboratable):
- def __init__(self, sys_clk_freq=100e6, pod_bits=25):
+ def __init__(self, sys_clk_freq=100e6, pod_bits=16):
self.sys_clk_freq = sys_clk_freq
self.pod_bits = pod_bits
+ # DDR clock control signals
+ self.ddr_clk_stop = Signal()
+ self.ddr_clk_reset = Signal()
+
def elaborate(self, platform):
m = Module()
i_GSR=gsr1),
]
- # PLL
- m.submodules.pll = pll = PLL(ClockSignal("rawclk"), reset=~reset)
-
- # Power-on delay (655us)
+ # Power-on delay
podcnt = Signal(self.pod_bits, reset=-1)
pod_done = Signal()
- with m.If((podcnt != 0) & pll.locked):
+ with m.If(podcnt != 0):
m.d.rawclk += podcnt.eq(podcnt-1)
m.d.rawclk += pod_done.eq(podcnt == 0)
+ # PLL
+ m.submodules.pll = pll = PLL(ClockSignal("rawclk"), reset=~pod_done|~reset)
+
# Generating sync2x (200Mhz) and init (25Mhz) from extclk
- cd_sync2x = ClockDomain("sync2x", local=False)
+ cd_sync2x = ClockDomain("sync2x", local=False, reset_less=True)
cd_sync2x_unbuf = ClockDomain("sync2x_unbuf",
local=False, reset_less=True)
cd_init = ClockDomain("init", local=False)
pll.create_clkout(ClockSignal("init"), 25e6)
m.submodules += Instance("ECLKSYNCB",
i_ECLKI = ClockSignal("sync2x_unbuf"),
- i_STOP = 0,
+ i_STOP = self.ddr_clk_stop,
o_ECLKO = ClockSignal("sync2x"))
m.domains += cd_sync2x_unbuf
m.domains += cd_sync2x
reset_ok = Signal(reset_less=True)
m.d.comb += reset_ok.eq(~pll.locked|~pod_done)
m.d.comb += ResetSignal("init").eq(reset_ok)
- m.d.comb += ResetSignal("sync").eq(reset_ok)
- m.d.comb += ResetSignal("dramsync").eq(reset_ok)
+ m.d.comb += ResetSignal("sync").eq(reset_ok|self.ddr_clk_reset)
+ m.d.comb += ResetSignal("dramsync").eq(reset_ok|self.ddr_clk_reset)
# # Generating sync (100Mhz) from sync2x
p_DIV="2.0",
i_ALIGNWD=0,
i_CLKI=ClockSignal("sync2x"),
- i_RST=0,
+ i_RST=ResetSignal("dramsync"),
o_CDIVX=ClockSignal("sync"))
# temporarily set dram sync clock exactly equal to main sync
# DDRDLLA/DDQBUFM/ECLK initialization sequence ---------------------------------------------
t = 8 # in cycles
tl = Timeline([
- (1*t, [freeze.eq(1)]), # Freeze DDRDLLA
- (2*t, [self.stop.eq(1)]), # Stop ECLK domain
+ (1*t, [ freeze.eq(1)]), # Freeze DDRDLLA
+ (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
+ (5*t, [ self.stop.eq(0)]), # Release ECLK domain stop
+ (6*t, [ freeze.eq(0)]), # Release DDRDLLA freeze
(7*t, [self.pause.eq(1)]), # Pause DQSBUFM
- (8*t, [update.eq(1)]), # Update DDRDLLA
- (9*t, [update.eq(0)]), # Release DDRDMMA update
+ (8*t, [ update.eq(1)]), # Update DDRDLLA
+ (9*t, [ update.eq(0)]), # Release DDRDMMA update
(10*t, [self.pause.eq(0)]), # Release DQSBUFM pause
])
m.d.comb += tl.trigger.eq(lock & ~lock_d) # Trigger timeline on lock rising edge
self.pads = pads
self._sys_clk_freq = sys_clk_freq
+ self.init = ECP5DDRPHYInit()
databits = len(self.pads.dq.io)
if databits % 8 != 0:
m.d.sync += burstdet_reg.eq(0)
# Init -------------------------------------------------------------------------------------
- m.submodules.init = init = ECP5DDRPHYInit()
+ m.submodules.init = init = self.init
# Parameters -------------------------------------------------------------------------------
cl, cwl = get_cl_cw("DDR3", tck)
i_D2=dq_o_data_muxed[2],
i_D3=dq_o_data_muxed[3],
o_Q=dq_o),
- Instance("DELAYF",
- p_DEL_MODE="DQS_ALIGNED_X2",
- i_LOADN=1,
- i_MOVE=0,
- i_DIRECTION=0,
- i_A=dq_i,
- o_Z=dq_i_delayed),
+ Instance("DELAYG",
+ p_DEL_MODE = "DQS_ALIGNED_X2",
+ i_A = dq_i,
+ o_Z = dq_i_delayed),
Instance("IDDRX2DQA",
i_RST=ResetSignal("dramsync"),
i_ECLK=ClockSignal("sync2x"),