From 2d93e70793b209da9f2d7beafaf2f74756b290cb Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 26 Jan 2019 18:07:59 +0000 Subject: [PATCH] lib.cdc: add ResetSynchronizer. --- nmigen/lib/cdc.py | 27 ++++++++++++++++++++++- nmigen/test/test_lib_cdc.py | 43 ++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/nmigen/lib/cdc.py b/nmigen/lib/cdc.py index 7ff459d..c7624bc 100644 --- a/nmigen/lib/cdc.py +++ b/nmigen/lib/cdc.py @@ -1,7 +1,7 @@ from .. import * -__all__ = ["MultiReg"] +__all__ = ["MultiReg", "ResetSynchronizer"] class MultiReg: @@ -23,3 +23,28 @@ class MultiReg: 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 diff --git a/nmigen/test/test_lib_cdc.py b/nmigen/test/test_lib_cdc.py index af68d2f..4a6c1cf 100644 --- a/nmigen/test/test_lib_cdc.py +++ b/nmigen/test/test_lib_cdc.py @@ -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 @@ class MultiRegTestCase(FHDLTestCase): 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 @@ class MultiRegTestCase(FHDLTestCase): 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() -- 2.30.2