Module resync
This document contains technical documentation for the resync
module.
resync_counter.vhd
View source code on github.com.

Synchronize a counter value between two domains, using Gray coded values.
Note
This entity has a scoped constraint file that must be used.
Note that unlike e.g. resync_level.vhd, it is safe to drive the input of this entity with LUTs as well as FFs.
Warning
This entity assumes that the input counter value only increments and decrements in steps of one. Erroneous values can appear on the output if this is not followed.
This entity converts the linear input counter word to Gray code, resynchronizes it to the
output clock domain with an async_reg
chain, and converts it back to a linear number.
A set_bus_skew
constraint is a applied to the Gray coded bits that are sampled in the
output clock domain. That constraint imposes an upper limit for the difference in the
inter-word routing delay. This in turn means that the bits are always sampled coherently with
regards to changes on the input side. It is possible to sample while one bit is transitioning,
but the meta-stability protection of an async_reg
chain will resolve that to a “clean”
'0'
or '1'
.
Since the value is Gray coded, there will never be more than one bit transitioning for each value
change, which means that it does not matter if the transitioning value is resolved
to '0'
or '1'
.
Resource utilization
This entity has netlist builds set up with
automatic size checkers
in module_resync.py
.
The following table lists the resource utilization for the entity, depending on
generic configuration.
Generics |
Total LUTs |
FFs |
---|---|---|
width = 16 |
23 |
48 |
resync_cycles.vhd
View source code on github.com.

Resynchronizes a bit, so that the output bit is asserted as many clock cycles as the input bit.
Note
This entity instantiates resync_counter.vhd which has a scoped constraint file that must be used.
This module counts each clk_in
cycle the input bit is asserted.
The counter is resynchronized to clk_out
, and used as a reference to know
how many clk_out
cycles the output bit should be asserted.
The module may fail when clk_out
is slower than clk_in
and the input is
asserted many cycles in a row. An assertion is made to check for this case.
Note that unlike e.g. resync_level.vhd, it is safe to drive the input of this entity with LUTs as well as FFs.
resync_level.vhd
View source code on github.com.

Resync a single bit from one clock domain to another, using two async_reg
registers.
Note
This entity has a scoped constraint file that must be used.
The two registers will be placed in the same slice, in order to minimize Mean Time Between Failure (MTBF). This guarantees proper resynchronization of semi-static “level”-type signals without meta stability on rising/falling edges. It can not handle “pulse” type signals. Pulses can be missed and single-cycle pulse behavior will not work.
The clk_in
port does not necessarily have to be set. But if you want to have
a deterministic latency through the resync block (via a set_max_delay
constraint) it has to be set. If not, a simple set_false_path
constraint will
be used and the latency can be arbitrary, depending on the placer/router.
Input register
There is an option to include a register on the input side before the async_reg
flip-flop
chain.
This option is to prevent sampling of data when the input is in a transient “glitch” state, which
can occur if it is driven by a LUT as opposed to a flip-flop. If the input is already driven by
a flip-flop, you can safely set the generic to false
in order to save resources.
Note that this is a separate issue from meta-stability; they can happen independently of
each other.
When this option is enabled, the clk_in
port must be driven with the correct clock.
Some motivation why the input needs to be driven by a register:
While LUTs are designed to be glitch-free in order to save switching power, this can only be
achieved as long as only one LUT input value changes state.
When more than one input changes state per clock cycle, glitches will almost certainly appear on
the LUT output before reaching its steady state.
This is partly due to difference in propagation delay between the inputs, and partly due to
the electrical structure of a LUT. In a regular synchronous design, the Vivado timing engine
guarantees that all these glitches have been resolved and LUT output has reached its
steady state before the value is sampled by a FF. When the value is fed to our async_reg
FF
chain however there is no control over this, and we may very well sample an erroneous
glitch value.
So given this knowledge the rule of thumb is to always drive resync_level
input by a FF.
However since LUTs are glitch-free in some scenarios, exceptions can be made if we are sure
of what we are doing. For example if the value is inverted in a LUT before being fed to
resync_level
, then that is a scenario where we do not actually need the extra FF.
resync_level_on_signal.vhd
View source code on github.com.

