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: 
Scholar wzab
Scholar
20,894 Views
Registered: ‎08-24-2011

Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

In my design I have two clocks, generated in a PLL, which I'd like to use to drive different clock domains,

e.g. like below:

 

    mmcm1: MMCME2_BASE
        generic map(
            clkfbout_mult_f => 5.0,
            clkout1_divide => 27,
            clkout2_divide => 32,
            clkin1_period => 5.0
        )
        port map(
            clkin1 => sysclk,
            clkfbin => clkfb,
            clkfbout => clkfb,
            clkout1 => clk_f1,
            clkout2 => clk_f2,
            locked => dcm_locked,
            rst => '0',
            pwrdwn => '0'
        );

 

Signals crossing domains driven by clk_f1 and clk_f2 generate many problems with timing.

I'd like to treat them as asynchronous, even though in fact they originate from the same 200MHz sysclk.

However the timing constraints wizard doesn't propose to create clocks clk_f1 and clk_f2

 

Is it correct to create clocks manually and define the asynchronous groups as below?

 

    create_clock -period 32.000 -name clk_f1 -waveform {0.000 16.000} [get_nets *clk_f1*]
    create_clock -period 27.000 -name clk_f2 -waveform {0.000 13.500} [get_nets *clk_f2*]
    set_clock_groups -asynchronous -group clk_f1 -group clk_f2 -group sysclk

0 Kudos
1 Solution

Accepted Solutions
Historian
Historian
32,346 Views
Registered: ‎01-23-2009

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

It is not a good idea to override the automatically created clocks created by the PLL - they are correct, and include propagation from the pins and through the PLL. Putting a create_clock on their output disables all of that and makes the clocks start at the outputs of the PLL.

 

To define the clocks as asynchronous, you don't need to redefine the clocks - they already exist, you just need to put the set_clock_groups on it. So, all you need to do is define which clocks you want as asynchronous.

 

When the clocks are automatically created by the PLL, they are given somewhat arbitrary names. They do follow some naming rules, but I never count on them. Instead, I get the clocks by knowing what they are attached to - in this case, we know that these clocks come out on different pins of the PLL, so, all you need to do is

 

set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins mmcm1/clkout1]] \

                                                              -group [get_clocks -of_objects [get_pins mmcm1/clkout2]]

                                          

 

(you could also use [get_nets clk_f1] and [get_nets clk_f2], instead of teh get_pins).

 

Now, I will caution you. I am strongly against using set_clock_groups. Using this command means that any paths between the two domains have absolutely no constraints on them. However, if such paths exists, your design has to deal with the fact that they are crossing asynchronous domains. This means that they must have proper clock crossing circuits on them. Most clock crossing circuits (other than those that are crossing single bit slow chainging signals) must have some mechanism for constraining skew - otherwise they may fail. If you use the set_clock_groups (which is the highest priority constraint), there is no way to constrain these circuits.

 

(If you need more information on this, search for other posts from me on this topic...)

 

Avrum

13 Replies
Scholar wzab
Scholar
20,892 Views
Registered: ‎08-24-2011

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

Of course I have mistaken, it should be:

 

    create_clock -period 32.000 -name clk_f2 -waveform {0.000 16.000} [get_nets *clk_f2*]
    create_clock -period 27.000 -name clk_f1 -waveform {0.000 13.500} [get_nets *clk_f1*]
    set_clock_groups -asynchronous -group clk_f1 -group clk_f2 -group sysclk

0 Kudos
Historian
Historian
32,347 Views
Registered: ‎01-23-2009

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

It is not a good idea to override the automatically created clocks created by the PLL - they are correct, and include propagation from the pins and through the PLL. Putting a create_clock on their output disables all of that and makes the clocks start at the outputs of the PLL.

 

To define the clocks as asynchronous, you don't need to redefine the clocks - they already exist, you just need to put the set_clock_groups on it. So, all you need to do is define which clocks you want as asynchronous.

 

