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: 7acea8f3ce84
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: f44ca291c129
Choose a head ref
  • 3 commits
  • 3 files changed
  • 1 contributor

Commits on Jan 26, 2019

  1. back.pysim: give better names to unnamed fragments and their signals.

    Was: top.#0, top.None_clk
    Now: top.U0, top.U0_clk
    
    (U for Unnamed, or similarly, an unit refdes.)
    whitequark committed Jan 26, 2019
    Copy the full SHA
    8686e9a View commit details
  2. back.pysim: support async reset.

    whitequark committed Jan 26, 2019
    Copy the full SHA
    e74dbc3 View commit details
  3. lib.cdc: add ResetSynchronizer.

    whitequark committed Jan 26, 2019
    Copy the full SHA
    f44ca29 View commit details
Showing with 86 additions and 9 deletions.
  1. +18 −7 nmigen/back/pysim.py
  2. +26 −1 nmigen/lib/cdc.py
  3. +42 −1 nmigen/test/test_lib_cdc.py
25 changes: 18 additions & 7 deletions nmigen/back/pysim.py
Original file line number Diff line number Diff line change
@@ -454,7 +454,7 @@ def add_fragment(fragment, scope=()):
hierarchy[fragment] = scope
for index, (subfragment, name) in enumerate(fragment.subfragments):
if name is None:
add_fragment(subfragment, (*scope, "#{}".format(index)))
add_fragment(subfragment, (*scope, "U{}".format(index)))
else:
add_fragment(subfragment, (*scope, name))
add_fragment(root_fragment, scope=("top",))
@@ -504,9 +504,9 @@ def add_domain_signal(signal, domain):

signal_slot = self._signal_slots[signal]

for subfragment, name in fragment.subfragments:
for i, (subfragment, name) in enumerate(fragment.subfragments):
if signal in subfragment.ports:
var_name = "{}_{}".format(name, signal.name)
var_name = "{}_{}".format(name or "U{}".format(i), signal.name)
break
else:
var_name = signal.name
@@ -550,10 +550,21 @@ def add_domain_signal(signal, domain):
self._domain_signals[domain] |= signals_bits

statements = []
for signal in fragment.iter_comb():
statements.append(signal.eq(signal.reset))
for domain, signal in fragment.iter_sync():
statements.append(signal.eq(signal))
for domain, signals in fragment.drivers.items():
reset_stmts = []
hold_stmts = []
for signal in signals:
reset_stmts.append(signal.eq(signal.reset))
hold_stmts .append(signal.eq(signal))

if domain is None:
statements += reset_stmts
else:
if self._domains[domain].async_reset:
statements.append(Switch(self._domains[domain].rst,
{0: hold_stmts, 1: reset_stmts}))
else:
statements += hold_stmts
statements += fragment.statements

compiler = _StatementCompiler(self._signal_slots)
27 changes: 26 additions & 1 deletion nmigen/lib/cdc.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .. import *


__all__ = ["MultiReg"]
__all__ = ["MultiReg", "ResetSynchronizer"]


class MultiReg:
@@ -23,3 +23,28 @@ def elaborate(self, platform):
m.d[self.odomain] += o.eq(i)
m.d.comb += self.o.eq(self._regs[-1])
return m


class ResetSynchronizer:
def __init__(self, arst, domain="sync", n=2):
self.arst = arst
self.domain = domain

self._regs = [Signal(name="arst{}".format(i), reset=1,
attrs={"no_retiming": True})
for i in range(n)]

def elaborate(self, platform):
if hasattr(platform, "get_reset_sync"):
return platform.get_reset_sync(self)

m = Module()
m.domains += ClockDomain("_reset_sync", async_reset=True)
for i, o in zip((0, *self._regs), self._regs):
m.d._reset_sync += o.eq(i)
m.d.comb += [
ClockSignal("_reset_sync").eq(ClockSignal(self.domain)),
ResetSignal("_reset_sync").eq(self.arst),
ResetSignal(self.domain).eq(self._regs[-1])
]
return m
43 changes: 42 additions & 1 deletion nmigen/test/test_lib_cdc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from .tools import *
from ..hdl.ast import *
from ..hdl.cd import *
from ..hdl.dsl import *
from ..back.pysim import *
from ..lib.cdc import *

@@ -23,7 +25,7 @@ def process():
sim.add_process(process)
sim.run()

def test_basic(self):
def test_reset_value(self):
i = Signal(reset=1)
o = Signal()
frag = MultiReg(i, o, reset=1)
@@ -40,3 +42,42 @@ def process():
self.assertEqual((yield o), 0)
sim.add_process(process)
sim.run()


class ResetSynchronizerTestCase(FHDLTestCase):
def test_basic(self):
arst = Signal()
m = Module()
m.domains += ClockDomain("sync")
m.submodules += ResetSynchronizer(arst)
s = Signal(reset=1)
m.d.sync += s.eq(0)

with Simulator(m, vcd_file=open("test.vcd", "w")) as sim:
sim.add_clock(1e-6)
def process():
# initial reset
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield s), 0)
yield Tick(); yield Delay(1e-8)

yield arst.eq(1)
yield Delay(1e-8)
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield s), 1)
yield arst.eq(0)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield s), 1)
yield Tick(); yield Delay(1e-8)
self.assertEqual((yield s), 0)
yield Tick(); yield Delay(1e-8)
sim.add_process(process)
sim.run()