UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
2,943 Views
Registered: ‎02-13-2018

how to know when to set clocks asynchronous and how to do so

Jump to solution

I'm having a lot of timing issues related to the MIG and the separate clocks I have running the DDR and the rest of the fpga. The only data i have crossing the clock bounds go through a async fifo, or are a couple status signals that are held for many clock cycles I have going through 2 flip flops. 

 

I know vivado will try to relate(?) clocks if they arnt claimed as async. So is the proper way to make vivado not relate the clocks in timing analysis is:

set_clock_groups -asyncronous -group {CLK_P} -group {other_clk_p another_clk_p}. 

 

Will this make vivado not relate CLK_p to the other clocks other_clk_p another_clk_p?

Also if it matters CLK_p is the name of the clk pin in the top level. Im not sure if I can use that, or I have to use all the intra clocks from the timing report. 

0 Kudos
1 Solution

Accepted Solutions
Historian
Historian
3,906 Views
Registered: ‎01-23-2009

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

I tried running a build with the set_clock_groups -asynchronous -group {CLK_P} constraint and it cleared up a lot of my Memory Interface Generator's clocking problems. A lot of these problems were internal clocking issues so I assume the timing analysis vivado was doing was trying to relate non-associated clocks. But if i remove the set_clock_group, how should I deal with the MIG's internal clocking problems? Just set a false path for each one?

 

I don't know exactly what kind of problems you are seeing, but my initial response is "absolutely not!"

 

The MIG is a complex block with complex clocking that has been fully designed and debugged by Xilinx. It contains a complete set of constraints required to constrain it. If these are failing, then the failures are real and cannot simply be ignored...

 

These failures are either because

  - you are using the block incorrectly (i.e. using the wrong clock to drive a port of the design) or

  - the rest of your design is making it impossible to meet the timing goals of the MIG

 

You need to figure out which they are. I would venture to say it is never acceptable to put any timing exceptions on internal nodes of the MIG.

 

Although looking at the fifo IP's xdc files (fifo.xdc, fifo_clocks.xdc, fifo_ooc.xdc) all the constraints are commented out. Are these ment to be uncommented or copied to my main project constraints file?

 

Again without knowing more I can't give you a complete answer, but you are not supposed to copy constraints from an IP's scoped XDC file to your main XDC file. If these constraints are commented out, then they are likely not needed. The FIFO generator can generate lots of different types of FIFOs, and not all of them need the same constraints. Of particular note FIFOs based on the "built-in" FIFO capability of the block RAMs, do not need exceptions on the clock crossing paths - they are internal to the hard core and hence are "correct by design". So if you are using a built-in FIFO it is reasonable to not have any constraints - maybe the FIFO generator leaves them in but commented out...

 

Avrum

9 Replies
Historian
Historian
2,915 Views
Registered: ‎01-23-2009

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

So first, when you do a set clock group you need to specify the clocks not the ports. Clocks and ports are different objects.

 

Now it is possible that when the clock was created on the CLK_P port it was also given the name "CLK_P" - this would be done with a command like

 

create_clock -name CLK_P -period <period> [get_ports CLK_P]

 

(I just want to make sure that is clear since it sounds like you are implying that the clock is the port name...)

 

When you use the set_clock_groups command, you are saying that the clocks in one group are asynchronous from the clocks in the other group - it does not change the relationship on clocks that are in the same group. So with your command paths between "other_clk_p" and "another_clk_p" are not affected; only paths CLK_P <-> other_clk_p and CLK_P <-> another_clk_p are affected - these paths are declared false.

 

Furthermore you can use the set_clock_groups command with only one group - this says "the clocks in this group are asynchronous to all other clocks in the design"

 

set_clock_groups -asynchronous -group {CLK_P}

 

now all paths between CLK_P and any other clock are declared false.

 

Finally I want to issue my standard caution regarding the set_clock_groups command. I advise against using this command (pretty much ever). It is dangerous. By doing this, you declare any paths between the clocks as false, and there is nothing you can do that will place any constraint on them. Generally, this is not safe.

 

Clock crossing circuits only work properly if the paths associated with the crossing are correctly constrained. It is true that the "default" timing relationship that the tool uses is incorrect for these clocks, and therefore a timing exception is required, but most clock domain crossing circuits require at least some constraints. For example, if your clock crossing FIFO is implemented in block RAM (not using the built-in FIFO) or distributed RAM, then the empty/full generation mechanism relies on proper clock crossing. For these to work, the clock crossing paths must be constrained with a set_max_delay -datapath_only, and the FIFO IP adds these constraints automatically (with the scoped constraints associated with the IP). However, if you then use the set_clock_groups command, this exception overrides the correct set_max_delay -datapath_only, and now your clock crossing circuit is under-constrained and can fail.

 

