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: 
Explorer
Explorer
3,525 Views
Registered: ‎07-29-2009

Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

I have an array value that is written via the AXI bus from a Zynq, essentially once, and then is used by a high-speed clock internal to the fabric.
Let's call the axi input signal: s_axis_tdata[31:0].
This is obviously crossing a clock boundary from the axi_clk domain (from the Zynq) to a register that can be read from the high-speed clock process, let's call that register phaseinc[31:0].  It really doesn't matter WHEN phaseinc get's the value from s_axis_tdata (the axi_bus) since phaseinc is in a continuous process always reading from the phaseinc register at the high-speed clock rate and a one, or two or, even more, hs_clk cycle initial glitch on the phaseinc register is acceptable.

I have used a single-bit synchronizer setup for all bits and set (*ASYNC_REG=TRUE*) for the two intermediate registers phaseinclo[31:0] (axi clock domain) and phaseinchi[31:0] (hi speed clock domain).

I have set up a constraint:

 set_false_path -from [get_cells reference_emitter_i/siggen_jesd_axi_0/inst/siggen_jesd_axi_v1_0_S00_AXI_inst/U1/phaseinclo_reg*]\
    -to [get_cells reference_emitter_i/siggen_jesd_axi_0/inst/siggen_jesd_axi_v1_0_S00_AXI_inst/U1/phaseinchi_reg*]

 

I obviously get a CDC-6 warning because that's not really the right method for a mutli-bit synchronizer: "Multibit synchronized with ASYNC_REG" property". 

  What's the best way to constrain this path?

Should I remove the ASYNC_REG property, since I have it set up as a false path anyways?

Should it be a false path from my description?

Is it really a REALLY-long multi-cycle path since the AXI write to the register rarely occurs, and it can arrive at the High-speed clock domain at any time?

 

On the other hand, going through a lot of effort of setting up fifos and more unusual clocking for something that should be "low threat" seems a little overboard.

 

In general, I'd like to know the thoughts and opinions.

Kurt

 

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
Historian
Historian
5,475 Views
Registered: ‎01-23-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Are you suggesting I should have the Write enable be synchronized before it crosses the AXI_CLK to HS_CLK boundary, or, just use an AXI_CLK delayed version of it to enable the HS clock FF?

 

In the MUX synchronizer I showed above, there are two inputs - the data (bus_in) and a signal which is pulsed whenever data changes state (valid_in). Both of these are on the "source" clock, which in your case is the AXI_CLK. So, in other words we need a signal that is pulsed for one AXI_CLK cycle on the first clock cycle where bus_in has the new data present.

 

We know that on a given clock, the AXI register is given a "write enable" and some new data on its input. On the clock after that, the AXI register has its new data. So to get a signal that is pulsed on that first clock where the new data is present, we need a clocked version of the "write enable" that loaded the AXI register. This clocked write enable becomes the "valid_in" above, and the output of the AXI register becomes the bus_in above.

 

Then, with a proper event synchronizer in the box marked "event synchronizer" - either a pulse synchronizer or a toggle synchronizer - the entire system will act as a MUX synchronizer. This makes the value of the AXI register continously available on the destination clock domain - the bus_out will update to the new value several clock cycles after the AXI register updates. but bus_out is guaranteed to be stable and coherent - either the old value or the new value - nothing else.

 

Avrum

0 Kudos
19 Replies
Voyager
Voyager
3,519 Views
Registered: ‎06-24-2013

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Hey @petersk,

 

I have used a single-bit synchronizer setup for all bits and set (*ASYNC_REG=TRUE*) for the two intermediate registers phaseinclo[31:0] (axi clock domain) and phaseinchi[31:0] (hi speed clock domain).

Why use a synchronizer at all if you do not care about metastability or delay on the phaseinchi[31:0]?

Wouldn't it be simpler to just connect them and declare all pathes as false pathes?

 

That said, the proper solution would be to register the data in the slow domain, propagate a (pulse) signal via a synchronizer to the high speed domain and use that signal to register the now stable low speed data. Then send back a signal to confirm that the data was captured (again via synchronizer, this time in the other direction).

 

Hope this helps,

Herbert

-------------- Yes, I do this for fun!
0 Kudos
Historian
Historian
3,509 Views
Registered: ‎01-23-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

I have used a single-bit synchronizer setup for all bits and set (*ASYNC_REG=TRUE*) for the two intermediate registers phaseinclo[31:0] (axi clock domain) and phaseinchi[31:0] (hi speed clock domain).

 

