--- /dev/null
+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)})