“Setup fails on this path. Do you fix it in RTL or with an ECO?” A follow-up adds a hold violation on a neighbouring path.
The question tests fix direction. Setup is about too much delay, hold about too little, and the two fixes pull opposite ways.
Setup slack is required minus arrival with the period inside required. Anything that shortens arrival or lengthens the budget helps: less logic, a faster implementation, or a pipeline cut.
For the ordinary same-clock hold relationship, slack is minimum data arrival minus required, without a period term. Added minimum data delay is common; reducing harmful capture-minus-launch skew also helps. Moving capture earlier or launch later can improve hold but spend setup margin. Recheck both checks in every required view.
Violation | What helps | What does not help |
|---|---|---|
Setup (too slow) | Pipeline the cone, resize or buffer, useful skew, slower clock | Adding delay cells |
Hold (too fast) | Minimum-data-delay insertion or correction of harmful capture-minus-launch skew | Slowing an ordinary same-clock period |
Both at once | Fix setup structurally first, then re-check hold | Fixing hold first, since setup work moves it |
A pipeline cut is a candidate structural setup remedy: two adder levels in one cycle become one level per cycle, with the second operand delayed to match. Mapped topology and STA across the required views must establish the actual setup improvement and hold closure.
Read each row left to right from the inputs to register y. The highlighted registers are the pipeline cut.
Top row: two adder levels sit between the inputs and y, so both count against one clock period.
Bottom row: each period sees only one adder level, at the cost of one more cycle of latency.
c1 exists only to keep c in step with s1. Without it, the second adder would add this cycle's c to last cycle's a + b.
Both forms plus the testbench sit in one block below. The check sweeps all 4096 input combinations of the 4-bit operands.
module add_comb #(parameter int W = 4) (
input logic clk,
input logic [W-1:0] a, b, c,
output logic [W-1:0] y
);
always_ff @(posedge clk) y <= a + b + c; // two adder levels in one cycle
endmodule
module add_pipe #(parameter int W = 4) (
input logic clk,
input logic [W-1:0] a, b, c,
output logic [W-1:0] y
);
logic [W-1:0] s1, c1;
always_ff @(posedge clk) begin
s1 <= a + b; // first level
c1 <= c; // delay c to match s1
end
always_ff @(posedge clk) y <= s1 + c1; // second level, one cycle later
endmodule
Q: The pipeline cut changes latency. Who approves that? The block owner and the system architect. Latency is a protocol change, so the valid and handshake logic must move with the data.
Q: Hold fails after your ECO added buffers. What now? Compare the before/after minimum-delay reports and clock paths. Data-path delay normally helps hold; a changed clock skew or faster data branch may explain the regression. Add only the missing minimum delay on the failing data branch, or correct the clock change, then recheck setup and hold. Reducing data-path delay would worsen that hold failure.
Q: When is an RTL change wrong and a gate-level ECO right? Late in the flow with a small, local violation. An ECO avoids re-verification of the whole block.
“Buffers always fix setup.” Buffering can improve setup on high-load or long RC nets by improving slew and drive, but unnecessary stages add delay. Compare total cell-plus-net delay before and after; recheck minimum delay and all affected endpoints too.
“Pipeline without delaying the side inputs.” The listing above delays c beside s1 for a reason. An undelayed side input mixes cycles and corrupts the sum.
“Fix hold first, it is smaller.” Setup restructuring moves hold afterwards. Order fixes setup first, then hold.
The setup fix sped slow paths and starved fast ones of delay. Hold must be re-checked after every setup change, with minimal delay added only where needed.
The pipeline-cut bench is untimed RTL, run with Icarus Verilog 13.0 (2026-10-16), and checks function and latency only. No timing result is claimed.