I always prefer a minimalist approach to exceptions. If you have a "couple of status signals" that also go through proper clock domain crossing circuits (if they are slow changing signals, then a couple of back-to-back flip-flops with the ASYNC_REG property set are proper clock domain crossing circuits for them), then a set_false_path exception is valid on the path between the domains; apply the set_false_path on that path not on any path between the clock domains. This is safer...

 

Avrum

Tags (1)
2,869 Views
Registered: ‎02-13-2018

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

Thank you for that great explanation. That first part cleared a lot of my questions up. 

 

I tried running a build with the set_clock_groups -asynchronous -group {CLK_P} constraint and it cleared up a lot of my Memory Interface Generator's clocking problems. A lot of these problems were internal clocking issues so I assume the timing analysis vivado was doing was trying to relate non-associated clocks. But if i remove the set_clock_group, how should I deal with the MIG's internal clocking problems? Just set a false path for each one?

 

But now I have a couple timing issues related to my fifo's overflow pin which are using block rams. So this sounds much exactly what you described. I'll be removing the set_clock_groups -async constraint. But then I have a whole bunch of timing problems with all this clocking stuff in the MIG that I'm not sure how to fix. 

 

Although looking at the fifo IP's xdc files (fifo.xdc, fifo_clocks.xdc, fifo_ooc.xdc) all the constraints are commented out. Are these ment to be uncommented or copied to my main project constraints file?

 

These are the constraints I'm referencing:

## set_max_delay -from [get_cells inst_fifo_gen/gconvfifo.rf/grf.rf/gntv_or_sync_fifo.gcx.clkx/*rd_pntr_gc_reg[*]] -to [get_cells inst_fifo_gen/gconvfifo.rf/grf.rf/gntv_or_sync_fifo.gcx.clkx/*gsync_stage[1].wr_stg_inst/Q_reg_reg[*]] -datapath_only [get_property -min PERIOD $rd_clock]
## set_bus_skew -from [get_cells inst_fifo_gen/gconvfifo.rf/grf.rf/gntv_or_sync_fifo.gcx.clkx/*rd_pntr_gc_reg[*]] -to [get_cells inst_fifo_gen/gconvfifo.rf/grf.rf/gntv_or_sync_fifo.gcx.clkx/*gsync_stage[1].wr_stg_inst/Q_reg_reg[*]] $skew_value
## set_max_delay -from [get_cells inst_fifo_gen/gconvfifo.rf/grf.rf/gntv_or_sync_fifo.gcx.clkx/*wr_pntr_gc_reg[*]] -to [get_cells inst_fifo_gen/gconvfifo.rf/grf.rf/gntv_or_sync_fifo.gcx.clkx/*gsync_stage[1].rd_stg_inst/Q_reg_reg[*]] -datapath_only [get_property -min PERIOD $wr_clock]
## set_bus_skew -from [get_cells inst_fifo_gen/gconvfifo.rf/grf.rf/gntv_or_sync_fifo.gcx.clkx/*wr_pntr_gc_reg[*]] -to [get_cells inst_fifo_gen/gconvfifo.rf/grf.rf/gntv_or_sync_fifo.gcx.clkx/*gsync_stage[1].rd_stg_inst/Q_reg_reg[*]] $skew_value

 

 

 

 

 

0 Kudos
Historian
Historian
3,907 Views
Registered: ‎01-23-2009

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

I tried running a build with the set_clock_groups -asynchronous -group {CLK_P} constraint and it cleared up a lot of my Memory Interface Generator's clocking problems. A lot of these problems were internal clocking issues so I assume the timing analysis vivado was doing was trying to relate non-associated clocks. But if i remove the set_clock_group, how should I deal with the MIG's internal clocking problems? Just set a false path for each one?

 

I don't know exactly what kind of problems you are seeing, but my initial response is "absolutely not!"

 

The MIG is a complex block with complex clocking that has been fully designed and debugged by Xilinx. It contains a complete set of constraints required to constrain it. If these are failing, then the failures are real and cannot simply be ignored...

 

These failures are either because

  - you are using the block incorrectly (i.e. using the wrong clock to drive a port of the design) or

  - the rest of your design is making it impossible to meet the timing goals of the MIG

 

You need to figure out which they are. I would venture to say it is never acceptable to put any timing exceptions on internal nodes of the MIG.

 

