Testbench Anatomy

Interactive guide to self-checking testbenches in Verilog

= You complete this code

Signal Declarations
`timescale 1ns/1ps       // time units
module and_gate_tb;      // no ports!
    reg  a, b;           // inputs (we drive)
    wire y;              // output (we observe)
    wire expected;       // correct answer
    integer error_count; // track failures
    ...
endmodule                // end testbench
Key Concept: In testbenches, use reg for signals you assign values to (inputs to UUT), and wire for signals you observe (outputs from UUT).
Data Flow Visualization
Testbench reg a, b wire y wire expected UUT (and_gate) a b y y reg (drives) wire (observes)
Module Instantiation
    and_gate UUT (   // module instance
        .a(a),        // connect port a
        .b(b),        // connect port b
        .y(y)         // connect port y
    );               // end instance
Syntax: module_name instance_name (.port(signal), ...);

Named port connections (.port(signal)) are preferred because they:
  • Make connections explicit and readable
  • Allow ports in any order
  • Prevent ordering bugs
Port Connection Diagram
.a(a) .b(b) .y(y) Testbench a (reg) b (reg) y (wire) UUT (and_gate) .a .b .y input (.port) output (.port)
Hover over code lines to see the corresponding connections light up in the diagram.
The Initial Block
    initial begin              // runs once at t=0
        error_count = 0;        // reset counter
        $display("Testing...");  // print header
        // test vectors here
        // report results here
        $finish;                // end simulation
    end                        // end initial
initial begin...end executes once at simulation start (time 0).

$ = System Task — Built-in simulator commands:
    $display prints to console  |  $finish ends simulation
Execution Timeline
Simulation Time → t=0 Initialize error_count=0 Display Header Test Vectors Results Summary Console Output:
Click boxes above to step through
Applying Test Vectors
    initial begin
        error_count = 0;
        $display("Testing...");

        {a,b}=2'b00; #10; check_output(); // a=0, b=0
        {a,b}=2'b01; #10; check_output(); // a=0, b=1
        {a,b}=2'b10; #10; check_output(); // a=1, b=0
        {a,b}=2'b11; #10; check_output(); // a=1, b=1

        // report results...
        $finish;
    end
# = Delay — Pauses execution for specified time units.
    #10 waits 10 time units for the output to stabilize before checking.

{a, b} is concatenation — sets both inputs in one statement.
Truth Table Progress
a b y (actual) expected Result
00-0-
01-0-
10-0-
11-1-
Click "Step" to apply test vectors one at a time.
Self-Checking Code
assign expected = a & b;      // golden model
task check_output;             // reusable checker
    if (y !== expected) begin  // mismatch?
        $display("FAIL");        // report error
        error_count = error_count + 1; // count it
    end else                    // match!
        $display("PASS");        // report success
endtask                        // end task
Golden Model: assign expected = a & b; computes what y SHOULD be.
Comparator: y !== expected checks for exact match (including X/Z states).
Live Comparison Demo
Inputs: a = 0, b = 0
y (actual)
0
===
expected
0
PASS
error_count = 0