A block does not live alone. Its inputs come from registers somewhere else, and its outputs go to registers somewhere else. The clock constraint only describes the block's own registers, so the tool still needs to know how much of the period is already spent outside. That is the job of input and output delays.
Reading time: about 8 minutes.
5.1 The four path types
Every timing path in a block starts at one of two places, a register clock pin or an input port, and ends at one of two places, a register data pin or an output port. That gives four path types.
- Register to register โ fully inside the block, timed by the clock alone.
- Input port to register โ needs an input delay.
- Register to output port โ needs an output delay.
- Input port to output port โ a purely combinational path through the block, needing both.
In our accumulator, din to din_q is type 2, sum to nxt to sum is type 1, sum to the output pin is type 3, sum and din_q through the adder to ovf are also type 3, and en to ovf is type 4. Without port constraints, types 2, 3 and 4 are not timed at all, and the tool is free to make them as slow as it likes.
5.2 Input delay
An input delay says how long after the launching clock edge the data arrives at the port. Let us consider a clock of period 2.0 ns, and data that arrives 0.4 ns after the clock edge at the port. The data has 2.0 โ 0.4 = 1.6 ns left, minus the setup time of the capturing flop, for the logic inside the block.
set_input_delay [-clock clock_name]
[-clock_fall]
[-max] [-min]
[-add_delay]
delay_value
port_list
set_input_delay 0.40 -clock clk [get_ports {din en}]
The -clock option is required in practice. It names the clock whose edge the delay is measured from. When -max and -min are omitted, the same value is used for setup and hold. They are often given separately, because the earliest arrival (for hold) and the latest arrival (for setup) differ:
set_input_delay -max 0.40 -clock clk [get_ports din]
set_input_delay -min 0.10 -clock clk [get_ports din]
Thus, a larger input delay means less time inside the block. Choosing it too small makes the block look easier than it is. Choosing it too large forces the tool to over-optimize.
5.3 Output delay
An output delay is the time the outside world needs after the data leaves the port, before the capturing edge. With a period of 2.0 ns and an output delay of 0.5 ns, the block has 2.0 โ 0.5 = 1.5 ns from the launching edge to produce valid data at the port.
set_output_delay 0.50 -clock clk [get_ports {sum ovf}]
The same -max and -min pair applies. Note that the meaning is opposite to the input case: here, a larger number gives the block less time.
5.4 Combinational paths from input to output
The path from en to ovf receives an input delay of 0.4 and an output delay of 0.5, so the logic in between has 2.0 โ 0.4 โ 0.5 = 1.1 ns, minus any uncertainty. This is often the most surprising result for beginners, because the path never touches a register in the block. If the budget looks unreasonably tight, either the constraints are wrong or the block needs a register on that path.
5.5 Virtual clocks
Sometimes the data outside is launched by a clock that does not enter the block, for example from a neighbouring chip. A virtual clock is defined without a source.
create_clock -name vclk -period 2.0
set_input_delay 0.4 -clock vclk [get_ports din]
It exists only so port delays have a reference, and is typically used when the launching clock is outside the design or has a different latency than the internal one. Using a real clock for port delays when the launch is actually external can give a wrong picture of the clock latency, because the internal latency is added.
5.6 What drives the input and what the output sees
Port delays say when the data arrives. They do not say how well the signal is driven. A weak driver gives a slow transition, which makes the first cell in the block slower. Two further constraints describe the environment.
set_driving_cell -lib_cell BUFX2 [get_ports {din en}]
set_load 0.020 [all_outputs]
set_driving_cell names a library cell to model the outside driver, and set_load states the capacitance on each output in pF. If they are left out, the tool assumes an ideal driver and zero load, which is almost always optimistic. Remember the unit trap from Lesson 2: set_load expects pF.
5.7 Asynchronous inputs
A port such as rst_n is not launched by the clock at a known time. Giving it an input delay would time the reset path as if it were synchronous. If it is not, mark the path as a false path. Note that this also removes the recovery and removal checks on the flops it resets, so it is only safe when the release of reset is synchronized elsewhere. Otherwise, give the release an input delay so those checks run:
set_false_path -from [get_ports rst_n]
We cover exceptions in the next lesson. For now, the point is that every input port needs a decision: constrain it with a delay, or exclude it explicitly. A port with neither is a hole in the constraints.
5.8 A quick sanity check
After writing the constraints, ask the tool which ports have no delay.
report_timing -lint
Typical lint output lists unconstrained endpoints and ports with no input delay. Treat each entry as a question to answer, not as noise.
5.9 Why an interviewer asks about this
Port delays are asked about because they connect two designers' work: the block owner and the chip integrator. Be ready to compute the time left for logic from a period and a delay, to explain why an input-to-output path is unusual, and to say when a virtual clock is used.
Key takeaways
- Input and output delays state how much of the period the outside world uses, so the block gets exactly what remains.
- A larger delay at either side leaves less time inside the block.
- Combinational input-to-output paths get both delays, so their budget is the period minus both, which can be tight in a block with large port delays.
- Describe the environment as well, with
set_driving_cellandset_load, and decide explicitly what to do with every asynchronous port.