from nmigen import (Elaboratable, Module, Signal, ClockDomain, Instance,
ClockSignal, ResetSignal)
+from nmigen.lib.cdc import ResetSynchronizer
+import math
__ALL__ = ["ArtyCRG"]
yield int(current) if math.floor(current) == current else current
current += step
+
# Xilinx / Generic -----------------------------------------------------
-class XilinxClocking(Module):
+class XilinxClocking(Elaboratable):
clkfbout_mult_frange = (2, 64+1)
clkout_divide_range = (1, 128+1)
- def __init__(self, vco_margin=0):
+ def __init__(self, clkin, vco_margin=0):
+ self.clkin = clkin
self.vco_margin = vco_margin
self.reset = Signal()
self.locked = Signal()
self.config = {}
self.params = {}
- def register_clkin(self, clkin, freq):
- self.clkin = Signal()
- if isinstance(clkin, (Signal, ClockSignal)):
- self.comb += self.clkin.eq(clkin)
- elif isinstance(clkin, Record):
- self.specials += DifferentialInput(clkin.p, clkin.n, self.clkin)
- else:
- raise ValueError
+ def set_clkin_freq(self, freq):
self.clkin_freq = freq
- register_clkin_log(self.logger, clkin, freq)
def create_clkout(self, cd, freq, phase=0, buf="bufg",
margin=1e-2, with_reset=True, ce=None):
assert self.nclkouts < self.nclkouts_max
clkout = Signal()
- self.clkouts[self.nclkouts] = (clkout, freq, phase, margin)
- if with_reset:
- self.specials += AsyncResetSynchronizer(cd, ~self.locked |
- self.reset)
- if buf is None:
- self.comb += cd.clk.eq(clkout)
- else:
- clkout_buf = Signal()
- self.comb += cd.clk.eq(clkout_buf)
- if buf == "bufg":
- self.specials += Instance("BUFG", i_I=clkout, o_O=clkout_buf)
- elif buf == "bufr":
- self.specials += Instance("BUFR", i_I=clkout, o_O=clkout_buf)
- elif buf == "bufgce":
- if ce is None:
- raise ValueError("BUFGCE requires user to provide "
- "a clock enable ce Signal")
- self.specials += Instance("BUFGCE", i_I=clkout,
- o_O=clkout_buf, i_CE=ce)
- elif buf == "bufio":
- self.specials += Instance("BUFIO", i_I=clkout,
- o_O=clkout_buf)
+ self.clkouts[self.nclkouts] = (clkout, freq, phase, margin, cd,
+ buf, with_reset, ce)
+
+ def elaborate(self, platform):
+ assert self.clkin_freq is not None
+ m = Module()
+ comb = m.d.comb
+ for n, clkcfg in self.clkouts.items():
+ (clkout, freq, phase, margin, cd, buf, with_reset, ce) = clkcfg
+ if with_reset:
+ arst = Signal()
+ m.submodules += ResetSynchronizer(arst, domain=cd.name)
+ comb += arst.eq(~self.locked | self.reset)
+ if buf is None:
+ comb += cd.clk.eq(clkout)
else:
- raise ValueError("Unsupported clock buffer: {}".format(buf))
- create_clkout_log(self.logger, cd.name, freq, margin, self.nclkouts)
- self.nclkouts += 1
- assert hasattr(self, "clkin")
+ clkout_buf = Signal()
+ comb += cd.clk.eq(clkout_buf)
+ if buf == "bufg":
+ m.submodules += Instance("BUFG",
+ i_I=clkout,
+ o_O=clkout_buf)
+ elif buf == "bufr":
+ m.submodules += Instance("BUFR",
+ i_I=clkout,
+ o_O=clkout_buf)
+ elif buf == "bufgce":
+ if ce is None:
+ raise ValueError("BUFGCE requires user to provide "
+ "a clock enable ce Signal")
+ m.submodules += Instance("BUFGCE",
+ i_I=clkout,
+ o_O=clkout_buf,
+ i_CE=ce)
+ elif buf == "bufio":
+ m.submodules += Instance("BUFIO",
+ i_I=clkout,
+ o_O=clkout_buf)
+ else:
+ raise ValueError("Unsupported clock buffer: %s" % buf)
+ print(cd.name, freq, margin, self.nclkouts)
+
+ return m
def compute_config(self):
config = {}
(vco_freq_min, vco_freq_max) = self.vco_freq_range
if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and
vco_freq <= vco_freq_max*(1 - self.vco_margin)):
- for n, (clk, f, p, m) in sorted(self.clkouts.items()):
+ for n, clkcfg in sorted(self.clkouts.items()):
+ (clkout, f, p, m, _, _, _, _) = clkcfg
valid = False
d_ranges = [self.clkout_divide_range]
r = getattr(self, "clkout%d_divide_range" % n, None)
if all_valid:
config["vco"] = vco_freq
config["clkfbout_mult"] = clkfbout_mult
- compute_config_log(self.logger, config)
+ print(config)
return config
raise ValueError("No PLL config found")
nclkouts_max = 6
clkin_freq_range = (19e6, 800e6)
- def __init__(self, speedgrade=-1):
+ def __init__(self, clkin, speedgrade=-1):
+ super().__init__(clkin)
#self.logger = logging.getLogger("S7PLL")
print ("Creating S7PLL, speedgrade %d" % speedgrade)
- XilinxClocking.__init__(self)
self.divclk_divide_range = (1, 56+1)
self.vco_freq_range = {
-1: (800e6, 1600e6),
-3: (800e6, 2133e6),
}[speedgrade]
- def do_finalize(self):
- XilinxClocking.do_finalize(self)
+ def elaborate(self, platform):
+ m = super().elaborate(platform)
config = self.compute_config()
pll_fb = Signal()
self.params.update(
p_DIVCLK_DIVIDE=config["divclk_divide"],
i_CLKIN1=self.clkin, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,
)
- for n, (clk, f, p, m) in sorted(self.clkouts.items()):
- self.params["p_CLKOUT{}_DIVIDE".format(n)] = \
- config["clkout{}_divide".format(n)]
- self.params["p_CLKOUT{}_PHASE".format(n)] = \
- config["clkout{}_phase".format(n)]
+ for n, (clk, f, p, _, _, _, _, _) in sorted(self.clkouts.items()):
+ div = config["clkout{}_divide".format(n)]
+ phs = config["clkout{}_phase".format(n)]
+ self.params["p_CLKOUT{}_DIVIDE".format(n)] = div
+ self.params["p_CLKOUT{}_PHASE".format(n)] = phs
self.params["o_CLKOUT{}".format(n)] = clk
- self.specials += Instance("PLLE2_ADV", **self.params)
-
+ m.submodules += Instance("PLLE2_ADV", **self.params)
+ return m
class ECP5PLL(Elaboratable):
#cd_clk200 = ClockDomain("cd_clk200")
#cd_eth = ClockDomain("cd_eth")
dramsync = ClockDomain("dramsync")
-
+
m.domains += sync
#m.domains += sync2x
#m.domains += sync4x
#m.domains += cd_clk200
#m.domains += cd_eth
m.domains += dramsync
-
+
clk100_ibuf = Signal()
clk100_buf = Signal()
m.submodules += [
- Instance("IBUF", i_I=ckl100, o_O=clk100_ibuf),
+ Instance("IBUF", i_I=clk100, o_O=clk100_ibuf),
Instance("BUFG", i_I=clk100_ibuf, o_O=clk100_buf)
]
- self.submodules.pll = pll = S7PLL(speedgrade=-1)
+ m.submodules.pll = pll = S7PLL(clk100_buf, speedgrade=-1)
reset = platform.request(platform.default_rst).i
- self.comb += pll.reset.eq(~reset)
- pll.register_clkin(clk100_buf, 100e6)
- pll.create_clkout(self.sync, sys_clk_freq)
+ m.d.comb += pll.reset.eq(~reset)
+ pll.set_clkin_freq(100e6)
- platform.add_period_constraint(clk100_buf, 1e9/100e6)
- platform.add_period_constraint(sync.clk, 1e9/sys_clk_freq)
- platform.add_false_path_constraints(clk100_buf, sync.clk)
+ pll.create_clkout(sync, self.sys_clk_freq)
+
+ #platform.add_period_constraint(clk100_buf, 1e9/100e6)
+ #platform.add_period_constraint(sync.clk, 1e9/sys_clk_freq)
+ #platform.add_false_path_constraints(clk100_buf, sync.clk)
# temporarily set dram sync clock exactly equal to main sync
m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
+ return m
class ECPIX5CRG(Elaboratable):