From 0336c38770d1fba5b9c81ad42211b0c390dbefc4 Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 28 Jun 2019 07:34:10 +0000 Subject: [PATCH] lib.cdc: avoid interior clock domains in ResetSynchronizer. Such clock domains will "leak" into the enclosing scope, which is generally undesirable. Also, this is instructive for a platform overriding the behavior, since it provides guidance on how to correctly instantiate platform-specific flops. I've considered also doing this for MultiReg(), but it is very challenging in presence of non-reset-less CDC FFs, since Yosys' $dffsr primitive has separate set and clear inputs, and reshuffling the reset value for those results in quite a bit of additional logic. (That said, it might have to be done anyway, precisely because letting Yosys generate this additional logic might prove too much for the toolchain to cope with, and again, platform-independent code should provide guidance to platform-specific code.) --- nmigen/lib/cdc.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/nmigen/lib/cdc.py b/nmigen/lib/cdc.py index 5d52503..802a865 100644 --- a/nmigen/lib/cdc.py +++ b/nmigen/lib/cdc.py @@ -82,12 +82,16 @@ class ResetSynchronizer(Elaboratable): 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]) - ] + for i, o in zip((Const(0, 1), *self._regs), self._regs): + m.submodules += Instance("$adff", + p_CLK_POLARITY=1, + p_ARST_POLARITY=1, + p_ARST_VALUE=Const(1, 1), + p_WIDTH=1, + i_CLK=ClockSignal(self.domain), + i_ARST=self.arst, + i_D=i, + o_Q=o + ) + m.d.comb += ResetSignal(self.domain).eq(self._regs[-1]) return m -- 2.30.2