So, if I understand this correctly, you are using the ASYNC_REG property incorrectly.

 

The proper "two flip-flop metastability hardener" has two back to back flip-flops on the destination domain with the ASYNC_REG property set to true. The input of the first of these two FFs should be fed directly from a FF on the source domain. The FF on the source domain must not have the ASYNC_REG property set.

 

 

since phaseinc is in a continuous process always reading from the phaseinc register at the high-speed clock rate and a one, or two or, even more, hs_clk cycle initial glitch on the phaseinc register is acceptable

 

I just want to be clear on this. During these couple of clocks, the value of phaseinc is literally unknown - it may be the "old" value, the "new" value, or pretty much any combination of the old or new bits. The classic example is if you go from 0x7fff_ffff to 0x8000_0000 you can literally get any of the 2^32 possible values for this field from this system

 

But, as long as you use a properly defined 2 (or more) back to back FF chain with ASYNC_REG set, and you can tolerate literally any value, then this is OK. Of course, if you don't have the two back-to-back FFs with ASYNC_REG set, then you can crash your system - even if you could tolerate any value during the transition clocks (since metastability is much worse than "any value").

 

What's the best way to constrain this path?

 

From your description, the constraint is "correct" - the system has been designed to work with some number of clock cycles where this value is unknown around a change, so it is a false path.

 

That being said, this has nothing to do with the CDC checks. From the clock domain crossing point of view, structurally (forget about constraints) this looks like an illegal clock crossing. This is not a MUX, CE, or Gray Code clock crosser, therefore it is structurally not a true CDC. But in your case, that is OK - you have verified that your system will work in spite of the fact that this is not a true CDC.

 

So, the proper way to deal with this is (first) to verify, re-verify an re-re-verify that what you have said above is true - the system really won't fail in spite of the fact that you can get any value for a couple of clocks around the change. If that is the case, then you would put in a CDC waiver on this CDC. Unfortunately, CDC waivers are not yet implemented in 2017.2 - my understanding is that they are going in to 2017.3...

 

On the other hand, going through a lot of effort of setting up fifos and more unusual clocking for something that should be "low threat" seems a little overboard.

 

There are legal clock domain crossing structures that will deal with this case far more cheaply then a clock domain crossing FIFO. This situation (where you have a value on a different clock domain that only changes rarely) is the perfect application of a MUX (or CE) clock domain crosser (these are really the same thing).

 

This is the "general" structure of a MUX synchronizer (this one uses CE so I call it a CE synchronizer)

 

CE_sync.png

 

 

For the "Event Synchronizer" within, you can use any pulse synchronizer - I prefer the toggle event synchronizer shown in this post.

 

In this case, the "bus_in" would be the AXI register, and the valid_in would be a one clock cycle delayed version of the "write enable" to the AXI register.

 

Avrum

 

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

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Why use a synchronizer at all if you do not care about metastability or delay on the phaseinchi[31:0]?

 

You always care about metastability. The only time it is "legal" to bring an asynchronous input into a clock domain is when the asynchronous input either cannot change at all, or can only change when the data in the destination clock domain is held "inactive" - in reset, in a state where the clock is gated around the asynchronous input change, or in a static state where it is completely ignoring its inputs. In any other case - even if you can tolerate a "don't care" on an input - a metastable signal can crash a system...

 

Avrum

0 Kudos
Scholar drjohnsmith
Scholar
3,492 Views
Registered: ‎07-09-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

If your using ultra scale,

  then xilinx have a bunch of macros to solve this ever present problem of coding.

 

https://www.xilinx.com/support/documentation/sw_manuals/xilinx2016_1/ug974-vivado-ultrascale-libraries.pdf

 

many in there, but try page 20  XPM_CDC_PULSE

 

and I've just seen there is one for 7 series as well

 

https://www.xilinx.com/support/documentation/sw_manuals/xilinx2016_2/ug953-vivado-7series-libraries.pdf

 

Explorer
Explorer
3,481 Views
Registered: ‎07-29-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

I didn't realize the ASYNC_REG should only be on the receivers.  I will fix that.  Also, Are you suggesting I should have the Write enable be synchronized before it crosses the AXI_CLK to HS_CLK boundary, or, just use an AXI_CLK delayed version of it to enable the HS clock FF?

 

I really appreciate all the great insight in the responses, btw.

Tags (1)
0 Kudos
Voyager
Voyager
3,475 Views
Registered: ‎06-24-2013

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Hey @petersk,

 

