Learning UVM with me Day 2
Day 2 學習目標
Wiki topics:
EDU · Education & Learning
Learning UVM with me Day 2
Day 2 學習目標
- 寫出
uvm_sequence_item - 寫出
uvm_sequence - 理解
sequencer到底在做什麼 - 寫出基本
driver - 寫出基本
monitor - 理解
get_next_item()/item_done() - 理解
start_item()/finish_item() - 看懂完整的 transaction flow
- 能自己畫出 UVM data flow

UVM架構示意圖
假設有個簡單的Adder
module adder (
input logic clk,
input logic [7:0] a,
input logic [7:0] b,
output logic [8:0] sum
);
always_ff @(posedge clk) begin
sum <= a + b;
end
endmodule
首先我們要先建立一個Transaction
class my_adder_transaction extends uvm_sequence_item;
rand bit [7:0] a;
rand bit [7:0] b;
bit [8:0] sum;
constraint adder_c{
a<255;
b<255;
}
`uvm_object_utils(my_adder_transaction) //註冊到 UVM Factory
`uvm_field_int(a,UVM_DEFAULT)
`uvm_field_int(b,UVM_DEFAULT)
`uvm_field_int(sum,UVM_DEFAULT)
`uvm_object_utils_end
function new(string name = "adder_transaction");
super.new(name);
endfunction
endclass
1. Sequence
接著建立Sequence
class my_adder_sequence extends uvm_sequence #(my_adder_transaction); //這個 Sequence 產生的是 my_adder_transaction
`uvm_object_utils(my_adder_sequence)
my_adder_transaction trans;
function new(string name = "my_adder_sequence");
super.new(name);
endfunction : new
task body(); //Sequence 真正產生 stimulus 的地方
trans = new(); //建立一個transaction
start_item(trans); //把這個 transaction 交給 Sequencer
assert(req.randmize());
finish_item(trans); //transaction 準備好了,可以交給 Sequencer / Driver 了
endtask : body
endclass : my_adder_sequence
body()是Sequence 真正產生 stimulus 的地方,Sequence 要做什麼事情,都寫在 body 裡
body()
↓
產生 transaction
↓
randomize
↓
送出去
整個sequence在做的事情就是
建立 transaction
↓
randomize
↓
完成 transaction
↓
交給 Sequencer
如果要產生多筆transaction呢? 要在body()中加入repeat()
task body(); //Sequence 真正產生 stimulus 的地方
repeat(200) begin
trans = new(); //建立一個transaction
start_item(trans); //把這個 transaction 交給 Sequencer
assert(trans.randmize());
finish_item(trans); //transaction 準備好了,可以交給 Sequencer / Driver 了
end
endtask : body
2. Sequencer
接著是sequencer,前面有提到Sequencer 負責管理 Sequence 產生的 transaction,並提供給 Driver
class my_adder_sequencer extends uvm_sequencer #(my_adder_transaction);
`uvm_component_utils(my_adder_sequencer)
function new(string name = "my_adder_sequencer", uvm_component.parent = null);
super.new(name, parent);
endfunction
endclass
3. Driver
從 Sequencer 拿 transaction,然後轉成pin-level輸入到 DUT
class my_adder_driver extends uvm_driver #(my_adder_transaction);
virtual my_adder_if vif;
uvm_analysis_port#(my_adder_transaction) drv_port
`uvm_component_utils(my_adder_driver)
function new(string name = "my_adder_driver", uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual my_adder_if)::get(this, "","my_adder_if", vif)) begin
`uvm_fatal("TB", $sformatf("cannot get adder interface from %m"))
end
drv_port = new("drv_port", this);
end function
extern task driver_start(my_adder_transaction trans)
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(trans); //Driver 向 Sequencer 要一個 transaction
repeat(1)@(posedge vif.clk);
vif.a <= req.a;
vif.b <= req.b;
drv_port.write(my_adder_transaction)
seq_item_port.item.done(); //Driver 告訴 Sequencer:這筆 transaction 我處理完了
end
endtsak
endclass
4. monitor
Monitor 做的事情跟 Driver 相反,driver送transaction進DUT,而monitor從DUT接收transaction
class my_adder_monitor extends uvm_monitor#(my_adder_transaction);
virtual my_adder_if vif;
uvm_analysis_port#(my_adder_transaction) ap
`uvm_component_utils(my_adder_monitor)
function new(string name = "my_adder_monitor", uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual my_adder_if)::get(this, "","my_adder_if", vif)) begin
`uvm_fatal("TB", $sformatf("cannot get adder interface from %m"))
end
ap = new("ap", this);
end function
extern task main_phase(uvm_phase phase);
endclass
task my_adder_monitor::main_phase(uvm_phase phase);
my_adder_transaction tr;
forever begin
@(posedge vif.clk);
tr = new("tr");
tr.a = vif.a;
tr.b = vif.b;
tr.sum = vif.sum;
`uvm_info("MONITOR","Monitor received transaction", UVM_LOW)
ap.write(tr);
end
endtask
總結:
Sequence
│
│ create
↓
Sequence Item
│
│
↓
Sequencer
│
│ get_next_item()
↓
Driver
│
│ drive
↓
DUT
│
│ observe
↓
Monitor
│
│ write()
↓
Transaction 메타데이터
- post_id
- 7fd79fb665b0
- slug
- learning-uvm-with-me-day-2-7fd79fb665b0
- url
- https://medium.com/@chiantsai1997/learning-uvm-with-me-day-2-7fd79fb665b0
- canonical_url
- https://medium.com/@chiantsai1997/learning-uvm-with-me-day-2-7fd79fb665b0
- author_url
- https://medium.com/@chiantsai1997
- status
- ok
- fetched_at
- 2026-08-22 01:25:53