migen/genlib/cdc: fix BusSynchronizer
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 17 Sep 2015 21:16:03 +0000 (23:16 +0200)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Sat, 19 Sep 2015 04:18:39 +0000 (12:18 +0800)
ping/pong token can be lost when:
- source clock domain starts before destination clock domain.
- a clock domain stops.

This fix add a timeout to detect such situation and create another token.

migen/genlib/cdc.py

index caa0ec4bbe0a49eb02abf4069f46d913329ca54b..2fc144929ea116a2e26b5f76afc463bfdee5918b 100644 (file)
@@ -2,6 +2,7 @@ from migen.fhdl.std import *
 from migen.fhdl.bitcontainer import value_bits_sign
 from migen.fhdl.specials import Special
 from migen.fhdl.tools import list_signals
+from migen.genlib.misc import WaitTimer
 
 
 class NoRetiming(Special):
@@ -88,7 +89,7 @@ class BusSynchronizer(Module):
     Ensures that all the bits form a single word that was present
     synchronously in the input clock domain (unlike direct use of
     ``MultiReg``)."""
-    def __init__(self, width, idomain, odomain):
+    def __init__(self, width, idomain, odomain, timeout=128):
         self.i = Signal(width)
         self.o = Signal(width)
 
@@ -102,8 +103,10 @@ class BusSynchronizer(Module):
             sync_i += starter.eq(0)
             self.submodules._ping = PulseSynchronizer(idomain, odomain)
             self.submodules._pong = PulseSynchronizer(odomain, idomain)
+            self.submodules._timeout = WaitTimer(timeout)
             self.comb += [
-                self._ping.i.eq(starter | self._pong.o),
+                self._timeout.wait.eq(~self._ping.i),
+                self._ping.i.eq(starter | self._pong.o | self._timeout.done),
                 self._pong.i.eq(self._ping.i)
             ]