UVM: How to Pass a Virtual Interface from Testbentch to Environment

Connecting a verification environment with a DUT is not a straight forward task for someone new to UVM and the purpose of this post is to give a quick tutorial on how to do it fast and correctly.

Let’s assume that we have a verification environment with two APB agents like in the picture below.


I’ll describe two methods:

  • quick way which can be used in most of the cases
  • an advanced way suitable for scenarios in which you have two or more interfaces of the same type



The Quick Way

Step #1: declare the interfaces in the testbench

An interface is instantiated just as any other verilog module

1
2
3
4
5

//instance of the APB interface used by APB agent agent0
cfs_apb_if intf0(.pclk(clk));

//instance of the APB interface used by APB agent agent1
cfs_apb_if intf1(.pclk(clk));

Step #2: put the interfaces in the database

UVM comes with a database which you can use to save some information for future use. In our case, we can use it from the testbench to save the virtual interfaces and use them when the two APB agents are created.

1
2
3
4
5
6
7

initial begin
   //put in the database the interface used by APB agent agent0
   uvm_config_db#(virtual cfs_apb_if)::set(null, "uvm_test_top.env.agent0*", "VIRTUAL_INTERFACE", intf0);

   //put in the database the interface used by APB agent agent1
   uvm_config_db#(virtual cfs_apb_if)::set(null, "uvm_test_top.env.agent1*", "VIRTUAL_INTERFACE", intf1);
end

There are a few things you need to pay attention to here:

  • the parameter of uvm_config_db is a virtual interface (virtual cfs_apb_if), NOT the interface (cfs_apb_if)
  • the second argument of the set() function is the full name of the agent which must get the interface.
    This full name is build by concatenating the names of components not the names of the “physical” SystemVerilog variables:

    1

    apb_agent_0 = cfs_apb_agent::type_id::create("agent0", this);

    In this example “apb_agent0” is the name of the “physical” SystemVerilog variable while “agent0” is the name of the component.

  • The third argument of the set() function is like a “key” which the agents will use to get from the database the virtual interface. The same name must be used on Step#3

Step #3: get the interfaces from the database

The hardest part was already done by the set() function. All we have to do in the agent class is to get the virtual interface:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

class cfs_apb_agent extends uvm_component;
   
   //pointer to the interface
   virtual cfs_apb_if vif;
   
   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
     
      if(uvm_config_db::#(virtual cfs_apb_if)::get(this, "", "VIRTUAL_INTERFACE", vif) == 0) begin
         `uvm_fatal("ALGORITHM_ISSUE", "Could not get from the database the virtual interface for the APB agent")
      end
   endfunction

endclass

The most important thing here is the third argument of the get() function – it must be the same key used by the set() function in Step#2.

That’s it!

The “Be Prepared For Future Changes” Way

The steps above work fine in most of the cases. But what if our design will change from two APB interfaces to four, or ten, or one hundred? Copy-Paste won’t do.
Let’s see how we can change the code to work with a generic number of interfaces.

Step #1: put in the database the number of APB interfaces

Ideally we should change only in one place the number of interfaces used by the DUT. One option is to have a define in the testbench which we can pass to the environment via the database.

1
2
3
4
5
6

//define the number of APB interfaces
`define NUM_OF_APB_INTF 4

initial begin
   uvm_config_db#(integer)::set(null, "uvm_test_top.env*", "NUM_OF_APB_INTF", `NUM_OF_APB_INTF);
end

Step #2: use “generate” block to declare interfaces and put them in the database

1
2
3
4
5
6
7
8
9
10
11
12

generate
   for(genvar idx = 0; idx < `NUM_OF_APB_INTF; idx++) begin
      //instance of the APB interface used by APB agent with index idx
      cfs_apb_if intf(.pclk(clk));

      initial begin
         //put in the database the interface used by APB agent with index idx
         uvm_config_db#(virtual cfs_apb_if)::set(null,
            $sformatf("uvm_test_top.env.agent[%d]*", idx), "VIRTUAL_INTERFACE", intf);
      end
   end
endgenerate

You will probably need to do some extra work here for connecting each interface with the DUT, but in most of the cases you will probably get away with some assings based on idx.

Step #3: instantiate the APB agents based on the number of interfaces

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

class cfs_env extends uvm_component;

   cfs_apb_agent agents[$];

   virtual function void build_phase(uvm_phase phase);
      integer num_of_agents;
     
      if(uvm_config_db::#(integer)::get(this, "", "NUM_OF_APB_INTF", num_of_agents) == 0) begin
         `uvm_fatal("ALGORITHM_ISSUE", "Could not get from the database the number of APB interfaces")
      end
      else begin
         for(int i = 0; i < num_of_agents; i++) begin
            agents.push_back(cfs_apb_agent::type_id::create($sformatf("agent[%d]", i), this));
         end
      end
   endfunction

The are some things to pay attention to here:

  • The key used to get the number of agents (e.g. “NUM_OF_APB_INTF”) must be the same as used at Step#1
  • The name of the agent used in create() function must be the same as used in Step#2

Step #4: get the interfaces from the database

This step is identical with Step#3 from “The Quick Way”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

class cfs_apb_agent extends uvm_component;
   
   //pointer to the interface
   virtual cfs_apb_if vif;
   
   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
     
      if(uvm_config_db::#(virtual cfs_apb_if)::get(this, "", "VIRTUAL_INTERFACE", vif) == 0) begin
         `uvm_fatal("ALGORITHM_ISSUE", "Could not get from the database the virtual interface for the APB agent")
      end
   endfunction

endclass

Hope you found this information useful 🙂

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值