A self-checking testbench is a type of testbench that is designed to automatically check the correctness of a digital design's output, without the need for manual intervention. In a self-checking testbench, the testbench itself verifies the design's output, rather than relying on a separate verification tool or manual inspection. Here's an example of a simple self-checking testbench:
module tb();
// Declare inputs and outputs
logic clk;
logic rst;
logic [7:0] data_in;
logic [7:0] data_out;
// Clock generator
always #(5ns) clk = ~clk;
// Instantiate DUT
dut u_dut(clk, rst, data_in, data_out);
// Test data
int test_data[4] = {0, 1, 2, 3};
// Test loop
initial begin
// Reset DUT
rst = 1;
@(posedge clk);
rst = 0;
// Loop over test data
for (int i = 0; i < 4; i++) begin
// Set input data
data_in = test_data[i];
// Wait for output data
repeat (10) @(posedge clk);
// Check output data
if (data_out !== (test_data[i] + 1)) begin
$error("Incorrect output data");
end
end
// Finish test
$display("Test passed");
$finish;
end
endmodule
In this example, the testbench sets the input data to a predefined set of values, and then waits for the DUT to produce output data. The testbench then checks the output data to ensure that it matches the expected output (in this case, the input data plus one). If the output data does not match the expected output, an error is generated using the built-in $error
function. Once all test cases have been run, the testbench prints a message indicating that the test has passed (assuming no errors were generated) and finishes.
Self-checking testbenches can be useful for automating the verification process and reducing the risk of human error. However, they can also be more complex to design and may require additional verification code to be written, which can increase the overall design and verification time.
Most modern testbenches and testcases are self-checking in nature so that they can be used in a random constrained environment and regressed over many days.