Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20718 Discussions

Timequest constraints for a dynamically phase-shifted PLL

Altera_Forum
Honored Contributor II
3,238 Views

I've been trying to properly constrain a design that uses dynamic phase shifting of an instance of an altera_pll core that I created. I.e. to enable phase-shifting I checked the "enable access to dynamic phase shift ports" in the IP creation dialog box for my PLL. 

 

The dynamically phase-shifted PLL output is used to drive synchronous logic. I use a separate clock to actually dynamically shift the PLL and am careful to use the Altera-recommended 'asynchronous assert, synchronous de-assert' reset paradigm on the logic driven by the phase-shifted PLL after I do a phase shift. 

 

My .SDC file contains: 

 

derive_pll_clocks 

derive_clock_uncertainty 

 

...at the top of my file, yet there's no Timequest constraints automatically created w.r.t. phase shifting, which is disappointing because the wizard should know that I can only shift eight 45-degree increments and it knows all other parameters thereof because I gave it to the wizard, sigh. 

 

The intent here is to have a total of eight logically-exclusive clocks coming off of the output pin of the PLL. So I attempted to create some constraints: 

 

create_generated_clock -add -name apg_phase00_045 -source {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|vco0ph} -divide_by 1 -multiply_by 1 -duty_cycle 50.00 -phase 44.9 {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|divclk} create_generated_clock -add -name apg_phase00_090 -source {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|vco0ph} -divide_by 1 -multiply_by 1 -duty_cycle 50.00 -phase 90 {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|divclk} create_generated_clock -add -name apg_phase00_135 -source {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|vco0ph} -divide_by 1 -multiply_by 1 -duty_cycle 50.00 -phase 135 {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|divclk} create_generated_clock -add -name apg_phase00_180 -source {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|vco0ph} -divide_by 1 -multiply_by 1 -duty_cycle 50.00 -phase 179.9 {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|divclk} create_generated_clock -add -name apg_phase00_225 -source {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|vco0ph} -divide_by 1 -multiply_by 1 -duty_cycle 50.00 -phase 225 {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|divclk} create_generated_clock -add -name apg_phase00_270 -source {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|vco0ph} -divide_by 1 -multiply_by 1 -duty_cycle 50.00 -phase 270 {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|divclk} create_generated_clock -add -name apg_phase00_315 -source {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|vco0ph} -divide_by 1 -multiply_by 1 -duty_cycle 50.00 -phase 314.9 {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter.output_counter|divclk} 

 

...the '44.9', '179.9' and '314.9' were echoed to me by the Altera wizard after I tried entering '45'. '180', and '315' degrees for those respective phase shifts, so that’s why I chose those. 

 

That's seven generated clocks from eight possible phase-shifts, so where's the eighth? Answer: that's the default i.e. the PLL output pin (Wizard was given a 0-degree shift as the default): 

 

{drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk} 

 

Then I declare each of the eight clocks selections as logically-exclusive in my .SDC: 

 

set_clock_groups -logically_exclusive -group {apg_phase00_045} -group {apg_phase00_090} -group {apg_phase00_135} -group {apg_phase00_180} -group {apg_phase00_225} -group {apg_phase00_270} -group {apg_phase00_315} -group {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk} 

 

I should mention that the PLL instance is fed a 50MHz clock "{u0|hps_0|fpga_interfaces|clocks_resets|h2f_user1_clk}", which comes from my Cyclone V's HPS (i.e. as created through the HPS section of the Qsys IP component), which is also used to drive an Avalon memory-mapped slave which does the triggering.  

 

The PLL output is 300 MHz (input mult’ed by 12, divided by 2), so as can be imagined, I've had to create a lot of timing constraints so that everything fits and makes timing, which it does, successfully, thanks to false-paths and multicycles where they can be used. 

 

Everything works great - the clocks look fine from the Timequest report, etc. I can see that the phase shifting is working via my oscilloscope - it's a pretty sight to see I must say. :) 

 

but there is one big problem - I am seeing apparent metastabiltiy when I trigger my dynamically-shifted synchronous logic via the Avalon slave – it sometimes causes the dynamically-phase shifted circuit to activate one cycle early or late, as if my carefully defined constraints were not in play and were violating T[SUB]sh[/SUB]/T[SUB]h[/SUB]. 

 

As can be guessed, the behavior of the metastabiltiy is a function of which phase I choose – some phases are very unstable, others apparently not at all, which is expected from eight logically-exclusive clocks sharing one fitted path. 

 

I'm baffled at this because all clocks look good, and everything appears perfectly constrained. In fact, for the dynamically-phase shifted logic, one way I checked that there was one fitting common to all of the clocks on the trigger path was to verify that there was the same 'clock skew' and 'data delay' for each of the phases as I varied 'to_clock' parameter - checking between phases via these Timequest reports, for example: 

 

report_timing -from_clock { u0|hps_0|fpga_interfaces|clocks_resets|h2f_user1_clk } -to_clock { apg_phase00_180 } -to *rEnableOutput* -setup -npaths 100 -detail full_path -panel_name {xxx} -multi_corner report_timing -from_clock { u0|hps_0|fpga_interfaces|clocks_resets|h2f_user1_clk } -to_clock { apg_phase00_225 } -to *rEnableOutput* -setup -npaths 100 -detail full_path -panel_name {xxx} -multi_corner 

 

I'm not sure what to do. I've scoured the internet for examples on how to properly constrain a design that uses PL dynamic phase shifting and haven't had any luck. Any help would be appreciated. Perhaps some timing quirk related to phase-shifting has been overlooked. or perhaps because some of my phases aren’t exactly 0, 44.9, 90, 135, 179,9, 225, 270, or 314.9 degrees? 

 

