xilinx: use FDPE instances to implement get_async_ff_sync() #1091
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This closes #721 by implementing
get_async_ff_sync()
using FDPE primitives to obtain exactly the netlist that we want. This consits of a chain ofN
FPDEs (by defaultN = 2
) with all their PRE pins connected to the reset for a positive edgereset
or to the~reset
for a negative edge reset. The D pin of the first FDPE in the chain is connected to GND.To make timing analysis work correctly, two new attributes are introduced:
amaranth.vivado.false_path_pre
andamaranth.vivado.max_delay_pre
. These work similarly toamaranth.vivado.false_path
andamaranth.vivado.max_delay
, but affect only the PRE pin, which is what is needed for this synchronizer. The TCL has been modified to generate constraints using these attributes, and there are comments explaining how to use the attributes directly in an XDC file in case the user wants to manage their XDC file manually instead of using the TCL.I have tested this with the following example.
These are the constraints I'm using
The implementation schematic is as follows. Paths that are timed normally are highlighted in blue. Paths timed of a 3 ns max delay are highlighted in red. The paths that are not highlighted are not timed.
This looks correct to me. I haven't found detailed information about the timing characteristics of the FDPE, but my thinking is that if PRE is asserted then the output of
stage1
will go high in a short time regardless of what is happening with the clock. If PRE is deasserted, the worst that can happen is that this happens close to a clock edge. In this case I think that the output ofstage0
might go metastable, but the output ofstage1
should be a stable 1, because when this happens,stage1
has a stable 1 at its input. At the next clock edge, hopefully the metastability ofstage0
should have resolved to a stable 0 or a stable 1 (and if not, use a longer chain). If it has resolved to a 0, then the output ofstage1
will pick the 0 in this clock cycle. If it has resolved to a 1, thenstage0
will pick the 0 in this clock cycle, andstage1
will pick it in the next clock cycle.Besides testing this example with the constraints shown above, I have deleted the
set_false_path
andset_max_delay
constraints and checked that running the TCL commands that I have added generates the correct constraints.A question to make sure I understand what
async_edge="neg"
means: my interpretation is that when the input is 0, then the output should be 1 immediately. When the input is 1, then the output should be 0 at the next clock edge. Is this right?By the way, now that I have given some more thought to this reset synchronizer, I wonder how useful it is in a typical Xilinx design. Flip-flops are normally synchronous reset, so if the clock is off, they won't reset even if the reset is asserted (I guess that the main use case of
AsyncFFSynchronizer
instead ofFFSynchronizer
is to be able to assert the output even when there is no clock).