lib.cdc: adjust MultiReg for new CDC primitive conventions.

Refs #97.
This commit is contained in:
whitequark 2019-09-12 13:48:24 +00:00
parent 8c30147e39
commit 8f659b6cd6
3 changed files with 23 additions and 11 deletions

View file

@ -1,5 +1,7 @@
import warnings
from ...tools import deprecated from ...tools import deprecated
from ...lib.cdc import MultiReg from ...lib.cdc import MultiReg as NativeMultiReg
from ...hdl.ast import * from ...hdl.ast import *
from ..fhdl.module import CompatModule from ..fhdl.module import CompatModule
from ..fhdl.structure import If from ..fhdl.structure import If
@ -8,6 +10,16 @@ from ..fhdl.structure import If
__all__ = ["MultiReg", "GrayCounter", "GrayDecoder"] __all__ = ["MultiReg", "GrayCounter", "GrayDecoder"]
class MultiReg(NativeMultiReg):
def __init__(self, i, o, odomain="sync", n=2, reset=0):
if odomain != "sync":
warnings.warn("instead of `MultiReg(..., odomain={!r})`, "
"use `MultiReg(..., o_domain={!r})`"
.format(odomain, odomain),
DeprecationWarning, stacklevel=2)
super().__init__(i, o, o_domain=odomain, n=n, reset=reset)
@deprecated("instead of `migen.genlib.cdc.GrayCounter`, use `nmigen.lib.coding.GrayEncoder`") @deprecated("instead of `migen.genlib.cdc.GrayCounter`, use `nmigen.lib.coding.GrayEncoder`")
class GrayCounter(CompatModule): class GrayCounter(CompatModule):
def __init__(self, width): def __init__(self, width):

View file

@ -16,7 +16,7 @@ class MultiReg(Elaboratable):
Signal to be resynchronised Signal to be resynchronised
o : Signal(), out o : Signal(), out
Signal connected to synchroniser output Signal connected to synchroniser output
odomain : str o_domain : str
Name of output clock domain Name of output clock domain
n : int n : int
Number of flops between input and output. Number of flops between input and output.
@ -24,7 +24,7 @@ class MultiReg(Elaboratable):
Reset value of the flip-flops. On FPGAs, even if ``reset_less`` is True, the MultiReg is Reset value of the flip-flops. On FPGAs, even if ``reset_less`` is True, the MultiReg is
still set to this value during initialization. still set to this value during initialization.
reset_less : bool reset_less : bool
If True (the default), this MultiReg is unaffected by ``odomain`` reset. If True (the default), this MultiReg is unaffected by ``o_domain`` reset.
See "Note on Reset" below. See "Note on Reset" below.
Platform override Platform override
@ -42,17 +42,17 @@ class MultiReg(Elaboratable):
consider setting ``reset_less`` to False if any of the following is true: consider setting ``reset_less`` to False if any of the following is true:
- You are targeting an ASIC, or an FPGA that does not allow arbitrary initial flip-flop states; - You are targeting an ASIC, or an FPGA that does not allow arbitrary initial flip-flop states;
- Your design features warm (non-power-on) resets of ``odomain``, so the one-time - Your design features warm (non-power-on) resets of ``o_domain``, so the one-time
initialization at power on is insufficient; initialization at power on is insufficient;
- Your design features a sequenced reset, and the MultiReg must maintain its reset value until - Your design features a sequenced reset, and the MultiReg must maintain its reset value until
``odomain`` reset specifically is deasserted. ``o_domain`` reset specifically is deasserted.
MultiReg is reset by the ``odomain`` reset only. MultiReg is reset by the ``o_domain`` reset only.
""" """
def __init__(self, i, o, odomain="sync", n=2, reset=0, reset_less=True): def __init__(self, i, o, *, o_domain="sync", n=2, reset=0, reset_less=True):
self.i = i self.i = i
self.o = o self.o = o
self.odomain = odomain self.o_domain = o_domain
self._regs = [Signal(self.i.shape(), name="cdc{}".format(i), reset=reset, self._regs = [Signal(self.i.shape(), name="cdc{}".format(i), reset=reset,
reset_less=reset_less) reset_less=reset_less)
@ -64,7 +64,7 @@ class MultiReg(Elaboratable):
m = Module() m = Module()
for i, o in zip((self.i, *self._regs), self._regs): for i, o in zip((self.i, *self._regs), self._regs):
m.d[self.odomain] += o.eq(i) m.d[self.o_domain] += o.eq(i)
m.d.comb += self.o.eq(self._regs[-1]) m.d.comb += self.o.eq(self._regs[-1])
return m return m

View file

@ -315,7 +315,7 @@ class AsyncFIFO(Elaboratable, FIFOInterface):
produce_enc = m.submodules.produce_enc = \ produce_enc = m.submodules.produce_enc = \
GrayEncoder(self._ctr_bits) GrayEncoder(self._ctr_bits)
produce_cdc = m.submodules.produce_cdc = \ produce_cdc = m.submodules.produce_cdc = \
MultiReg(produce_w_gry, produce_r_gry, odomain="read") MultiReg(produce_w_gry, produce_r_gry, o_domain="read")
m.d.comb += produce_enc.i.eq(produce_w_nxt), m.d.comb += produce_enc.i.eq(produce_w_nxt),
m.d.write += produce_w_gry.eq(produce_enc.o) m.d.write += produce_w_gry.eq(produce_enc.o)
@ -324,7 +324,7 @@ class AsyncFIFO(Elaboratable, FIFOInterface):
consume_enc = m.submodules.consume_enc = \ consume_enc = m.submodules.consume_enc = \
GrayEncoder(self._ctr_bits) GrayEncoder(self._ctr_bits)
consume_cdc = m.submodules.consume_cdc = \ consume_cdc = m.submodules.consume_cdc = \
MultiReg(consume_r_gry, consume_w_gry, odomain="write") MultiReg(consume_r_gry, consume_w_gry, o_domain="write")
m.d.comb += consume_enc.i.eq(consume_r_nxt) m.d.comb += consume_enc.i.eq(consume_r_nxt)
m.d.read += consume_r_gry.eq(consume_enc.o) m.d.read += consume_r_gry.eq(consume_enc.o)