Keywords: $setup, $hold, $width
This section, the final part of the delay modeling chapter, discusses some of the various system tasks that exist for the purposes of timing checks. Verilog contains many timing-check system tasks, but only the three most common tasks are discussed here: $setup, $hold and $width. Timing checks are used to verify that timing constraints are upheld, and are especially important in the simulation of high-speed sequential circuits such as microprocessors. All timing checks must be contained within specify blocks as shown in the example below.
The $setup and $hold tasks are used to monitor the setup and hold constraints during the simulation of a sequential circuit element. In the example, the setup time is the minimum allowed time between a change in the input d and a positive clock edge. Similarly, the hold time is the minimum allowed time between a positive clock edge and a change in the input d.
The $width task is used to check the minimum width of a positive or negative-going pulse. In the example, this is the time between a negative transition and the transition back to 1.

NB: data_change, reference and reference1 must be declared wires.
$setup(data_change, reference, time_limit);
data_change: signal that is checked against the reference
reference: signal used as reference
time_limit: minimum time required between the two events.
Violation if: Treference - Tdata_change < time_limit.
$hold(reference, data_change, time_limit);
reference: signal used as reference
data_change: signal that is checked against the reference
time_limit: minimum time required between the two events.
Violation if: Tdata_change - Treference < time_limit
$width(reference1, time_limit);
reference1: first transition of signal
time_limit: minimum time required between transition1 and transition2.
Violation if: Treference2 - Treference1 < time_limit
Example:
module d_type(q, clk, d);
output q;
input clk, d;
reg q;
always @(posedge clk)
q = d;
endmodule // d_type
module stimulus;
reg clk, d;
wire q, clk2, d2;
d_type dt_test(q, clk, d);
assign d2=d;
assign clk2=clk;
initial
begin
$display ("\t\t clock d q");
$display ($time," %b %b %b", clk, d, q);
clk=0;
d=1;
#7 d=0;
#7 d=1; // causes setup violation
#3 d=0;
#5 d=1; // causes hold violation
#2 d=0;
#1 d=1; // causes width violation
end // initial begin
initial
#26 $finish;
always
#3 clk = ~clk;
always
#1 $display ($time," %b %b %b", clk, d, q);
specify
$setup(d2, posedge clk2, 2);
$hold(posedge clk2, d2, 2);
$width(negedge d2, 2);
endspecify
endmodule // stimulus
Output:
clock d q
0 x x x
1 0 1 x
2 0 1 x
3 1 1 x
4 1 1 1
5 1 1 1
6 0 1 1
7 0 0 1
8 0 0 1
9 1 0 1
10 1 0 0
11 1 0 0
12 0 0 0
13 0 0 0
14 0 1 0
15 1 1 0
"timechecks.v", 46: Timing violation in stimulus
$setup( d2:14, posedge clk2:15, 2 );
16 1 1 1
17 1 0 1
18 0 0 1
19 0 0 1
20 0 0 1
21 1 0 1
22 1 1 0
"timechecks.v", 47: Timing violation in stimulus
$hold( posedge clk2:21, d2:22, 2 );
23 1 1 0
24 0 0 0
25 0 1 0
"timechecks.v", 48: Timing violation in stimulus
$width( negedge d2:24, : 25, 2 );