EN
← Back to Skills
IntermediateVerification

Testbench Generator

Generate self-checking Verilog/SystemVerilog testbenches with clock/reset generation, constrained-random stimulus, expected-value checking, pass/fail reporting, and VCD waveform dumping.

💡 Copy this Skill description into your AI Agent's system prompt (Cursor, Claude Code, Copilot), then describe your design needs. The Agent will generate code following the rules defined in this Skill. Download the .md file at the bottom of this page.


name: testbench-simple description: > Generate a complete, self-checking Verilog/SystemVerilog testbench for a given module under test (DUT). The testbench includes clock generation, reset sequence, constrained-random stimulus generation, expected-value checking with automatic pass/fail reporting, and coverage of all specified test scenarios. Suitable for module-level verification in any SystemVerilog-compatible simulator (VCS, Questa, Xcelium, Vivado XSim, Icarus Verilog, Verilator). category: verification level: intermediate

Purpose

Generate a testbench that thoroughly exercises a DUT, automatically checks results, and reports pass/fail without manual waveform inspection. The testbench must be self-contained: compile the DUT + testbench, run the simulation, and read the PASS/FAIL from the log.

Input Specification

Required

  • DUT module name and port list (or the complete DUT source)
  • Test scenarios: what normal and corner-case behavior to verify

Optional

  • Clock frequency (default: 100MHz)
  • Reset polarity and duration (default: active-low, 10 cycles)
  • Number of random test vectors (default: 100)
  • Coverage goals: toggle, functional, assertion
  • Waveform dump format: VCD (default), FSDB, WLF, none

Core Design Rules

Rule 1: Clock and Reset Generation

systemverilog
`timescale 1ns / 1ps

module tb_top;

    // Parameters
    parameter CLK_PERIOD = 10;  // 100MHz
    parameter RESET_CYCLES = 10;

    // DUT signals
    logic clk;
    logic rst_n;
    // ... DUT ports ...

    // Clock generation
    initial clk = 1'b0;
    always #(CLK_PERIOD/2) clk = ~clk;

    // Reset sequence
    initial begin
        rst_n = 1'b0;
        repeat (RESET_CYCLES) @(posedge clk);
        rst_n = 1'b1;
    end

Rule 2: Self-Checking with Assertions

Every testbench must automatically check results. Never rely on visual waveform inspection.

systemverilog
    // Expected value tracking
    logic [WIDTH-1:0] expected_value;

    // Checker: compare DUT output against expected
    always_ff @(posedge clk) begin
        if (!rst_n) begin
            expected_value <= '0;
        end else begin
            // Update expected value based on DUT behavior model
            if (en) expected_value <= expected_value + 1;

            // Check after reset release
            if (check_enable) begin
                if (dut_output !== expected_value) begin
                    $error("[%0t] MISMATCH: got %0d, expected %0d",
                           $time, dut_output, expected_value);
                    error_count++;
                end
            end
        end
    end

Rule 3: Test Scenario Organization

Organize tests into named tasks for clarity:

systemverilog
    task test_basic_write();
        $display("[%0t] --- Test: Basic Write ---", $time);
        // Setup
        @(posedge clk);
        wr_en   = 1'b1;
        wr_data = 8'hA5;
        @(posedge clk);
        wr_en   = 1'b0;
        // Check
        repeat (2) @(posedge clk);  // wait for pipeline
        if (rd_data !== 8'hA5) begin
            $error("Basic write failed");
            error_count++;
        end
    endtask

    task test_empty_flag();
        $display("[%0t] --- Test: Empty Flag ---", $time);
        if (!empty) begin
            $error("Empty flag not set after reset");
            error_count++;
        end
    endtask

Rule 4: Random Stimulus Generation

Use constrained random for corner-case exploration:

systemverilog
    logic [WIDTH-1:0] random_data;

    initial begin
        // Wait for reset
        wait(rst_n);
        repeat (2) @(posedge clk);

        // Random test loop
        for (int i = 0; i < NUM_RANDOM_TESTS; i++) begin
            random_data = $urandom_range(0, (1 << WIDTH) - 1);
            wr_en       = $urandom_range(0, 1);
            rd_en       = $urandom_range(0, 1);
            wr_data     = random_data;
            @(posedge clk);
        end
    end

Rule 5: VCD / Waveform Dump

Generate waveform for debug but keep it optional:

systemverilog
    initial begin
        if ($test$plusargs("DUMP_VCD")) begin
            $dumpfile("tb_top.vcd");
            $dumpvars(0, tb_top);
        end
    end

Rule 6: Final Pass/Fail Report

systemverilog
    integer error_count = 0;

    final begin
        if (error_count == 0) begin
            $display("========================================");
            $display("  SIMULATION PASSED — 0 errors");
            $display("========================================");
        end else begin
            $display("========================================");
            $display("  SIMULATION FAILED — %0d errors", error_count);
            $display("========================================");
        end
    end

Rule 7: Timeout to Prevent Infinite Simulation

systemverilog
    initial begin
        #(TIMEOUT_NS);
        $error("TIMEOUT: simulation exceeded %0d ns", TIMEOUT_NS);
        $finish;
    end

Complete Testbench Template

systemverilog
`timescale 1ns / 1ps

