UVM Transaction 是验证环境中数据传输的核心单元,用于封装与DUT(Design Under Test)交互的数据和协议信息。它是验证组件(如Driver、Monitor、Scoreboard)之间通信的基础。以下是Transaction的详细解析:
Transaction 的核心作用
- 数据封装:将DUT接口的信号(如总线数据、控制信号)抽象为高层次的数据对象。
- 组件通信:通过TLM(Transaction Level Modeling)在Driver、Monitor、Scoreboard等组件间传递。
- 随机化支持:通过SystemVerilog的随机约束(
rand
和constraint
)生成多样化的测试场景。 - 功能覆盖:定义覆盖率点(Coverpoint),跟踪关键数据组合。
Transaction 的定义
Transaction通常继承自 uvm_sequence_item
类,需包含以下内容:
1. 数据字段
- 定义与DUT接口相关的信号(如地址、数据、控制位)。
- 使用
rand
关键字声明可随机化字段。
class my_transaction extends uvm_sequence_item;
rand logic [31:0] addr; // 随机化地址
rand logic [31:0] data; // 随机化数据
rand bit wr_en; // 随机化读写使能
// 其他字段(如协议控制信号)
...
`uvm_object_utils(my_transaction) // 注册到Factory
endclass
2. 约束(Constraints)
- 通过
constraint
限制随机化范围,确保生成合法的激励。
class my_transaction extends uvm_sequence_item;
// 数据字段定义同上
constraint valid_addr {
addr inside {[0x0000_0000 : 0xFFFF_FFFF]}; // 地址范围约束
}
constraint write_ratio {
wr_en dist {1 := 70, 0 := 30}; // 70%写操作,30%读操作
}
endclass
3. 方法(Methods)
- 可自定义方法用于数据格式化、比对或协议检查。
class my_transaction extends uvm_sequence_item;
// 数据字段和约束同上
// 自定义方法:打印事务内容
function string convert2string();
return $sformatf("addr=0x%8h, data=0x%8h, wr_en=%0d", addr, data, wr_en);
endfunction
// 自定义方法:数据比对
function bit compare(my_transaction tr);
return (this.addr == tr.addr) && (this.data == tr.data) && (this.wr_en == tr.wr_en);
endfunction
endclass
Transaction 的生命周期
生成(Generation)
- 由 Sequence 创建并随机化,通过
start_item()
和finish_item()
发送到Sequencer。
class my_sequence extends uvm_sequence; task body(); my_transaction tr; tr = my_transaction::type_id::create("tr"); start_item(tr); assert(tr.randomize()); // 随机化事务 finish_item(tr); endtask endclass
- 由 Sequence 创建并随机化,通过
传输(Transfer)
- Driver 从Sequencer获取Transaction,将其转换为DUT的接口信号。
class my_driver extends uvm_driver; task run_phase(uvm_phase phase); forever begin seq_item_port.get_next_item(req); // 获取事务 vif.drive(req.addr, req.data, req.wr_en); // 驱动到DUT seq_item_port.item_done(); end endtask endclass
捕获(Capture)
- Monitor 从DUT接口捕获信号,重新组装为Transaction并发送给Scoreboard。
class my_monitor extends uvm_monitor; uvm_analysis_port #(my_transaction) analysis_port; task run_phase(uvm_phase phase); forever begin @(posedge vif.clk); my_transaction tr = my_transaction::type_id::create("tr"); tr.addr = vif.addr; // 捕获地址 tr.data = vif.data; // 捕获数据 tr.wr_en = vif.wr_en; // 捕获读写使能 analysis_port.write(tr); // 发送到Scoreboard end endtask endclass
验证(Validation)
- Scoreboard 接收Transaction,检查其是否符合预期行为。
class my_scoreboard extends uvm_scoreboard; uvm_analysis_imp #(my_transaction, my_scoreboard) analysis_export; function void write(my_transaction tr); if (tr.wr_en && (tr.data != expected_data)) `uvm_error("SCB", $sformatf("Data mismatch: Got %0h, Expected %0h", tr.data, expected_data)) endfunction endclass
Transaction 的高级特性
1. Factory 机制
- 动态对象创建:通过
type_id::create()
创建Transaction对象,支持Factory重载。 - 对象替换:可自定义Transaction子类并覆盖默认类型。
class debug_transaction extends my_transaction; `uvm_object_utils(debug_transaction) // 添加调试字段或方法 endclass // 在Test中替换默认Transaction类型 initial begin debug_transaction::type_id::set_type_override(my_transaction::get_type()); end
2. 分层Transaction
- 可继承基类Transaction,扩展出特定协议或场景的子类。
class axi_transaction extends my_transaction; rand logic [3:0] burst_length; // 新增AXI协议字段 rand logic [1:0] burst_type; constraint valid_burst { burst_length inside {[1:16]}; } `uvm_object_utils(axi_transaction) endclass
3. 协议时序封装
- 在Transaction中定义时序控制字段(如延迟、握手信号)。
class my_transaction extends uvm_sequence_item; rand int delay_cycles; // 事务之间的延迟周期 constraint max_delay { delay_cycles inside {[0:5]}; } endclass
4. 覆盖率收集
- 在Transaction中定义覆盖率点(Covergroup)。
class my_transaction extends uvm_sequence_item; covergroup cg; coverpoint addr { bins low = {[0:1000]}; bins high = {[1001:$]}; } coverpoint data { bins even = {[0:$] with (item % 2 == 0)}; } cross addr, data; endgroup function new(); cg = new(); endfunction function void sample(); cg.sample(); // 在Monitor或Scoreboard中调用 endfunction endclass
Transaction 的最佳实践
- 原子化设计:每个Transaction对应DUT接口的一次完整操作(如一次总线读写)。
- 约束分层:将通用约束定义在基类中,场景特定约束定义在子类中。
- 避免过度随机化:约束需确保生成的Transaction符合协议要求。
- 复用与扩展:通过继承创建协议特定的Transaction,减少重复代码。
示例:完整的Transaction流程
// 定义Transaction
class packet extends uvm_sequence_item;
rand logic [7:0] payload;
rand logic error;
constraint no_error { error == 0; } // 默认不生成错误
`uvm_object_utils(packet)
function new(string name = "packet");
super.new(name);
endfunction
endclass
// Sequence生成Transaction
class test_sequence extends uvm_sequence;
`uvm_object_utils(test_sequence)
task body();
packet pkt;
repeat(10) begin
pkt = packet::type_id::create("pkt");
start_item(pkt);
assert(pkt.randomize());
finish_item(pkt);
end
endtask
endclass
// Driver处理Transaction
class my_driver extends uvm_driver;
virtual task run_phase(uvm_phase phase);
packet pkt;
forever begin
seq_item_port.get_next_item(pkt);
`uvm_info("DRV", $sformatf("Driving packet: payload=0x%2h", pkt.payload), UVM_LOW)
// 驱动到DUT接口...
seq_item_port.item_done();
end
endtask
endclass
总结
UVM Transaction 是验证环境的数据核心,通过封装、随机化和通信机制,实现了高效的测试场景生成和协议验证。合理设计Transaction的结构和约束,能够显著提升验证的灵活性和覆盖率。