All of my logic is on rising edges, so I tried to add some T[SUB]sh[/SUB] elbow room by adding constraints like this (one per phase shift, of course), but that didn’t help: 

 

set_clock_uncertainty -rise_from -rise_to 0.380  

 

...default was 0.140. 

 

-Eric
0 Kudos
29 Replies
Altera_Forum
Honored Contributor II
339 Views

Do you mean changing: 

always_ff @(posedge dynshift_clk) begin d <= c; end 

 

...to: 

 

always_ff @(posedge dynshift_clk) begin if (clock_enable == 1'b1) begin d <= c; end else begin d <= 1'b0; end end 

 

???
0 Kudos
Altera_Forum
Honored Contributor II
339 Views

A clock enable is usually written like this: 

 

always_ff @(posedge dynshift_clk) 

begin 

if (clock_enable == 1'b1) 

begin 

d <= c[11]; 

end 

end 

 

But, I cannot say if using a clock enable actually helps in your application.
0 Kudos
Altera_Forum
Honored Contributor II
339 Views

Ah, okay - I already have such data-gating in my actual code for when the latched clock is in the process of being shifted. The problem of concern is why there's apparent metastability long after the shifting has taken place i.e. effectively once 'clock_enable' is set.

0 Kudos
Altera_Forum
Honored Contributor II
339 Views

I think you are still missing the point. Let's just analyse what you have got.  

1. You have a reference clock (50 MHz) and a derived/generated PLL clock (300 MHz) with adjustable phase.  

2. At one or perhaps more of the phase settings you get inconsistent results which you describe as metastability. 

3. At those phase settings, it is quite possible that the transfer of data from the 50 MHz clock edge to a 300 MHz clock edge (not necessarily the closest edge) may result in inconsistency/uncertainty/metastability because the setup and/or hold times for that transfer are not being met. 

4. Applying multicycle constraints to this will not alter anything other than make it look like you are meeting timing when in reality you are not. 

 

I don't think I can put it in clearer terms than this.
0 Kudos
Altera_Forum
Honored Contributor II
339 Views

I assert that:  

 

1) Setup and hold times are being met - the timing analysis report says so - for each phase. 

2) The shifting and opening of the window was needed and was done properly - for each phase. 

3) The bitmaps and my pasted timing constraints support these conclusions. 

 

I don't think we have any disagreement, except about the multicycle constraints - do you think they're incorrect? If so, how?
0 Kudos
Altera_Forum
Honored Contributor II
339 Views

So are you saying you have created extra logic or only applied timing constraints to achieve 2)? I am assuming the latter in which case the following comments apply otherwise I have got hold of the wrong end of the stick. 

 

Applying your constraints doesn't stop launch register to latch register transfers happening at every clock edge including those which may not meet setup and hold times of the latch register. Your constraints may satisfy TimeQuest but they do not alter the physical reality. 

 

e.g. If you use the typically advised 2 stage register chain to re-sample a signal from one clock domain to another asynchronous domain, it is usual to cut the timing to prevent TimeQuest from analyzing the transfers (since they would fail). However, this does not actually in any way stop metastability from occuring on the first register in the chain. It's a physical reality which cannot be somehow "fixed" by TimeQuest.
0 Kudos
Altera_Forum
Honored Contributor II
339 Views

So I went back to take a long and hard look my assumptions and verify them against the .PNGs I posted. It turns out that my statement: 

 

] ...the window is both opened and shifted, by these. The window's opening is much less than how rapidly c[11] changes so the hold time is actually more tightly constrained than it could. 

 

...appears totally wrong w.r.t. to the opening of the window. It has nothing to do with the launching data and how fast it toggles. To avoid metastability, a window can only be opened if gating the latching clock explicitly or implicitly gating the clock by gating its data, neither of which I'm doing. If the latching clock is not gated, then the fitter may violate setup time by fitting erroneously close to the latching clock edge prior to the one being targeted, and therefore result in metastability. This may be acceptable in some cases e.g. such as a async RAM example in the Timequest User Guide, but is unacceptable for my needs. 

 

So my current understanding (hope it's correct!) appears to be fairly congruent to what you we're getting at, de-em, so nice work following and understanding the thread - much appreciated. 

 

As might be expected, the fitter figuratively explodes when trying to fit with a proper 3.333ns window, regardless of how much the window is shifted. This is because the intersection of solutions for 8 phase-shifted clocks with that clock period leave a theoretical maximum fitting window of 416.66 picoseconds - so good luck to me - LOL?. 

 

Thanks to everyone who piped in.
0 Kudos
Altera_Forum
Honored Contributor II
339 Views

As for solutions, is there a way in which you could utilize a dual clock fifo? By nature, you would cut paths between the 2 clocks therefore, phase of the 300 MHz clock doesn't really matter, only frequency (which doesn't change regardless of phase setting). 

 

So I'm thinking that you could clock data into the fifo on each edge of the 50MHz clock and clock it out of the fifo when it indicates NOT empty. The data coming out would naturally be synchronized to the phase shifted clock. Again, I'm not quite sure what you are trying to achieve overall but it seems that this approach might deserve some consideration.
0 Kudos
Altera_Forum
Honored Contributor II
339 Views

Yeah, some time ago I had tried to instantiate a dual-clock FIFO IP because I was sick and tired of false-path'ing and using synchronizers each of my timing-irrelevant paths, but the IP wizard's GUI failed - probably because I'm running Quartus on a non-supported Linux distro. 

 

So your idea does have merit and I think I'll revisit that again, especially if it'll allow the fitter to make the less than 416.66ps window needed for non-metastability across all phases when clocked at 300MHz. 

 

Thanks, 

 

-E
0 Kudos
Reply