When the clocks are automatically created by the PLL, they are given somewhat arbitrary names. They do follow some naming rules, but I never count on them. Instead, I get the clocks by knowing what they are attached to - in this case, we know that these clocks come out on different pins of the PLL, so, all you need to do is

 

set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins mmcm1/clkout1]] \

                                                              -group [get_clocks -of_objects [get_pins mmcm1/clkout2]]

                                          

 

(you could also use [get_nets clk_f1] and [get_nets clk_f2], instead of teh get_pins).

 

Now, I will caution you. I am strongly against using set_clock_groups. Using this command means that any paths between the two domains have absolutely no constraints on them. However, if such paths exists, your design has to deal with the fact that they are crossing asynchronous domains. This means that they must have proper clock crossing circuits on them. Most clock crossing circuits (other than those that are crossing single bit slow chainging signals) must have some mechanism for constraining skew - otherwise they may fail. If you use the set_clock_groups (which is the highest priority constraint), there is no way to constrain these circuits.

 

(If you need more information on this, search for other posts from me on this topic...)

 

Avrum

Scholar wzab
Scholar
20,876 Views
Registered: ‎08-24-2011

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

Thanks! Yes I'm aware of the skew problems, when crossing clock domains.

Usually I either use FIFO's or separate single bit strobe signal which is delayed one clock pulse after the transmitted signals change (but it requires that the skew is less than one period of clock in the sending domain).

 

BTW. It would be good, if there were possibility to define required maximum acceptable skew for a group of signals transmitted from one clock domain to another...

 

0 Kudos
Highlighted
Historian
Historian
20,865 Views
Registered: ‎01-23-2009

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

So, two things.

 

First, I want to reiterate my concern with set_clock_groups. You say you use clock crossing FIFOs for crossing the domains - but how are the FIFOs constructed? If they use the built-in hard FIFOs (FIFO18*, FIFO36*) then that's fine. But if they use any other FIFO, then you have a problem.

 

Lets take a FIFO generated by the FIFO wizard - so either an independent clocks BRAM based FIFO (not using the built-in FIFO), or an independent clocks distributed RAM based FIFO. Both of these use address counters and have clock crossing circuitry built in to them to handle the correct generation of the EMPTY and FULL conditions. Because these are multi-bit clock crossing circuits, they need a constraint to control skew, and these constraints are built in to the .xdc files that come with the FIFOs. They are set_max_delay -datapath_only constraints between the addresses on one domain and the other (almost certainly Gray coded). Thus, these paths have the correct exceptions on it.

 

But, what happens if you put a set_clock_groups between the two clocks? While the .xdc file for the FIFO has the correct set_max_delay -datapath_only constraints, the set_clock_groups constraint has higher priority. Therefore your set_clock_groups command overrides the (correct) set_max_delay -datapath_only, and now your clock crossing FIFO is under constrained (and can cause system failures)!

 

Similarly, with your strobe signal that determines when the rest of the bus is stable - it presumes a constrained skew between the strobe and the data signals. Again, the only way to constrain this skew is with a set_max_delay -datapath_only. Even if you correctly specify this in your XDC on the correct paths, they will be overridden by the set_clock_groups (and your clock crosser will be underconstrained, and hence possibly fail).

 

As for your last comment about having a command that limits skew, I highly suspect that it is never going to happen. It is pretty fundamentally against the philosophy of the SDC (Synopsys Design Constraints), on which XDC is built. In SDC, all timing is path based, and each path can be independently analyzed based on the requirements for that path, which are derived based on the system constraints applied (clocks, and exceptions). The skew on nets doesn't fit this definition since nets are not paths. Even if we talk about the "skew on a bunch of related paths" - this cannot be analyzed independently for each path - you need to look at all paths in the "path group" together. There is no syntax to define a "path group" - the concept doesn't exist in SDC - and I doubt one will be added.

 

