System tasks and functions are the simulator's built-in toolbox — identified by a leading $. They let you print signal values, query simulation time, generate random stimulus, load memory from files, control waveform capture, and gracefully exit simulation. None of them synthesize to hardware.
| Task | When it prints | Newline? |
|---|---|---|
$display | Immediately when statement executes | Yes |
$write | Immediately when statement executes | No |
$strobe | End of current time step (after NBA updates) | Yes |
$monitor | Whenever any listed signal changes; auto-triggered | Yes |
initial begin $display("Time=%0t a=%b b=%b", $time, a, b); // prints now $write("hex=%h ", data); // no newline $write("dec=%0d\n", data); // manual newline end // $strobe — see settled NBA values always @(posedge clk) $strobe("t=%0t q=%h", $time, q); // prints after q<= updates // $monitor — one active at a time initial $monitor("t=%0t a=%b b=%b sum=%h", $time, a, b, sum);
<=). $display inside the same always block sees the old value; $strobe sees the new settled value at the end of the time step.| Specifier | Format | Example output |
|---|---|---|
%b | Binary | 0101_1100 |
%o | Octal | 134 |
%h / %x | Hexadecimal | 5c |
%d | Decimal (signed, padded) | 92 |
%0d | Decimal (no leading spaces) | 92 |
%s | String | hello |
%t | Time (uses $timeformat) | 100 ns |
%e | Scientific notation | 9.200e+01 |
%f | Fixed-point real | 92.000000 |
\n | Newline (in $write) | — |
\t | Tab | — |
// $timeformat(units, precision, suffix, width) initial $timeformat(-9, 2, " ns", 10); // -9 = nanoseconds, 2 decimal places, " ns" suffix, 10 chars wide initial $display("t=%t", $time); // e.g. "t= 100.00 ns"
| Function | Return type | Notes |
|---|---|---|
$time | 64-bit integer | Scaled to the timescale time unit |
$realtime | real (float) | More precise; needed for fractional time steps |
$stime | 32-bit integer | Truncated; use only for very short simulations |
`timescale 1ns/1ps initial begin #10.5; $display("$time = %0t", $time); // 10 (truncated to ns) $display("$realtime= %f", $realtime); // 10.500000 end
$finish; // exit simulator — use in automated regression $finish(0); // exit quietly (no time/location message) $finish(2); // exit with full diagnostic message $stop; // suspend; drop into interactive debug mode $stop(0); // suspend quietly
$finish at the end of your testbench. Without it the simulator will either hang waiting for events or the simulation will end without clear output. Put it after your pass/fail summary print.These are IEEE 1800-2009 (SystemVerilog) additions, but supported by most Verilog-2001 simulators including Icarus Verilog 11+.
$info ("Simulation started at t=%0t", $time); // informational $warning("Unexpected X on bus at t=%0t", $time); // warning, continues $error ("FAIL: expected %h got %h", exp, got); // error, continues $fatal ("Unrecoverable error — aborting"); // error + $finish
$fatal is like $error followed by $finish — it marks the simulation as failed and exits. In regressions, simulator exit code reflects whether $fatal was called.
// $random returns signed 32-bit data = $random; // any signed 32-bit value data = {$random} % 256; // unsigned 0–255 data = $random % 16; // signed -15 to +15 (watch for negatives) // Seed for reproducibility integer seed = 42; data = $random(seed); // reproducible sequence from seed // Random testbench pattern integer i; initial begin for (i=0; i<100; i++) begin @(posedge clk); data_in <= {$random} % 256; // random 8-bit value addr <= {$random} % 16; // random 4-bit address end end
$random % N can return negative values because $random is signed. Use {$random} % N (wrap in concatenation to make unsigned) or mask: ($random & 32'hFFFF) % N.integer fh; // file handle initial begin fh = $fopen("results.txt", "w"); // open for write if (fh == 0) begin $error("Cannot open results.txt"); $finish; end $fdisplay(fh, "Simulation log — %0t", $time); $fwrite (fh, "data=%h\n", data); $fclose(fh); $finish; end
File mode strings: "r" read, "w" write (truncate), "a" append, "rb"/"wb" binary. $fopen returns 0 on failure — always check it.
$readmemh loads hex values from a text file into a Verilog memory array. Each whitespace-separated token in the file becomes one element.
reg [7:0] rom [0:255]; // 256-byte ROM initial begin $readmemh("program.hex", rom); // fill [0:255] $readmemh("program.hex", rom, 0, 127); // fill only [0:127] $readmemb("init.bin", rom); // binary version end
Example program.hex file (each hex value separated by whitespace or newlines):
// program.hex A5 3C 00 FF 12 AB CD EF 10 20 30 40 50 60 70 80 // @address can skip to an offset @10 DE AD BE EF
@address directive inside the file lets you specify a non-contiguous address. Values before @10 fill indices 0–7; values after fill from index 16 (0x10).initial begin $dumpfile("wave.vcd"); // output VCD filename $dumpvars(0, tb_top); // 0=all levels, tb_top=scope $dumpvars(1, tb_top.dut); // 1=top level of dut only $dumpvars(0, tb_top.dut.clk); // specific signal end // Pause/resume dump for a specific window initial begin #1000; $dumpoff; // stop recording #500; $dumpon; // resume recording $dumpall; // force dump of current state end
Open the resulting wave.vcd in GTKWave (gtkwave wave.vcd) to view signal waveforms. For large simulations, use $dumpoff to record only the window of interest — VCD files grow quickly.
| Function | Description | Example |
|---|---|---|
$clog2(n) | ⌈log₂(n)⌉ — bits needed for n values | $clog2(256)=8, $clog2(200)=8 |
$signed(expr) | Treat expression as signed | $signed(8'hFF) = -1 |
$unsigned(expr) | Treat expression as unsigned | $unsigned(-1) = 255 (8-bit) |
$bits(type) | Bit-width of a type or variable | $bits(reg[7:0]) = 8 |
$high(arr) | Highest index of array dimension | — |
$low(arr) | Lowest index of array dimension | — |
parameter DEPTH = 1024; parameter ADDR_W = $clog2(DEPTH); // = 10 — auto-size the address bus reg [7:0] a = 8'hFF; initial begin $display("unsigned: %0d", a); // 255 $display("signed: %0d", $signed(a)); // -1 end
| System Task / Function | One-line description |
|---|---|
$display(fmt, args) | Print + newline, immediately |
$write(fmt, args) | Print, no newline, immediately |
$strobe(fmt, args) | Print + newline, at end of time step |
$monitor(fmt, args) | Auto-print on any signal change |
$monitoron / $monitoroff | Enable / disable $monitor output |
$time | Current time as 64-bit integer |
$realtime | Current time as real number |
$timeformat(u,p,s,w) | Configure %t display format |
$finish[(n)] | Terminate simulation |
$stop[(n)] | Suspend simulation (interactive debug) |
$info / $warning / $error / $fatal | Severity-tagged messages |
$random[(seed)] | Signed 32-bit pseudo-random integer |
$fopen(name, mode) | Open file, returns handle |
$fclose(handle) | Close file |
$fdisplay(h, fmt, …) | $display to file handle |
$fwrite(h, fmt, …) | $write to file handle |
$readmemh(file, mem) | Load hex file into array |
$readmemb(file, mem) | Load binary file into array |
$dumpfile(name) | Set VCD output file |
$dumpvars(levels, scope) | Enable VCD recording |
$dumpon / $dumpoff | Resume / pause VCD recording |
$dumpall | Force dump of all current values |
$clog2(n) | Ceiling log₂(n) — synthesis-time constant |
$signed(x) / $unsigned(x) | Type cast for arithmetic |