From 192d2413515e7618851bd3e40f79a95036a175d7 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 23 Sep 2019 16:42:44 +0000 Subject: [PATCH] lib.cdc: avoid modifying synchronizers in their elaborate() method. --- nmigen/lib/cdc.py | 24 ++++++++++++++---------- nmigen/vendor/xilinx_7series.py | 9 ++++++--- nmigen/vendor/xilinx_spartan_3_6.py | 23 ++++++++++++++--------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/nmigen/lib/cdc.py b/nmigen/lib/cdc.py index 62d3939..602d957 100644 --- a/nmigen/lib/cdc.py +++ b/nmigen/lib/cdc.py @@ -57,19 +57,22 @@ class FFSynchronizer(Elaboratable): self.i = i self.o = o - self._o_domain = o_domain - self._stages = [Signal(self.i.shape(), name="stage{}".format(index), - reset=reset, reset_less=reset_less) - for index in range(stages)] + self._reset = reset + self._reset_less = reset_less + self._o_domain = o_domain + self._stages = stages def elaborate(self, platform): if hasattr(platform, "get_ff_sync"): return platform.get_ff_sync(self) m = Module() - for i, o in zip((self.i, *self._stages), self._stages): + flops = [Signal(self.i.shape(), name="stage{}".format(index), + reset=self._reset, reset_less=self._reset_less) + for index in range(self._stages)] + for i, o in zip((self.i, *flops), flops): m.d[self._o_domain] += o.eq(i) - m.d.comb += self.o.eq(self._stages[-1]) + m.d.comb += self.o.eq(flops[-1]) return m @@ -82,8 +85,7 @@ class ResetSynchronizer(Elaboratable): self.arst = arst self._domain = domain - self._stages = [Signal(1, name="stage{}".format(i), reset=1) - for i in range(stages)] + self._stages = stages def elaborate(self, platform): if hasattr(platform, "get_reset_sync"): @@ -91,11 +93,13 @@ class ResetSynchronizer(Elaboratable): m = Module() m.domains += ClockDomain("reset_sync", async_reset=True, local=True) - for i, o in zip((0, *self._stages), self._stages): + flops = [Signal(1, name="stage{}".format(index), reset=1) + for index in range(self._stages)] + for i, o in zip((0, *flops), flops): 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._stages[-1]) + ResetSignal(self._domain).eq(flops[-1]) ] return m diff --git a/nmigen/vendor/xilinx_7series.py b/nmigen/vendor/xilinx_7series.py index 2e7706c..b25c4e9 100644 --- a/nmigen/vendor/xilinx_7series.py +++ b/nmigen/vendor/xilinx_7series.py @@ -363,8 +363,11 @@ class Xilinx7SeriesPlatform(TemplatedPlatform): def get_ff_sync(self, ff_sync): m = Module() - for i, o in zip((ff_sync.i, *ff_sync._stages), ff_sync._stages): - o.attrs["ASYNC_REG"] = "TRUE" + flops = [Signal(ff_sync.i.shape(), name="stage{}".format(index), + reset=ff_sync._reset, reset_less=ff_sync._reset_less, + attrs={"ASYNC_REG": "TRUE"}) + for index in range(ff_sync._stages)] + for i, o in zip((ff_sync.i, *flops), flops): m.d[ff_sync._o_domain] += o.eq(i) - m.d.comb += ff_sync.o.eq(ff_sync._stages[-1]) + m.d.comb += ff_sync.o.eq(flops[-1]) return m diff --git a/nmigen/vendor/xilinx_spartan_3_6.py b/nmigen/vendor/xilinx_spartan_3_6.py index 382e3a1..284cfab 100644 --- a/nmigen/vendor/xilinx_spartan_3_6.py +++ b/nmigen/vendor/xilinx_spartan_3_6.py @@ -413,22 +413,27 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform): def get_ff_sync(self, ff_sync): m = Module() - for i, o in zip((ff_sync.i, *ff_sync._stages), ff_sync._stages): - o.attrs["ASYNC_REG"] = "TRUE" + flops = [Signal(ff_sync.i.shape(), name="stage{}".format(index), + reset=ff_sync._reset, reset_less=ff_sync._reset_less, + attrs={"ASYNC_REG": "TRUE"}) + for index in range(ff_sync._stages)] + for i, o in zip((ff_sync.i, *flops), flops): m.d[ff_sync._o_domain] += o.eq(i) - m.d.comb += ff_sync.o.eq(multireg._stages[-1]) + m.d.comb += ff_sync.o.eq(flops[-1]) return m - def get_reset_sync(self, resetsync): + def get_reset_sync(self, reset_sync): m = Module() m.domains += ClockDomain("reset_sync", async_reset=True, local=True) - for i, o in zip((0, *resetsync._stages), resetsync._stages): - o.attrs["ASYNC_REG"] = "TRUE" + flops = [Signal(1, name="stage{}".format(index), reset=1, + attrs={"ASYNC_REG": "TRUE"}) + for index in range(reset_sync._stages)] + for i, o in zip((0, *flops), flops): m.d.reset_sync += o.eq(i) m.d.comb += [ - ClockSignal("reset_sync").eq(ClockSignal(resetsync._domain)), - ResetSignal("reset_sync").eq(resetsync.arst), - ResetSignal(resetsync._domain).eq(resetsync._stages[-1]) + ClockSignal("reset_sync").eq(ClockSignal(reset_sync._domain)), + ResetSignal("reset_sync").eq(reset_sync.arst), + ResetSignal(reset_sync._domain).eq(flops[-1]) ] return m -- 2.30.2