UVM Testbench Top

2023-11-16
UVM

其實這一章節看得有點沒感覺,不過我還是先嘗試翻譯跟照著練習一下。

What is testbench top module?

所有的驗證元件(component)、介面(interface)和 DUT 都會在 testbench 的Top Level模組中被實例化(instantiate)。它是一個靜態容器(static container)容納模擬所需的所有內容,並且為hierarchy中的root node。通常命名為 tbtb_top

Alt text

Simulators通常需要知道Top Level模組,才能夠分析在top module底下的component並詳細說明design hierarchy。

Testbench Top Example

下面的例子是一個 tb 內的所有元素。其中會先產生一個dut_if1 instance然後pass給Design,另外也會用uvm_config_dbset function把他註冊到uvm_config_db database上,在tb內需要用到的話可以使用uvm_config_dbget function。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import uvm_pkg::*;
`include "uvm_macros.svh"

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

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

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

initial begin
$dumpvars;
$dumpfile("dump.vcd");
end
endmodule
  • tb_top 是一個module,是一個靜態容器裡面會包含其他所有內容
  • 要import uvm_pkg 才能使用UVM的東西
  • Clock在testbench產生並傳給dut_if1這個interface
  • dut_if1 透過 set 設定為 uvm_config_db 中的object,在其他testbench class中可使用 get 方法使用這個interface
  • 這個tbrun_test這個method跑起base_test這個test

Clock generation

真實的design可能有在不同clock頻率下運行的module,因此testbench需要產生多個clock並作為design的input。所以clock generation不會像上面例子只有用一個always block這麼簡單。為了測試design的不同功能,許多clock參數(如frequency、duty cycle、phase)可能需要動態更新,testbench需要支援這類型的動態操作。

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

module clk_main (...);

// Code for clock generation

endmodule

module tb_top;
bit clk_main_out;

clk_main clk_main_0(.out(clk_main_out),
...
);

dut_if dut_if0 ( clk_main_out, ...);
endmodule

上面的方法可能不容易擴展,因為它們被實例化為module,而且要使用分層訊號路徑從testbench驅動。更好的UVM替代方式是為clock建立一個agent,以便可以使用agent configuration object比較容易的從sequence和test中控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class clk_agent extends uvm_agent;
clk_cfg clk_cfg_0;

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
endclass

class base_test extends uvm_test;
clk_cfg clk_cfg_0;

virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);

clk_cfg_0.m_freq = 500;
endfunction
end class

Reset Generation

同樣的,也可以寫一個reset agent來處理所有reset request。通常系統都會有hardware reset 和software reset。
Software reset通常透register model完成,並且與reset agent分開。
Hardware reset包含在持續時間內對system reset pin做assertion,或在應用實際reset之前照著特定的sequence的event就會實際reset。
所有此類scenario都可以使用此reset agent單獨處理該agent需要handle的reset interface。

1
2
3
4
5
6
7
8
9
10
11
12
13
class reset_agent extends uvm_agent;

reset_cfg reset_cfg_0;

endclass

class my_sequence extends uvm_sequence;

virtual task body();
hw_reset_seq hw_reset_seq_0;
hw_reset_seq_0.start(p_sequencer);
endtask
endclass

Creation of internal tap points

有些testbench components可能需要design中的內部網路(internal nets)來強制或sample值來測試某些功能。這些內部網路可能需要根據input分配不同的值,並且可以在testbench 的top level module中完成。這類signal可以綁定到通用interface並由另一個agent驅動。

1
2
3
4
5
6
7
8
9
10
interface gen_if;
logic [255:0] signals;
endinterface

module tb_top;
gen_if u_if0();
des u_des( ... );

assign u_if0.signals[2] = u_des.xxx.status;
endmodule