文章目录
概要
在 UVM 验证环境中,Sequence 是生成激励事务(Transaction)的核心组件。下面通过一个完整示例,详细说明 Sequence 的结构、关键组件及使用方法。
一、基本 Sequence 结构示例
// 1. 定义事务类
class my_transaction extends uvm_sequence_item;
rand bit [7:0] addr;
rand bit [15:0] data;
rand bit wr_rd; // 1=写, 0=读
// 约束条件
constraint c_addr_range { addr inside {[8'h00:8'hFF]}; }
constraint c_wr_data { wr_rd == 1 -> data > 16'h100; }
// 注册到UVM工厂
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(addr, UVM_ALL_ON)
`uvm_field_int(data, UVM_ALL_ON)
`uvm_field_int(wr_rd, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "my_transaction");
super.new(name);
endfunction
// 自定义方法:打印事务信息
virtual function void print_info();
`uvm_info("TRANS", $sformatf("Addr=0x%02h, Data=0x%04h, Wr/Rd=%b",
addr, data, wr_rd), UVM_MEDIUM)
endfunction
endclass
// 2. 定义基础Sequence类
class base_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(base_sequence)
// 存储配置参数的句柄
my_config cfg;
function new(string name = "base_sequence");
super.new(name);
endfunction
// body()方法:Sequence的核心执行体
virtual task body();
my_transaction tx;
// 1. 从config_db获取配置参数(如果有)
if (!uvm_config_db#(my_config)::get(null, get_full_name(), "cfg", cfg))
`uvm_warning("CFG", "No config provided, using default values")
// 2. 创建并随机化事务
`uvm_do(tx) // 等价于:
// tx = my_transaction::type_id::create("tx");
// start_item(tx);
// if (!tx.randomize()) `uvm_fatal("RAND", "Transaction randomization failed");
// finish_item(tx);
// 3. 可选:修改事务属性
tx.print_info();
endtask
endclass
// 3. 定义具体测试Sequence(继承自base_sequence)
class write_sequence extends base_sequence;
`uvm_object_utils(write_sequence)
function new(string name = "write_sequence");
super.new(name);
endfunction
// 重写body()方法
virtual task body();
my_transaction tx;
// 生成5个写事务
repeat (5) begin
`uvm_do_with(tx, { wr_rd == 1; addr < 8'h80; })
tx.print_info();
end
endtask
endclass
class read_sequence extends base_sequence;
`uvm_object_utils(read_sequence)
function new(string name = "read_sequence");
super.new(name);
endfunction
// 重写body()方法
virtual task body();
my_transaction tx;
// 生成3个读事务
repeat (3) begin
`uvm_do_with(tx, { wr_rd == 0; addr >= 8'h80; })
tx.print_info();
end
endtask
endclass
// 4. 定义复合Sequence(包含多个子Sequence)
class mixed_sequence extends base_sequence;
`uvm_object_utils(mixed_sequence)
write_sequence write_seq;
read_sequence read_seq;
function new(string name = "mixed_sequence");
super.new(name);
endfunction
virtual task body();
// 创建子Sequence
write_seq = write_sequence::type_id::create("write_seq");
read_seq = read_sequence::type_id::create("read_seq");
// 顺序执行子Sequence
`uvm_info("MIXED", "Starting write sequence", UVM_MEDIUM)
write_seq.start(m_sequencer);
`uvm_info("MIXED", "Starting read sequence", UVM_MEDIUM)
read_seq.start(m_sequencer);
// 可选:并行执行子Sequence
// fork
// write_seq.start(m_sequencer);
// read_seq.start(m_sequencer);
// join
endtask
endclass
二、关键组件解析
1. 事务类(Transaction Class)
核心要素:
- 随机化属性(rand变量)
- 约束条件(constraint块)
- 工厂注册(uvm_object_utils宏)
- 自动化字段(uvm_field_*宏)
作用:封装激励数据,定义合法取值范围
2. Sequence 类
核心方法:
- body():Sequence 的主执行体
- start():启动 Sequence
- pre_body()/post_body():执行前 / 后的钩子函数
关键 API:
- uvm_do():创建、随机化并发送事务
- uvm_do_with():带约束的事务生成
- start_item()/finish_item():手动控制事务流程
3. Sequencer
作用:
- 调度和管理 Sequence 执行
- 实现 Sequence 间的同步和仲裁
连接方式:
- 通过seq_item_port连接到 Driver
- 通过analysis_port发布生成的事务
三、在验证环境中使用 Sequence
1. 环境配置
class my_agent extends uvm_agent;
my_sequencer sequencer;
my_driver driver;
my_monitor monitor;
`uvm_component_utils(my_agent)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// 创建组件
if (is_active == UVM_ACTIVE) begin
sequencer = my_sequencer::type_id::create("sequencer", this);
driver = my_driver::type_id::create("driver", this);
end
monitor = my_monitor::type_id::create("monitor", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// 连接driver和sequencer
if (is_active == UVM_ACTIVE) begin
driver.seq_item_port.connect(sequencer.seq_item_export);
end
endfunction
endclass
2. 在测试中启动 Sequence
class my_test extends uvm_test;
my_env env;
`uvm_component_utils(my_test)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = my_env::type_id::create("env", this);
endfunction
virtual task run_phase(uvm_phase phase);
mixed_sequence seq;
phase.raise_objection(this, "Running mixed sequence");
// 创建并启动Sequence
seq = mixed_sequence::type_id::create("seq");
seq.start(env.agent.sequencer);
phase.drop_objection(this, "Sequence completed");
endtask
endclass
3. Driver 接收并执行事务
class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils(my_driver)
virtual my_if vif; // 接口句柄
function new(string name, 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_if)::get(this, "", "vif", vif))
`uvm_fatal("DRV", "Could not get vif")
endfunction
virtual task run_phase(uvm_phase phase);
my_transaction tx;
forever begin
// 从sequencer获取事务
seq_item_port.get_next_item(tx);
// 执行事务(驱动DUT)
drive_transaction(tx);
// 通知sequencer事务完成
seq_item_port.item_done();
end
endtask
virtual task drive_transaction(my_transaction tx);
// 根据事务内容驱动接口信号
if (tx.wr_rd) begin
// 写操作
vif.addr <= tx.addr;
vif.data <= tx.data;
vif.wr_en <= 1'b1;
@(posedge vif.clk);
vif.wr_en <= 1'b0;
end else begin
// 读操作
vif.addr <= tx.addr;
vif.rd_en <= 1'b1;
@(posedge vif.clk);
vif.rd_en <= 1'b0;
// 读取数据...
end
endtask
endclass
四、Sequence 高级特性
1. 参数化 Sequence
class param_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(param_sequence)
rand int num_trans;
rand bit [7:0] addr_range;
constraint c_num { num_trans inside {[5:10]}; }
function new(string name = "param_sequence");
super.new(name);
endfunction
virtual task body();
my_transaction tx;
repeat (num_trans) begin
`uvm_do_with(tx, { addr < addr_range; })
end
endtask
endclass
2. Sequence 回调(Callback)
class my_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(my_sequence)
function new(string name = "my_sequence");
super.new(name);
endfunction
// 预回调函数
virtual function void pre_body();
if (starting_phase != null)
starting_phase.raise_objection(this, "Running sequence");
endfunction
// 主执行体
virtual task body();
// ...
endtask
// 后回调函数
virtual function void post_body();
if (starting_phase != null)
starting_phase.drop_objection(this, "Sequence completed");
endfunction
endclass
五、验证流程总结
1、定义事务类:
-
包含随机化字段和约束条件
-
注册到 UVM 工厂
2、创建 Sequence:
- 继承自uvm_sequence
- 在body()方法中生成事务
3、配置环境:
- 创建 Sequencer 和 Driver
- 连接 Sequencer 和 Driver 的端口
4、启动 Sequence:
- 在测试的run_phase中实例化 Sequence
- 调用start()方法并指定目标 Sequencer
5、执行与验证:
- Driver 接收事务并驱动 DUT
- Monitor 捕获 DUT 响应
- Scoreboard 比较预期与实际结果
通过这种方式,Sequence 机制实现了激励生成与驱动的分离,提高了验证环境的可重用性和可维护性。