So I’ve asked a question and hopefully you made it through it, possibly with a little help. Now, depending on experience, I’ll ask if you’ve worked in either Quartus or Vivado to develop constraints for the circuits. This helps fill me in how much of the flow you’ve worked on. So lets discuss constraining the synchronizer.
How would you constrain the synchronizer in Quartus or Vivado?Answer
The design half of the synchronizer is done, but now how do we constrain the tools for the best results. Years ago, we would simply set_false_path between the two clocks. Then clock groups were added. These worked fine for older technologies where clock speeds were relatively low. However, now even FPGAs can get up to >500Mhz in some cases.
In order to reduce the MTBF of the synchronizer, the RX_CLOCK FFs should be placed near to each other. From experience, both Quartus and Vivado pack back to back FFs pretty tightly and in general no extra constraints are needed. Xilinx offers Metastability hardened FFs in the Ultrascale and Ultrascale+ or a constraint on synchronizers can be applied: (*async_reg = “true”*)
In Xilinx, I’ve also applied a set_max_delay between the RX and TX clock domains:
set_max_delay -datapath_only -from [get_clocks TX_CLOCK] -to [get_clocks RX_CLOCK] [expr min([join [get_property PERIOD [get_clocks “TX_CLOCK RX_CLOCK”]] ,])]
Unfortunately, Altera doesn’t offer the datapath_only switch, although a similar max delay could be set, it would just be a little tighter.
Since not everyone has worked all aspects of the flow I consider this knowledge less critical than actually how to implement the synchronizer. It’s just nice to know and a plus for me that someone has worked on more of the flow.
The explanation here is right on point Thank you!
However, I have a question on constraining paths for a slightly different scenario. If the data is changing in the source clock domain at much lower frequency, will applying a combination of max path and multicycle path be a good idea?
For example, data is moving from 100Mhz domain to 20Mhz. The data in 100Mhz domain changes at a much lower frequency – say 1Mhz. This means, the 100Mhz-20Mhz boundary needs to get the data transfer done within 1/1Mhz seconds (1000ns). Please note that synchronizers (dual flop or async fifo) are in place.
Noting the window for transition is 1000ns, we set a max delay between source flop and destination flop to be 500ns (pessimistic constraint).
And as 500ns corresponds to 10 clock cycles of destination clock, we set setup multi cycle to 10 (and get back hold to launching edge to 0).
This is just a thought, and I’m wondering if this would be a right approach.
Would like to know your inputs. Thanks,
Sorry for taking so long to get back to you.
I never (well almost never) use multicycle paths. The reason for this is that you are telling the tool the data will be valid in n clock cycles, however, in simulation this cannot be simulated. You could argue that set_max_delay is similar, but since I reserve this for clock crossing paths, I’m taking extra care to ensure that the path is correct by design. There are CDC checking tools available, but I haven’t found much use for them.
As for your question, I believe both the multicycle path and set max delay would start at the same point and accomplish the same thing, but set_max_delay is cleaner IMHO. One thing to remember is that you are telling the tool it has that much time to do whatever it wants with the signal, so it could route it around the chip multiple times using all 500ns if it wanted to. 500ns of setup is more than enough for metastability, so I don’t see much of an issue with it, and in reality since it’s point to point, most likely the FFs will be much closer together.