Where you absolutely must put a generated clock is for a ripple clock, i.e. one that goes through a register, as TimeQuest won't propagate clocks through registers. When you're gating clocks(going through logic), that is just a delay, and the clock will go through it.
A classic example would be a 2:1 clock mux, where the select is driven by a registers.
- TimeQuest will propagate both clocks through the mux to all downstream logic and analyze the logic under both domains.
- It will also analyze the worst case scenario where clkA feeds through the mux to launch registers and then clkB feeds the destinations(basically if you're switching on the fly). This is almost never wanted, so you need to cut timing between clkA and clkB, with something like:
set_clock_groups -asynchronous -group {clkA} -group {clkB}
This could be part of a much larger set_clock_groups.
- The path from the select is not analyzed as a clock, since it is through a register.
So most people doing a clock mux like that would only have to constrain clkA and clkB with create_clock and then cut timing between them, and it does what they want.
Why would you put create_generated_clock assignments on the output of the mux? The benefit is that it names the domains downstream from the mux, for cases you might want that. For example, if you add something like:
create_generated_clock -name clkAmux -source clkA [get_cells {muxname|combout}]
create_generated_clock -name clkBmux -source clkB [get_cells {muxname|combout}]
So one benefit that isn't even related to constraints is that you can do:
report_timing -to_clock clkAmux ...
This allows you to analyze that logic separately. But you can also use it for constraints. For example, let's say there's a source register fed by clkA(not the muxed version) and a destination fed by clkB, and you wanted that to be timed. In the previous example, that path would be cut since you cut timing between clkA and clkB. By having clocks generated on the mux output, you can do:
set_clock_groups -exclusive -group {clkAmux} -group {clkBmux}
In this case, I've only cut timing between A and B after the mux, and the path directly fed by clkA and clkB would be analyzed. There are various combinations of this. (For example, you might want to cut timing from clkA to clkAmux, and you can do this now). It basically gives you more flexibility than the simpler case, although I find many people get by with the simpler case.