module tb_top;

    // === Parameters ===
    parameter CLK_PERIOD   = 10;    // 100MHz
    parameter RESET_CYCLES = 10;
    parameter NUM_TESTS    = 100;
    parameter TIMEOUT_NS   = 1000000;  // 1ms

    // === Signals ===
    logic clk;
    logic rst_n;
    // ... DUT ports (match DUT exactly) ...

    // === DUT Instantiation ===
    dut_module #(
        .PARAM1(VALUE1),
        .PARAM2(VALUE2)
    ) u_dut (
        .clk    (clk),
        .rst_n  (rst_n),
        // ... port connections ...
    );

    // === Clock ===
    initial clk = 1'b0;
    always #(CLK_PERIOD/2) clk = ~clk;

    // === Reset ===
    initial begin
        rst_n = 1'b0;
        repeat (RESET_CYCLES) @(posedge clk);
        rst_n = 1'b1;
    end

    // === Checker Logic ===
    integer error_count = 0;
    // ... expected value tracking and comparison ...

    // === Test Scenarios ===
    initial begin
        // Wait for reset release
        wait(rst_n);
        repeat (2) @(posedge clk);

        // Run test sequence
        test_reset_state();
        test_basic_operation();
        test_random_stimulus(NUM_TESTS);
        test_corner_cases();

        // Report
        #100;
        if (error_count == 0)
            $display("PASS");
        else
            $error("FAIL: %0d errors", error_count);
        $finish;
    end

    // === Timeout ===
    initial begin
        #TIMEOUT_NS;
        $error("TIMEOUT");
        $finish;
    end

    // === Waveform ===
    initial begin
        if ($test$plusargs("DUMP_VCD")) begin
            $dumpfile("tb_top.vcd");
            $dumpvars(0, tb_top);
        end
    end

endmodule

Interaction with Other Skills

  • verilog-module: The DUT being tested
  • fifo-generator: Specialized testbench for FIFO corner cases
  • fsm-generator: Testbench that covers all state transitions
  • assertion-writer: Add formal assertions to the testbench
  • rtl-reviewer: Verify testbench quality and coverage

Disclaimer

This skill is provided "as is" for reference and educational purposes only. Code generated using this skill should be independently reviewed and verified before use in any production design, tape-out, or safety-critical application. The author(s) and ICHDL assume no liability for any errors, omissions, or damages arising from the use of this skill or any code generated with it.

Usage Rights

You are free to use, modify, and distribute this skill for personal or commercial purposes. Attribution to ICHDL (ichdl.com) is appreciated but not required. Redistribution of this skill in substantially unmodified form must retain this notice.

Download this Skill as .md file

Copy into your AI Agent's system prompt to activate this Skill.