By default, the tool times every path for exactly one clock cycle. Most paths are indeed meant to work that way. A few are not, and for those the designer must tell the tool. These instructions are called timing exceptions, and they are the part of the constraints where a single wrong line can hide a real failure.
Reading time: about 8 minutes.
6.1 The default rule
For a path from a launching flop to a capturing flop on the same clock, the tool assumes data launched at one edge must be captured at the next edge, one period later. The setup check uses that next edge, and the hold check uses the same edge as the launch. This is correct for ordinary synchronous logic.
An exception is needed when the real behaviour differs from this, in one of three ways:
- The path never matters, so it should not be timed โ a false path.
- The path is allowed more than one cycle โ a multicycle path.
- The path must be faster, or slower, than the clock period alone implies โ a min/max delay.
6.2 False paths
A false path is a path that exists in the netlist but is never used in a way that needs timing. Examples are a static configuration register written once at boot, an asynchronous reset whose release is synchronized elsewhere, and a path between two clocks that are never active together.
set_false_path [-setup] [-hold]
[-from from_list]
[-through through_list]
[-to to_list]
# Asynchronous reset; release is synchronized outside this block
set_false_path -from [get_ports rst_n]
# A mode register that is written only at boot
set_false_path -from [get_cells cfg_reg*] -to [get_cells core_reg*]
When -setup and -hold are omitted, both checks are removed. That is often more than intended. Hold checks catch real problems that have nothing to do with how often a signal changes. If only the setup check should go, say so with -setup.
The main risk is that a false path is a promise. The tool stops looking at the path, so if the promise is wrong, no tool downstream will catch it. It is better to keep the -from and -to lists as narrow as possible, and to comment every false path with the reason it is safe.
6.3 Multicycle paths
A multicycle path is one where the capturing flop only needs the data every N cycles, and the logic is designed to allow it. Let us consider a path with a period of 2 ns and logic that takes 3.5 ns, ignoring setup time and clock-to-Q delay to keep the numbers simple. As a single-cycle path it fails. If a control signal guarantees that the capturing flop only samples every second cycle, the path has 4 ns and passes.
set_multicycle_path path_multiplier
[-setup] [-hold]
[-start] [-end]
[-from from_list] [-to to_list] [-through through_list]
set_multicycle_path 2 -setup -from [get_cells slow_a_reg*] -to [get_cells slow_b_reg*]
set_multicycle_path 1 -hold -from [get_cells slow_a_reg*] -to [get_cells slow_b_reg*]
The second line is the one people forget. When the setup check moves out by one cycle, the hold check moves with it by default. The hold check then sits one period later than usual, which demands that the shortest path be at least one period plus the hold time. That is far too strict, and a later hold-fixing step would add delay cells to meet it. Setting the hold multiplier to 1 brings the hold check back to its normal position. Thus, a setup multicycle of N is almost always paired with a hold multicycle of N โ 1.
Whether the multiplier counts from the launch clock or the capture clock matters when the two clocks have different periods. The -start and -end options select which clock is used. If both clocks have the same period, it makes no difference.
6.4 Min and max delay
Some paths need a specific delay limit that is not related to any clock.
# Overrides the clock-derived setup limit for this pair (illustration only)
set_max_delay 0.9 -from [get_ports en] -to [get_ports ovf]
set_min_delay 0.1 -from [get_ports din] -to [get_cells din_q_reg*]
A set_max_delay replaces the usual setup limit for the selected paths. It is typically used for purely combinational paths through a block, for paths between asynchronous domains, and for quick experiments. Because it overrides the clock-based requirement, the number must be chosen with care.
6.5 Clock groups
Two situations call for removing the paths between clocks, and they use different options. Clocks that run at the same time but have no fixed phase relation, such as two unrelated oscillators, are asynchronous. Clocks that are never active together, for example a functional clock and a slower test clock sharing a pin, are exclusive. Marking every path with a false path is possible but tedious. One statement says it directly:
set_clock_groups -asynchronous -group {clk_core} -group {clk_io}
# Never active at the same time
set_clock_groups -physically_exclusive -group {clk_func} -group {clk_test}
Clocks in different groups are treated as having no timing relationship. A common mistake is to declare two clocks asynchronous when they are in fact derived from one another. The tool then stops checking a path that really exists.
6.6 Cost groups in Genus
Genus optimizes by minimizing the worst negative slack inside each cost group. By default each clock gets its own group, and everything else goes into a default group. A designer can add groups to keep one difficult path from starving the others of effort.
define_cost_group -name inputs -design acc8
path_group -from [all_inputs] -to [all_registers] -group inputs -name in2reg
The exact option list may differ between versions, so check help define_cost_group and help path_group. The idea carries over to other tools through the SDC command group_path.
6.7 Auditing exceptions
Exceptions pile up over a project, and nobody remembers why the third one was added. Two habits help.
- Write the reason next to each exception, as a comment.
- Ask the tool to report timing for a given exception, to see what it covers:
report_timing -exceptions <exception_name>
This confirms that the exception selects the paths you intended, and not more.
6.8 Why an interviewer asks about this
Exceptions are the richest interview topic in constraints, because mistakes are costly. Typical questions: "when would you use a false path versus a clock group", "why does a multicycle setup need a hold multicycle", and "how do you make sure a false path is safe". A good answer includes the N and N โ 1 rule and the idea that a false path is a promise the tools cannot verify.
Key takeaways
- The default is one cycle per path, and exceptions exist for paths whose real behaviour differs.
- A false path removes timing checks, so keep it narrow and document why it is safe.
- A multicycle setup of N normally needs a hold multicycle of N โ 1, or the tool will add unnecessary delay.
- Use clock groups for clocks that never interact, and audit exceptions with
report_timing -exceptions.