From: Luke Kenneth Casson Leighton Date: Fri, 25 Mar 2022 14:55:03 +0000 (+0000) Subject: rename ECP5 CRG, move source, remove duplicate version X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aba538ce926eb66c775beb63e1a6909c27055744;p=ls2.git rename ECP5 CRG, move source, remove duplicate version --- 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/crg.py deleted file mode 100644 index a5370b7..0000000 --- a/src/crg.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright (c) 2020 LambdaConcept -# Copyright (c) 2021 Luke Kenneth Casson Leighton -# Copyright (c) 2018-2020 Florent Kermarrec -# Copyright (c) 2019 Michael Betz -# -# Based on code from LambaConcept, from the gram example which is BSD-2-License -# https://github.com/jeanthom/gram/tree/master/examples -# -# Modifications for the Libre-SOC Project funded by NLnet and NGI POINTER -# under EU Grants 871528 and 957073, under the LGPLv3+ License - - -from nmigen import (Elaboratable, Module, Signal, ClockDomain, Instance, - ClockSignal, ResetSignal, Const) - -__ALL__ = ["ECPIX5CRG"] - -class PLL(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()): - self.clkin = clkin - self.clkin_freq = None - self.clksel = clksel - self.locked = locked - 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): - (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) - #create_clkout_log(self.logger, cd.name, freq, margin, self.nclkouts) - print("clock domain", cd.domain, freq, margin, self.nclkouts) - 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) 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): - 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) 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 - - m = Module() - 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, - ) - - -class ECPIX5CRG(Elaboratable): - def __init__(self, sys_clk_freq=100e6): - self.sys_clk_freq = sys_clk_freq - - def elaborate(self, platform): - m = Module() - - # Get 100Mhz from oscillator - extclk = platform.request(platform.default_clk) - cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True) - m.d.comb += cd_rawclk.clk.eq(extclk) - m.domains += cd_rawclk - - # Reset - if platform.default_rst is not None: - reset = platform.request(platform.default_rst).i - else: - reset = Const(0) # whoops - - 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), - ] - - # PLL - m.submodules.pll = pll = PLL(ClockSignal("rawclk"), reset=~reset) - - # Power-on delay (655us) - podcnt = Signal(25, 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 extclk - 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 PLL clocks - pll.set_clkin_freq(platform.default_clk_frequency) - 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 - 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 - - 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/ecp5_crg.py b/src/ecp5_crg.py new file mode 100644 index 0000000..7546742 --- /dev/null +++ b/src/ecp5_crg.py @@ -0,0 +1,256 @@ +# Copyright (c) 2020 LambdaConcept +# Copyright (c) 2021 Luke Kenneth Casson Leighton +# Copyright (c) 2018-2020 Florent Kermarrec +# Copyright (c) 2019 Michael Betz +# +# Based on code from LambaConcept, from the gram example which is BSD-2-License +# https://github.com/jeanthom/gram/tree/master/examples +# +# Modifications for the Libre-SOC Project funded by NLnet and NGI POINTER +# under EU Grants 871528 and 957073, under the LGPLv3+ License + + +from nmigen import (Elaboratable, Module, Signal, ClockDomain, Instance, + ClockSignal, ResetSignal, Const) + +__all__ = ["ECP5CRG"] + + +class PLL(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()): + self.clkin = clkin + self.clkin_freq = None + self.clksel = clksel + self.locked = locked + 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): + (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) + #create_clkout_log(self.logger, cd.name, freq, margin, self.nclkouts) + print("clock domain", cd.domain, freq, margin, self.nclkouts) + 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) 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): + 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) 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 + + m = Module() + 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, + ) + + +class ECP5CRG(Elaboratable): + def __init__(self, sys_clk_freq=100e6): + self.sys_clk_freq = sys_clk_freq + + def elaborate(self, platform): + m = Module() + + # Get 100Mhz from oscillator + extclk = platform.request(platform.default_clk) + cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True) + m.d.comb += cd_rawclk.clk.eq(extclk) + m.domains += cd_rawclk + + # Reset + if platform.default_rst is not None: + reset = platform.request(platform.default_rst).i + else: + reset = Const(0) # whoops + + 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), + ] + + # PLL + m.submodules.pll = pll = PLL(ClockSignal("rawclk"), reset=~reset) + + # Power-on delay (655us) + podcnt = Signal(25, 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 extclk + 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 PLL clocks + pll.set_clkin_freq(platform.default_clk_frequency) + 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 + 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 + + 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/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)