uvm 覆盖率怎么写
时间: 2025-05-20 10:39:11 浏览: 46
### 如何在 UVM 中实现覆盖率的编写
在 UVM(Universal Verification Methodology)框架中,功能覆盖率是一个重要的验证目标。通过定义覆盖组(covergroup)、覆盖点(coverage points),以及交叉覆盖(cross coverage),可以在测试过程中自动收集设计的功能覆盖率数据。
以下是关于如何在 UVM 中实现覆盖率编写的详细介绍:
#### 1. 定义 Covergroup 和 Coverage Points
在 UVM 验证环境中,可以通过 `covergroup` 来定义覆盖率模型。Covergroup 是 SystemVerilog 提供的一种机制,用于捕获变量的不同取值范围及其分布情况[^1]。
```systemverilog
class my_transaction extends uvm_sequence_item;
rand bit [7:0] addr;
rand bit [31:0] data;
covergroup cg_addr_data with function sample();
option.per_instance = 1; // 每个实例单独计算覆盖率
ADDR_COV : coverpoint addr {
bins low_addrs = {[0:63]};
bins high_addrs = {[64:127]};
}
DATA_COV : coverpoint data {
bins small_values = {[0:100]};
bins large_values = {[1000:$]};
}
CROSS_ADDR_DATA : cross addr, data { // 跨越覆盖
ignore_bins ignored_crosses = binsof(DATA_COV.small_values);
}
endgroup
function new(string name = "my_transaction");
super.new(name);
cg_addr_data = new(); // 初始化 covergroup
endfunction
function void do_print(uvm_printer printer);
super.do_print(printer);
printer.print_field_int("addr", this.addr, $bits(this.addr));
printer.print_field_int("data", this.data, $bits(this.data));
endfunction
endclass
```
在此代码片段中,创建了一个名为 `cg_addr_data` 的 covergroup,并定义了两个覆盖点:`ADDR_COV` 和 `DATA_COV`,还定义了一个跨覆盖项 `CROSS_ADDR_DATA`。这些覆盖点会记录地址和数据的变化情况并生成相应的覆盖率报告[^4]。
---
#### 2. 使用 Sequence 或 Driver 自动采样
为了确保每次事务发生时都能触发覆盖率采样操作,通常会在序列(Sequence)或者驱动程序(Driver)中调用 `sample()` 方法。
```systemverilog
task driver::run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req); // 获取下一个请求对象
send_to_dut(req); // 将请求发送到被测设备 (DUT)
req.cg_addr_data.sample(); // 对当前事务进行覆盖率采样
seq_item_port.item_done(); // 告知完成处理此请求
end
endtask
```
在这个例子中,每当一个新的事务到达时,都会对其执行覆盖率采样的动作。这样可以保证所有的输入条件都被充分考虑到了验证流程之中[^1]。
---
#### 3. 寄存器级覆盖率扩展
对于复杂的寄存器映射结构,可能需要自定义覆盖率逻辑以适应特定需求。例如,在 SPI 访问寄存器的情况下,由于底层协议细节的影响,标准 UVM_REG 内置的覆盖率支持可能存在局限性[^2]。此时可采用如下方式解决:
- **手动构建寄存器级别的 COVERGROUP**
如果默认的 UVM_REG 不足以满足复杂场景下的覆盖率需求,则可以选择基于实际应用重新定制化的解决方案。比如针对某个特殊字段增加额外的行为约束或状态机转换路径分析等功能。
```systemverilog
// 扩展后的寄存器类定义
class spi_register extends uvm_reg;
rand bit [7:0] reg_value;
covergroup cg_spi_reg;
REG_VAL_COVERAGE : coverpoint reg_value {
bins valid_vals = {[0:255]} with (%c >= 1 && %c <= 255);
}
endgroup
extern function new(string name="spi_register");
virtual function void build();
super.build();
cg_spi_reg = new();
endfunction
function new(string name="spi_register");
super.new(name,8,UVM_NO_COVERAGE); // 初始时不启用内置覆盖率
add_coverage(UVM_CVR_ALL); // 后续显式开启全部类型的覆盖率跟踪
endfunction
endclass
```
这里展示了如何为一个假设性的 SPI 寄存器建立专门的覆盖率监测体系。注意我们禁用了原始版本中的自动化部分以便完全掌控整个过程[^2]。
---
#### 4. 断言与覆盖率结合
除了传统的随机激励生成外,还可以利用断言技术进一步增强系统的鲁棒性和可靠性检测能力。System Verilog 提供了一套强大的形式化工具集允许开发者轻松指定期望行为模式并通过仿真确认其正确无误运行状况[^3]。
```systemverilog
module top;
logic reset_n, clk, a, b, c;
initial begin
$dumpfile("waveform.vcd");
$dumpvars(0,top);
@(posedge clk) disable iff (!reset_n)
assert property (@(posedge clk) a |-> ##1 b |=> c) else $error("Assertion failed!");
sequence s_a_b_c;
@(posedge clk) a ##1 b ##1 c;
endsequence
cover property(s_a_b_c) { ->> Report success when covered;}
end
endmodule
```
上述模块实现了简单的同步电路断言检查及相应事件序列的覆盖率测量。当信号关系不符合预期设定规则时将会抛出错误提示;而一旦成功匹配给定的时间窗口组合则计入总统计数列当中去[^3]。
---
### 总结
综上所述,UVM 功能覆盖率的设计主要围绕以下几个方面展开:
- 明确待测项目所需关注的关键参数;
- 构造合理的 Covergroups 并设置合适的 Bins;
- 在合适位置加入 Sample() 函数调用语句;
- 结合实际情况灵活调整策略应对各种挑战如寄存器层面难题等;
- 可选地引入 SVA 表达式强化整体质量保障水平。
以上便是有关于怎样在 UVM 下开展有效率高的覆盖率编码工作的指导说明[^1][^2][^3].
阅读全文
相关推荐


















