Today we continue with the Logic Design series on SystemVerilog in order to talk about the Program Block.
So, without further ado, let's get straight into it!
Design and Testbench
In Verilog, both the design and the testbench are defined as a module. Each such module can contain other modules (hierarchical design), nets, variables, procedural blocks etc. in order to describe the hardware functionality.
In order to separate the design and testbench, SystemVerilog introduces the program block. This block is all about verification and created in a way that allows it to be more effective and re-usable.
Program Block
A program block is enclosed within the program and endprogram keywords, and has the following syntax:
program<name>[port_list];...endprogram
So, it's quite similar to a module.
Reactive Region of Simulation Cycle
One of the main differences of modules and program blocks is that program blocks execute just before the simulation time advances. This region of the simulation cycle is known as the reactive region, allowing all of the design statements to execute correctly, and giving the testbench / program access to the correct updated values. In other words, the race conditions between the design and testbench are avoided.
Allowed Constructs
Program blocks are very similar to modules. They can contain ports, interfaces, and initial, final blocks, but not always blocks. That way the clocking of the design is used when driving or sampling signals.
Additionally, tasks and functions defined within modules (the design) can be called from within a program block. But, tasks and functions defined within a program block cannot be called from within modules (the design).
When the number of ports is large, interfaces should be used in order to connect with the design (DUT). This improves the readability by quite a bit.
Finally, the $exit control task should be added to the end of the testbench / program (at the end of some initial block) in order to close down all "spawned" threads.