Sample a bit from one clock domain to another.
Note
This entity has a scoped constraint file that must be used.
This entity does not utilize any meta stability protection.
It is up to the user to ensure that data_in
is stable when sample_value
is asserted.
Note that unlike e.g. resync_level.vhd, it is safe to drive the input of this entity with LUTs as well as FFs.
resync_pulse.vhd
View source code on github.com.

A robust way of resyncing a pulse signal from one clock domain to another.
Note
This entity instantiates resync_level.vhd which has a scoped constraint file that must be used.
This entity features a feedback input gating which makes it robust in all configurations. Without input gating, if multiple pulses arrive close to each other, pulse overload will occur and some, or even all of them, can be missed and not arrive on the output. With input gating, if multiple pulses arrive one and only one will arrive on the output.
Note that unlike e.g. resync_level.vhd, it is safe to drive the input of this entity with LUTs as well as FFs.
resync_slv_level.vhd
View source code on github.com.

Resync a vector from one clock domain to another.
Note
This entity instantiates resync_level.vhd which has a scoped constraint file that must be used.
This simple vector resync mechanism does not guarantee any coherency between the bits. There might be a large skew between different bits. It will also not be able to handle pulses in the input data, but can instead only handle semi-static “level”-type signals.
It does however have meta-stability protection.
See resync_level.vhd for details about constraining and usage of
the enable_input_register
generic.
resync_slv_level_coherent.vhd
View source code on github.com.

Resynchronize a data vector from one clock domain to another. Unlike e.g. resync_slv_level.vhd, this entity contains a mechanism that guarantees bit coherency.
Note
This entity has a scoped constraint file that must be used.
This entity is great for resynchronizing e.g. a control/status register or a counter value, which are scenarios where bit coherency is crucial. It will not be able to handle pulses in the input data, it is very likely that pulses will be missed. Hence the “level” in the name.
Note that unlike e.g. resync_level.vhd, it is safe to drive the input of this entity with LUTs as well as FFs.
A level signal is rotated around between input and output side, with three registers in each direction. The level toggles for each roundtrip, and data is sampled on each side upon a level transition. This ensures that data is sampled on the output side only when we know that the sampled input data is stable. Conversely, input data is only sampled when we know that data has been sampled on the output in a stable fashion.
Latency and resource utilization
The latency is less than or equal to
3 * period(clk_in) + 3 * period(clk_out)
This is also the sampling period of the signal. As such this resync is not suitable for signals that change quickly. It is instead typically used for e.g. monotonic counters, slow moving status words, and other data where the different bits are correlated.
The LUT utilization is always 3. The FF utilization increases linearly at a rate
of 2 * width
.
Compared to resync_counter.vhd this entity has lower LUT and FF usage in all scenarios. It does however have higher latency.
Another way of achieving the same functionality is to use a shallow asynchronous_fifo.vhd
with write_valid
and read_ready
statically set to 1
.
This entity will however have lower LUT usage.
FF usage is lower up to around width 32 where this entity will consume more FF.
Latency is about the same for both.
Resource utilization
This entity has netlist builds set up with
automatic size checkers
in module_resync.py
.
The following table lists the resource utilization for the entity, depending on
generic configuration.
Generics |
Total LUTs |
FFs |
---|---|---|
width = 16 |
3 |
38 |
resync_slv_level_on_signal.vhd
View source code on github.com.

Sample a vector from one clock domain to another.
Note
This entity instantiates resync_level_on_signal.vhd which has a scoped constraint file that must be used.
This modules does not utilize any meta stability protection.
It is up to the user to ensure that data_in
is stable when sample_value
is asserted.
It will not be able to handle pulses in the data and does not feature any bit coherency.
Hence it can only be used with semi-static “level”-type signals.
Note that unlike e.g. resync_level.vhd, it is safe to drive the input of this entity with LUTs as well as FFs.