litex/migen/genlib/cdc.py

102 lines
2.2 KiB
Python
Raw Normal View History

from migen.fhdl.std import *
2013-12-03 16:12:40 -05:00
from migen.fhdl.bitcontainer import value_bits_sign
2013-02-23 13:03:35 -05:00
from migen.fhdl.specials import Special
2013-04-14 07:50:26 -04:00
from migen.fhdl.tools import list_signals
2013-02-23 13:03:35 -05:00
2013-04-25 08:56:45 -04:00
class NoRetiming(Special):
def __init__(self, reg):
Special.__init__(self)
self.reg = reg
# do nothing
@staticmethod
def lower(dr):
return Module()
class MultiRegImpl(Module):
2013-03-15 14:49:24 -04:00
def __init__(self, i, o, odomain, n):
2013-02-23 13:03:35 -05:00
self.i = i
self.o = o
self.odomain = odomain
w, signed = value_bits_sign(self.i)
self.regs = [Signal((w, signed)) for i in range(n)]
2013-04-25 08:56:45 -04:00
###
2014-10-17 05:08:37 -04:00
2013-02-23 13:03:35 -05:00
src = self.i
for reg in self.regs:
2013-04-25 08:56:45 -04:00
sd = getattr(self.sync, self.odomain)
sd += reg.eq(src)
2013-02-23 13:03:35 -05:00
src = reg
2013-04-25 08:56:45 -04:00
self.comb += self.o.eq(src)
self.specials += [NoRetiming(reg) for reg in self.regs]
2013-02-23 13:03:35 -05:00
class MultiReg(Special):
def __init__(self, i, o, odomain="sys", n=2):
2013-02-23 13:03:35 -05:00
Special.__init__(self)
self.i = i
self.o = o
self.odomain = odomain
self.n = n
def iter_expressions(self):
yield self, "i", SPECIAL_INPUT
yield self, "o", SPECIAL_OUTPUT
def rename_clock_domain(self, old, new):
Special.rename_clock_domain(self, old, new)
if self.odomain == old:
self.odomain = new
def list_clock_domains(self):
r = Special.list_clock_domains(self)
r.add(self.odomain)
2013-02-23 13:03:35 -05:00
return r
@staticmethod
def lower(dr):
2013-03-15 14:49:24 -04:00
return MultiRegImpl(dr.i, dr.o, dr.odomain, dr.n)
2013-02-23 13:03:35 -05:00
2013-07-24 13:25:14 -04:00
class PulseSynchronizer(Module):
2013-02-23 13:03:35 -05:00
def __init__(self, idomain, odomain):
self.i = Signal()
self.o = Signal()
2013-07-24 13:25:14 -04:00
###
2013-02-23 13:03:35 -05:00
toggle_i = Signal()
toggle_o = Signal()
toggle_o_r = Signal()
2013-07-24 13:25:14 -04:00
sync_i = getattr(self.sync, idomain)
sync_o = getattr(self.sync, odomain)
2014-10-17 05:08:37 -04:00
2013-07-24 13:25:14 -04:00
sync_i += If(self.i, toggle_i.eq(~toggle_i))
self.specials += MultiReg(toggle_i, toggle_o, odomain)
sync_o += toggle_o_r.eq(toggle_o)
self.comb += self.o.eq(toggle_o ^ toggle_o_r)
2013-04-24 13:13:36 -04:00
class GrayCounter(Module):
def __init__(self, width):
self.ce = Signal()
self.q = Signal(width)
self.q_next = Signal(width)
2013-04-25 07:11:15 -04:00
self.q_binary = Signal(width)
self.q_next_binary = Signal(width)
2013-04-24 13:13:36 -04:00
###
self.comb += [
If(self.ce,
2013-04-25 07:11:15 -04:00
self.q_next_binary.eq(self.q_binary + 1)
2013-04-24 13:13:36 -04:00
).Else(
2013-04-25 07:11:15 -04:00
self.q_next_binary.eq(self.q_binary)
2013-04-24 13:13:36 -04:00
),
2013-04-25 07:11:15 -04:00
self.q_next.eq(self.q_next_binary ^ self.q_next_binary[1:])
2013-04-24 13:13:36 -04:00
]
self.sync += [
2013-04-25 07:11:15 -04:00
self.q_binary.eq(self.q_next_binary),
2013-04-24 13:13:36 -04:00
self.q.eq(self.q_next)
]