Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16556 Discussions

Using the set_clock_groups command without hiding domain-crossing signals

Altera_Forum
Honored Contributor II
1,803 Views

Hi, 

 

I'm trying to use the set_clock_groups command to remove spurious  

timing violations on a multiplexed clock with limited success and would  

appreciate some guidance. 

 

I have a device with synchronous logic in a number of clock domains  

plus a test port which can be configured to monitor test signals  

originating in three of those domains. The data out has an associated  

clock out and both are multiplexed using a common select value which  

is driven manually so can be taken as static. 

 

I need to avoid spurious reports of cross-domain violations between  

registers which are both clocked by the multiplexed clock, the  

classic reason for using a set_clock_groups command, but I DO want  

reports of violations other signals in the system which cross the clock  

domains deliberately. These should be covered by other false_path  

or multicycle constraints but any that have been missed or where  

the number of cycles allowed is inadequate or wrongly specified need  

to be reported. Is there a way to use set_clock_groups to eliminate  

the spurious reports on the multiplexed clock without hiding the  

genuine timing problems elsewhere? 

 

George
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
569 Views

You don't get into what you tried to do that isn't working, but for muxes: 

1) Simple muxes, users often don't put any constraints on the mux. I.e. if it's a 2:1 clock mux and A and B are separate, then they just put A and B in separate groups and TQ analyzes as if A goes through the mux, then independently if B goes through the mux. 

2) If you're relating logic clocked by the mux to other clock domains(or maybe the original clock domains, unmuxed), then you generally want to put multiple create_generated_clock assignments on the output of the mux. Now you have clock names for the original clock and the muxed version of each clock, and can usually create the proper groups that you want. If that's been tried and doesn't cover it, explain what you have and why it's not working, and maybe we can help more.
0 Kudos
Altera_Forum
Honored Contributor II
569 Views

 

--- Quote Start ---  

If you're relating logic clocked by the mux to other clock domains(or maybe the original clock domains, unmuxed), then you generally want to put multiple create_generated_clock assignments on the output of the mux. Now you have clock names for the original clock and the muxed version of each clock, and can usually create the proper groups that you want. If that's been tried and doesn't cover it, explain what you have and why it's not working, and maybe we can help more. 

--- Quote End ---  

 

 

Creating groups as you suggest is exactly what I am attempting to do. It started getting messy when I tried to explain the details so I've created an example project which is attached. It has for example one 'and' gate and one 'or' gate representing around 20,000 logic elements each. The real data mux has 8 channels, 32 bits wide from 3 clock domains domains but this example is as simple as I can make it and still be representative of the problem. The real data includes busses which obviously can't have different delays on the bits hence I need to constrain the data path through the mux for all clocks. I haven't bothered constraining the input and output ports in the example but they are done in the real design. 

 

The core design includes a simple SDC file, TQ_test.sdc including clock definitions, and a TCL script that can be run to produce various reports. Then there's another SDC file, TQ_fix_mux.sdc, which can be read manually. It contains both the cross-domain commands for genuine signals and also the clock group commands intended to remove the spurious violations caused by muxing the clocks. It improves the performance but leaves two deliberate errors on the setup from inst16 to inst13 and the hold from inst14 to inst13. These are the sort of warnings I want to keep because I need to investigate and either adjust the constraints or the design to ensure data is passed accurately. The violations shown from inst13 to inst10 using different launch and latch clocks are the ones I want to get rid of. 

 

Thanks for your help, it is much appreciated. 

 

George
0 Kudos
Altera_Forum
Honored Contributor II
569 Views

I don't completely get what you're issue is, but one thing that is apparent is that the generated clocks for the mux were on the output port, not the output of the mux. I changed them to: 

create_generated_clock -name {clk_A_mux}  

-source [get_pins {inst19|altpll_component|pll|clk[0]}]  

[get_pins {clk_mux|combout}] 

 

create_generated_clock -name {clk_B_mux}  

-source [get_ports {clk_B}]  

[get_pins {clk_mux|combout}] -add  

 

(Note that I added an LCELL after the clock mux, and called it clk_mux. This way the name of this combinatorial mux won't change compile-to-compile. Also note that a single LCELL doesn't add a level of logic. An LCELL just says this point is the output of a logic cell, and all the combinatorial logic can still be put into the LUT before it. You'd have to have two LCELLs to get an empty combinatorial node. I mention this since it's a common mis-perception.) 

Anyway, without doing that, your CLK_B and CLK_A_POST_PLL both went through the mux and both fed inst13, etc. There was no way to have control and analyze paths from CLK_B to CLK_B_MUX without also analyzying between CLK_B and CLK_A_MUX. With this change you have that control. 

(If you still want generated clocks on the output port, just add those in two, base them off of these two clocks, and be sure to use the -master_clock to specify which one it is based off of.)
0 Kudos
Altera_Forum
Honored Contributor II
569 Views

 

--- Quote Start ---  

I don't completely get what you're issue is, but one thing that is apparent is that the generated clocks for the mux were on the output port, not the output of the mux. I changed them to: 

create_generated_clock -name {clk_A_mux}  

-source [get_pins {inst19|altpll_component|pll|clk[0]}]  

[get_pins {clk_mux|combout}] 

 

create_generated_clock -name {clk_B_mux}  

-source [get_ports {clk_B}]  

[get_pins {clk_mux|combout}] -add  

 

(Note that I added an LCELL after the clock mux, and called it clk_mux. This way the name of this combinatorial mux won't change compile-to-compile. Also note that a single LCELL doesn't add a level of logic. An LCELL just says this point is the output of a logic cell, and all the combinatorial logic can still be put into the LUT before it. You'd have to have two LCELLs to get an empty combinatorial node. I mention this since it's a common mis-perception.) 

Anyway, without doing that, your CLK_B and CLK_A_POST_PLL both went through the mux and both fed inst13, etc. There was no way to have control and analyze paths from CLK_B to CLK_B_MUX without also analyzying between CLK_B and CLK_A_MUX. With this change you have that control. 

--- Quote End ---  

 

 

Thanks, that tells me where the problem lies. Actually, this is the first time I've used Quartus to produce a design, the real thing is in Mentor Graphics, but the parts shown are scaterred over half a dozen different entities so it was impratical to post it. 

 

The reason for using the output port is that the muxes get absorbed into other logic in the process so I did the same in the example. I'll have to find a way to do something equivalent to your LCELL with Mentor. 

 

I think I do still need the generated clock on the mux in order to specify the external setup and hold relationship between the clock and data pins but that's a separate task. 

 

Thanks again for your help. 

 

George
0 Kudos
Reply