代码覆盖率和功能覆盖率,到底差在哪
在 FPGA 开发中,编写 HDL 往往是最省时间的环节,真正耗时、也最磨人的通常是验证。根据最终应用不同,验证可以简单到只检查大多数功能,也可以复杂到运行一套完全独立开发的测试平台,借功能和代码覆盖率来证明设计行为。

功能和代码覆盖率在验证里都很重要,因为它们从不同角度描述设计及其验证情况。理想状态下,两者当然都应该达到 100%;如果只有其中一项到了 100%,那通常意味着还有验证工作没做完。
两者的常见定义如下:
- 代码覆盖率:代码覆盖率是一种间接度量软件质量的方法,通过统计测试过程中被执行的源代码占全部源代码的比例,来判断是否遍历了所有分支和语句,例如是否翻转了所有触发器。
- 功能覆盖率:反映测试平台覆盖被测单元功能行为程度的信息。要实现功能覆盖,开发人员或验证工程师必须定义覆盖组和覆盖点。
两者最明显的区别在于:功能覆盖率必须依赖需求。
需要补充的是,代码覆盖率和功能覆盖率都应在设计阶段提前规划。代码覆盖率本身有局限,它既不能识别缺失的功能,也无法说明是否覆盖了所有可能的边界值或极端情况;同时它也不关心事件发生的顺序。功能覆盖正好可以补上这一环,因为它直接针对功能声明进行测试。
通常,代码和功能覆盖率需要昂贵的仿真工具,但通过 Vivado 2021.1 的 Vivado 仿真器就能实现。使用 Vivado 时,开发人员可以验证设计并确认 RTL 功能符合预期。
在 Vivado 里配置覆盖率
对于代码覆盖率,第一步是在项目设置里的“仿真”选项卡中,进入细化(Elaboration)设置,配置覆盖类型。Vivado 提供以下选项:
- Line / Statement(行/语句)
- Branch(分支)
- Condition(条件)
- Toggle(切换)

同时,还可以指定覆盖率报告名称和覆盖率目录的位置。
仿真结束后会生成覆盖信息。在细化设置指定的路径下,就能看到 codeCov 目录。

如果要创建功能覆盖,则需要在 RTL 内部定义覆盖组。
此时得到的是用于生成报告的数据库,后续还需要在 Vivado 中进一步处理,把数据库转换成可读的报告。
从仿真结果生成报告
如果想了解 Vivado 仿真器的功能和代码覆盖率,最好的起点是 UG937 Vivado 设计套件教程:逻辑仿真。
https://docs.xilinx.com/r/en-US/ug937-vivado-design-suite-simulation-tutorial/Tutorial-Description
这份教程提供了几个设计示例,可用来测试 Vivado 仿真器功能的不同方面,包括代码/功能覆盖范围以及 UVM 支持。
功能和代码覆盖率示例基于 AXI VIP 参考设计。跟着教程完成后,再添加覆盖组,就能得到功能和代码覆盖率数据。
仿真完成后,需要运行 xcrg 命令来创建 HTML 报告。

生成的 HTML 报告可以在任意浏览器中打开。

单击 Groups 按钮,会打开覆盖组详情。在这个示例里,覆盖组结构相对简单。

运行代码覆盖率转换后,就能看到生成的代码覆盖率报告。

单击右上角的 Files,可以查看每个文件的具体覆盖结果。

小结
总而言之,Vivado 仿真器的能力相当全面。善用这些功能,有助于开发人员创建更优设计,也有望减少后续硬件调试的时间。更多 FPGA 验证与覆盖率实践,欢迎到 云栈社区 一起交流。