One path fails setup the morning after an RTL edit. Everything else still passes with the same constraints and the same library.
The failing path runs from one flop through new muxing to the next flop. The report points at added depth, not at a changed clock.
Check | Before the edit | After the edit |
|---|---|---|
Failing paths | 0 | 1 |
Combinational delay on that path | 1.55 ns (EXAMPLE) | 1.75 ns (EXAMPLE) |
Constraints and library | Unchanged | Unchanged |
Diff first: RTL, constraints, and library versions against the last green run. A changed constraint or library explains a regression with no RTL cause.
Then read the failing path stage by stage. Rank the causes before touching anything.
Rank | Likely cause | How to confirm |
|---|---|---|
1 | Added logic depth from the edit | Compare stage counts on the failing path. |
2 | Higher fanout from a widened bus | Compare loads on the driving net. |
3 | A changed constraint or exception | Diff the constraint files. |
4 | A changed library or tool version | Diff versions against the green run. |
Slack is required minus arrival. The calc block substitutes the EXAMPLE parameters; the program below rechecks them.
EXAMPLE parameters (not real silicon): period 2.00 ns, clock-to-Q 0.15 ns, setup 0.06 ns, uncertainty 0.10 ns
required = 2.00 - 0.06 - 0.10 = 1.84 ns
arrival before = 0.15 + 1.55 = 1.70 ns
slack before = 1.84 - 1.70 = +0.14 ns (passes)
added mux level = 0.20 ns (EXAMPLE)
arrival after = 1.70 + 0.20 = 1.90 ns
slack after = 1.84 - 1.90 = -0.06 ns (fails by 0.06 ns)import sys
PERIOD = 2.00
TCQ = 0.15
TCOMB_BEFORE = 1.55
ADDED = 0.20
SETUP = 0.06
UNC = 0.10
def close(got, want):
return abs(got - want) < 1e-9
required = PERIOD - SETUP - UNC
arr_before = TCQ + TCOMB_BEFORE
slack_before = required - arr_before
arr_after = arr_before + ADDED
slack_after = required - arr_after
bad = 0
if not close(required, 1.84):
bad = bad + 1
if not close(slack_before, 0.14):
bad = bad + 1
if not close(slack_after, -0.06):
bad = bad + 1
if not close(arr_after - arr_before, 0.20):
bad = bad + 1
if bad != 0:
print("FAIL: slack arithmetic broke on " + str(bad) + " checks")
sys.exit(1)
print("PASS: slack +0.14 ns before and -0.06 ns after the change")Move the added select before the register or restructure the mux tree. One extra pipeline stage also closes timing but adds a cycle of latency.
The constraint below is an illustrative sketch, not a runnable script. It shows the shape of the clock definition only.
Illustrative SDC sketch (not a runnable script; command names are standard SDC):
create_clock -period 2.0 [get_ports clk]
set_input_delay 0.4 -clock clk [all_inputs]
set_output_delay 0.4 -clock clk [all_outputs]Before: 1.84 minus 1.70 is +0.14 ns. After: 1.84 minus 1.90 is -0.06 ns.
The constraint files against the last green run. A changed exception explains the failure with no RTL cause.