[EDIT (2018): While everything else in this thread is still valid, in the intervening 4 years, Xilinx has, indeed, introduced a new constraint set_bus_skew. This command allows you to constrain the skew on a set of paths - the tools will ensure that the difference between the longest path and the shortest path (at the same timing corner) are less than or equal to the skew specified by the set_bus_skew command. Almost more importantly, the set_bus_skew is between paths, rather than on particular paths - as such, it is not affected by other constraints on the paths themselves. Notably this means that the set_bus_skew command still takes effect even if the paths involved are covered by a high priority constraint such as set_clock_groups.]

 

Avrum

Scholar wzab
Scholar
20,844 Views
Registered: ‎08-24-2011

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

Thanks for very detailed explanation.

So if I understood your most important points correctly, instead of using set_clock_groups in situation where I have multiple clock domains, I should identify each path, where signals are transmitted from one clock domain to another, and define "set_max_delay -datapath_only" for each such path.

Is it correct?

Thanks, Wojtek

 

0 Kudos
Historian
Historian
20,835 Views
Registered: ‎01-23-2009

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

So if I understood your most important points correctly, instead of using set_clock_groups in situation where I have multiple clock domains, I should identify each path, where signals are transmitted from one clock domain to another, and define "set_max_delay -datapath_only" for each such path.

Is it correct?

 

 

Generally speaking, yes. I am not against set_false_path when they are appropriate, it is the "blanket" declaring of clock domains as false paths that I worry about. So, on a case by case basis, you should declare paths as set_false_path or set_max_delay -datapath_only, but not do a set_clock_groups or set_false_path -from <clock> -to <clock>.

 

[And yes, I know, not everyone will agree with me]

 

At the same time, you want to be efficient about it. Processing lots of constraints takes some amount of time, so you want to construct your constraints efficiently; use wild cards when appropriate, but don't go too far. It is also worth pointing out that set_max_delay -datapath_only (I have been told) will slow down your compile time somewhat (I don't know how significant this is). But, I would rather my compile take a little longer and be sure my clock crossing circuits work than getting a bitstream a bit earlier that may have a bad clock crosser.

 

Avrum

Tags (1)
0 Kudos
Scholar dwisehart
Scholar
20,823 Views
Registered: ‎06-23-2013

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

"It is not a good idea to override the automatically created clocks created by the PLL - they are correct, and include propagation from the pins and through the PLL. Putting a create_clock on their output disables all of that and makes the clocks start at the outputs of the PLL."

 

Avrum why is important that the clock path trace back to the pins instead of starting from the PLL--or the output of the clock BUF if that is what was specified in the constraint?  So long as all registers get the clock from the PLL or BUF, not a separate path from the pins, why is it important for static timing to use the path all the way back to the pins in its calculations?

 

Thanks,

Daniel

 

0 Kudos
Historian
Historian
20,818 Views
Registered: ‎01-23-2009

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

Daniel,

 

For internal paths that are driven by the MMCM outputs, it probably doesn't matter much. But for some other paths, it does.

 

For example if you have a path to/from an output/input of the FPGA, it does matter.  If you have a clock created on the input pin of the FPGA (which would normally propagate through the MMCM, BUFG and to the capture FF), and you specify a set_input_delay referenced to the same clock, then the path would be completely timed; The source clock delay would be 0 (the clock at the input pin of the FPGA), the data path would be the set_input_delay value, the IBUF and the input flip-flop, and the destination clock delay would start at the same clock (at the pin of the FPGA), propagate through the IBUFG, the MMCM, the BUFG and end at the capture FF.

 

If you override the constraints at the output of the MMCM, then the destination clock delay would start at time 0 with the clock specified by the create clock command. In essence, you would lose the delay of the IBUFG, and the MMCM, so the path would be incorrectly timed.

 

