nmigen.lib.cdc: port PulseSynchronizer.
Co-authored-by: Luke Wren <wren6991@gmail.com>
This commit is contained in:
parent
71d9eea4a0
commit
fcbabfeefc
2 changed files with 81 additions and 1 deletions
|
|
@ -2,7 +2,7 @@ from .._utils import deprecated
|
|||
from .. import *
|
||||
|
||||
|
||||
__all__ = ["FFSynchronizer", "ResetSynchronizer"]
|
||||
__all__ = ["FFSynchronizer", "ResetSynchronizer", "PulseSynchronizer"]
|
||||
|
||||
|
||||
def _check_stages(stages):
|
||||
|
|
@ -156,3 +156,47 @@ class ResetSynchronizer(Elaboratable):
|
|||
ResetSignal(self._domain).eq(flops[-1])
|
||||
]
|
||||
return m
|
||||
|
||||
|
||||
class PulseSynchronizer(Elaboratable):
|
||||
"""A one-clock pulse on the input produces a one-clock pulse on the output.
|
||||
|
||||
If the output clock is faster than the input clock, then the input may be safely asserted at
|
||||
100% duty cycle. Otherwise, if the clock ratio is n : 1, the input may be asserted at most once
|
||||
in every n input clocks, else pulses may be dropped.
|
||||
Other than this there is no constraint on the ratio of input and output clock frequency.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
i_domain : str
|
||||
Name of input clock domain.
|
||||
o-domain : str
|
||||
Name of output clock domain.
|
||||
sync_stages : int
|
||||
Number of synchronisation flops between the two clock domains. 2 is the default, and
|
||||
minimum safe value. High-frequency designs may choose to increase this.
|
||||
"""
|
||||
def __init__(self, i_domain, o_domain, sync_stages=2):
|
||||
if not isinstance(sync_stages, int) or sync_stages < 1:
|
||||
raise TypeError("sync_stages must be a positive integer, not '{!r}'".format(sync_stages))
|
||||
|
||||
self.i = Signal()
|
||||
self.o = Signal()
|
||||
self.i_domain = i_domain
|
||||
self.o_domain = o_domain
|
||||
self.sync_stages = sync_stages
|
||||
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
|
||||
itoggle = Signal()
|
||||
otoggle = Signal()
|
||||
ff_sync = m.submodules.ff_sync = \
|
||||
FFSynchronizer(itoggle, otoggle, o_domain=self.o_domain, stages=self.sync_stages)
|
||||
otoggle_prev = Signal()
|
||||
|
||||
m.d[self.i_domain] += itoggle.eq(itoggle ^ self.i)
|
||||
m.d[self.o_domain] += otoggle_prev.eq(otoggle)
|
||||
m.d.comb += self.o.eq(otoggle ^ otoggle_prev)
|
||||
|
||||
return m
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue