In this post we will set up a minimal example of a VHDL verification environment using the UVVM Verification Framework. We will discuss what the UVVM Verification Framework is, how it is structured, and which files are needed to run a minimal simulation.
Contents
What is the UVVM Verification Framework?
The UVVM Verification Framework provides the infrastructure for creating verification environments that use UVVM verification IP components, also known as VHDL Verification Components, VVCs.
The UVVM Verification Framework includes mechanisms for passing commands and data through different verification components. Its main advantage with respect to the UVVM Light Bus Functional Models, which we explored in previous posts, is that the Verification Framework supports non-blocking calls to the VVCs, making it easier to create complex test cases using several interfaces in a single VHDL process.
What is the structure of a UVVM Verification Environment?
If we’re using readily available VVCs, we only need one or two files to setup a verification environment.
The two-file solution is used in the UVVM examples, and consists of a Test Harness and a Testbench. The Test Harness instantiates the Design Under Test (DUT) and the VVCs, and connects the signals between them. The Testbench instantiates the Test Harness, initializes the environment, and runs the test cases by sending commands to the VVCs and evaluating their response.
In the one-file solution there is no Test Harness. The Testbench instantiates the DUT and the VVCs, and it also generates the stimuli and validates the DUT output.
Each solution has its strengths and weaknesses. Assuming that only UVVM verification components are used to interact with the DUT, the two-file solution keeps the component instantiation and signal connections separate from the stimuli and checks, which makes the Testbench file smaller and easier to maintain.
On the other hand, the one-file solution produces a longer file that is more difficult to read and maintain. However, this solution makes it easier to interact with the DUT using something other than UVVM verification components.
The example in this post uses the two-file solution.
Hello UVVM Framework World
Let’s start with the Test Harness. Because this is a minimalist example we will include neither a DUT nor VVCs, we’ll just set up the infrastructure so that they can be added later.
The Test Harness instantiates the UVVM Engine, whose job is to initialise the verification environment.
-- Test harness entity
entity uvvm_environment_th is
end entity uvvm_environment_th;
-- Test harness architecture
architecture behavioral of uvvm_environment_th is
begin
-- Instantiate the concurrent procedure that initializes the UVVM
ti_uvvm_engine_inst : entity uvvm_vvc_framework.ti_uvvm_engine;
end behavioral;
The Testbench instantiates the Test Harness and waits for the initialisation of the UVVM environment to complete. After that the VVC Framework is ready to start running tests.
This minimal testcase doesn’t generate any stimuli, it simply uses a few logging commands to confirm that the verification environment works as expected.
-- Test bench entity
entity uvvm_environment_tb is
end entity uvvm_environment_tb;
-- Test bench architecture
architecture behavioral of uvvm_environment_tb is
begin
-- Instantiate the test harness
uvvm_environment_th_inst : entity work.uvvm_environment_th;
-- Test process
test_p : process
begin
await_uvvm_initialization(VOID); -- Wait for UVVM to finish initialization
log(ID_LOG_HDR, "SIMULATION STARTED", C_SCOPE);
report_alert_counters(FINAL);
log(ID_LOG_HDR, "SIMULATION COMPLETED", C_SCOPE);
std.env.stop; -- Finish the simulation
wait;
end process test_p;
end architecture behavioral;
After running the simulation we can see that our custom messages are printed, along with a summary of the alerts logged while running the test.
Cheers,
Isaac