rename ECP5 CRG, move source, remove duplicate version
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 25 Mar 2022 14:55:03 +0000 (14:55 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 25 Mar 2022 14:55:03 +0000 (14:55 +0000)
src/arty_crg.py
src/crg.py [deleted file]
src/ecp5_crg.py [new file with mode: 0644]
src/ls2.py

index 04b22b4e74695b08f62edac315b517f4b59013cd..2ddf010b6f655f6dfb32e6eb9618a3cd711f9e8f 100644 (file)
@@ -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 (file)
index a5370b7..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-# Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
-# Copyright (c) 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
-# Copyright (c) 2018-2020 Florent Kermarrec <florent@enjoy-digital.fr>
-# Copyright (c) 2019 Michael Betz <michibetz@gmail.com>
-#
-# 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 (file)
index 0000000..7546742
--- /dev/null
@@ -0,0 +1,256 @@
+# Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
+# Copyright (c) 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+# Copyright (c) 2018-2020 Florent Kermarrec <florent@enjoy-digital.fr>
+# Copyright (c) 2019 Michael Betz <michibetz@gmail.com>
+#
+# 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
+
index 7d79c245edd4b06c4e7fe9ed90537e4dfbe3ae3d..9c057ac1c3aa6a465636a68b8aff737abd3c2959 100644 (file)
@@ -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)