HDL_FINAL - DilipKrishnappa/UVM GitHub Wiki
HDL access routines
UVM provides the backdoor access sub-routines for force/release or read/deposit some vale on any hierarchical path provided in the argument. These functions acts as an interface between SystemVerilog and C code to perform various operations. These functions can not only be used for backdoor accesses, but also for forcing some value in any RTL modules.
Following is a list of API’s(Application programming interface) that are provided by UVM to perform various things. We can directly call these functions from the testbench and provide proper string based path as an input argument. This will automatically invoke the DPI-C(Direct programming interface) code in UVM BCL(Base class library).
They are seven HDL access routine function which are,
1. uvm_hdl_check_path
Checks that the given HDL path exists are not.
import "DPI-C" function int uvm_hdl_check(string path);
In the Example shown below, the uvm_hdl_check_path function will check the given path exist are not in below code the path top.Ripple.A is exist, so it return the uvm_info as path exit, otherwise it will return the else condition.
if(uvm_hdl_check_path("top.Ripple.A")) begin
`uvm_info("checking",$sformatf(" 1.check the path exist top.Ripple.A = %0d",top.Ripple.A),UVM_LOW)
end
else begin
`uvm_info("checking",$sformatf(" 1.The path does not exist top.Ripple.A = %0d",top.Ripple.A),UVM_LOW)
end
2. uvm_hdl_deposit
Sets the given HDL path to the specified value.
import "DPI-C" function int uvm_hdl_deposit(string path, uvm_hdl_data_t value);
The Example shown below, the uvm_hdl_deposit function will set the given HDL path to the specified value, in below code the path uvm_hdl_deposit("top.Ripple.B",2) is set to the specified value 2 it is deposited in the HDL path, otherwise it will return the else condition.
if(uvm_hdl_deposit("top.Ripple.B",2)) begin
`uvm_info("checking",$sformatf(" After Deposit of specified value top.Ripple.B = %0d",top.Ripple.B),UVM_LOW)
end else begin
`uvm_info("checking",$sformatf(" Value is not Deposited to the Specified path top.Ripple.B = %0d",top.Ripple.B),UVM_LOW)
end
3. uvm_hdl_force
Forces the value on the given path.
import "DPI-C" function int uvm_hdl_force(string path, uvm_hdl_data_t value);
force preserves the value on the signal until we explicitly call release. The Example shown below, the uvm_hdl_force function it will force the value on the given path. here the path is uvm_hdl_force("top.Ripple.B",7) it will force value '7' to the path top.Ripple.B. if path does not exist it will return the else statement.
if(uvm_hdl_force("top.Ripple.B",7)) begin
`uvm_info("checking",$sformatf(" Forced value of the specified path top.Ripple.B= %0d",top.Ripple.B),UVM_LOW)
end
else begin
`uvm_info("checking",$sformatf("value is not forced to the specified path top.Ripple.B= %0d",top.Ripple.B),UVM_LOW)
end
4. uvm_hdl_release
Release a value previously set with uvm_hdl_force.
import "DPI-C" function int uvm_hdl_release(string path);
Release used to help come out from the previous set forced value. The Example shown below, the uvm_hdl_release function it will release the previously forced value to the HDL specified path. here the path is uvm_hdl_release("top.Ripple.B") it will release the forced value '7' and take the assigned value of that particular path. if path does not exist it will return the else statement.
if(uvm_hdl_release("top.Ripple.B"))begin
`uvm_info("checking",$sformatf("After release the previous forced value it is able to take other values top.Ripple.B =
%0d",top.Ripple.B),UVM_LOW)
end
else begin
`uvm_info("checking",$sformatf("forced value not released top.Ripple.B = %0d",top.Ripple.B),UVM_LOW)
5. uvm_hdl_read
Gets the value at the given path.
import "DPI-C" function int uvm_hdl_read(string path, output uvm_hdl_data_t value);
Gets the value at the specified path. The Example shown below, the uvm_hdl_read function it will read the value in the specified path and display the value of given path. here the path is uvm_hdl_read("top.Ripple.C0",val) it will read the value in path top.Ripple.C0 and gives the value of that path.
uvm_hdl_read("top.Ripple.c0",val);
`uvm_info("checking",$sformatf(" Reading the value in the specified path top.Ripple.C0 = %0d",val),UVM_LOW)
Example:code snippet:
//-------------------------------------------------------
// module 1-bit full adder
//-------------------------------------------------------
module fulladder(a,b,c,sum,carry);
//-------------------------------------------------------
// Declaration of input and output signals
// of 1-bit full adder
//-------------------------------------------------------
input a;
input b;
input c;
output sum;
output carry;
//continuous assignment statement
assign sum = a^b^c;
assign carry = (a&b) | (b&c) | (c&a);
endmodule:fulladder
//-------------------------------------------------------
//module 4-bit Ripple carry adder using the 1-bit Fulladder
//-------------------------------------------------------
module bit4adder(input [3:0]A,
//-------------------------------------------------------
//Decalration of input and output signals
//of 4-bit Ripple carry adder
//-------------------------------------------------------
input [3:0]B,
input C0,
output [3:0]S,
output C4);
//To connect between two 1-bit full adder
wire C1,C2,C3;
fulladder fa0(.a(A[0]),.b(B[0]),.c(C0),.sum(S[0]),.carry(C1));
fulladder fa1(.a(A[1]),.b(B[1]),.c(C1),.sum(S[1]),.carry(C2));
fulladder fa2(.a(A[2]),.b(B[2]),.c(C2),.sum(S[2]),.carry(C3));
fulladder fa3(.a(A[3]),.b(B[3]),.c(C3),.sum(S[3]),.carry(C4));
endmodule:bit4adder
//Access for class uvm package
import uvm_pkg::*;
//Acess for uvm_macros
`include "uvm_macros.svh"
//-------------------------------------------------------
// Interface module
//-------------------------------------------------------
interface inter();
logic [3:0]A;
logic [3:0]B;
logic C0;
logic [3:0]S;
logic C4;
endinterface
//class test
class test extends uvm_test;
`uvm_component_utils(test)
logic [3:0]val;
function new(string name="test",uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
task run_phase(uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this);
//Check specified HDL path exist
if(uvm_hdl_check_path("top.Ripple.A")) begin
`uvm_info("checking",$sformatf(" 1.check the path exist top.Ripple.intf.A = %0d",top.Ripple.A),UVM_LOW)
end
else begin
`uvm_info("checking",$sformatf(" 1.The path does not exist top.Ripple.A = %0d",top.Ripple.A),UVM_LOW)
end
$display("");
#15;
`uvm_info("checking",$sformatf(" Before Depositing a specified value top.Ripple.B = %0d",top.Ripple.B),UVM_LOW)
//set the given HDL path to a specified value
if(uvm_hdl_deposit("top.Ripple.B",2)) begin
`uvm_info("checking",$sformatf(" After Deposit of specified value top.Ripple.B = %0d",top.Ripple.B),UVM_LOW)
end else begin
`uvm_info("checking",$sformatf(" Value is not Deposited to the Specified path top.Ripple.B = %0d",top.Ripple.B),UVM_LOW)
end
$display("");
#15; //30ns
//get the value in the given path
uvm_hdl_read("top.Ripple.B",val);
`uvm_info("checking",$sformatf(" Reading the value in the specified path top.Ripple.B = %0d",val),UVM_LOW)
$display("");
#15; //45ns
//force the value to the specified path
if(uvm_hdl_force("top.Ripple.B",7)) begin
`uvm_info("checking",$sformatf(" Forced value of the specified path top.Ripple.B= %0d",top.Ripple.B),UVM_LOW)
end
else begin
`uvm_info("checking",$sformatf("value is not forced to the specified path top.Ripple.B= %0d",top.Ripple.B),UVM_LOW)
end
$display("");
#15; //60ns
//Release the value previous set by uvm_hdl_force
if(uvm_hdl_release("top.Ripple.B"))begin
`uvm_info("checking",$sformatf("After release the previous forced value it is able to take other values top.Ripple.B = %0d",top.Ripple.B),UVM_LOW)
end
else begin
`uvm_info("checking",$sformatf("forced value not released top.Ripple.B = %0d",top.Ripple.B),UVM_LOW)
end
$display("");
#5; //65ns
//Read the value from specified HDL path
uvm_hdl_read("top.Ripple.A",val);
`uvm_info("checking",$sformatf(" Reading the value in the specified path top.Ripple.A = %0d",val),UVM_LOW)
$display("");
#75 $finish;
phase.drop_objection(this);
endtask
endclass
//-------------------------------------------------------
// Top Module
//-------------------------------------------------------
//run the test
initial run_test("test");
//instantiation of interface
inter intf();
//instatiation of 4bit Ripple carry adder
bit4adder Ripple(.A(intf.A), .B(intf.B), .C0(intf.C0), .S(intf.S), .C4(intf.C4));
initial begin
intf.A = 6;
intf.B = 5;
intf.C0 = 1;
#15
intf.A=9;
intf.C0=1;
#15 //30ns
intf.A = 1;
intf.B = 3;
#15; //45ns
intf.A =4;
#10; //55ns
intf.B=5;
intf.A=2;
#10; //65ns
intf.B =3;
intf.A=1;
#1; //66ns
`uvm_info("checking","Ending Simualtion now........",UVM_LOW)
end
endmodule:top
Transcript output:
Initially at 0ns it will check the path exist are not. if path exist it will give the path value top.Ripple.A = 6. Now at #10ns, checking the value of B is 5, After at 15ns the value of 'B' is deposited using function uvm_hdl_deposit this function deposit the value, which we are given in the path uvm_hdl_deposit("top.Ripple.B",2). At 30ns we use a function uvm_hdl_read("top.Ripple.B") it is to read the value of the path so it 30ns it will read value of 'B' is 2. then At 45ns, we force the value by using the function uvm_hdl_force("top.Ripple.B", 7) it will force the value '7' to the path it will remain same through the path until we call for function uvm_hdl_release("top.Ripple.B").At 60ns, It will release previous value which we are forced. then the variable 'B' updated with the other values which we are passing through top module, then at 65ns, we use the function uvm_hdl_read("top.Ripple.A") to read the value of the path.
Fig: Trancript output
output waveform
Fig:output waveform of 4-bit Ripple carry adder