The linear testbench approach expects the test writer to create combinations of input stimuli. The same stimuli can be applied by also reading a file
However, a file I/O based testbench is a type of verification testbench in which the test stimuli and expected results are read from files rather than being generated dynamically. This approach can be useful for testing complex designs where generating input stimuli and expected results programmatically may be time-consuming or impractical. Here is an example of a file I/O based testbench for a simple digital circuit that performs a bitwise AND operation:
A verification testbench is a hardware verification language (HVL) code written in Verilog or SystemVerilog that is used to verify the functionality of a digital design. The testbench is a simulation environment that generates stimulus for the design under test (DUT) and checks the response of the DUT against expected results. The testbench may also include functional coverage and assertions to ensure that all functional scenarios have been exercised and the DUT behaves as expected. The testbench typically consists of three main parts: the testbench framework, the stimulus generator, and the response checker.
Evolution
Since the advent of Verilog in the 1980s, testbenches have undergone significant evolution to become more powerful, automated, and efficient.
Constrained-random testbenches: In the 1990s, constraint-random testbenches were introduced as a way to generate input stimuli and testcases automatically. This allowed designers to test their designs more thoroughly and to explore a wider range of input scenarios than was possible with linear testbenches.
The ASIC Design Flow consists of several steps, including design specification, design entry, design synthesis, design verification, physical design, and design sign-off.
Design verification (DV) typically refers to the pre-silicon effort of functional validation of the design using simulation tools.
Verilog has system tasks and functions that can open files, output values into files, read values from files and load into other variables and close files.
Opening and closing files
module tb;
// Declare a variable to store the file handler
integer fd;
initial begin
// Open a new file by the name "my_file.txt"
// with "write" permissions, and store the file
// handler pointer in variable "fd"
fd = $fopen("my_file.txt", "w");
// Close the file handle pointed to by "fd"
$fclose(fd);
end
endmodule
Most programming languages have a characteristic feature called scope which defines the visibility of certain sections of code to variables and methods. The scope defines a namespace to avoid collision between different object names within the same namespace.
Verilog defines a new scope for modules, functions, tasks, named blocks and generate blocks.
module tb;
reg signal;
// Another variable cannot be declared with
// an already existing name in the same scope
reg signal;
// However, the name 'signal' can be reused inside
// a task because it belongs to a different scope.
task display();
reg signal = 1;
$display("signal = %0b", signal);
endtask
endmodule
An identifier, like a signal name, can be used to declare only one type of item in a given scope. This means that two variables of different or same data types cannot have the same name, or a task and a variable of the same name, or even a net and gate instance with the same name in the same scope.