uvm testbench顶层和testcase的编写

本篇主要介绍UVM testbench top和test case如何来写。

test top

testbench 的顶层应该是整个UVM结构的根, 如下图所示, 顶层中可以包含几个test case, test case的下层是XXX_env, env下面又分成几个部门,比如多个uvm_component.

比如是一个testbench 顶层的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module tb_top;
import uvm_pkg::*;
import test_pkg::*;

bit clk;
always #10 clk <= ~clk;

dut_if dut_if1 (clk);
dut_wrapper dut_wr0 (._if (dut_if1));

initial begin
uvm_config_db #(virtual dut_if)::set (null, "uvm_test_top", "dut_if", dut_if1);
run_test ("base_test");
end

endmodule

test case

test case要做的就是这对电路的spec设置不同的激励或者配置,然后检测DUT是否符合设计要求。不同的test case可以设置不同的参数, 但是env可以不必修改。

那么怎么来写一个uvm 的test case呢?

  1. 使用uvm_test来派生出一个新的class, 比如my_test; 然后使用factory 机制注册, 并写‘new’函数:
1
2
3
4
5
6
7
8
9
class my_test extends uvm_test;
// [Recommended] Makes this driver more re-usable
`uvm_component_utils (my_test
// This is standard code for all components
function new (string name = "my_test", uvm_component parent = null);
super.new (name, parent);
endfunction
// Code for rest of the steps come here
endclass
  1. 申明env和其他uvm_componet, 并且在build_phase创建实例;
1
2
3
4
5
6
7
8
9
10
11
12
13
my_env   m_top_env; //environment that contains other agents, register models, etc
my_cfg m_cfg0; // Configuration object to tweak the environment for this test
// Instantiate and build components declared above
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
// [Recommended] Instantiate components using "type_id::create()" method instead of new()
m_top_env = my_env::type_id::create ("m_top_env", this);
m_cfg0 = my_cfg::type_id::create ("m_cfg0", this);
// Configure testbench components if required, get virtual interface handles, etc
set_cfg_params ();
// [Optional] Make the cfg object available to all components in environment/agent/etc
uvm_config_db #(my_cfg) :: set (this, "m_top_env.my_agent", "m_cfg0", m_cfg0);
endfunction
  1. 如果有需要可以打印uvm的拓扑结构
1
2
3
virtual function void end_of_elaboration_phase (uvm_phase phase);
uvm_top.print_topology ();
endfunction
  1. 启动sequence, 发送激励
1
2
3
4
5
6
7
8
9
10
11
12
 
// Start a virtual sequence or a normal sequence for this particular test
virtual task run_phase (uvm_phase phase);
// Create and instantiate the sequence
my_seq m_seq = my_seq::type_id::create ("m_seq");
// Raise objection - else this test will not consume simulation time*
phase.raise_objection (this);
// Start the sequence on a given sequencer
m_seq.start (m_env.seqr);
// Drop objection - else this test will not finish
phase.drop_objection (this);
endtask

在上文testbench top的介绍中, test case的执行如下:

1
2
3
initial begin
run_test ("base_test");
end

其中的参数base_test就是test case的名字, 但是实际上可能有很多的test case, 不可能每测试一个case就去修改testbench_top文件, 所以这个参数常常不用给值, 可以在仿真器的命令行中添加:

1
$> [simulator] -f filelist.f +UVM_TESTNAME=base_test