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.