def __init__(self, clkin, vco_margin=0):
self.clkin = clkin
self.vco_margin = vco_margin
- self.reset = Signal()
- self.locked = Signal()
+ self.reset = Signal(reset_less=True)
+ self.locked = Signal(reset_less=True)
+ self.pod_done = Signal(reset_less=True) # provide this @ rawclk
self.clkin_freq = None
self.vcxo_freq = None
self.nclkouts = 0
if with_reset:
arst = Signal()
m.submodules += ResetSynchronizer(arst, domain=cd.name)
- comb += arst.eq(~self.locked | self.reset)
+ comb += arst.eq(~self.locked | self.reset | ~self.pod_done)
if buf is None:
comb += cd.clk.eq(clkout)
else:
def __init__(self, clkin,
clksel=Signal(shape=2, reset=2),
reset=Signal(reset_less=True),
- locked=Signal()):
+ locked=Signal(reset_less=True)):
self.clkin = clkin
self.clkin_freq = None
self.clksel = clksel
self.locked = locked
+ self.pod_done = Signal(reset_less=True) # must be set in rawclk
self.reset = reset
self.nclkouts = 0
self.clkouts = {}
assert freq <= clki_freq_max
self.clkin_freq = freq
- def create_clkout(self, cd, freq, phase=0, margin=1e-2):
+ def create_clkout(self, cd, freq, phase=0, margin=1e-2, reset=True):
(clko_freq_min, clko_freq_max) = self.clko_freq_range
assert freq >= clko_freq_min
assert freq <= clko_freq_max
assert self.nclkouts < self.nclkouts_max
- self.clkouts[self.nclkouts] = (cd, freq, phase, margin)
+ self.clkouts[self.nclkouts] = (cd, freq, phase, margin, reset)
#create_clkout_log(self.logger, cd.name, freq, margin, self.nclkouts)
- print("clock domain", cd.domain, freq, margin, self.nclkouts)
+ print("clock domain", cd.domain, freq, margin, self.nclkouts, reset)
self.nclkouts += 1
def compute_config(self):
vco_freq = self.clkin_freq/clki_div*clkfb_div*1 # clkos3_div=1
(vco_freq_min, vco_freq_max) = self.vco_freq_range
if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max:
- for n, (clk, f, p, m) in sorted(self.clkouts.items()):
+ for n, (clk, f, p, m, rst) in sorted(self.clkouts.items()):
valid = False
for d in range(*self.clko_div_range):
clk_freq = vco_freq/d
raise ValueError("No PLL config found")
def elaborate(self, platform):
+ m = Module()
+
config = self.compute_config()
clkfb = Signal()
self.params.update(
o_LOCK = self.locked,
)
# for each clock-out, set additional parameters
- for n, (clk, f, p, m) in sorted(self.clkouts.items()):
+ for n, (clk, f, p, m, rst) in sorted(self.clkouts.items()):
n_to_l = {0: "P", 1: "S", 2: "S2"}
div = config["clko{}_div".format(n)]
cphase = int(p*(div + 1)/360 + div)
self.params["p_CLKO{}_CPHASE".format(n_to_l[n])] = cphase
self.params["o_CLKO{}".format(n_to_l[n])] = clk
- m = Module()
+ # for each clock-out, do a reset sync if required
+ arst = Signal()
+ comb += arst.eq(~self.locked | self.reset | ~self.pod_done)
+ for n, (clk, f, p, m, rst) in sorted(self.clkouts.items()):
+ rsts = ResetSynchroniser(arst, domain=clk)
+ m.submodules['%s_rst' % clk] = rsts
+
+ # actual PLL, finally
print ("params", self.params)
pll = Instance("EHXPLLL", **self.params)
m.submodules.pll = pll
return m
- pll = Instance("EHXPLLL",
- p_OUTDIVIDER_MUXA='DIVA',
- p_OUTDIVIDER_MUXB='DIVB',
- p_CLKOP_ENABLE='ENABLED',
- p_CLKOS_ENABLE='ENABLED',
- p_CLKOS2_ENABLE='DISABLED',
- p_CLKOS3_ENABLE='DISABLED',
- p_CLKOP_DIV=self.CLKOP_DIV,
- p_CLKOS_DIV=self.CLKOS_DIV,
- p_CLKFB_DIV=self.CLKFB_DIV,
- p_CLKI_DIV=self.CLKI_DIV,
- p_FEEDBK_PATH='INT_OP',
- p_CLKOP_TRIM_POL="FALLING",
- p_CLKOP_TRIM_DELAY=0,
- p_CLKOS_TRIM_POL="FALLING",
- p_CLKOS_TRIM_DELAY=0,
- i_CLKI=self.clkin,
- i_RST=0,
- i_STDBY=0,
- i_PHASESEL0=0,
- i_PHASESEL1=0,
- i_PHASEDIR=0,
- i_PHASESTEP=0,
- i_PHASELOADREG=0,
- i_PLLWAKESYNC=0,
- i_ENCLKOP=1,
- i_ENCLKOS=1,
- i_ENCLKOS2=0,
- i_ENCLKOS3=0,
- o_CLKOP=self.clkout1,
- o_CLKOS=self.clkout2,
- o_CLKOS2=self.clkout3,
- o_CLKOS3=self.clkout4,
- o_LOCK=self.lock,
- )
# CRG ----------------------------------------------------------------
class ArtyA7CRG(Elaboratable):
def __init__(self, sys_clk_freq):
self.sys_clk_freq = sys_clk_freq
+ self.reset = Signal(reset_less=True)
def elaborate(self, platform):
m = Module()
+ # reset
+ reset = platform.request(platform.default_rst).i
+ m.d.comb += self.reset.eq(reset)
+
# Get 100Mhz from oscillator
clk100 = platform.request("clk100")
cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True)
#m.domains += cd_eth
m.domains += dramsync
+ # PLL module
m.submodules.pll = pll = S7PLL(clk100, speedgrade=-1)
- reset = platform.request(platform.default_rst).i
+
+ # Power-on delay (a LOT)
+ podcnt = Signal(18, reset=-1)
+ pod_done = Signal(reset_less=True)
+ with m.If((podcnt != 0) & pll.locked):
+ m.d.rawclk += podcnt.eq(podcnt-1)
+ m.d.rawclk += pod_done.eq(podcnt == 0)
+
+ # PLL setup
m.d.comb += pll.reset.eq(reset)
+ m.d.comb += pll.pod_done.eq(pod_done)
pll.set_clkin_freq(100e6)
-
pll.create_clkout(sync, self.sys_clk_freq)
#platform.add_period_constraint(clk100_buf, 1e9/100e6)
# temporarily set dram sync clock exactly equal to main sync
m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
+
return m
class ECPIX5CRG(Elaboratable):
def __init__(self, sys_clk_freq=100e6):
self.sys_clk_freq = sys_clk_freq
+ self.reset = Signal(reset_less=True)
def elaborate(self, platform):
m = Module()
# Reset
reset = platform.request(platform.default_rst).i
+ m.d.comb += self.reset.eq(reset)
+
gsr0 = Signal()
gsr1 = Signal()
i_GSR=gsr1),
]
- # Power-on delay (655us)
- podcnt = Signal(3, reset=-1)
+ # create PLL module
+ m.submodules.pll = pll = ECP5PLL(ClockSignal("rawclk"), reset=~reset)
+
+ # Power-on delay (lots)
+ podcnt = Signal(8, reset=-1)
pod_done = Signal()
- with m.If(podcnt != 0):
+ with m.If((podcnt != 0) & pll.locked):
m.d.rawclk += podcnt.eq(podcnt-1)
m.d.rawclk += pod_done.eq(podcnt == 0)
cd_init = ClockDomain("init", local=False)
cd_sync = ClockDomain("sync", local=False)
cd_dramsync = ClockDomain("dramsync", local=False)
- m.submodules.pll = pll = ECP5PLL(ClockSignal("rawclk"), reset=~reset)
+
+ # create clocks for the PLL
+ m.d.comb += pll.pod_done.eq(pod_done)
pll.set_clkin_freq(100e6)
pll.create_clkout(ClockSignal("sync2x_unbuf"), 2*self.sys_clk_freq)
pll.create_clkout(ClockSignal("init"), 25e6)
m.domains += cd_init
m.domains += cd_sync
m.domains += cd_dramsync
- 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)
# # Generating sync (100Mhz) from sync2x