무언가를 배울 때 개념을 쌓고 가는 것도 좋지만, 가장 빠르게 배울 수 있는 방법은 따라하는 것이다. Chipverify에서 제공하는 예시를 따라하며 UVM에 대해 배워보자.
UVM 기반 Simulation은 다음 과정을 거치게 된다.
- clk 생성
- DUT와 interface 연결
- UVM 환경에 인터페이스 등록 (uvm_config_db)
- base_test 실행 → UVM 시나리오 작동
- $dumpvars로 waveform 기록 (디버깅용)
module tb_top;
import uvm_pkg::*;
// Complex testbenches will have multiple clocks and hence multiple clock
// generator modules that will be instantiated elsewhere
// For simple designs, it can be put into testbench top
bit clk;
always #10 clk <= ~clk;
// Instantiate the Interface and pass it to Design
dut_if dut_if1 (clk);
dut_wrapper dut_wr0 (._if (dut_if1));
// At start of simulation, set the interface handle as a config object in UVM
// database. This IF handle can be retrieved in the test using the get() method
// run_test () accepts the test name as argument. In this case, base_test will
// be run for simulation
initial begin
uvm_config_db #(virtual dut_if)::set (null, "uvm_test_top", "dut_if", dut_if1);
run_test ("base_test");
end
// Multiple EDA tools have different system task calls to specify and dump waveform
// in a given format or path. Some do not need anything to be placed in the testbench
// top module. Lets just dump a very generic waveform dump file in *.vcd format
initial begin
$dumpvars;
$dumpfile("dump.vcd");
end
endmodule
- import uvm_pkg::*;
- UVM의 모든 클래스, 함수, 매크로 등을 불러옴
- UVM 환경 구성(uvm_test, uvm_env, 등)을 사용할 수 있게 해줌
- dut_if dut_if1 (clk);
- DUT와 TB 사이를 연결하는 인터페이스 인스턴스화
- 이 인터페이스에 clk, rst, addr, data 등의 신호가 정의되어있다.
- dut_wrapper dut_wr0 (._if (dut_if1));
- DUT 인스턴스. 인터페이스로 연결된다.
initial begin
uvm_config_db #(virtual dut_if)::set (null, "uvm_test_top", "dut_if", dut_if1);
run_test ("base_test");
end
- uvm_config_db::set(...)
- UVM config DB를 통해 인터페이스 전달
- "uvm_test_top"이라는 UVM 테스트 환경에서 "dut_if"라는 이름으로 dut_if1을 사용할 수 있게 함
- run_test("base_test");
- base_test라는 이름의 UVM 테스트 클래스 실행
- 내부에서 my_env, my_seq, my_agent 등이 동작하게 됨
initial begin
$dumpvars;
$dumpfile("dump.vcd");
end
- $dumpvars;
- 시뮬레이션 신호를 기록 (VCD)
- $dumpfile("dump.vcd");
- 출력 파일 지정 → GTKWave 등에서 확인 가능
- 일반적으로 시뮬레이션 결과를 waveform으로 보고 디버깅하기 위해 사용
위의 예시는 정말 간단하게 표현한 것이고, 실제 설계에서는 여러 개의 클럭 도메인과 다양한 리셋 타입을 가지게 된다. 따라서, 테스트벤치는 이 신호들을 단순히 always #10 clk = ~clk; 형태로 처리할 수 없는데, 이를 위해 동적으로 제어 가능한 클럭/리셋/내부 신호 관리가 필요하다. 이를 수행해주는 것이 에이전트라는 개념이다.
// Example of Clk Agent
class clk_agent extends uvm_agent;
clk_cfg m_clk_cfg;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// m_clk_cfg 정보 기반으로 agent 구성
endfunction
endclass
class clk_cfg extends uvm_object;
rand int m_freq; // 클럭 주파수
rand int m_duty; // 듀티 비율
rand int m_phase; // 위상 차이
endclass
// Example of Reset Agent
class reset_agent extends uvm_agent;
reset_cfg m_reset_cfg;
// 하드웨어/소프트웨어 리셋 시나리오 관리
endclass
'이론 공부 > UVM (Universal Verification Methodology)' 카테고리의 다른 글
UVM Testbench Structure - 05. Monitor (0) | 2025.04.19 |
---|---|
UVM Testbench Structure - 04. Driver (0) | 2025.04.19 |
UVM Testbench Structure - 03. Sequencer (0) | 2025.04.18 |
UVM Testbench Structure - 02. Agent (0) | 2025.04.18 |
UVM 개요 (0) | 2025.04.18 |