SystemVerilog provides support for parallel or concurrent threads through fork join
construct. Multiple procedural blocks can be spawned off at the same time using fork
and join
. There are variations to fork join
that allow the main thread to continue executing rest of the statements based on when child threads finish.
Syntax
fork
// Thread 1
// Thread 2
// ...
// Thread 3
join
Simulation is typically ended by calling $finish
system task in traditional SystemVerilog testbenches. UVM has introduced many phases that aid in a very structural methodology for building testbench environments and applying stimulus. These phases are grouped into three main categories - build and connect, run-time and clean up.
Build-connect and clean-up phases are executed in zero time and do not cause any advancement in simulation. However, run-time phases consume simulation time. Each phase ends when there are no more pending objections for that phase. The end of test happens when all its time consuming phases come to an end.
As you already know, testbench components step through each phase during the course of a simulation and execution does not move to the next phase unless all components in the current phase are done. The way this is achieved is through phase objections. Simply put, each component raises a flag as soon as they enter the phase which indicates that they are currently busy with something and the flag is returned as soon as the component is done with what it was doing. So unless all components have indicated that they are finished, by dropping the flag, the current phase will continue. A more formal word for the flag is an objection.
UVM testbench components which uses an objection mechanism share a counter between them. The method raise_objection
increments the count and drop_objection
decrements the count. Once the value of the shared counter reaches zero from a higher value, it indicates that all participating components have dropped their objections and the phase is ready to end.
phase_ready_to_end
SystemVerilog covergroup
is a user-defined type that encapsulates the specification of a coverage model. They can be defined once and instantiated muliple times at different places via the new
function.
covergroup
can be defined in either a package, module, program, interface, or class and usually encapsulates the following information:
- A set of coverage points
- Cross coverage between coverage points
- An event that defines when the covergroup is sampled
- Other options to configure coverage object