Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
7 years ago

Timequest constraints for a dynamically phase-shifted PLL

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

29 Replies