Wire up missing CRG / DDR3 clock control / reset signals
authorRaptor Engineering Development Team <support@raptorengineering.com>
Sat, 9 Apr 2022 20:00:47 +0000 (15:00 -0500)
committerRaptor Engineering Development Team <support@raptorengineering.com>
Sat, 9 Apr 2022 20:00:47 +0000 (15:00 -0500)
Swap DELAYF for DELAYG on DQ lines

examples/ecp5_crg.py
gram/phy/ecp5ddrphy.py

index 5c975d66c1dacaed906e13e96cb4781ceb64593a..82ff66d193c924209440e82bc27e291b2667285a 100644 (file)
@@ -169,10 +169,14 @@ class PLL(Elaboratable):
 
 
 class ECP5CRG(Elaboratable):
-    def __init__(self, sys_clk_freq=100e6, pod_bits=25):
+    def __init__(self, sys_clk_freq=100e6, pod_bits=16):
         self.sys_clk_freq = sys_clk_freq
         self.pod_bits = pod_bits
 
+        # DDR clock control signals
+        self.ddr_clk_stop = Signal()
+        self.ddr_clk_reset = Signal()
+
     def elaborate(self, platform):
         m = Module()
 
@@ -204,18 +208,18 @@ class ECP5CRG(Elaboratable):
                              i_GSR=gsr1),
         ]
 
-        # PLL
-        m.submodules.pll = pll = PLL(ClockSignal("rawclk"), reset=~reset)
-
-        # Power-on delay (655us)
+        # Power-on delay
         podcnt = Signal(self.pod_bits, reset=-1)
         pod_done = Signal()
-        with m.If((podcnt != 0) & pll.locked):
+        with m.If(podcnt != 0):
             m.d.rawclk += podcnt.eq(podcnt-1)
         m.d.rawclk += pod_done.eq(podcnt == 0)
 
+        # PLL
+        m.submodules.pll = pll = PLL(ClockSignal("rawclk"), reset=~pod_done|~reset)
+
         # Generating sync2x (200Mhz) and init (25Mhz) from extclk
-        cd_sync2x = ClockDomain("sync2x", local=False)
+        cd_sync2x = ClockDomain("sync2x", local=False, reset_less=True)
         cd_sync2x_unbuf = ClockDomain("sync2x_unbuf",
                                       local=False, reset_less=True)
         cd_init = ClockDomain("init", local=False)
@@ -228,7 +232,7 @@ class ECP5CRG(Elaboratable):
         pll.create_clkout(ClockSignal("init"), 25e6)
         m.submodules += Instance("ECLKSYNCB",
                 i_ECLKI = ClockSignal("sync2x_unbuf"),
-                i_STOP  = 0,
+                i_STOP  = self.ddr_clk_stop,
                 o_ECLKO = ClockSignal("sync2x"))
         m.domains += cd_sync2x_unbuf
         m.domains += cd_sync2x
@@ -238,8 +242,8 @@ class ECP5CRG(Elaboratable):
         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)
+        m.d.comb += ResetSignal("sync").eq(reset_ok|self.ddr_clk_reset)
+        m.d.comb += ResetSignal("dramsync").eq(reset_ok|self.ddr_clk_reset)
 
         # # Generating sync (100Mhz) from sync2x
 
@@ -247,7 +251,7 @@ class ECP5CRG(Elaboratable):
             p_DIV="2.0",
             i_ALIGNWD=0,
             i_CLKI=ClockSignal("sync2x"),
-            i_RST=0,
+            i_RST=ResetSignal("dramsync"),
             o_CDIVX=ClockSignal("sync"))
 
         # temporarily set dram sync clock exactly equal to main sync
index 585031d18976377a58acd642e18e4bce953c8058..32a679244b4dd639001f4805503b82993d2fb03d 100644 (file)
@@ -52,15 +52,15 @@ class ECP5DDRPHYInit(Elaboratable):
         # DDRDLLA/DDQBUFM/ECLK initialization sequence ---------------------------------------------
         t = 8  # in cycles
         tl = Timeline([
-            (1*t,  [freeze.eq(1)]),  # Freeze DDRDLLA
-            (2*t,  [self.stop.eq(1)]),   # Stop ECLK domain
+            (1*t,  [    freeze.eq(1)]),  # Freeze DDRDLLA
+            (2*t,  [ self.stop.eq(1)]),   # Stop ECLK domain
             (3*t,  [self.reset.eq(1)]),  # Reset ECLK domain
             (4*t,  [self.reset.eq(0)]),  # Release ECLK domain reset
-            (5*t,  [self.stop.eq(0)]),   # Release ECLK domain stop
-            (6*t,  [freeze.eq(0)]),  # Release DDRDLLA freeze
+            (5*t,  [ self.stop.eq(0)]),   # Release ECLK domain stop
+            (6*t,  [    freeze.eq(0)]),  # Release DDRDLLA freeze
             (7*t,  [self.pause.eq(1)]),  # Pause DQSBUFM
-            (8*t,  [update.eq(1)]),  # Update DDRDLLA
-            (9*t,  [update.eq(0)]),  # Release DDRDMMA update
+            (8*t,  [    update.eq(1)]),  # Update DDRDLLA
+            (9*t,  [    update.eq(0)]),  # Release DDRDMMA update
             (10*t, [self.pause.eq(0)]),  # Release DQSBUFM pause
         ])
         m.d.comb += tl.trigger.eq(lock & ~lock_d) # Trigger timeline on lock rising edge
@@ -120,6 +120,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
 
         self.pads = pads
         self._sys_clk_freq = sys_clk_freq
+        self.init = ECP5DDRPHYInit()
 
         databits = len(self.pads.dq.io)
         if databits % 8 != 0:
@@ -190,7 +191,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
             m.d.sync += burstdet_reg.eq(0)
 
         # Init -------------------------------------------------------------------------------------
-        m.submodules.init = init = ECP5DDRPHYInit()
+        m.submodules.init = init = self.init
 
         # Parameters -------------------------------------------------------------------------------
         cl, cwl = get_cl_cw("DDR3", tck)
@@ -460,13 +461,10 @@ class ECP5DDRPHY(Peripheral, Elaboratable):
                         i_D2=dq_o_data_muxed[2],
                         i_D3=dq_o_data_muxed[3],
                         o_Q=dq_o),
-                    Instance("DELAYF",
-                        p_DEL_MODE="DQS_ALIGNED_X2",
-                        i_LOADN=1,
-                        i_MOVE=0,
-                        i_DIRECTION=0,
-                        i_A=dq_i,
-                        o_Z=dq_i_delayed),
+                    Instance("DELAYG",
+                        p_DEL_MODE = "DQS_ALIGNED_X2",
+                        i_A        = dq_i,
+                        o_Z        = dq_i_delayed),
                     Instance("IDDRX2DQA",
                         i_RST=ResetSignal("dramsync"),
                         i_ECLK=ClockSignal("sync2x"),