The same would be true of any internal path where the one end of the path is clocked on an output of the MMCM, but the other end is not. For example, if the start of the timing path comes from a FF driven by the output of the MMCM, but the endpoint of the timing path is a FF coming clocked from the clock coming directly from the pin and (say) through a BUFR. If only the input clock is specified, it will correctly trace both parts of the path back to the common startpoint - the input clock pin. With the clock overridden at the output of the MMCM, you will (again) lose the part of the clock propagation through the IBUFG and MMCM.

 

One important thing to understand is that the clocks automatically created by the tool when a clock goes through the MMCM are generated clocks, not primary clocks. While a generated clock may have different characteristics from the clock which generates it (frequency multiplication/division, phase shifting, etc...), the clock propagation always starts at the primary clock and propagates through the point where the generated clock is created. That is a very fundamental difference between the create_clock command and the create_generated_clock command.

 

Avrum

 

Visitor patrckhl
Visitor
7,641 Views
Registered: ‎01-22-2018

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

Hello Avrum,

I would like to resume this old thread with a bit more details.

 

In our design, we have two clocks "generated" from PLL, and clocking two domains (as usual...).

Since we have some extra constraints that have to be set with the two clocks, so we have to use a "name" to indicate them.

 

If "create_clock" is not recommended on the auto-generated clocks, is there a way to indicate them and also inherit the constraints auto-generated by the PLL setting?

Always replace the name like this? [get_clocks -of_objects [get_pins PLL_inst/clkout1]]

OR

Always replace the name by the nets that connect to the pin? [get_nets pll_clk1]

 

Thanks a lot!

/Patrick

 

BTW, if I use create_clock, Synplify can figout the auto-generated clocks and the manually created clocks at the same time.

 

Since we are using spartan 6 and synplify+ISE, so please also consider the translation from synplify SDC to ISE ucf. 

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

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

First, I stand by the "never override the automatically generated clocks on the output of the PLL/MMCM".

 

Given that, you should never use a create_clock on the output of these cells.

 

So, you have two choices

 

1) Use the clock without knowing its name. This is done by the [get_clocks -of_objects [get_pins ...]] (or get_nets). You can use this command anywhere you need the clock, or you can use a Tcl variable

 

set my_clk [get_clocks -of_objects [get_pins ...]]

 

Now you can refer to the clock as $my_clk anywhere within the same XDC file after this command.

 

2) Rename the clock.

 

Xilinx has a specific notation to rename a clock. While it uses the create_generated_clock command, it is not overriding the clock; merely renaming it. The difference between the two is that when used to rename a clock, you do not use the -source (or -master_clock) options of the command

 

create_generated_clock -name my_clk [get_pins <output_pin_of_pll>]

 

renames the automatically generated clock to "my_clk" - but the generation of the clock (and hence all the other properties of the clock) are still the ones that were automatically generated by the tool.

 

In ISE this stuff is more complicated; there aren't real equivalents to either of these two approaches.

 

In ISE (as opposed to Vivado) the name of the automatically generated clock is fixed. You can look at the timing report, but it is (something like - I haven't looked in a while) TS_<instance_name_of_MMCM_or_PLL>_<output_of_MMCM_or_PLL>. The instance name is the full hierarchical instance name (with underscores?) so it is "guaranteed" to be unique within the design.

 

While you can't find or use this name in the constraints wizard (at least not before synthesis has been performed), it is legal to use it in the UCF file.

 

This being said, the name of the PERIOD TIMESPEC (which is what this gives you) is not often needed in ISE (but it is sometimes). Often what you need is the "group of flip-flops clocked by this clock". This can be done by creating a new group for these flip-flops, using TNM_NET, and using the output pin of the MMCM or BUFG. Creating a new group does not affect any constraints that exist on the paths; so you can create this new group

 

PIN "<instance_name_of_MMCM_or_PLL>.<output_of_MMCM_or_PLL>" TNM_NET = my_group;

 

Now you can use the timing name (group) my_group in a later constraint...

 

Avrum

Tags (3)
0 Kudos
Visitor patrckhl
Visitor
3,749 Views
Registered: ‎01-22-2018

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

 


@avrumw wrote:

First, I stand by the "never override the automatically generated clocks on the output of the PLL/MMCM".

 

Given that, you should never use a create_clock on the output of these cells.

 

So, you have two choices

 

1) Use the clock without knowing its name. This is done by the [get_clocks -of_objects [get_pins ...]] (or get_nets). You can use this command anywhere you need the clock, or you can use a Tcl variable

 

