Interactive guide to self-checking testbenches in Verilog
= You complete this code
`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
reg for signals you assign values to (inputs to UUT),
and wire for signals you observe (outputs from UUT).
and_gate UUT ( // module instance .a(a), // connect port a .b(b), // connect port b .y(y) // connect port y ); // end instance
module_name instance_name (.port(signal), ...);.port(signal)) are preferred because they:
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
$display prints to console | $finish ends simulation
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
#10 waits 10 time units for the output to stabilize before checking.| a | b | y (actual) | expected | Result |
|---|---|---|---|---|
| 0 | 0 | - | 0 | - |
| 0 | 1 | - | 0 | - |
| 1 | 0 | - | 0 | - |
| 1 | 1 | - | 1 | - |
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
assign expected = a & b; computes what y SHOULD be.y !== expected checks for exact match (including X/Z states).