Although looking at the fifo IP's xdc files (fifo.xdc, fifo_clocks.xdc, fifo_ooc.xdc) all the constraints are commented out. Are these ment to be uncommented or copied to my main project constraints file?

 

Again without knowing more I can't give you a complete answer, but you are not supposed to copy constraints from an IP's scoped XDC file to your main XDC file. If these constraints are commented out, then they are likely not needed. The FIFO generator can generate lots of different types of FIFOs, and not all of them need the same constraints. Of particular note FIFOs based on the "built-in" FIFO capability of the block RAMs, do not need exceptions on the clock crossing paths - they are internal to the hard core and hence are "correct by design". So if you are using a built-in FIFO it is reasonable to not have any constraints - maybe the FIFO generator leaves them in but commented out...

 

Avrum

Scholar markcurry
Scholar
2,849 Views
Registered: ‎09-16-2009

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

 

Allow me to express a counter-point to Avrum's advice.  We've always used async clock groups, and feel it's the right choice for all our designs.  Some of the reasons include:

  • It clearly expresses design intent.  When you mark to clocks as asynchronous - you're stating design reality.  A free running oscillator on a board at 33 MHz, and another at 54 MHz are completely asynchronous.  There's no frequency,  nor phase alignment between the two - the tools should treat them as such. 
  • Forcing async clocks to be treated synchronously, like SDC states as the default behavior, forces the tool to assume a phase alignment which DOESN'T exist in reality.  Any analysis done with this (false) assumption is simply a random number generator.  And the way STA tools work is that if this (random number) falls outside some window, it'll report a failure.  So even using the STA tool as a "poor mans" CDC checker doesn't work reliably (the random number could hit a false good, as well as a false bad)
  • Managing individual cross clocking constraints is an intractable (for us, impossible) job.  The sheer number of cross-clock paths that can exists in these larger FPGAs can be QUITE high.  Last time I checked (6-7 years ago) on one our FPGAs this number was in the thousands.  Not maintainable at all.

However, as Avrum states - one must be careful.  You must insure that all CDCs are safe.  We have many ways of insuring such, but the tools include:

  • Design Reviews
  • Shared clock-crossing logic blocks (this is a VERY good idea) (Read up or ask me about scoped XDC files)
  • Dedicated CDC tools

 

So, if careful, and have a good design methodology for managing multiple clocks, you'll be fine using async_clock groups.

 

Regards,

 

Mark

Historian
Historian
2,839 Views
Registered: ‎01-23-2009

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

@markcurry,

 

Thank your for your counter-point...

 

But I have to ask - what happens when you have a clock domain crossing circuit between two different clocks that needs a constraint - like a Gray code clock crossing circuit. If the clocks involved are already declared as asynchronous groups, you cannot use a set_max_delay -datapath_only; the set_clock_groups overrides it. And without constraints, no matter how carefully designed a clock domain crossing circuit is, it can still fail.

 

The set_clock_groups command has the highest priority of all timing constraints. The only constraint that does still take effect with a set_clock_groups is the (new) set_bus_skew commands. In some clock domain crossing circuits, you can adequately (or at least mostly adequately) constrain clock domain crossing circuits with the set_bus_skew, but

  - this command is fairly new and not used by many people yet and

  - is not perfect for all clock domain crossing circuits that need constraints

 

So what do you do in these cases?

 

Forcing async clocks to be treated synchronously, like SDC states as the default behavior, forces the tool to assume a phase alignment which DOESN'T exist in reality

 

Absolutely! On this we agree! If the clocks are not related to eachother, you need to have exceptions on all clock crossing paths between the domains. However, the question is "what exception". If you use the set_clock_groups command, that question is already answered - the paths are declared false. If this is not the right exception (i.e. the Gray code clock crossing circuit), then your clock domain crossing circuit is under-constrained by the set_clock_groups, and the circuit can fail.

 

Avrum

Scholar markcurry
Scholar
2,832 Views
Registered: ‎09-16-2009

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

@avrumw wrote:

But I have to ask - what happens when you have a clock domain crossing circuit between two different clocks that needs a constraint - like a Gray code clock crossing circuit. If the clocks involved are already declared as asynchronous groups, you cannot use a set_max_delay -datapath_only; the set_clock_groups overrides it. And without constraints, no matter how carefully designed a clock domain crossing circuit is, it can still fail.

 

