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
Timing errors can sometimes occur when paths are inappropriately or mistakenly cut either through setting an exclusive clock group or by explicitly cutting a path (I know, I have done this myself). If there are or should be valid clock transfers which should be analyzed between each of the phases and some other reference clock, then that clock presumably could be included in each of the exclusive groups.
Maybe something like (though I haven't tried this): set_clock_groups -logically_exclusive -group {apg_phase00_045 clock_x} -group {apg_phase00_090 clock_x} -group {apg_phase00_135 clock_x} -group {apg_phase00_180 clock_x} -group {apg_phase00_225 clock_x} -group {apg_phase00_270 clock_x} -group {apg_phase00_315 clock_x} -group {drv1|mypll_apg_ph0|*|altera_pll_i|cyclonev_pll|co unter[0].output_counter|divclk clock_x} - Altera_Forum
Honored Contributor
--- Quote Start --- 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. --- Quote End --- Is it? Lets say that we have clock CLK_A which feeds PLL with one output, PLL dynamic phase shift feature is used and PLL can generate two clocks CLK_B_0deg or CLK_B_90deg on same output. Data is launched from CLK_A domain and latched in CLK_B_0deg/CLK_B_0deg domain. so we have following constrains:
CLK_B_0deg and CLK_B_90deg can not be active both in same time, any paths between those two clocks are cut. So TimeQuest should detect that CLK_A is synchronous to CLK_B_0deg and CLK_A is synchronous to CLK_B_90deg. If my understanding is correct we should be able to generate following timing reports: 1 - from CLK_A to CLK_B_0deg. 2 - from CLK_A to CLK_B_90deg. And we should be able to see if one of those paths fail timing and one of those PLL clock phases can not be used right?#Base clock create_clock -period 10 -name CLK_A # PLL constrains create_generated_clock -name CLK_B_0deg -master -source ] -phase 0 ] create_generated_clock -name CLK_B_90deg -master -source ]] -phase 90 ] -add # Clock groups set_clock_groups -exclusive -group {CLK_B_0deg} -group {CLK_B_90deg} \ - Altera_Forum
Honored Contributor
For those following this thread visually, a post from more than a day ago by me containing screenshots and updated info was just cleared by a moderator, but it appeared above an existing post. Apparently posts are sorted by the webserver according to authored time, not accepted time.
- Altera_Forum
Honored Contributor
Why do you need the multicycle constraints? Have you tried not having them?
- Altera_Forum
Honored Contributor
Yeah, it fails timing without the relaxed constraints, because there's a default setup relationship of 416.66 picoseconds for the 45-degree phase shift (because the phase shifted clock is running 300MHz therefore a 3.333 nanosecond period, and then the divide by eight for the phase shifts).
- Altera_Forum
Honored Contributor
So are you generating appropriate clock enables to sample the signal with enough setup and hold time for each clock transfer at each phase setting? It's not enough just to define a multicycle constraint as that will not alter the physical clock relationship and if this is the case then I would expect metastability issues to arise.
- Altera_Forum
Honored Contributor
Yeah, that's what I believe I did, and I think that's what the waveform and clock relationship screenshots show in the .ZIP files I attached to this thread. I'd very much like to be proven wrong so I can fix my code.
- Altera_Forum
Honored Contributor
With respect, I'm not sure if you understood what I am asking (you say that you "believe you did"??). It is all very well to apply your constraints as you have (and the images show the relaxed setup relationships etc), but the fact is that without specific clock enable signals to enable the latch register at the appropriate time, you are setting things up for timing failure or metastability.
- Altera_Forum
Honored Contributor
I read your "generating appropriate clock enables to sample the signal with enough setup and hold time for each clock transfer at each phase setting" to mean do I have the timing constraints properly in place for all phases by having only two ‘set_multicycle_paths’ in my Timequest constraints file (because it seems unlikely at first glance that those two would cover all eight phases, but they appear to me to do).
So, do you mean am I using clock enables AKA gated clocks? I.e. such as those described in the “Clock Enable Multicycle” section of ‘mnl_timequest_cookbook.pdf’, page 25 {document revision 2017.11.21}]? If that’s what you meant, I am not using any gated clocks. Thanks for your continued interest. - Altera_Forum
Honored Contributor
Clock enables are not the same as gated clocks though (the clock would still be running freely but the clock enable would enable the register). There may be some of your clock phases where the latch register is sampling the data input in a time frame where the result could be metastable or uncertain (I think that much is clear from the description of your problem). So simply relaxing the setup time with a multicycle constraint does not alter the outcome.
Imagine a system where you generate a series of clock enable signals which enable the latch register clocked by the selected 300 MHz clock phase; now in that system, the multicycle constraints would make sense because they describe exactly when the actual launch and latch occur. You only have half of the solution and that is the constraints. This is how I see it anyway. I'm not suggesting that the clock enable idea is a solution because I don't fully understand what the firmware is attempting to achieve and I can only see the small bit currently under the microscope.