SystemVerilog learning (3)-UVM routines

1. UVM architecture analysis

The architecture of UVM, the calling relationship between objects, the direction of data transmission (arrow) and the way of data transmission (marked on the arrow) are shown in the figure below. The part
we need to modify when testing other modules is the part marked in blue and yellow. The specific modification is introduced below.
The other parts can follow the program template without modification.
Insert picture description here
The tree structure of UVM is shown in the figure below, where each node represents an instance (object) of a class.
The uvm_root class comes with the UVM structure and does not need to be created.
Insert picture description here

Each class in UVM contains several main internal functions:
new function: used for object initialization, equivalent to the constructor in C++.
Build_phase function: used to perform some initial operations and build the relationship between objects. It runs automatically after the object is initialized and does not need to be called.
main_phase function: The main tasks are executed in main_phase. When the entire program starts to run automatically, no need to call.
connect_phase function: used for connection, analysis_export (sending end) and blocking_get_export (receiving end) of fifo between different instances. When the whole program starts to run automatically, there is no need to call.

Two, UVM routines

The following implements a UVM routine. When using UVM later, you can refer to the routine to modify it.
The download link of the example :
https://download.csdn.net/download/meng1506789/13385880

Three, DUT program

The function of the DUT is to use the register to calculate the sum of two 8-bit numbers, and output the 9-bit result and out_en.
Insert picture description here

Four, UVM program

(1) UVM basic element my_if

clk and rst_n are used as input signals, and other data signals are described by logic.
The pin configuration should correspond to the one in the DUT.
Insert picture description here

(2) UVM basic element my_transaction

It is the format of the " data packet " we want to transmit when the program is running . Input data (a, b) and output data (p) are defined in this class. All are defined as rand type, the purpose is to be initialized to random data when driven by the driver.
Insert picture description here

(3) my_driver class

The program is more complicated at first, but we only need to consider the writing of the main_phase and drive_one_pkt functions. The other content is necessary in the UVM architecture and does not need to be changed.
At the beginning of the class, vif is defined for interface connection and communication with the DUT.
Insert picture description here

The main_phase function writes the data-driven operations we need to do on the DUT, which can be changed according to requirements.
Among them @(posedge vif.clk); statement is used to detect a rising edge of vif.clk.
The content before while(1) can be regarded as the initialization of data, and the content executed in while(1) is the main data driver. Among them, seq_item_port.get_next_item(req); and seq_item_port.item_done(); are also included in UVM.
Insert picture description here

The main data-driven program is written in the drive_one_pkt function. After each rising edge of vif.clk, the random data from the data packet tr is sent to vif, so that vif drives the operation of the DUT.
Insert picture description here

The uvm_info macro appears here, we can use this function to output some status information.
This macro is functional and powerful, and its output information automatically includes: (corresponding to the red box in the figure below)
how many lines of which module the information comes from, and at what
time in the simulation,
which specific object is output from the UVM tree
Insert picture description here

(4) my_monitor class

Among them, we need to consider the main_phase and collect_one_pkt functions.
The main_phase function is used to continuously collect data packets tr, and send the data packets tr to my_model or my_scoreboard through the fifo channel.
Insert picture description here

The collect_one_pkt function is used to collect data. The data received in vif is packaged as tr, and the data package tr is sent to my_model or my_scoreboard through main_phase.
Insert picture description here

In the program, I defined an IO_TYPE variable to determine whether the object is an input monitor or an output monitor when the object is initialized, so as to confirm the capture of the vif data on the input or the vif data on the output. (The value of this variable is set in my_agent.sv during initialization)

(5) my_model class

That is, the reference model, only the main_phase function needs to be paid attention to in this class.
The function of the function: get the data packet tr sent from the input monitor through port.get(tr);, let the data packet tr flow through the golden of the high-level language, and generate the reference output tr_send.p. Finally, the expected data packet tr_send is sent to my_scoreboard.
Insert picture description here

The golden class and add function are defined in the golden.sv file. Note that the golden.sv file should be included at the beginning of the my_model.sv file:
Insert picture description here

The functions in the golden.sv file are as follows: (to realize the addition function, it must be consistent with the function of the DUT )
Insert picture description here

(6) my_scoreboard class

Among them, we need to pay attention to the main_phase function.
The function of the function: two while(1) threads are formed through fork and join .

The first thread continuously captures the expected data packet get_expect sent from my_model and stores it in the expect_queue queue.
The second thread captures the actual output data packet get_actual from the DUT, and then pops the expected data packet tmp_tran corresponding in order from the expect_queue queue, and compares get_actual.p and tmp_tran.p to obtain the comparison result.
Insert picture description here

If there is a comparison error, the uvm_error macro will output an error message. And UVM will automatically record the number of times the uvm_error macro is run, and display it in the final report.

(7) my_case0.sv file

Two classes are defined in this file. We only need to pay attention to the case0_sequence class, which can control the number of random data injections into the DUT by controlling the number of repeats.
Insert picture description here

(8) top_tb.sv file

This file is the top file of the simulation environment, instantiating the interface, instantiating the DUT module, clock and reset control, generating waveform files, etc.
After the above steps are configured, you need to instantiate the DUT in the top_tb.sv file.

Five, run the program

The running mode of the program is in the ./sim/run_tc.sh script, where +UVM_TESTNAME can select the my_casen to run

Open the terminal in the sim folder and directly source run_tc.sh.
Insert picture description here

After running, generate top_tb.vcd and run.log
Insert picture description here
All Compare are SUCCESSFULLY and finally output TEST CASE PASSED

Guess you like

Origin blog.csdn.net/meng1506789/article/details/110632261