Electronics > FPGA
How to set a false path in Vivado using an MMCM or PLL output clock?
(1/1)
trossin:
I'm messing around with some asynchronous FIFOs where the clock for the write side comes from an external pin (PAD) and the read side comes from an MMCM. The input to the MMCM comes from an external pin.
--- Code: ---clk_wiz_0 MmcmPllThing(
.clk_out1(Clk)
,.locked(Locked)
,.clk_in1(RefClk)
);
--- End code ---
There seems to be some magic with the clock wizard in that I get a complaint if I use a create_clock for the input to the MMCM (RefClk) saying that this clock is already defined. So, I assumed there is also something with the output since the timing engine knows what frequency the system clock is running at when doing a simple design that only uses the MMCM output.
I defined the FIFO write clock with:
create_clock -period 100.000 -name ExtWrClk [get_ports ExtWrClk]
When I try to reference the MMCM output for set_false_path or for set_clock_groups using [get_clocks Clk], I get failures about the clock unless I use:
set_false_path -from [get_clocks ExtWrClk] -to [get_clocks clk_out1_clk_wiz_0]
This upsets the Synthesis phase but makes the Implementation phase happy and gets rid of the timing violations (seems to work).
What is the correct way to get the output of the MMCM to the synthesis phase that also works into the implementation phase?
I did not have luck creating a clock named Clk using create_clock.
P.S. I got to learn about the need to send a clock into the FPGA on a "Clock Capable Pin" (MRCC or SRCC using the P version for single ended).
asmi:
--- Quote from: trossin on January 20, 2025, 02:20:04 am ---There seems to be some magic with the clock wizard in that I get a complaint if I use a create_clock for the input to the MMCM (RefClk) saying that this clock is already defined. So, I assumed there is also something with the output since the timing engine knows what frequency the system clock is running at when doing a simple design that only uses the MMCM output.
--- End quote ---
Whenever you invoke a wizard, it automatically creates xdc entries using the values you provide via their wirard. So no need to provide them again.
trossin:
So it seems like it uses my net name for the input to the NMCM but a different name than my net for the output. I’m able to add a create_clock for my output net with no warning. Also, if I don’t create one, the net name is unknown as a clock(which is my question).
Is there a place to look for the wizard created constraint so I can figure out the name of the output clock? It seems this could have been made a bit easier for folks new to these tools. It has been about 30 years since I first started using Synopsys at work and most stuff feels the same.
trossin:
Here are all the xdc files I found in the directory of my project (the last three are ones I added for the project) and none of the other files mentions the output of the MMCM. The clk_wiz_0.xdc just describes the 12 MHz input clock and not the 100 MHz output clock. I included the non-comment lines after the file list.
--- Code: ---$ find | grep xdc
./AsyncTest2.gen/sources_1/ip/clk_wiz_0/clk_wiz_0.xdc
./AsyncTest2.gen/sources_1/ip/clk_wiz_0/clk_wiz_0_board.xdc
./AsyncTest2.gen/sources_1/ip/clk_wiz_0/clk_wiz_0_ooc.xdc
./AsyncTest2.runs/clk_wiz_0_synth_1/.Xil/clk_wiz_0_propImpl.xdc
./AsyncTest2.runs/clk_wiz_0_synth_1/dont_touch.xdc
./AsyncTest2.runs/synth_1/.Xil/AsyncTest2_propImpl.xdc
./FalsePaths.xdc
./FifoReadPort.xdc
./FifoWritePort.xdc
--- End code ---
Non-commented lines in clk_wiz_0.xdc
--- Code: ---create_clock -period 83.333 [get_ports clk_in1]
set_input_jitter [get_clocks -of_objects [get_ports clk_in1]] 0.833
set_property PHASESHIFT_MODE WAVEFORM [get_cells -hierarchical *adv*]
--- End code ---
This seems to be magic to me that it can time the logic sitting on the output of the MMCM.
trossin:
So I found a second solution that seem to work. Give up on referencing the output of the MMCM/PLL and just use the reference clock input (the tools seem to time through the device). This produced no critical warnings or other complaints about my false path.
I created my own lower latency asynchronous FIFO as the FIFO generator code is sluggish. I made a little test bench using two Microchip 18F27Q10 microcontrollers. One drives bytes into my async FIFO in the FPGA at a little under 4 MHz and inside the FPGA reads at 100 MHz with pseudo random stuttering then uses the data to drive another async FIFO of mine at 100 MHz while the other microcontroller reads out of the FPGA at a little over 4 MHz and checks the results. The microcontrollers use internal RC oscillators and I mess with the clock tunning to make one fast and one slow so they are not in sync.
Both microcontrollers stutter and the checker displays the number of loops on an OLED display. In two days, it has pushed through 62 Gbytes without error. I did some sanity checks of removing the gray encoding to make sure the setup is able to detect errors and found that it fails after a few K bytes repeatably.
I included my false path experiments below:
--- Code: ---# This worked as well. It seems that the timing tool was able to make a
# false path through the MMCM/PLL. Trying to do clk_wiz_0/clk_out1 to ExtRdClk.
set_false_path -from [get_clocks ExtRdClk] -to [get_clocks RefClk]
set_false_path -to [get_clocks ExtRdClk] -from [get_clocks RefClk]
set_false_path -from [get_clocks ExtWrClk] -to [get_clocks RefClk]
set_false_path -to [get_clocks ExtWrClk] -from [get_clocks RefClk]
# This technique generates a warning during synthesis about the clock not
# existing but in the end generates a result without Critical Warnings
# in the Mehodology Summay (TIMING-6 and TIMING-7).
# It seems like you have to either guess the net name or first get an error about
# the clocks having no common source then use that name. A warning shows up during
# synthesis but the methodology warnings vanish during implementation.
#set_false_path -from [get_clocks ExtRdClk] -to [get_clocks clk_out1_clk_wiz_0]
#set_false_path -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks ExtRdClk]
#set_false_path -from [get_clocks ExtWrClk] -to [get_clocks clk_out1_clk_wiz_0]
#set_false_path -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks ExtWrClk]
#This technique generates no errors for synthesis or implmentation but instead
# generates Critical Warnings about no common primary clock between related clocks
#set_false_path -from [get_clocks ExtRdClk] -to [get_clocks clk_wiz_0/clk_out1]
#set_false_path -to [get_clocks ExtRdClk] -from [get_clocks clk_wiz_0/clk_out1]
#set_false_path -from [get_clocks ExtWrClk] -to [get_clocks clk_wiz_0/clk_out1]
#set_false_path -to [get_clocks ExtWrClk] -from [get_clocks clk_wiz_0/clk_out1]
# This technique generates no errors for synthesis or implmentation but instead
# generates Critical Warnings about no common primary clock between related clocks
# Seem to need to manually create output of MMCM
#create_clock -period 10.0 -name Clk
#
#set_false_path -from [get_clocks ExtRdClk] -to [get_clocks Clk]
#set_false_path -to [get_clocks ExtRdClk] -from [get_clocks Clk]
#
#set_false_path -from [get_clocks ExtWrClk] -to [get_clocks Clk]
#set_false_path -to [get_clocks ExtWrClk] -from [get_clocks Clk]
--- End code ---
Navigation
[0] Message Index
Go to full version