genlib: clock domain crossing elements
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 23 Feb 2013 18:03:35 +0000 (19:03 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 23 Feb 2013 18:03:35 +0000 (19:03 +0100)
migen/genlib/cdc.py [new file with mode: 0644]

diff --git a/migen/genlib/cdc.py b/migen/genlib/cdc.py
new file mode 100644 (file)
index 0000000..d28b984
--- /dev/null
@@ -0,0 +1,69 @@
+from migen.fhdl.structure import *
+from migen.fhdl.specials import Special
+from migen.fhdl.tools import value_bits_sign, list_signals
+
+class MultiRegImpl:
+       def __init__(self, i, idomain, o, odomain, n):
+               self.i = i
+               self.idomain = idomain
+               self.o = o
+               self.odomain = odomain
+
+               w, signed = value_bits_sign(self.i)
+               self.regs = [Signal((w, signed)) for i in range(n)]
+
+       def get_fragment(self):
+               src = self.i
+               o_sync = []
+               for reg in self.regs:
+                       o_sync.append(reg.eq(src))
+                       src = reg
+               comb = [
+                       self.o.eq(src)
+               ]
+               return Fragment(comb, {self.odomain: o_sync})
+
+class MultiReg(Special):
+       def __init__(self, i, idomain, o, odomain, n=2):
+               Special.__init__(self)
+               self.i = i
+               self.idomain = idomain
+               self.o = o
+               self.odomain = odomain
+               self.n = n
+
+       def list_ios(self, ins, outs, inouts):
+               r = set()
+               if ins:
+                       r.update(list_signals(self.i))
+               if outs:
+                       r.update(list_signals(self.o))
+               return r
+
+       @staticmethod
+       def lower(dr):
+               return MultiRegImpl(dr.i, dr.idomain, dr.o, dr.odomain, dr.n)
+
+class PulseSynchronizer:
+       def __init__(self, idomain, odomain):
+               self.idomain = idomain
+               self.odomain = odomain
+               self.i = Signal()
+               self.o = Signal()
+
+       def get_fragment(self):
+               toggle_i = Signal()
+               toggle_o = Signal()
+               toggle_o_r = Signal()
+               sync_i = [
+                       If(self.i, toggle_i.eq(~toggle_i))
+               ]
+               sync_o = [
+                       toggle_o_r.eq(toggle_o)
+               ]
+               comb = [
+                       self.o.eq(toggle_o ^ toggle_o_r)
+               ]
+               return Fragment(comb, 
+                       {self.idomain: sync_i, self.odomain: sync_o},
+                       specials={MultiReg(toggle_i, self.idomain, toggle_o, self.odomain)})