I didn't realize the ASYNC_REG should only be on the receivers.

Pardon my ignorance, but how did you arrive at this conclusion?

 

Thanks,

Herbert

-------------- Yes, I do this for fun!
0 Kudos
Explorer
Explorer
3,469 Views
Registered: ‎07-29-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

"So, if I understand this correctly, you are using the ASYNC_REG property incorrectly.

 

The proper "two flip-flop metastability hardener" has two back to back flip-flops on the destination domain with the ASYNC_REG property set to true. The input of the first of these two FFs should be fed directly from a FF on the source domain. The FF on the source domain must not have the ASYNC_REG property set."

From Avrum's post.

Tags (1)
Voyager
Voyager
3,464 Views
Registered: ‎06-24-2013

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Ah, so with receivers you are referring to the registers on the destination clock domain.

I was worried for a moment that you want to set the ASYNC_REG only on one FF, which would be pointless.

 

Thanks for clarifying,

Herbert

-------------- Yes, I do this for fun!
0 Kudos
Historian
Historian
5,476 Views
Registered: ‎01-23-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Are you suggesting I should have the Write enable be synchronized before it crosses the AXI_CLK to HS_CLK boundary, or, just use an AXI_CLK delayed version of it to enable the HS clock FF?

 

In the MUX synchronizer I showed above, there are two inputs - the data (bus_in) and a signal which is pulsed whenever data changes state (valid_in). Both of these are on the "source" clock, which in your case is the AXI_CLK. So, in other words we need a signal that is pulsed for one AXI_CLK cycle on the first clock cycle where bus_in has the new data present.

 

We know that on a given clock, the AXI register is given a "write enable" and some new data on its input. On the clock after that, the AXI register has its new data. So to get a signal that is pulsed on that first clock where the new data is present, we need a clocked version of the "write enable" that loaded the AXI register. This clocked write enable becomes the "valid_in" above, and the output of the AXI register becomes the bus_in above.

 

Then, with a proper event synchronizer in the box marked "event synchronizer" - either a pulse synchronizer or a toggle synchronizer - the entire system will act as a MUX synchronizer. This makes the value of the AXI register continously available on the destination clock domain - the bus_out will update to the new value several clock cycles after the AXI register updates. but bus_out is guaranteed to be stable and coherent - either the old value or the new value - nothing else.

 

Avrum

0 Kudos
Explorer
Explorer
3,009 Views
Registered: ‎07-29-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Thanks Avrum, I'll delay the wren one clock cycle and then feed it into the  XPM_CDC_PULSE which seems like it will do the job you describe.

 

result cdc_pulse.PNG

 

 

 

The image shows the results.  One final question: If I do the CE synchronizer as I did above, can I dispense with the ASYNC_REG on the phaseinchi and phaseoffsethi 'synchronizer' registers?  Should I put a (*S="TRUE"*) on them anyways?

0 Kudos
Historian
Historian
2,969 Views
Registered: ‎01-23-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

If I do the CE synchronizer as I did above, can I dispense with the ASYNC_REG on the phaseinchi and phaseoffsethi 'synchronizer' registers? 

 

The ASYNC_REG property should only be set on the chain of registers used for metastability reduction. In your example, these are the  two flip-flops that are synchronizing the delayed wren (wren_delay). These would be in the XPM_CDC_PULSE macro. The "*hi" registers (which are the equivalent of the bus_out_reg registers in my examples) are not metastability resolution circuits, and hence must not have the ASYNC_REG property set on them.

 

I suppose it is reasonable to put a DONT_TOUCH on these registers...

 

Avrum

0 Kudos
Scholar drjohnsmith
Scholar
2,953 Views
Registered: ‎07-09-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

would the macro not have all the 'constraints' needed as part of the macro ?

 

no need to add extra, 

0 Kudos
Explorer
Explorer
2,943 Views
Registered: ‎07-29-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

And, I assume the XPM_CDC_PULSE can go from a faster clock domain to a slower clock domain? Pretty cool if it does.

Kurt

0 Kudos
Historian
Historian
2,941 Views
Registered: ‎01-23-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

And, I assume the XPM_CDC_PULSE can go from a faster clock domain to a slower clock domain? Pretty cool if it does.

 

Yes.

 

While not explicitly documented, the XPM_CDC_PULSE is probably a toggle synchronizer. The nice thing about these is that they will work from both fast to slow and slow to fast. The clock rates only determine the minimum spacing between "events" that can be crossed between the domains.

 

Take a look a this post which shows how a toggle synchronizer is constructed.

 

