add in extra delay-for-core in ECP5CRG
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 16 Apr 2022 12:31:55 +0000 (13:31 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 16 Apr 2022 14:03:43 +0000 (15:03 +0100)
actually, it is a separate delay for everything-else-except-the-init domain
which is run at a really slow 25 mhz

src/ecp5_crg.py
src/ls2.py

index 980e62d87d778ecaecbcce63a672199239de2455..403ff7d1ce1427bcc6b71ae27d7c910a19d25075 100644 (file)
@@ -169,13 +169,18 @@ class PLL(Elaboratable):
 
 
 class ECP5CRG(Elaboratable):
-    def __init__(self, sys_clk_freq=100e6, dram_clk_freq=None, pod_bits=25):
+    def __init__(self, sys_clk_freq=100e6, dram_clk_freq=None,
+                       pod_bits=25, sync_bits=26):
         """when dram_clk_freq=None, a dramsync domain is still created
         but it is an alias of sync domain.  likewise the 2x
         """
         self.sys_clk_freq = sys_clk_freq
         self.dram_clk_freq = dram_clk_freq
-        self.pod_bits = pod_bits
+        self.pod_bits = pod_bits # for init domain
+        self.sync_bits = sync_bits # for all other domains
+        assert pod_bits <= sync_bits, \
+            "power-on-delay bits %d should " \
+            " be less than sync_bits %d" % (pod_bits, sync_bits)
 
     def phase2_domain(self, m, pll, name, freq, esyncb):
         """creates a domain that can be used with xdr=4 platform resources.
@@ -251,14 +256,21 @@ class ECP5CRG(Elaboratable):
 
         # Power-on delay (655us)
         podcnt = Signal(self.pod_bits, reset=-1)
+        synccnt = Signal(self.sync_bits, reset=-1)
         pod_done = Signal()
+        sync_done = Signal()
+        with m.If((synccnt != 0) & pll.locked):
+            m.d.rawclk += synccnt.eq(synccnt-1)
         with m.If((podcnt != 0) & pll.locked):
             m.d.rawclk += podcnt.eq(podcnt-1)
         m.d.rawclk += pod_done.eq(podcnt == 0)
+        m.d.rawclk += sync_done.eq(synccnt == 0)
 
         # and reset which only drops when the PLL is done and pod completes
         reset_ok = Signal(reset_less=True)
+        sync_reset_ok = Signal(reset_less=True)
         m.d.comb += reset_ok.eq(~pll.locked|~pod_done)
+        m.d.comb += sync_reset_ok.eq(~pll.locked|~sync_done)
 
         # create PLL input clock from platform default frequency
         pll.set_clkin_freq(platform.default_clk_frequency)
@@ -275,8 +287,8 @@ class ECP5CRG(Elaboratable):
             # xdr=4 can be requested on the sync domain. also do not request
             # an edge-clock-stop
             self.phase2_domain(m, pll, "sync", self.sys_clk_freq, True)
-            m.d.comb += ResetSignal("sync2x").eq(reset_ok)
-        m.d.comb += ResetSignal("sync").eq(reset_ok)
+            m.d.comb += ResetSignal("sync2x").eq(sync_reset_ok)
+        m.d.comb += ResetSignal("sync").eq(sync_reset_ok)
 
         # DRAM clock: if not requested set to sync, otherwise create with
         # a CLKESYNCB (which is set to no-stop at the moment)
@@ -292,10 +304,12 @@ class ECP5CRG(Elaboratable):
             m.domains += cd_dramsync2x
             m.d.comb += ClockSignal("dramsync2x").eq(ClockSignal("sync2x"))
         # resets for the dram domains
-        m.d.comb += ResetSignal("dramsync2x").eq(reset_ok)
-        m.d.comb += ResetSignal("dramsync").eq(reset_ok)
+        m.d.comb += ResetSignal("dramsync2x").eq(sync_reset_ok)
+        m.d.comb += ResetSignal("dramsync").eq(sync_reset_ok)
 
         # create 25 mhz "init" clock, straight (no 2x phase stuff)
+        # this domain can be used before all others, has its own delay
+        # (sync_bits)
         cd_init = ClockDomain("init", local=False)
         pll.create_clkout(ClockSignal("init"), 25e6)
         m.domains += cd_init
index 514b724f335048f34aed6ebb2478ac2373a4603c..bb918818cc70543fa14588214caab65c05af0bba 100644 (file)
@@ -9,7 +9,8 @@
 # under EU Grants 871528 and 957073, under the LGPLv3+ License
 
 from nmigen import (Module, Elaboratable, DomainRenamer, Record,
-                    Signal, Cat, Const, ClockSignal, ResetSignal)
+                    Signal, Cat, Const, ClockSignal, ResetSignal,
+                    )
 from nmigen.build.dsl import Attrs
 from nmigen.cli import verilog
 from nmigen.lib.cdc import ResetSynchronizer
@@ -288,12 +289,14 @@ class DDR3SoC(SoC, Elaboratable):
 
         # set up clock request generator
         pod_bits = 25
+        sync_bits = 26
         if fpga in ['versa_ecp5', 'versa_ecp5_85', 'isim', 'ulx3s',
                     'orangecrab']:
             if fpga in ['isim']:
-                pod_bits = 6
+                pod_bits = 5
+                sync_bits = 6
             self.crg = ECP5CRG(clk_freq, dram_clk_freq=dram_clk_freq,
-                               pod_bits=pod_bits)
+                               pod_bits=pod_bits, sync_bits=sync_bits)
         if fpga in ['arty_a7']:
             self.crg = ArtyA7CRG(clk_freq)
 
@@ -301,9 +304,10 @@ class DDR3SoC(SoC, Elaboratable):
         if self.dram_clk_freq is None:
             self.dram_clk_freq = clk_freq
 
-        # set up CPU, with 64-to-32-bit downconverters
+        # set up CPU, with 64-to-32-bit downconverters, and a delayed Reset
         if add_cpu:
             self.cpu = ExternalCore(name="ext_core")
+
             cvtdbus = wishbone.Interface(addr_width=30, data_width=32,
                                          granularity=8, features={'stall'})
             cvtibus = wishbone.Interface(addr_width=30, data_width=32,
@@ -602,7 +606,7 @@ class DDR3SoC(SoC, Elaboratable):
 
     def elaborate(self, platform):
         m = Module()
-        comb = m.d.comb
+        comb, sync = m.d.comb, m.d.sync
 
         # add the peripherals and clock-reset-generator
         if platform is not None and hasattr(self, "crg"):
@@ -641,10 +645,6 @@ class DDR3SoC(SoC, Elaboratable):
             m.submodules.extcore = self.cpu
             m.submodules.dbuscvt = self.dbusdowncvt
             m.submodules.ibuscvt = self.ibusdowncvt
-            # create stall sigs, assume wishbone classic
-            #ibus, dbus = self.cvtibus, self.cvtdbus
-            #comb += ibus.stall.eq(ibus.stb & ~ibus.ack)
-            #comb += dbus.stall.eq(dbus.stb & ~dbus.ack)
 
         m.submodules.arbiter = self._arbiter
         m.submodules.decoder = self._decoder
@@ -856,7 +856,8 @@ def build_platform(fpga, firmware):
         dram_clk_freq = clk_freq
     if fpga == 'isim':
         clk_freq = 50e6 # below 50 mhz, stops DRAM being enabled
-        dram_clk_freq = 100e6
+        dram_clk_freq = clk_freq
+        #dram_clk_freq = 100e6
     if fpga == 'versa_ecp5':
         clk_freq = 50e6 # crank right down to test hyperram
         #dram_clk_freq = 100e6
@@ -908,7 +909,7 @@ def build_platform(fpga, firmware):
 
     # Get SPI resource pins
     spi_0_pins = None
-    if False and platform is not None and \
+    if platform is not None and \
        fpga in ['versa_ecp5', 'versa_ecp5_85', 'isim']:
         # Override here to get FlashResource out of the way and enable Tercel
         # direct access to the SPI flash.