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
`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;
endRule 2: Self-Checking with Assertions
Every testbench must automatically check results. Never rely on visual waveform inspection.
// 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
endRule 3: Test Scenario Organization
Organize tests into named tasks for clarity:
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
endtaskRule 4: Random Stimulus Generation
Use constrained random for corner-case exploration:
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
endRule 5: VCD / Waveform Dump
Generate waveform for debug but keep it optional:
initial begin
if ($test$plusargs("DUMP_VCD")) begin
$dumpfile("tb_top.vcd");
$dumpvars(0, tb_top);
end
endRule 6: Final Pass/Fail Report
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
endRule 7: Timeout to Prevent Infinite Simulation
initial begin
#(TIMEOUT_NS);
$error("TIMEOUT: simulation exceeded %0d ns", TIMEOUT_NS);
$finish;
endComplete Testbench Template
`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
endmoduleInteraction with Other Skills
verilog-module: The DUT being testedfifo-generator: Specialized testbench for FIFO corner casesfsm-generator: Testbench that covers all state transitionsassertion-writer: Add formal assertions to the testbenchrtl-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.