Avrum

0 Kudos
Historian
Historian
2,938 Views
Registered: ‎01-23-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

would the macro not have all the 'constraints' needed as part of the macro ?

 

I don't think so. The XPM macros are macros - they are not IP (which carry constraints with them through a scoped XDC file), they are more like library cells. The flip-flops within the macros will have the ASYNC_REG property set on them as appropriate, but I don't think they have timing exceptions (others can correct me if I am wrong).

 

Furthermore, by using these macros, you don't actually know the names of the underlying flip-flops (that will really end up in your design), which makes the exceptions hard to write; you may need to end up doing them "clock to clock", which is overly vague and open to potential underconstraints of other clock domain crossing circuits.

 

As a result, I still prefer to manually write my clock domain crossing circuits. The equivalent one to this macro (XPM_CDC_PULSE) is probably a toggle synchronizer.

 

Avrum

0 Kudos
Highlighted
Explorer
Explorer
2,926 Views
Registered: ‎07-29-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Thanks Avrum.  I do have another question: I noticed you said use (* DONT_TOUCH ="TRUE" *) instead of my suggested "(* S= "TRUE" *).  Why do you recommend DONT_TOUCH over S?

Kurt

Tags (1)
0 Kudos
Historian
Historian
2,924 Views
Registered: ‎01-23-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

Why do you recommend DONT_TOUCH over S?

 

I am not even certain that the S (Save) attribute is supported in Vivado - this is an XST (ISE) attribute...

 

In any case, the proper thing is to use DONT_TOUCH. In addition to preventing optimization at the synthesis stage, the DONT_TOUCH attribute is forwarded in the netlist to ensure that no optimizations of these cells are done by the later processes as well.

 

Avrum

0 Kudos
Explorer
Explorer
2,876 Views
Registered: ‎07-29-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

One more follow-up question:

On your toggle event synchronizer, what is a good rule-of-thumb or choice for a value for set_max_delay -datapath_only between the event_toggle_reg and signal_meta_reg?

 

I found this: "

Without constraints (i.e. declaring the clocks unrelated) the routing between src_din_reg and data_dst_clk is unconstrained (as is the path from src_send_toggle_src_clk to event_toggle_meta). This means that it can (for example) take 2ns for the path between src_send_toggle_src_clk to event_toggle_meta, and 3000ns for the path between src_din_reg and data_dst_clk. So data_dst_clk is updated 2-3 dst_clk periods plus 2ns after the edge of src_clk that causes src_send_toggle_src_clk to toggle, but the data only arrives at data_dst_clk 3000ns after that edge of src_clk - clearly your synchronizer will fail under these conditions.

 

So you absolutely need constraints to limit the skew between these paths - the best way to do that is with a set_max_delay -datapath_only with a "reasonable" time (say one dst_clk period, or even one period of the smaller clock) on each path that crosses the clock domain boundary."

at this link:

https://forums.xilinx.com/t5/Timing-Analysis/how-to-constrain-a-CDC/m-p/748174/highlight/true#M11067

 

0 Kudos
Historian
Historian
2,855 Views
Registered: ‎01-23-2009

Re: Multi-cycle, false path, ASYNC_REG or other...?

Jump to solution

On your toggle event synchronizer, what is a good rule-of-thumb or choice for a value for set_max_delay -datapath_only between the event_toggle_reg and signal_meta_reg?

 

 

There are two paths that need set_max_delay -datapath_only

  - from the thing driving bus_in to bus_out_reg

  - from the output of the toggle flip-flop to the first metastability flip-flop in the synchronizer

 

Both of these should probably use the same value (for simplicity).

 

The value of the set_max_delay -datapath_only must be strictly smaller than the shortest delay of the synchronizer - this is required to make sure that the routing of the "bus_in" can't be so long that the data doesn't make it to the "bus_out_reg" flip-flops before the synchronized enable. For a toggle synchronizer, this is one source clock period plus 2-3 destination clock periods - if it is longer than that, the synchronizer can fail.

 

In general it is best to keep it small - the smaller the value the more "events" you can bring across the synchronizer. The only issue with being "too small" is that it may cause timing violations if you make it really really short. Generally anything over 4ns is not going to cause a timing problem.

 

So, anything between this range is going to work. The original post gave some recommendations

  - the length of the destination clock period

  - the minimum of the source and destination clock period

 

So, if the clocks involved are both less than 200MHz, I would use the latter one - the smaller of the two periods...

 

Avrum

 

 

0 Kudos