From aba538ce926eb66c775beb63e1a6909c27055744 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Fri, 25 Mar 2022 14:55:03 +0000 Subject: [PATCH] rename ECP5 CRG, move source, remove duplicate version --- src/arty_crg.py | 206 ------------------------------------ src/{crg.py => ecp5_crg.py} | 5 +- src/ls2.py | 4 +- 3 files changed, 5 insertions(+), 210 deletions(-) rename src/{crg.py => ecp5_crg.py} (99%) diff --git a/src/arty_crg.py b/src/arty_crg.py index 04b22b4..2ddf010 100644 --- a/src/arty_crg.py +++ b/src/arty_crg.py @@ -182,132 +182,6 @@ class S7PLL(XilinxClocking): return m -class ECP5PLL(Elaboratable): - nclkouts_max = 3 - clki_div_range = (1, 128+1) - clkfb_div_range = (1, 128+1) - clko_div_range = (1, 128+1) - clki_freq_range = ( 8e6, 400e6) - clko_freq_range = (3.125e6, 400e6) - vco_freq_range = ( 400e6, 800e6) - - def __init__(self, clkin, - clksel=Signal(shape=2, reset=2), - reset=Signal(reset_less=True), - 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 = {} - self.config = {} - self.params = {} - - def ports(self): - return [ - self.clkin, - self.clksel, - self.lock, - ] + list(self.clkouts.values()) - - def set_clkin_freq(self, freq): - (clki_freq_min, clki_freq_max) = self.clki_freq_range - assert freq >= clki_freq_min - assert freq <= clki_freq_max - self.clkin_freq = freq - - 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, reset) - #create_clkout_log(self.logger, cd.name, freq, margin, self.nclkouts) - print("clock domain", cd.domain, freq, margin, self.nclkouts, reset) - self.nclkouts += 1 - - def compute_config(self): - config = {} - for clki_div in range(*self.clki_div_range): - config["clki_div"] = clki_div - for clkfb_div in range(*self.clkfb_div_range): - all_valid = True - 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, rst) in sorted(self.clkouts.items()): - valid = False - for d in range(*self.clko_div_range): - clk_freq = vco_freq/d - if abs(clk_freq - f) <= f*m: - config["clko{}_freq".format(n)] = clk_freq - config["clko{}_div".format(n)] = d - config["clko{}_phase".format(n)] = p - valid = True - break - if not valid: - all_valid = False - else: - all_valid = False - if all_valid: - config["vco"] = vco_freq - config["clkfb_div"] = clkfb_div - #compute_config_log(self.logger, config) - print ("PLL config", config) - return config - raise ValueError("No PLL config found") - - def elaborate(self, platform): - m = Module() - - config = self.compute_config() - clkfb = Signal() - self.params.update( - # attributes - a_FREQUENCY_PIN_CLKI = str(self.clkin_freq/1e6), - a_ICP_CURRENT = "6", - a_LPF_RESISTOR = "16", - a_MFG_ENABLE_FILTEROPAMP = "1", - a_MFG_GMCREF_SEL = "2", - # parameters - p_FEEDBK_PATH = "INT_OS3", # CLKOS3 rsvd for feedback with div=1. - p_CLKOS3_ENABLE = "ENABLED", - p_CLKOS3_DIV = 1, - p_CLKFB_DIV = config["clkfb_div"], - p_CLKI_DIV = config["clki_div"], - # reset, input clock, lock-achieved output - i_RST = self.reset, - i_CLKI = self.clkin, - o_LOCK = self.locked, - ) - # for each clock-out, set additional parameters - 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{}_ENABLE".format(n_to_l[n])] = "ENABLED" - self.params["p_CLKO{}_DIV".format(n_to_l[n])] = div - self.params["p_CLKO{}_FPHASE".format(n_to_l[n])] = 0 - self.params["p_CLKO{}_CPHASE".format(n_to_l[n])] = cphase - self.params["o_CLKO{}".format(n_to_l[n])] = clk - - # 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 - - # CRG ---------------------------------------------------------------- class ArtyA7CRG(Elaboratable): @@ -370,83 +244,3 @@ class ArtyA7CRG(Elaboratable): 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() - - # Get 100Mhz from oscillator - clk100 = platform.request("clk100") - cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True) - m.d.comb += cd_rawclk.clk.eq(clk100) - m.domains += cd_rawclk - - # Reset - reset = platform.request(platform.default_rst).i - m.d.comb += self.reset.eq(reset) - - gsr0 = Signal() - gsr1 = Signal() - - m.submodules += [ - Instance("FD1S3AX", p_GSR="DISABLED", - i_CK=ClockSignal("rawclk"), - i_D=~reset, - o_Q=gsr0), - Instance("FD1S3AX", p_GSR="DISABLED", - i_CK=ClockSignal("rawclk"), - i_D=gsr0, - o_Q=gsr1), - Instance("SGSR", i_CLK=ClockSignal("rawclk"), - i_GSR=gsr1), - ] - - # 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) & pll.locked): - m.d.rawclk += podcnt.eq(podcnt-1) - m.d.rawclk += pod_done.eq(podcnt == 0) - - # Generating sync2x (200Mhz) and init (25Mhz) from clk100 - cd_sync2x = ClockDomain("sync2x", local=False) - cd_sync2x_unbuf = ClockDomain("sync2x_unbuf", - local=False, reset_less=True) - cd_init = ClockDomain("init", local=False) - cd_sync = ClockDomain("sync", local=False) - cd_dramsync = ClockDomain("dramsync", local=False) - - # 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.submodules += Instance("ECLKSYNCB", - i_ECLKI = ClockSignal("sync2x_unbuf"), - i_STOP = 0, - o_ECLKO = ClockSignal("sync2x")) - m.domains += cd_sync2x_unbuf - m.domains += cd_sync2x - m.domains += cd_init - m.domains += cd_sync - m.domains += cd_dramsync - - # # Generating sync (100Mhz) from sync2x - - m.submodules += Instance("CLKDIVF", - p_DIV="2.0", - i_ALIGNWD=0, - i_CLKI=ClockSignal("sync2x"), - i_RST=0, - o_CDIVX=ClockSignal("sync")) - - # temporarily set dram sync clock exactly equal to main sync - m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync")) - - return m diff --git a/src/crg.py b/src/ecp5_crg.py similarity index 99% rename from src/crg.py rename to src/ecp5_crg.py index a5370b7..7546742 100644 --- a/src/crg.py +++ b/src/ecp5_crg.py @@ -13,7 +13,8 @@ from nmigen import (Elaboratable, Module, Signal, ClockDomain, Instance, ClockSignal, ResetSignal, Const) -__ALL__ = ["ECPIX5CRG"] +__all__ = ["ECP5CRG"] + class PLL(Elaboratable): nclkouts_max = 3 @@ -167,7 +168,7 @@ class PLL(Elaboratable): ) -class ECPIX5CRG(Elaboratable): +class ECP5CRG(Elaboratable): def __init__(self, sys_clk_freq=100e6): self.sys_clk_freq = sys_clk_freq diff --git a/src/ls2.py b/src/ls2.py index 7d79c24..9c057ac 100644 --- a/src/ls2.py +++ b/src/ls2.py @@ -51,7 +51,7 @@ from nmigen_boards.arty_a7 import ArtyA7_100Platform from nmigen_boards.test.blinky import Blinky from icarusversa import IcarusVersaPlatform # Clock-Reset Generator (works for all ECP5 platforms) -from crg import ECPIX5CRG +from ecp5_crg import ECP5CRG from arty_crg import ArtyA7CRG import sys @@ -272,7 +272,7 @@ class DDR3SoC(SoC, Elaboratable): # set up clock request generator if fpga in ['versa_ecp5', 'versa_ecp5_85', 'isim', 'ulx3s']: - self.crg = ECPIX5CRG(clk_freq) + self.crg = ECP5CRG(clk_freq) if fpga in ['arty_a7']: self.crg = ArtyA7CRG(clk_freq) -- 2.30.2