Minimum Pulse Width Check
Minimum pulse width in STA: why a clock high or low pulse must stay wide enough, how unequal rise and fall delays shrink a pulse across a buffer chain, a worked slack example with uncertainty, and fixes like matched clock buffers and dual inversion.
A minimum pulse width check makes sure every clock pulse (and some data pulses) stays wide enough for the cell it drives to actually work. A flip-flop or latch needs its clock high phase and low phase to each last at least a minimum time so the internal nodes can charge and settle. If a pulse gets too narrow, the cell may capture nothing, capture the wrong value, or go metastable, and in a long chain the pulse can shrink until it disappears completely.
Why a pulse shrinks
Ordinary logic cells rarely have exactly equal rise and fall delays. If a buffer's rising-edge delay is a little larger than its falling-edge delay, it pushes the rising edge of the clock later than the falling edge, and the high phase between them gets a little shorter. One buffer barely matters, but a clock travels through a long chain of buffers on its way to the flops, and the shortening adds up. That is why clock trees are built from special clock buffers with closely matched rise and fall delays, and why the tool still checks the pulse width at every sink.
Worked example
Take a 1 GHz clock, so the period is 1000 ps and, at a 50% duty cycle, the ideal high pulse is 500 ps. Suppose the clock buffers each delay the rising edge slightly more than the falling edge, and across the whole chain the high phase loses 26 ps, leaving 474 ps. Now charge the usual clock uncertainty of 90 ps against it, so the high pulse the checker trusts is 474 - 90 = 384 ps. If the flip-flop's library requires a minimum high pulse of 410 ps, the slack is 384 - 410 = -26 ps: a minimum pulse width violation on the high phase. Notice that without the uncertainty term the pulse (474 ps) would have passed, which is why signoff includes it.
How to fix it
- Build the clock path from clock buffers and inverters chosen for matched rise and fall delays, so each stage shaves almost nothing off the pulse.
- Use dual inversion: place an inverter in the middle of the chain so the phase that was shrinking becomes the phase that grows for the rest of the chain, and the pulse comes out close to what went in.
- Avoid long chains of ordinary (non-clock) buffers on any signal that still has to meet a pulse-width check downstream.
A minimum pulse width violation is easy to miss because the path can still meet setup and hold. The pulse simply arrives too narrow to be captured reliably, so the flop can go metastable or drop data even though the timing report looks fine on the setup and hold checks. Always read the pulse-width and clock-checks section of the report, not just slack.
Reporting: report_timing -check_type min_pulse_width (or the tool's report_min_pulse_width) shows the check, and in the SDC you set the requirement with set_min_pulse_width, for example set_min_pulse_width -high 0.41 [get_clocks clk] and set_min_pulse_width -low 0.40 [get_clocks clk]. If you give neither -high nor -low, the value applies to both phases.