The following table assumes matching rising-edge clock waveforms, one period T apart, with setup moved relative to capture and the hold adjustment restoring the original same-edge relationship. For divided, phase-shifted or unequal-frequency clocks, list actual launch/capture times, choose whether -start shifts launch-clock cycles or -end shifts capture-clock cycles, and inspect both setup and hold reports before approving an exception.
Data launched on edge n must arrive before edge n+1 for setup. It must not arrive before edge n has finished capturing, which is the hold requirement.
Capturing only every N cycles moves the setup check to edge n+N. By default the hold check moves to edge n+N−1 as well, so a second exception moves it back.
Check | Default (1 cycle) | After | After |
|---|---|---|---|
Setup edge | n + 1 | n + N | n + N |
Hold edge | n | n + N − 1 | n |
Read each row left to right: the arrow is the setup check from the launch edge n to the capture edge it is measured against, and the dot is the edge the hold check uses.
Only the arrow moves in the first change: setup gets 3 periods instead of 1.
The dot moves too, to n+2, because the tool keeps the hold edge one period before the setup edge unless told otherwise.
That moved hold check would demand the data stay put for two extra periods, which is almost never real, so the second exception pulls it back to n.
set_multicycle_path 2 -setup -from $launch -to $capture
set_multicycle_path 1 -hold -from $launch -to $capture # N-1 = 1Illustrative edge | Launch enable | Capture enable | Actual interval |
|---|---|---|---|
E0 (0 ns) | 1 | 0 | Operands launch |
E1 (1 ns) | 0 | 1 | Only 1 ns since E0 |
E2 (2 ns) | 0 | 0 | Source holds |
E3 (3 ns) | 1 | 0 | Next launch |
E4 (4 ns) | 0 | 1 | Again only 1 ns since launch |
Both enables repeat every three edges, but their phase gives only one period, not three. A 3-cycle exception would hide a real violation. The multiplier below instead launches at E0 and captures at E3. Its finite checker observes that interval; the delay model below checks setup only and cannot validate the SDC hold pairing.
Five versions of a 1.0 ns clock launch and capture at different cadences. Each capture checks both the value launched K cycles earlier and the setup window. Setup slack uses K cycles of budget.
Case | Logic | Launch / capture | Intended cycles K | Slack with K cycles | Result |
|---|---|---|---|---|---|
0 | 1.4 ns | every 2nd cycle | 2 | +0.13 ns | 0 wrong captures |
1 | 1.4 ns | every cycle | 1 | −0.87 ns | every capture wrong |
2 | 2.4 ns | every 2nd cycle | 2 | −0.87 ns | every capture wrong |
3 | 2.4 ns | every 3rd cycle | 3 | +0.13 ns | 0 wrong captures |
4 | 1.6 ns | every 2nd cycle | 2 | -0.07 ns | Value arrives before capture but inside the 0.12 ns setup window |
Cases 0 and 1 use the same 1.4 ns logic and differ only in cadence. A path is only too slow relative to how often it is captured, and the exception records that RTL property without making hardware faster.
-setup 3, where does the default hold check move to, and which exception restores it?To edge n + 2 (N − 1). set_multicycle_path 2 -hold moves it back to edge n.
The five path variants plus a directed setup-boundary regression. Case 4 must have zero value mismatches and nonzero setup violations: checking only the sampled value would miss it. This model does not check hold or replace STA.
`timescale 1ns/1ps
// Launch a new counter value every LAUNCH_EVERY cycles through a path with delay LOGIC.
// The capture register samples every CAP_EVERY cycles and is EXPECTED to see the value launched K cycles earlier.
module mcp_path #(parameter real LOGIC = 1.4, parameter int LAUNCH_EVERY = 2, CAP_EVERY = 2, K = 2) (
input logic clk,
output int mismatches, captures, setup_viol,
output real slack_k_cycles
);
localparam real TCQ = 0.35, TSU = 0.12, T = 1.0;
int e = 0; // edge counter
logic [7:0] q1, d2, q2;
logic [7:0] launched [0:255];
logic [7:0] value = 0;
realtime t_d = -100.0;
initial begin mismatches = 0; captures = 0; setup_viol = 0; q1 = 0; end
assign #(LOGIC) d2 = q1; // the combinational path
always @(d2) t_d = $realtime;
always @(posedge clk) begin
e++;
if (e % LAUNCH_EVERY == 0) begin // launch: a new value leaves the launch register TCQ after the edge
value = value + 1;
q1 <= #TCQ value;
end
launched[e] = value; // what the launch register holds, logically, after edge e
if (e % CAP_EVERY == 0 && e > 10) begin // capture: sample whatever has arrived at the capture register
if ($realtime - t_d < TSU) begin
setup_viol++;
q2 <= 'x;
end else q2 <= d2;
captures++;
if (d2 !== launched[e - K]) mismatches++;
end
end
assign slack_k_cycles = K * T - TSU - TCQ - LOGIC; // setup slack if the path is given K cycles
endmodule
The five-path simulation (1.0 ns clock, cases 0 to 4) checks captured values and the setup window. The delay model checks setup only and cannot validate the SDC hold pairing. The N and N-1 recipe assumes matching same-clock waveforms.