Forum Discussion

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

Quartus TimeQuest TA

Hi,

I have some clock muxes in the design and am using Stratix-IV GT. The Fitter automatically places the input clocks and output clocks of that clock mux in different clock tree. Thus resulting in large clock skew between the input and the output clocks.

I wish to constrain the output clock, but I am not able to get the proper object ID for that. I have tried "get_nets", "get_cells" and "get_nodes", to get the object ID of the clock mux module output port. But the "set_clock_groups" is giving warnings as these selcted objects are not of type {clk}.

Please suggest a work-around.

Thanks

Manish

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Hi,

    I have some clock muxes in the design and am using Stratix-IV GT. The Fitter automatically places the input clocks and output clocks of that clock mux in different clock tree. Thus resulting in large clock skew between the input and the output clocks.

    I wish to constrain the output clock, but I am not able to get the proper object ID for that. I have tried "get_nets", "get_cells" and "get_nodes", to get the object ID of the clock mux module output port. But the "set_clock_groups" is giving warnings as these selcted objects are not of type {clk}.

    Please suggest a work-around.

    Thanks

    Manish

    --- Quote End ---

    Hi,

    have look into this document: http://www.altera.com/literature/manual/mnl_timequest_cookbook.pdf?gsa_pos=2&wt.oss_r=1&wt.oss=cookbook

    Kind regards

    GPK
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    All the "get_ " return internal lists that are understood by other commands. So you can do:

    set_clock_groups -asynchronous -group {[get_clocks {*pll1* inclk}]} -group {[get_clocks {*pll2* inclk2}]}

    or something like that. Note that set_clock_groups can only use clocks for its arguments, so it will basically do a get_clocks on whatever you type anyway. I personally never type get_clocks in that command, and just do:

    set_clock_groups -asynchronous -group {*pll1* inclk} -group {*pll2* inclk2}

    (Actually, I always set up my input clocks with create_clock statements, add derive_pll_clocks, and then run TQ. I run the command "Report Clocks", which gives me the name of every clock created. I highlight all the names and paste them into my .sdc, and then format set_clock_groups around it.)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Rysc,

    Even if one doesn't use "get_clocks" in the "set_clock_groups", it automatically considers it. One can in fact check the actual command running at the console pane of TimeQuest Timing Analyzer.

    My issue is that I am having a clock mux, where the inputs are generated from transceiver PLL's, and hence I can find them in "[get_clocks *]" collections. This collection displays all the pins with type {clk} which is a must for all the commands that work on clocks, e.g- set_clock_groups. But I am not able to find the clock mux output in the collection [get_clocks *] and hence am not able to use "set_clock_groups" or "set_false_path" over the output clock.

    I am finding large skew b/w input and output clocks of this concerned clock mux, since Quartus puts them into different Clock Tree (Finding - All clock mux output going to GLOBAL clock tree). To reduce the implication of these large skew, I have added Phase Compensation FIFO's b/w the input and output clocks of the concerned clock mux. Since Phase Compensation FIFO has some controls that needs to be synchronized from one clock domain to another, I should use false path in such synchronization logic. Again, I can get the object ID of the clock mux output clock and am stuck with large setup as well hold violations.

    Please suggest a work-around either in design or in the tool/sdc.

    Thanks

    Manish
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I suggest that you use ALTCLKCTRL blocks to mux the clocks, if you aren't already doing so.

    As far as constraints go, the mux's output signal isn't handled as if it were a separate clock. Thus, set_clock_groups only takes the mux's inputs and the rest is handled automatically.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I suggest that you use ALTCLKCTRL blocks to mux the clocks, if you aren't already doing so.

    As far as constraints go, the mux's output signal isn't handled as if it were a separate clock. Thus, set_clock_groups only takes the mux's inputs and the rest is handled automatically.

    --- Quote End ---

    I could see that Quartus has added one CLKCTRL cell after the clock mux before pushing into Global Clock Tree and hence I can get the pin "clkctrl|outclk" using [get_pins -hierarchical *clkctrl|outclk]. But again "set_clock_groups" fails saying that the return value of the "get_pins" is not of type {clk}.

    I shall look into ALTCLKCTRL further and shall update this thread with the results.

    Regards

    Manish
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    - The altclkctrl is basically the global driver, so anytime you get onto a global, you will see this block. If you want to use it's muxing capabilities, then you need to manually instantiate it. (Note that it's not the most flexible, as the only dynamic muxing is between outputs of a PLL. Hopefully the hardware improves on this someday.)

    - If you have a mux, let's say a 2:1, you have two options:

    1) The clocks going into it are constrained and timing is cut between them. It will basically analyze the paths through the mux separately. This is easiest, but less flexibile.

    2) You can put a create_generated_clock assignment on the output of the mux, where the -source is where the base clock comes from(the physicaly source, not the base clock name). You actually would have two generated clock assignments. Now there are two generated clocks coming out of the mux, and you can use those clocks in your set_clock_groups assignment, or anything else. This provides a lot more flexibility(i.e. maybe you want to add a multicycle from the base clock to the muxed clock, or something like that). Right now your trying to find a clock where it doesn't exist, which I think is the problem.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    IMHO, your constraints are fine. That is, setting a clock group constraint as shown in the cookbook is all you need to do. And it's all you can do.

    IMHO, your problem lies with your design. You're using generic logic to implement the clock mux. In an FPGA, using regular logic for anything related to clocks (clock muxes, clock gating, ripple clocks.) is, generally, a bad idea.

    The generic interconnect and logic has rather large propagation delays, which is why you're seeing a large skew between input and output clocks.

    You need to remove your clock mux and use a ALT_CLKCTRL primitive to mux your clocks.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Just another 2 cents from rbugalho's comments:

    1) Yes, avoid logic muxes at all costs. The biggest problem is that there is a long delay to the muxed clock, so there is large skew from the non-muxed clock to the muxed clock. This makes timing closure between these domains difficult.

    2) Sometimes you can't avoid these muxes, and you may have that issue. I've seen cases where the base clocks never feed logic, they just go through the mux. In those cases, it tends to work out pretty good. One case was multiple clocks recovered from transceivers, where one was a redundant link, and hence it could be the clock driver for all internal logic.

    3) Finally, I work a lot with TQ and it's timing models, and am very impressed with all that is being modeled. So if you do muxes, and can close timing, then you should feel confident in the results. The reason these muxes should be avoided in general is they often make it harder to close timing. But it's a strong suggestion, not a rule.