Verilog Testbench Basics

Testbenches are non-synthesizable modules that provide stimulus to your design and check its responses during simulation.

Basic Testbench Structure

Complete Counter Testbench
`timescale 1ns/1ps
module counter_tb;
    // Testbench signals (no ports!)
    reg        clk;
    reg        rst_n;
    reg        enable;
    wire [7:0] count;
    // Instantiate DUT (Device Under Test)
    counter #(.WIDTH(8)) u_dut (
        .clk    (clk),
        .rst_n  (rst_n),
        .enable (enable),
        .count  (count)
    );
    // Clock generation: 100MHz (10ns period)
    initial clk = 0;
    always #5 clk = ~clk;
    // Stimulus
    initial begin
        // Initialize
        rst_n  = 0;
        enable = 0;
        // Apply reset
        #20 rst_n = 1;
        // Enable counting
        #10 enable = 1;
        // Let it run
        #200;
        // Disable and check
        enable = 0;
        #20;
        // End simulation
        $display("Test completed. Final count = %d", count);
        $finish;
    end
    // Monitor (optional)
    initial begin
        $monitor("Time=%0t rst_n=%b en=%b count=%d",
                 $time, rst_n, enable, count);
    end
endmodule

Clock Generation Patterns

Various Clock Styles
// Method 1: always block
reg clk;
initial clk = 0;
always #5 clk = ~clk;  // 10ns period
// Method 2: forever loop
initial begin
    clk = 0;
    forever #5 clk = ~clk;
end
// Method 3: Parameterized
localparam CLK_PERIOD = 10;
initial clk = 0;
always #(CLK_PERIOD/2) clk = ~clk;
// Multiple clocks
reg clk_100, clk_50;
initial begin
    clk_100 = 0;
    clk_50  = 0;
end
always #5  clk_100 = ~clk_100;  // 100MHz
always #10 clk_50  = ~clk_50;   // 50MHz

Self-Checking Testbench

Automatic Pass/Fail
module adder_tb;
    reg [7:0] a, b;
    wire [8:0] sum;
    integer errors = 0;
    adder u_dut (.a(a), .b(b), .sum(sum));
    initial begin
        // Test cases
        a = 8'd10; b = 8'd20; #10;
        check_result(30);
        a = 8'd255; b = 8'd1; #10;
        check_result(256);
        a = 8'd0; b = 8'd0; #10;
        check_result(0);
        // Report
        if (errors == 0)
            $display("TEST PASSED!");
        else
            $display("TEST FAILED: %d errors", errors);
        $finish;
    end
    task check_result;
        input [8:0] expected;
        begin
            if (sum !== expected) begin
                $display("ERROR: a=%d b=%d sum=%d expected=%d",
                         a, b, sum, expected);
                errors = errors + 1;
            end
        end
    endtask
endmodule

Common Interview Questions

  1. Why does a testbench have no ports?

    Testbenches are the top-level module in simulation. They connect to nothing external – they drive the DUT directly.

  2. What is `timescale?

    Defines time unit and precision. `timescale 1ns/1ps means #1 = 1ns, and time can be measured to 1ps precision.

  3. How do you end a simulation?

    Use $finish to end immediately or $stop to pause (allowing resume in some simulators).