False paths and multicycle paths
Write false and multicycle path exceptions, see where they move the setup and hold checks, and make sure the design keeps the promise each one makes.
- Lesson
- L2.8
- Time
- 30 min
- Runs on
- OpenROAD
- Check
- 5 questions
A datapath produces a result every second cycle, so its designer gave it two cycles: set_multicycle_path 2 -setup. Setup passed. Then both of its capture flops failed hold, the worst by 0.3389 ns, and a hold repair tool would have filled it with delay cells. The hold check had moved one cycle with the setup check.
a0_reg launches; y0_reg captures after one nand2_1. Both are enable flops on the same en.a0_reg → y0_reghold check, earliest arrival2 cells
- Clock latency
- Cell delay
- Hold time
- Fast data
Clock-to-Q and one gate: the new value reaches
y0_regat 0.5642 ns. - A hold edge one period late
The hold check now uses the edge at 1 ns, not 0 ns. Required after 0.9031 ns.
- Violated
Slack -0.3389 ns: the data would have to stay put for most of a period.
Read the path as a table
Launch: clk rise edge at 0.0000 ns, clock latency 0.0000 ns (ideal). Capture: clk rise edge at 1.0000 ns, latency 0.0000 ns, library hold time −0.0969 ns.
Arrival 0.5642 ns, required 0.9031 ns, slack −0.3389 ns (violated).
| Cell | Arc | Through | Edge | Delay (ns) | Time (ns) | Slew (ns) |
|---|---|---|---|---|---|---|
| 1 | a0_reg/CLK → a0_reg/Q | edfxtp_1 | fall | 0.4802 | 0.4802 | 0.1478 |
a0_reg/Q → u0/A | wire a0 | fall | 0.0000 | 0.4802 | 0.1478 | |
| 2 | u0/A → u0/Y | nand2_1 | rise | 0.0840 | 0.5642 | 0.0363 |
u0/Y → y0_reg/D | wire s0 | rise | 0.0000 | 0.5642 | 0.0363 |
The report
Startpoint: a0_reg (rising edge-triggered flip-flop clocked by clk)
Endpoint: y0_reg (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: min
Fanout Cap Slew Delay Time Description
-------------------------------------------------------------------------------------
0.1000 0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.1000 0.0000 0.0000 ^ a0_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
5 0.0190 0.1478 0.4802 0.4802 v a0_reg/Q (sky130_fd_sc_hd__edfxtp_1)
a0 (net)
0.1478 0.0000 0.4802 v u0/A (sky130_fd_sc_hd__nand2_1)
1 0.0019 0.0363 0.0840 0.5642 ^ u0/Y (sky130_fd_sc_hd__nand2_1)
s0 (net)
0.0363 0.0000 0.5642 ^ y0_reg/D (sky130_fd_sc_hd__edfxtp_1)
0.5642 data arrival time
0.1000 1.0000 1.0000 clock clk (rise edge)
0.0000 1.0000 clock network delay (ideal)
0.0000 1.0000 clock reconvergence pessimism
1.0000 ^ y0_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
-0.0969 0.9031 library hold time
0.9031 data required time
-------------------------------------------------------------------------------------
0.9031 data required time
-0.5642 data arrival time
-------------------------------------------------------------------------------------
-0.3389 slack (VIOLATED)OpenSTA 3.1.0 on the sky130 tt library, ideal 1 ns clock with a 0.1 ns clock slew, no wires.
Lesson R4.1 said the period never enters the hold check, and here it did, because an exception moved the hold edge.
An exception is a claim about the design
By default, STA checks every path for one cycle: launch on one edge, capture on the next. An exception tells the tool that this default is wrong for some paths. The tool cannot check the claim. It just times what you wrote.
| Exception | What it claims | Typical use |
|---|---|---|
set_false_path -from A -to B | the path never has to meet timing | a configuration register written once before use |
set_multicycle_path N -setup | data may take N cycles | a datapath that captures every Nth cycle |
set_multicycle_path N-1 -hold | hold stays at the launch edge | always paired with the setup multiplier |
set_max_delay, set_min_delay | a fixed limit in ns | the Gray pointer of L2.6 |
Each takes -from and -to lists of pins, cells, ports or clocks, and -through lists of pins, cells or nets.
The datapath here has a toggling enable en. The source flops a0_reg and a1_reg load only when en is 1, and so do the destination flops y0_reg and y1_reg. New data leaves a every second cycle and is captured two cycles later.
en is 1 every second cycle, so a changes only every second edge.Read the diagram as text
- en_reg: toggles every edge
- a0_reg, a1_reg: edfxtp_1, load when en
- u0 (nand2_1): short path
- u1-u6 (xor2_1): long path
- y0_reg, y1_reg: edfxtp_1, load when en
- en_reg → a0_reg, a1_reg: DE
- a0_reg, a1_reg → u0 (nand2_1): a0
- a0_reg, a1_reg → u1-u6 (xor2_1): a0, a1
- u0 (nand2_1) → y0_reg, y1_reg: D of y0
- u1-u6 (xor2_1) → y0_reg, y1_reg: D of y1
- en_reg → y0_reg, y1_reg: DE
Both ends load on the same enable, so data has two periods from launch to capture.
At a 1 ns clock the long path fails as a single-cycle path. Its arrival is 1.5180 ns against a required time of 0.7599 ns.
The long path, single-cycle
a0_reg → y1_regsetup check, latest arrival7 cells
- Clock latency
- Cell delay
- Setup time
Read the path as a table
Launch: clk rise edge at 0.0000 ns, clock latency 0.0000 ns (ideal). Capture: clk rise edge at 1.0000 ns, latency 0.0000 ns, library setup time −0.2401 ns.
Arrival 1.5180 ns, required 0.7599 ns, slack −0.7581 ns (violated).
| Cell | Arc | Through | Edge | Delay (ns) | Time (ns) | Slew (ns) |
|---|---|---|---|---|---|---|
| 1 | a0_reg/CLK → a0_reg/Q | edfxtp_1 | fall | 0.4802 | 0.4802 | 0.1478 |
a0_reg/Q → u1/A | wire a0 | fall | 0.0000 | 0.4802 | 0.1478 | |
| 2 | u1/A → u1/X | xor2_1 | fall | 0.2007 | 0.6809 | 0.0674 |
u1/X → u2/A | wire x1 | fall | 0.0000 | 0.6809 | 0.0674 | |
| 3 | u2/A → u2/X | xor2_1 | fall | 0.1692 | 0.8502 | 0.0754 |
u2/X → u3/A | wire x2 | fall | 0.0000 | 0.8502 | 0.0754 | |
| 4 | u3/A → u3/X | xor2_1 | fall | 0.1724 | 1.0226 | 0.0644 |
u3/X → u4/A | wire x3 | fall | 0.0000 | 1.0226 | 0.0644 | |
| 5 | u4/A → u4/X | xor2_1 | fall | 0.1680 | 1.1906 | 0.0754 |
u4/X → u5/A | wire x4 | fall | 0.0000 | 1.1906 | 0.0754 | |
| 6 | u5/A → u5/X | xor2_1 | fall | 0.1724 | 1.3630 | 0.0644 |
u5/X → u6/A | wire x5 | fall | 0.0000 | 1.3630 | 0.0644 | |
| 7 | u6/A → u6/X | xor2_1 | fall | 0.1550 | 1.5180 | 0.0604 |
u6/X → y1_reg/D | wire x6 | fall | 0.0000 | 1.5180 | 0.0604 |
The report
Startpoint: a0_reg (rising edge-triggered flip-flop clocked by clk)
Endpoint: y1_reg (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Fanout Cap Slew Delay Time Description
-------------------------------------------------------------------------------------
0.1000 0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.1000 0.0000 0.0000 ^ a0_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
5 0.0190 0.1478 0.4802 0.4802 v a0_reg/Q (sky130_fd_sc_hd__edfxtp_1)
a0 (net)
0.1478 0.0000 0.4802 v u1/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0674 0.2007 0.6809 v u1/X (sky130_fd_sc_hd__xor2_1)
x1 (net)
0.0674 0.0000 0.6809 v u2/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0754 0.1692 0.8502 v u2/X (sky130_fd_sc_hd__xor2_1)
x2 (net)
0.0754 0.0000 0.8502 v u3/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0644 0.1724 1.0226 v u3/X (sky130_fd_sc_hd__xor2_1)
x3 (net)
0.0644 0.0000 1.0226 v u4/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0754 0.1680 1.1906 v u4/X (sky130_fd_sc_hd__xor2_1)
x4 (net)
0.0754 0.0000 1.1906 v u5/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0644 0.1724 1.3630 v u5/X (sky130_fd_sc_hd__xor2_1)
x5 (net)
0.0644 0.0000 1.3630 v u6/A (sky130_fd_sc_hd__xor2_1)
1 0.0017 0.0604 0.1550 1.5180 v u6/X (sky130_fd_sc_hd__xor2_1)
x6 (net)
0.0604 0.0000 1.5180 v y1_reg/D (sky130_fd_sc_hd__edfxtp_1)
1.5180 data arrival time
0.1000 1.0000 1.0000 clock clk (rise edge)
0.0000 1.0000 clock network delay (ideal)
0.0000 1.0000 clock reconvergence pessimism
1.0000 ^ y1_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
-0.2401 0.7599 library setup time
0.7599 data required time
-------------------------------------------------------------------------------------
0.7599 data required time
-1.5180 data arrival time
-------------------------------------------------------------------------------------
-0.7581 slack (VIOLATED)With no exception, the capture edge is one period after launch, at 1 ns.
The setup multiplier moves both checks
set_multicycle_path 2 -setup moves the capture edge two periods after launch. The hold check is defined from the setup edge: one capture edge before it. So the hold edge moves too, from 0 to T.
a at edge 0. A 1 marks the edge each check uses.- Cycle 0
By default, setup is checked at edge 1 and hold at edge 0, the launch edge itself.
- Cycle 1
With
-setup 2alone, hold moves to edge 1. D0 must stay stable for a whole period after launch. - Cycle 2
Setup is at edge 2, where
yloads.-hold 1brings hold back from edge 1 to edge 0.
Edges 0 to 3 of the 1 ns clock, with the edge each check uses marked as a 1.
In the run, setup now passes with 0.2419 ns, and hold fails by 0.3389 ns. The hold check now sits at the edge at 1 ns, so the short path must hold its old value until 0.9031 ns, almost a whole period after launch. It needs 0.3389 ns of extra delay. That is the qualifier to R4.1's rule: with only the setup multiplier, T enters the hold check.
The long path with -setup 2
a0_reg → y1_regsetup check, latest arrival7 cells
- Clock latency
- Cell delay
- Setup time
Read the path as a table
Launch: clk rise edge at 0.0000 ns, clock latency 0.0000 ns (ideal). Capture: clk rise edge at 2.0000 ns, latency 0.0000 ns, library setup time −0.2401 ns.
Arrival 1.5180 ns, required 1.7599 ns, slack 0.2419 ns (met).
| Cell | Arc | Through | Edge | Delay (ns) | Time (ns) | Slew (ns) |
|---|---|---|---|---|---|---|
| 1 | a0_reg/CLK → a0_reg/Q | edfxtp_1 | fall | 0.4802 | 0.4802 | 0.1478 |
a0_reg/Q → u1/A | wire a0 | fall | 0.0000 | 0.4802 | 0.1478 | |
| 2 | u1/A → u1/X | xor2_1 | fall | 0.2007 | 0.6809 | 0.0674 |
u1/X → u2/A | wire x1 | fall | 0.0000 | 0.6809 | 0.0674 | |
| 3 | u2/A → u2/X | xor2_1 | fall | 0.1692 | 0.8502 | 0.0754 |
u2/X → u3/A | wire x2 | fall | 0.0000 | 0.8502 | 0.0754 | |
| 4 | u3/A → u3/X | xor2_1 | fall | 0.1724 | 1.0226 | 0.0644 |
u3/X → u4/A | wire x3 | fall | 0.0000 | 1.0226 | 0.0644 | |
| 5 | u4/A → u4/X | xor2_1 | fall | 0.1680 | 1.1906 | 0.0754 |
u4/X → u5/A | wire x4 | fall | 0.0000 | 1.1906 | 0.0754 | |
| 6 | u5/A → u5/X | xor2_1 | fall | 0.1724 | 1.3630 | 0.0644 |
u5/X → u6/A | wire x5 | fall | 0.0000 | 1.3630 | 0.0644 | |
| 7 | u6/A → u6/X | xor2_1 | fall | 0.1550 | 1.5180 | 0.0604 |
u6/X → y1_reg/D | wire x6 | fall | 0.0000 | 1.5180 | 0.0604 |
The report
Startpoint: a0_reg (rising edge-triggered flip-flop clocked by clk)
Endpoint: y1_reg (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Fanout Cap Slew Delay Time Description
-------------------------------------------------------------------------------------
0.1000 0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.1000 0.0000 0.0000 ^ a0_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
5 0.0190 0.1478 0.4802 0.4802 v a0_reg/Q (sky130_fd_sc_hd__edfxtp_1)
a0 (net)
0.1478 0.0000 0.4802 v u1/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0674 0.2007 0.6809 v u1/X (sky130_fd_sc_hd__xor2_1)
x1 (net)
0.0674 0.0000 0.6809 v u2/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0754 0.1692 0.8502 v u2/X (sky130_fd_sc_hd__xor2_1)
x2 (net)
0.0754 0.0000 0.8502 v u3/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0644 0.1724 1.0226 v u3/X (sky130_fd_sc_hd__xor2_1)
x3 (net)
0.0644 0.0000 1.0226 v u4/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0754 0.1680 1.1906 v u4/X (sky130_fd_sc_hd__xor2_1)
x4 (net)
0.0754 0.0000 1.1906 v u5/A (sky130_fd_sc_hd__xor2_1)
1 0.0042 0.0644 0.1724 1.3630 v u5/X (sky130_fd_sc_hd__xor2_1)
x5 (net)
0.0644 0.0000 1.3630 v u6/A (sky130_fd_sc_hd__xor2_1)
1 0.0017 0.0604 0.1550 1.5180 v u6/X (sky130_fd_sc_hd__xor2_1)
x6 (net)
0.0604 0.0000 1.5180 v y1_reg/D (sky130_fd_sc_hd__edfxtp_1)
1.5180 data arrival time
0.1000 2.0000 2.0000 clock clk (rise edge)
0.0000 2.0000 clock network delay (ideal)
0.0000 2.0000 clock reconvergence pessimism
2.0000 ^ y1_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
-0.2401 1.7599 library setup time
1.7599 data required time
-------------------------------------------------------------------------------------
1.7599 data required time
-1.5180 data arrival time
-------------------------------------------------------------------------------------
0.2419 slack (MET)With the setup multiplier, the capture edge moves to 2 ns, two periods after launch.
set_multicycle_path 1 -hold moves the hold edge back by one period, to the launch edge. The rule: for N cycles of setup, write N − 1 for hold.
Setup only
set_multicycle_path 2 -setup \
-from [get_cells {a0_reg a1_reg}] \
-to [get_cells {y0_reg y1_reg}]
Hold checked at T: slack -0.3389 ns.
Setup and hold
set_multicycle_path 2 -setup \
-from [get_cells {a0_reg a1_reg}] \
-to [get_cells {y0_reg y1_reg}]
set_multicycle_path 1 -hold \
-from [get_cells {a0_reg a1_reg}] \
-to [get_cells {y0_reg y1_reg}]
Hold checked at 0: slack 0.6611 ns.
a0_reg → y0_reghold check, earliest arrival2 cells
- Clock latency
- Cell delay
- Hold time
- Back at the launch edge
The hold edge is back at 0 ns, the edge that launched the data.
- Met
Slack 0.6611 ns: this is the normal hold check of a path launched and captured on one edge.
Read the path as a table
Launch: clk rise edge at 0.0000 ns, clock latency 0.0000 ns (ideal). Capture: clk rise edge at 0.0000 ns, latency 0.0000 ns, library hold time −0.0969 ns.
Arrival 0.5642 ns, required −0.0969 ns, slack 0.6611 ns (met).
| Cell | Arc | Through | Edge | Delay (ns) | Time (ns) | Slew (ns) |
|---|---|---|---|---|---|---|
| 1 | a0_reg/CLK → a0_reg/Q | edfxtp_1 | fall | 0.4802 | 0.4802 | 0.1478 |
a0_reg/Q → u0/A | wire a0 | fall | 0.0000 | 0.4802 | 0.1478 | |
| 2 | u0/A → u0/Y | nand2_1 | rise | 0.0840 | 0.5642 | 0.0363 |
u0/Y → y0_reg/D | wire s0 | rise | 0.0000 | 0.5642 | 0.0363 |
The report
Startpoint: a0_reg (rising edge-triggered flip-flop clocked by clk)
Endpoint: y0_reg (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: min
Fanout Cap Slew Delay Time Description
-------------------------------------------------------------------------------------
0.1000 0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.1000 0.0000 0.0000 ^ a0_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
5 0.0190 0.1478 0.4802 0.4802 v a0_reg/Q (sky130_fd_sc_hd__edfxtp_1)
a0 (net)
0.1478 0.0000 0.4802 v u0/A (sky130_fd_sc_hd__nand2_1)
1 0.0019 0.0363 0.0840 0.5642 ^ u0/Y (sky130_fd_sc_hd__nand2_1)
s0 (net)
0.0363 0.0000 0.5642 ^ y0_reg/D (sky130_fd_sc_hd__edfxtp_1)
0.5642 data arrival time
0.1000 0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.0000 0.0000 clock reconvergence pessimism
0.0000 ^ y0_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
-0.0969 -0.0969 library hold time
-0.0969 data required time
-------------------------------------------------------------------------------------
-0.0969 data required time
-0.5642 data arrival time
-------------------------------------------------------------------------------------
0.6611 slack (MET)The same netlist and clock, now with both -setup 2 and -hold 1 on the a-to-y paths.
Two clocks of different periods: -start and -end
Between clocks of different periods, N counts periods of one clock. By default the setup multiplier counts the capture clock's periods (-end) and the hold multiplier the launch clock's (-start). Add -start or -end to choose. For a slow launch clock feeding a fast capture clock, -setup -end 2 gives the path two fast periods.
Keep the claim true
A two-cycle exception is only safe if the design behaves that way. The source must change at most every second cycle, and the destination must load only when the data has had two cycles. Here both follow from the shared enable, as in R2.3.
False paths need the same care. The intent was to cut the static input cfg. Written with a wildcard, set_false_path -from [all_inputs] also cuts d0 and d1. Nothing fails: check_setup just lists a0_reg/D and a1_reg/D as unconstrained endpoints. report_checks -through d0 finds no path at all.
Too broad
set_false_path -from [all_inputs]
It cuts cfg, and it also cuts the real inputs d0 and d1.
Exact
set_false_path -from [get_ports cfg]
d0 → a0_reg is still timed: slack 0.5837 ns.
The path report_checks -through d0 finds with the exact false path
d0 → a0_regsetup check, latest arrival0 cells
- Clock latency
- Cell delay
- Input delay
- Setup time
Read the path as a table
Launch: clk rise edge at 0.0000 ns, clock latency 0.0000 ns (ideal). Capture: clk rise edge at 1.0000 ns, latency 0.0000 ns, library setup time −0.2163 ns.
Arrival 0.2000 ns, required 0.7837 ns, slack 0.5837 ns (met).
| Cell | Arc | Through | Edge | Delay (ns) | Time (ns) | Slew (ns) |
|---|---|---|---|---|---|---|
d0 → a0_reg/D | wire d0 | fall | 0.0000 | 0.2000 | 0.0000 |
The report
Startpoint: d0 (input port clocked by clk)
Endpoint: a0_reg (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Fanout Cap Slew Delay Time Description
-------------------------------------------------------------------------------------
0.1000 0.0000 0.0000 clock clk (rise edge)
0.0000 0.0000 clock network delay (ideal)
0.2000 0.2000 v input external delay
1 0.0017 0.0000 0.0000 0.2000 v d0 (in)
d0 (net)
0.0000 0.0000 0.2000 v a0_reg/D (sky130_fd_sc_hd__edfxtp_1)
0.2000 data arrival time
0.1000 1.0000 1.0000 clock clk (rise edge)
0.0000 1.0000 clock network delay (ideal)
0.0000 1.0000 clock reconvergence pessimism
1.0000 ^ a0_reg/CLK (sky130_fd_sc_hd__edfxtp_1)
-0.2163 0.7837 library setup time
0.7837 data required time
-------------------------------------------------------------------------------------
0.7837 data required time
-0.2000 data arrival time
-------------------------------------------------------------------------------------
0.5837 slack (MET)The setup path that report_checks -through d0 returns when only cfg is cut.
Never false-path a reset release. The release of an asynchronous reset must meet the flops' recovery and removal checks, as R2.2 explained. A false path on the reset synchronizer's output hides exactly the check that matters.
STA never checks an exception, so check it in simulation. An assertion can state the promise: the source is stable in the cycle before each capture.
$stable compares a with its value at the previous edge, when it could not load.// a only loads on en, and en alternates, so a is stable whenever y loads
assert property (@(posedge clk) en |=> !en);
assert property (@(posedge clk) en |-> $stable({a1, a0}));Asked in interviews
What is a multicycle path, and why do you need the hold multiplier?
A path allowed N cycles for setup. The hold check follows the setup edge, so with -setup N alone it moves N − 1 periods late. -hold N−1 moves it back to the launch edge.
When is a false path legitimate?
When the path can never carry a change that matters: a static configuration bit, a test-only path, or a crossing already made safe and not covered by clock groups.
How do you verify a timing exception?
STA trusts it, so check it elsewhere: assertions in simulation that the source holds still, a CDC or exception-verification tool, and a review of what each -from/-to actually matches.
What is the risk of a wildcard in an exception?
It can match real paths too. Those paths silently leave the report; check_setup shows them only as unconstrained endpoints.
Try it
This is the SDC of the opening figure. Run it: setup passes with 0.2419 ns, hold fails with -0.3389 ns.
Add the hold multiplier, set_multicycle_path 1 -hold -from [get_cells {a0_reg a1_reg}] -to [get_cells {y0_reg y1_reg}], and run again: Paths shows the hold check back at 0 ns. Then add set_false_path -from [all_inputs] and read Output: two flop D pins become unconstrained.
Run to draw the timing paths here.
WNS 0.2419 ns worst minimum slack -0.3389 nsRead the netlist: dp2.v
module dp2 (clk, d0, d1, cfg, y0, y1);
input clk;
input d0;
input d1;
input cfg;
output y0;
output y1;
wire en, nen, a0, a1, s0, x1, x2, x3, x4, x5, x6;
sky130_fd_sc_hd__dfxtp_1 en_reg (.CLK(clk), .D(nen), .Q(en));
sky130_fd_sc_hd__inv_1 u_en (.A(en), .Y(nen));
sky130_fd_sc_hd__edfxtp_1 a0_reg (.CLK(clk), .D(d0), .DE(en), .Q(a0));
sky130_fd_sc_hd__edfxtp_1 a1_reg (.CLK(clk), .D(d1), .DE(en), .Q(a1));
sky130_fd_sc_hd__nand2_1 u0 (.A(a0), .B(cfg), .Y(s0));
sky130_fd_sc_hd__xor2_1 u1 (.A(a0), .B(a1), .X(x1));
sky130_fd_sc_hd__xor2_1 u2 (.A(x1), .B(a0), .X(x2));
sky130_fd_sc_hd__xor2_1 u3 (.A(x2), .B(a1), .X(x3));
sky130_fd_sc_hd__xor2_1 u4 (.A(x3), .B(a0), .X(x4));
sky130_fd_sc_hd__xor2_1 u5 (.A(x4), .B(a1), .X(x5));
sky130_fd_sc_hd__xor2_1 u6 (.A(x5), .B(a0), .X(x6));
sky130_fd_sc_hd__edfxtp_1 y0_reg (.CLK(clk), .D(s0), .DE(en), .Q(y0));
sky130_fd_sc_hd__edfxtp_1 y1_reg (.CLK(clk), .D(x6), .DE(en), .Q(y1));
endmodule
Check yourself
Remember
- A false path removes paths from timing; a multicycle path gives them N cycles. STA trusts both.
- The hold check follows the setup edge: with -setup N alone, T enters the hold check.
- Always pair -setup N with -hold N−1 to keep hold at the launch edge.
- Keep exceptions exact and prove them in simulation; never false-path a reset release.