Forum Discussion
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. -Eric29 Replies
- Altera_Forum
Honored Contributor
Hi,
I have read your post but did not understand for what purpose you are using dynamic phase shift option? Is there some data transfer between different clock domains? - Altera_Forum
Honored Contributor
Hi vlrean,
The logic clocked by the dynamically phase-shifted PLL is used to drive an industrial device. -Eric - Altera_Forum
Honored Contributor
So you are seeing metastability issues in external device? Have you added set_output_delay constrains to your .sdc file?
- Altera_Forum
Honored Contributor
Hi vlrean,
The repro is purely in the domain of my synchronous logic driven by the dynamically phase-shifted PLL before our device is even hooked up. Not that it would matter anyway - our industrial device has no clock, so no source-synchronous constraints such as set_output_delay are needed. :) I should add that since I was concerned that the phase shifts weren't exactly every 45 degrees, I was able to derive what Quartus thinks they are via the technique discussed here (thanks, Brad!): https://www.alteraforum.com/forum/showthread.php?t=4567 (https://www.alteraforum.com/forum/showthread.php?t=4567) ...and that didn't help when I specified them as such, unfortunately. FYI, what I did was instantiate a special just-for-investigation PLL that was statically phase-shifted so I could see what values Quartus created for passing to the '-phase' parameter, then I used those values for the non-investigation dynamically phase-shifted PLL instantiation. What I really need is a timing guru to tell me whether my constraints look okay and if the '-logically_exclusive' does actually work for dynamically phase-shifted PLLs. Anyone? -Eric - Altera_Forum
Honored Contributor
Hi,
I think you are providing to little info about your project to attract gurus :) maybe draw some basic block diagram from which clocks and PLLs can be seen. In addition Can you post your .sdc file? As from my experience I would do like: 1. Constrain all base clocks. 2. Constrain generated clocks with correct properties frequency phase shift, use -add Argument if there is more than one clock. Check TimeQuest "Clock" and "Clock Tree" reports to see if all you clock constrains are correct. 3. Use set_clock_groups with -logically_exclusive Argument to cut clock transfers between PLL phase shifted clocks. Check TimeQuest "Clock Transfers" report to see if detected clock transfers are correct. 4. Check setup and hold reports for every phase shifted clock, check that you have proper launch and latch clock edge relationship. 5. set_multicycle_path if they are necessary. 6. Check if any constrains are ignored. That should be enough to constrain dynamically phase shifted PLL clocks (I am assuming you allready done that). As I understand you have some timing related issues when running on hardware but TimeQuest reports say that there are no timing errors in all corners? Maybe you have added some false path exceptions where you should not? - Altera_Forum
Honored Contributor
It's not clear what you mean by "activating one cycle early or late". However could it be that you are expecting a given phase to be "later" than another particular phase i.e. lag rather than "early" or lead?
I mean once it has activated, does it work fine? Does it malfunction in any other way? Is it just that the time of so called "activation" is not what you expect? - Altera_Forum
Honored Contributor
Hi vlrean,
Items 1 thru 6 you list are already done - my timing is fully constrained, and there are no errors reported. ] As I understand you have some timing related issues when running on hardware but TimeQuest reports say that there are no timing errors in all corners? Correct. ] Maybe you have added some false path exceptions where you should not? Yeah, that was one of the first things I thought of, but the affected path has the correct timing relationship, as verified by Timequest's reports. - Altera_Forum
Honored Contributor
Hi de-em,
Once the PLL is locked on a new phase, it will output correctly on most of the eight phases, but on some of the phases (varies by build which ones they are) the output randomly comes in one latching-clock early or late. This suggests to me that it is a metastability issue - as if my logically-exclusive timing constraints were NOT being analyzed correctly by Timequest and/or the fitter. - Altera_Forum
Honored Contributor
A variable phase-shifted clock domain has to be considered as asynchronous to other clocks, respective synchronization methods for domain crossing data signals are required. Timing constraints don't help because STA isn't able to check a variable timing. I guess that Timequest is simply calculating timing for the initial phase shift of the respective clock output.
By the way, 99% of random results in case of timing violations are not caused by true metastability but simple clock and data delay variations if a is latched in more than register. - Altera_Forum
Honored Contributor
eh291, what clock transfers does Timequest report? Presumably it does not report any between the multiple phases but at the boundary of the logic, are there any transfers between some other clock and each of the phases? Are these analyzed separately and do they all meet timing?
FvM, shouldn't Quartus report a critical warning if it cannot analyze this type of timing arrangement? There are examples in the cookbook of multiple clocks on a single node and I don't see how this is any different.