lib.cdc: avoid modifying synchronizers in their elaborate() method.
authorwhitequark <cz@m-labs.hk>
Mon, 23 Sep 2019 16:42:44 +0000 (16:42 +0000)
committerwhitequark <cz@m-labs.hk>
Mon, 23 Sep 2019 16:42:44 +0000 (16:42 +0000)
nmigen/lib/cdc.py
nmigen/vendor/xilinx_7series.py
nmigen/vendor/xilinx_spartan_3_6.py

index 62d39391e0c48353bad09bf40f60aabe603a3725..602d957a194533c24a111ede9747c434f8b4fd68 100644 (file)
@@ -57,19 +57,22 @@ class FFSynchronizer(Elaboratable):
         self.i = i
         self.o = o
 
-        self._o_domain = o_domain
-        self._stages = [Signal(self.i.shape(), name="stage{}".format(index),
-                               reset=reset, reset_less=reset_less)
-                        for index in range(stages)]
+        self._reset      = reset
+        self._reset_less = reset_less
+        self._o_domain   = o_domain
+        self._stages     = stages
 
     def elaborate(self, platform):
         if hasattr(platform, "get_ff_sync"):
             return platform.get_ff_sync(self)
 
         m = Module()
-        for i, o in zip((self.i, *self._stages), self._stages):
+        flops = [Signal(self.i.shape(), name="stage{}".format(index),
+                        reset=self._reset, reset_less=self._reset_less)
+                 for index in range(self._stages)]
+        for i, o in zip((self.i, *flops), flops):
             m.d[self._o_domain] += o.eq(i)
-        m.d.comb += self.o.eq(self._stages[-1])
+        m.d.comb += self.o.eq(flops[-1])
         return m
 
 
@@ -82,8 +85,7 @@ class ResetSynchronizer(Elaboratable):
         self.arst = arst
 
         self._domain = domain
-        self._stages = [Signal(1, name="stage{}".format(i), reset=1)
-                        for i in range(stages)]
+        self._stages = stages
 
     def elaborate(self, platform):
         if hasattr(platform, "get_reset_sync"):
@@ -91,11 +93,13 @@ class ResetSynchronizer(Elaboratable):
 
         m = Module()
         m.domains += ClockDomain("reset_sync", async_reset=True, local=True)
-        for i, o in zip((0, *self._stages), self._stages):
+        flops = [Signal(1, name="stage{}".format(index), reset=1)
+                 for index in range(self._stages)]
+        for i, o in zip((0, *flops), flops):
             m.d.reset_sync += o.eq(i)
         m.d.comb += [
             ClockSignal("reset_sync").eq(ClockSignal(self._domain)),
             ResetSignal("reset_sync").eq(self.arst),
-            ResetSignal(self._domain).eq(self._stages[-1])
+            ResetSignal(self._domain).eq(flops[-1])
         ]
         return m
index 2e7706c8cdc233eb310eb8fe06e346df85aa3dd8..b25c4e95c56a2389c556158d89632560bb63c8e1 100644 (file)
@@ -363,8 +363,11 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
 
     def get_ff_sync(self, ff_sync):
         m = Module()
-        for i, o in zip((ff_sync.i, *ff_sync._stages), ff_sync._stages):
-            o.attrs["ASYNC_REG"] = "TRUE"
+        flops = [Signal(ff_sync.i.shape(), name="stage{}".format(index),
+                        reset=ff_sync._reset, reset_less=ff_sync._reset_less,
+                        attrs={"ASYNC_REG": "TRUE"})
+                 for index in range(ff_sync._stages)]
+        for i, o in zip((ff_sync.i, *flops), flops):
             m.d[ff_sync._o_domain] += o.eq(i)
-        m.d.comb += ff_sync.o.eq(ff_sync._stages[-1])
+        m.d.comb += ff_sync.o.eq(flops[-1])
         return m
index 382e3a1799e9efa80a629ff2531330d08f9e6001..284cfab1934e9b2d16dd0d6bf55266f7990cf881 100644 (file)
@@ -413,22 +413,27 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
 
     def get_ff_sync(self, ff_sync):
         m = Module()
-        for i, o in zip((ff_sync.i, *ff_sync._stages), ff_sync._stages):
-            o.attrs["ASYNC_REG"] = "TRUE"
+        flops = [Signal(ff_sync.i.shape(), name="stage{}".format(index),
+                        reset=ff_sync._reset, reset_less=ff_sync._reset_less,
+                        attrs={"ASYNC_REG": "TRUE"})
+                 for index in range(ff_sync._stages)]
+        for i, o in zip((ff_sync.i, *flops), flops):
             m.d[ff_sync._o_domain] += o.eq(i)
-        m.d.comb += ff_sync.o.eq(multireg._stages[-1])
+        m.d.comb += ff_sync.o.eq(flops[-1])
         return m
 
-    def get_reset_sync(self, resetsync):
+    def get_reset_sync(self, reset_sync):
         m = Module()
         m.domains += ClockDomain("reset_sync", async_reset=True, local=True)
-        for i, o in zip((0, *resetsync._stages), resetsync._stages):
-            o.attrs["ASYNC_REG"] = "TRUE"
+        flops = [Signal(1, name="stage{}".format(index), reset=1,
+                        attrs={"ASYNC_REG": "TRUE"})
+                 for index in range(reset_sync._stages)]
+        for i, o in zip((0, *flops), flops):
             m.d.reset_sync += o.eq(i)
         m.d.comb += [
-            ClockSignal("reset_sync").eq(ClockSignal(resetsync._domain)),
-            ResetSignal("reset_sync").eq(resetsync.arst),
-            ResetSignal(resetsync._domain).eq(resetsync._stages[-1])
+            ClockSignal("reset_sync").eq(ClockSignal(reset_sync._domain)),
+            ResetSignal("reset_sync").eq(reset_sync.arst),
+            ResetSignal(reset_sync._domain).eq(flops[-1])
         ]
         return m