The set_clock_groups command has the highest priority of all timing constraints. The only constraint that does still take effect with a set_clock_groups is the (new) set_bus_skew commands. In some clock domain crossing circuits, you can adequately (or at least mostly adequately) constrain clock domain crossing circuits with the set_bus_skew, but

  - this command is fairly new and not used by many people yet and

  - is not perfect for all clock domain crossing circuits that need constraints

 

So what do you do in these cases?



I figured this would come up.

 

To be honest, until about a month ago, we mostly "buried our head in the sand" regarding the bus_skew (or other) constraint.  As you said, it's a fairly new tool (we've been waiting for it).  That darned SDC rule about "async" above all else really was a sore point. 

 

There was a post in these forums a few years ago talking about a flow that an ASIC designer used to work around this involving defining MULTIPLE clock definitions on the same pin.  We considered that to fill the gap, but never implemented that flow, as it was deemed too much of a "science project"

 

But in the end for the past many years, we've done:

 

  * Added appropriate physical constraints to "pull" synchronizer logic together.  This includes, ASYNC_REG = "true", and other techniques.  This is applicable to all cross-clock synchronizers.

 

  * where possible added an extra cycle of latency (or more) to our synchronizers. (This doesn't work for your Gray code example but works for others).   For each cycle of latency, this adds another full cycle (dest clock) of extra "settling time" which translates to a larger bus_skew minimum requirement (i.e. easy to achieve).

 

We checked a few of our synchronizers from time to time.  Sure enough the tools are "pulling" the logic nearby, and skew wasn't a problem.  We deemed the possibility of a rogue place and route run to be quite low.

 

But - I'm sure you're thinking - this is a bit seat-of-the pants.  And you'd be right.  And I've wished for a solution for a long time to actual do the check even if it's very unlikely to fail.

 

The bus_skew check does this.  With scoped_xdc, and the bus_skew check I believe we're 100% covered.  I do believe our synchronizers (we have a few different types) DO all work with a bus_skew check.  I'm curious as to what sort of synchronizer design you know of that could not be 100% covered with a bus_skew check.

 

This is all sort of forced on us - as I said - for our designs we're talking about many THOUSANDS of cross clock paths.  Way too many to manage with XDC exceptions for each.

 

And I'd argue that managing that many constraints would much more likely cause more trouble than the thing you're trying to check.  That's the thing with XDC constraints. They must be correct by design - there's no tool to double check them.  You can't "simulate" a XDC, nor formally verify it.  The only check is syntax, and if it hits a target.

 

For us, our XDC constraints are almost trivial - a few lines at most.  Almost ALL our designs just has clock definitions and     set_clock_groups -asynchronous statements.  Nothing else (i.e. NO false_paths nor multi_cycle paths).  Smaller constraint files = less errors.

 

And the problem with that large set of constraint definitions - most of the time the error is missing a false_path (either by forgetting the constraint or missing the target).  I'll call this a FALSELY_TIMED failure. 

 

What results from a FALSELY_TIMED failure is the tool wasting time (likely unsuccessfully) into trying to meet a timing goal that couldn't be met.  We'd often come back in the morning expecting an overnight FPGA build, but darned if the thing failed because of this, and we'd waste a day of debug.  This occurred WAY to often. (and still occasionally hits us when we forget to add the async_clock property).  The frustrated designer would often mutter a few expletives under his or her breath, add an overly aggressive false_path, and move on - just build my FPGA Darnit!  And the overly aggressive false_path leads too...

 

The other type of failure - a false path inadvertently targeting a TRUE path (FALSELY_SKIPPED) These are worse, in that you now have a circuit MEANT to be timed, but not.  I had one of these 8-9 years ago on a FPGA design that went to production. We found it about 7 months in.  I had to eat crow on that one as it was my bug.  (This was back in the ISE days with a HORRIBLE UCF syntax that I misinterpreted, but the idea's the same)

 

So we strongly prefer expressing true design intent as clearly, and succinctly as possible.

 

set_clock_groups -asynchronous, scoped XDC files with bus_skew constraints, and we're good to go.

 

Checking the new "bus_skew_report" leaves me confident that our past designs were likely fine as well.  All of them show a very healthy margin on bus_skew slack. (I'm unsure if bus_skew is a timing optimization that will effect place and route or not, or just a reported value).

 

So back to the OP, and the original question - I think async_clock groups are another valuable, and useful tool in your toolbox.  And it's not all or nothing either.  Most designs will likely have a bit of both solutions.  Like most engineering, there's many solutions, hardly any of which are perfect.

 

Regards,

 

Mark

 

Highlighted
Historian
Historian
2,822 Views
Registered: ‎01-23-2009

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

Added appropriate physical constraints to "pull" synchronizer logic together.  This includes, ASYNC_REG = "true", and other techniques.  This is applicable to all cross-clock synchronizers.

 

I am not sure I see a fool-proof mechanism of doing this. The ASYNC_REG property is only supposed to be used on flip-flops on the same clock domain that are part of the metastability resolution chain - specifically not for the path between clock domains.

 

While you can use LOC properties, on the flip-flops on either side of the domain crossing

  - these are complicated to use - I have not actually tried to use the equivalent of RLOG in Vivado - I don't know how they work

  - even if you get these right, they only constrain placement and not routing; the only way to control routing is with the equivalent of a DIRT string, and, again, I don't know how to use these in Vivado (or how complicated they are)

 

where possible added an extra cycle of latency (or more) to our synchronizers. (This doesn't work for your Gray code example but works for others).   For each cycle of latency, this adds another full cycle (dest clock) of extra "settling time" which translates to a larger bus_skew minimum requirement (i.e. easy to achieve).

 

This certainly reduces (probably drastically) the chance of failure, but doesn't (theoretically) reduce it to 0 (not counting the metastability probability that you can't avoid). I am sure that the likelihood of a failure of this system is effectively 0, but not theoretically 0...

 

I'm curious as to what sort of synchronizer design you know of that could not be 100% covered with a bus_skew check.

 

With the set_bus_skew, the latency through the synchronizer is technically unbounded. For most systems, this is fine, but for some, the latency of the synchronizer can have an effect on the throughput of the system. Without the set_max_delay -datapath_only, you cannot bound the latency.

 

Also (and I must admit that I am not an expert on the set_bus_skew - I haven't had time to really play with it), it has been mentioned on the forum that it is only good for a "bus"; not (for example) a bus and an extra control signal. I am not sure I believe that (but again, I haven't played with it), but if it is true, this is a problem for certain MUX synchronizers.

 

What results from a FALSELY_TIMED failure is the tool wasting time (likely unsuccessfully) into trying to meet a timing goal that couldn't be met. 

 

This is definitely a problem, but one that can be avoided using the report_clock_interaction, or a quick timing check after synthesis but before implementation. This is actually part of the UltraFast design methodology; verifying the correctness of your timing constraints after synthesis to prove that you don't have unreasonable requirements.

 

The other type of failure - a false path inadvertently targeting a TRUE path (FALSELY_SKIPPED) These are worse, in that you now have a circuit MEANT to be timed, but not.  I had one of these 8-9 years ago on a FPGA design that went to production. We found it about 7 months in.  I had to eat crow on that one as it was my bug.  (This was back in the ISE days with a HORRIBLE UCF syntax that I misinterpreted, but the idea's the same)

 

And this is exactly my reason for not using set_clock_groups commands. If you individually (or through scoped XDC files) constrain each synchronizer and don't have a set_clock_groups command, then a bad clock crossing is likely to show up as a timing failure. While this never should be the only mechanism you use to find bad clock crossings, it is one more check in the way of accidentally creating the situation above. And as you mention, the cost of these errors are huge.

 

(For the record, the report_clock_interaction and report_cdc commands are intended to help you find these kinds of bugs - neither of which were available in the ISE/UCF days - Hooray for Vivado!)

 

set_clock_groups -asynchronous, scoped XDC files with bus_skew constraints, and we're good to go.

 

It sounds like you have done a significant amount of work to develop your methodology for clock crossing, and  (with a few minor concerns above) it sounds reasonable.

 

But, for a less expert designer, I still feel that this approach is too dangerous. It is way too easy to make a "fatal" mistake when you are taking off all the protections by starting with the set_clock_groups command. That is just my opinion, though - as you say, there is never just one (or sometimes even as many as one) "correct" ways of solving an engineering problem...

 

Avrum

0 Kudos
2,709 Views
Registered: ‎02-13-2018

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

Great reply. You two are really masters of FPGA design. This post gave me much more options to consider. Thanks for taking the time to type all this out!!!

0 Kudos
2,708 Views
Registered: ‎02-13-2018

Re: how to know when to set clocks asynchronous and how to do so

Jump to solution

Thanks for all the info @avrumw. I took your tip and didn't use the set_clock_groups -async. I was able to properly constrain my design using ASYNC_REG and some set_max_delay and some set_false_path constraints where appropriate. Thanks for all the discussion. I was able to learn quite a few things that I'm sure will help me in the future. Also thank you @markcurry, I picked up a couple things from you to use in the future for my future clock crossing logic. Thank you both so much!!

0 Kudos