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.

hdl_7_11

                           Fig: Trancript output

output waveform

hdl_7

                            Fig:output waveform of 4-bit Ripple carry adder