Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 263d57732319
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4eadc1629ac9
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Dec 12, 2018

  1. genlib.cdc.MultiReg: pull in from Migen.

    whitequark committed Dec 12, 2018
    Copy the full SHA
    bc60631 View commit details
  2. Copy the full SHA
    4eadc16 View commit details
Showing with 81 additions and 6 deletions.
  1. +10 −0 examples/cdc.py
  2. +28 −5 nmigen/fhdl/ast.py
  3. 0 nmigen/genlib/__init__.py
  4. +22 −0 nmigen/genlib/cdc.py
  5. +21 −1 nmigen/tools.py
10 changes: 10 additions & 0 deletions examples/cdc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from nmigen.fhdl import *
from nmigen.back import rtlil, verilog
from nmigen.genlib.cdc import *


sys = ClockDomain()
i, o = Signal(name="i"), Signal(name="o")
frag = MultiReg(i, o).get_fragment(platform=None)
# print(rtlil.convert(frag, ports=[i, o], clock_domains={"sys": sys}))
print(verilog.convert(frag, ports=[i, o], clock_domains={"sys": sys}))
33 changes: 28 additions & 5 deletions nmigen/fhdl/ast.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import builtins
from collections import OrderedDict
from collections.abc import Iterable, MutableMapping, MutableSet

@@ -496,6 +497,11 @@ class Signal(Value, DUID):
If ``True``, do not generate reset logic for this ``Signal`` in synchronous statements.
The ``reset`` value is only used as a combinatorial default or as the initial value.
Defaults to ``False``.
min : int or None
max : int or None
If `bits_sign` is `None`, the signal bit width and signedness are
determined by the integer range given by `min` (inclusive,
defaults to 0) and `max` (exclusive, defaults to 2).
Attributes
----------
@@ -505,7 +511,7 @@ class Signal(Value, DUID):
reset : int
"""

def __init__(self, bits_sign=1, name=None, reset=0, reset_less=False):
def __init__(self, bits_sign=None, name=None, reset=0, reset_less=False, min=None, max=None):
super().__init__()

if name is None:
@@ -515,11 +521,28 @@ def __init__(self, bits_sign=1, name=None, reset=0, reset_less=False):
name = "$signal"
self.name = name

if isinstance(bits_sign, int):
bits_sign = bits_sign, False
self.nbits, self.signed = bits_sign
if bits_sign is None:
if min is None:
min = 0
if max is None:
max = 2
max -= 1 # make both bounds inclusive
if not min < max:
raise ValueError("Lower bound {!r} should be less than higher bound {!r}"
.format(min, max))
self.signed = min < 0 or max < 0
self.nbits = builtins.max(bits_for(min, self.signed), bits_for(max, self.signed))

elif isinstance(bits_sign, int):
if not (min is None or max is None):
raise ValueError("Only one of bits/signedness or bounds may be specified")
self.nbits, self.signed = 1, False

else:
self.nbits, self.signed = bits_sign

if not isinstance(self.nbits, int) or self.nbits < 0:
raise TypeError("Width must be a positive integer")
raise TypeError("Width must be a positive integer, not {!r}".format(self.nbits))
self.reset = reset
self.reset_less = reset_less

Empty file added nmigen/genlib/__init__.py
Empty file.
22 changes: 22 additions & 0 deletions nmigen/genlib/cdc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from ..fhdl import *


__all__ = ["MultiReg"]


class MultiReg(Module):
def __init__(self, i, o, odomain="sys", n=2, reset=0):
self.i = i
self.o = o
self.odomain = odomain

self.regs = [Signal(self.i.bits_sign(), name="cdc{}".format(i),
reset=reset, reset_less=True)#, attrs=("no_retiming",))
for i in range(n)]

def get_fragment(self, platform):
f = Module()
for i, o in zip((self.i, *self.regs), self.regs):
f.sync[self.odomain] += o.eq(i)
f.comb += self.o.eq(self.regs[-1])
return f.lower(platform)
22 changes: 21 additions & 1 deletion nmigen/tools.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from collections import Iterable


__all__ = ["flatten", "union"]
__all__ = ["flatten", "union", "log2_int", "bits_for"]


def flatten(i):
@@ -20,3 +20,23 @@ def union(i):
else:
r |= e
return r


def log2_int(n, need_pow2=True):
if n == 0:
return 0
r = (n - 1).bit_length()
if need_pow2 and (1 << r) != n:
raise ValueError("{} is not a power of 2".format(n))
return r


def bits_for(n, require_sign_bit=False):
if n > 0:
r = log2_int(n + 1, False)
else:
require_sign_bit = True
r = log2_int(-n, False)
if require_sign_bit:
r += 1
return r