Skip to content

Commit 23a07b9

Browse files
Wren6991whitequark
authored andcommitted
lib.cdc: add optional reset to MultiReg, and document its use cases.
1 parent a57c72d commit 23a07b9

File tree

1 file changed

+46
-2
lines changed

1 file changed

+46
-2
lines changed

nmigen/lib/cdc.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,57 @@
55

66

77
class MultiReg:
8-
def __init__(self, i, o, odomain="sync", n=2, reset=0):
8+
"""Resynchronise a signal to a different clock domain.
9+
10+
Consists of a chain of flip-flops. Eliminates metastabilities at the output, but provides
11+
no other guarantee as to the safe domain-crossing of a signal.
12+
13+
Parameters
14+
----------
15+
i : Signal(), in
16+
Signal to be resynchronised
17+
o : Signal(), out
18+
Signal connected to synchroniser output
19+
odomain : str
20+
Name of output clock domain
21+
n : int
22+
Number of flops between input and output.
23+
reset : int
24+
Reset value of the flip-flops. On FPGAs, even if ``reset_less`` is True, the MultiReg is
25+
still set to this value during initialization.
26+
reset_less : bool
27+
If True (the default), this MultiReg is unaffected by ``odomain`` reset.
28+
See "Note on Reset" below.
29+
30+
Platform override
31+
-----------------
32+
Define the ``get_multi_reg`` platform metehod to override the implementation of MultiReg,
33+
e.g. to instantiate library cells directly.
34+
35+
Note on Reset
36+
-------------
37+
MultiReg is non-resettable by default. Usually this is the safest option; on FPGAs
38+
the MultiReg will still be initialized to its ``reset`` value when the FPGA loads its
39+
configuration.
40+
41+
However, in designs where the value of the MultiReg must be valid immediately after reset,
42+
consider setting ``reset_less`` to False if any of the following is true:
43+
44+
- You are targeting an ASIC, or an FPGA that does not allow arbitrary initial flip-flop states;
45+
- Your design features warm (non-power-on) resets of ``odomain``, so the one-time
46+
initialization at power on is insufficient;
47+
- Your design features a sequenced reset, and the MultiReg must maintain its reset value until
48+
``odomain`` reset specifically is deasserted.
49+
50+
MultiReg is reset by the ``odomain`` reset only.
51+
"""
52+
def __init__(self, i, o, odomain="sync", n=2, reset=0, reset_less=True):
953
self.i = i
1054
self.o = o
1155
self.odomain = odomain
1256

1357
self._regs = [Signal(self.i.shape(), name="cdc{}".format(i),
14-
reset=reset, reset_less=True, attrs={"no_retiming": True})
58+
reset=reset, reset_less=reset_less, attrs={"no_retiming": True})
1559
for i in range(n)]
1660

1761
def elaborate(self, platform):

0 commit comments

Comments
 (0)