A 50 ps delay in the typical corner is about 65 ps in the slow corner and 40 ps in the fast one (scale factors 1.30, 1.00 and 0.80 are illustrative). The windows move with the corner too, so a value that sits comfortably in one can lie outside another. Signing off useful skew means checking the window per corner, with the skew that corner actually delivers.
m = 0.005
nominal_skew = 0.050
scale = {"slow": 1.30, "typical": 1.00, "fast": 0.80} # illustrative
base = { # corner: (s1, h1, s2, h2) for the skewed flop, ns
"slow": (-0.052, 0.085, 0.080, 0.080),
"typical": (-0.040, 0.060, 0.060, 0.060),
"fast": (-0.020, 0.035, 0.055, 0.050),
}
result = {}
for corner, (s1, h1, s2, h2) in base.items():
d = nominal_skew * scale[corner]
lo, hi = max(m - s1, m - h2), min(h1, s2) - m
result[corner] = (round(d, 3), round(lo, 3), round(hi, 3), lo <= d <= hi)
assert result == {"slow": (0.065, 0.057, 0.075, True), "typical": (0.05, 0.045, 0.055, True), "fast": (0.04, 0.025, 0.03, False)}
fails = [c for c, r in result.items() if not r[3]]
assert fails == ["fast"]
hold_fast = round(base["fast"][1] - result["fast"][0], 3)
assert hold_fast == -0.005
print("PASS: failing corner", fails, "; fast-corner hold slack", hold_fast, "ns")Corner | Skew delivered (ns) | Window (ns) | Inside? |
|---|---|---|---|
Slow | 0.065 | 0.057 to 0.075 | Yes |
Typical | 0.050 | 0.045 to 0.055 | Yes |
Fast | 0.040 | 0.025 to 0.030 | No: hold slack is -0.005 ns |
The skew passes in the slow and typical corners and fails in the fast one: there the cells deliver 40 ps, which exceeds the window's upper limit of 30 ps, so the hold check into the skewed flop is violated by 5 ps. Each corner's window uses all four bounds: the lower edge is the larger of the setup need into the flop and the hold need out of it, and the upper edge is the smaller of the hold limit into the flop and the setup limit out of it. The fix is not to change the skew in the slow corner (where it is needed) but to reduce the spread of delay across corners (fewer, more corner-stable cells in the skewing path) or to add hold delay to the data path of that stage, within its setup slack. This is a corner-dependent problem that only a per-corner check finds.
Item | Evidence |
|---|---|
List of skewed flops with intended offsets | Table with reason and owner |
Window per corner and per flop | The computation above, per scenario, using all four bounds |
Clock cells used and their variation | Cell list and sigma |
SI and power after skew | Clock net SI report, clock power |
Full-matrix timing | Per-scenario WNS and TNS with skew in place |
No skewed flop is checked in one corner only.
Skews are documented as intentional, so a future ECO does not 'fix' them away.
The slack of the downstream stage is part of the same table, not a separate report.
Hold is a fast-corner check, and in the fast corner the window's upper limit is lowest (hold slack is smallest) while the delivered skew, though smaller than in the slow corner, still exceeds that limit.