set my_clk [get_clocks -of_objects [get_pins ...]]

 

Now you can refer to the clock as $my_clk anywhere within the same XDC file after this command.

 

2) Rename the clock.

 

Xilinx has a specific notation to rename a clock. While it uses the create_generated_clock command, it is not overriding the clock; merely renaming it. The difference between the two is that when used to rename a clock, you do not use the -source (or -master_clock) options of the command

 

create_generated_clock -name my_clk [get_pins <output_pin_of_pll>]

 

renames the automatically generated clock to "my_clk" - but the generation of the clock (and hence all the other properties of the clock) are still the ones that were automatically generated by the tool.

 

In ISE this stuff is more complicated; there aren't real equivalents to either of these two approaches.

 

In ISE (as opposed to Vivado) the name of the automatically generated clock is fixed. You can look at the timing report, but it is (something like - I haven't looked in a while) TS_<instance_name_of_MMCM_or_PLL>_<output_of_MMCM_or_PLL>. The instance name is the full hierarchical instance name (with underscores?) so it is "guaranteed" to be unique within the design.

 

While you can't find or use this name in the constraints wizard (at least not before synthesis has been performed), it is legal to use it in the UCF file.

 

This being said, the name of the PERIOD TIMESPEC (which is what this gives you) is not often needed in ISE (but it is sometimes). Often what you need is the "group of flip-flops clocked by this clock". This can be done by creating a new group for these flip-flops, using TNM_NET, and using the output pin of the MMCM or BUFG. Creating a new group does not affect any constraints that exist on the paths; so you can create this new group

 

PIN "<instance_name_of_MMCM_or_PLL>.<output_of_MMCM_or_PLL>" TNM_NET = my_group;

 

Now you can use the timing name (group) my_group in a later constraint...

 

Avrum


Ok thanks a lot.

I think I got the principle inside.

Let me have a try.

 

/Patrick 

 

0 Kudos
3,106 Views
Registered: ‎05-30-2018

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution
Avrum,
If we consider the FIFO example, and more specifically each gray coded write and read pointer (each on separated clock domain), what is the definition of skew, given that on one pointer, only one bit will change at each write (for the write pointer) and read (for the read pointer).
Then, in my understanding, the skew between write and read pointer can not be define, as the concept of skew relies on the fact the related signals have a common source event, doesn't it ?

Finally, while reading this paper (http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf) from Clifford E. Cummings, I could not see any reference to SDC constraints to be setup in addition to use of gray encoded pointers, despite the comprehensiveness of the paper on this topic.

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

Re: Two clocks generated by the same PLL, treated as two asynchronous clocks...

Jump to solution

Your example is a good one. A Gray coded counter (captial G, since it is named after Frank Gray, from Bell Labs) can be synchronized directly (a Gray code clock domain crossing circuit) because only one bit changes at a time. It is therefore required that the receiver only see one bit changing at a time. If difference in routing of the different bits of the Gray code clock crossing circuit are sufficiently different (i.e. the skew is really big), one bit change can overtake the one before it, causing the receiver to see two bits changing too close together. Take a look at this post which shows the problem with unconstrained Gray code clock domain crossing circuits.

 

So in this case, the skew needs to be constrained to less than one source clock period. In the past, the only way to do this was to use a set_max_delay -datapath_only with a delay less than one source clock period.

 

In newer versions of Vivado, you can, however, directly constraint skew with the set_clock_skew command. This is done on a group of paths - in this case the paths that are all N bits of the Gray code synchronizer.

 

Avrum

0 Kudos