这一篇在干嘛?
仿真跑通了不代表测全了。代码覆盖(Code Coverage)回答的是另一个问题:你的测试激励到底执行了源代码里的哪些语句、分支、条件、表达式?哪些逻辑位从没翻转过?哪些 FSM 状态从没进过?这一章教你打开覆盖统计、读懂各种覆盖窗口和图标、排除不该统计的代码,并生成文本或 HTML 覆盖报告,把「没测到的代码」一眼找出来。示例设计仍是一个控制行为级存储器的有限状态机加 test bench。
编译设计
开启代码覆盖的流程很简单:编译设计文件时指定要收集哪些覆盖统计,然后加载设计并让 Questa SIM 产出这些统计。
示例文件路径:
- Verilog –
<install_dir>/questasim/examples/tutorials/verilog/coverage - VHDL –
<install_dir>/questasim/examples/tutorials/vhdl/coverage
本课以 Verilog 版本为例,有 VHDL license 的读者可改用 VHDL 版本。
- 新建目录,把
<install_dir>/questasim/examples/tutorials/verilog/coverage下所有文件复制进去(VHDL 用户复制vhdl/coverage目录)。 - 启动 Questa SIM 并切换目录:
- UNIX shell 输入
vsim,或 Windows 下点 Questa SIM 图标;欢迎对话框出现则点 Close。 - 选 File > Change Directory 切到练习目录。
- UNIX shell 输入
- 创建工作库:在 Questa SIM> 提示符输入
vlib work。 - 编译所有设计文件:
- Verilog:输入
vlog *.v。 - VHDL:输入
vcom *.vhd。
- Verilog:输入
- 指定要收集的覆盖统计类型。在 Questa SIM> 提示符输入:
vopt +cover=bcesxf test_sm -o test_sm_opt+cover=bcesxf 参数让 Questa SIM 收集 branch(分支)、condition(条件)、expression(表达式)、statement(语句)、extended toggle(扩展翻转)和 FSM(有限状态机)覆盖统计。更多覆盖类型见 User’s Manual 的 Overview of Code Coverage Types。
-o 参数为优化后的设计指定名字(这里是 test_sm_opt),vopt 命令必须带此参数。
默认情况下,Questa SIM 对所有设计执行优化(见 User’s Manual 的 Optimizing Designs with vopt)。
FPGA 语境
+cover=bcesxf的每个字母对应一类覆盖:b=branch、c=condition、e=expression、s=statement、x=extended toggle、f=FSM。做 FPGA 设计验证时,statement + branch(bs)通常是最基本的底线,toggle 覆盖对检查「上电后某些位从没动过」特别有用——这往往对应着没被复位或没被驱动的逻辑。
加载并运行设计
指定覆盖统计类型后,就可以加载并运行设计了。
- 加载设计。在 Questa SIM> 提示符输入(加载优化后的设计):
vsim -coverage test_sm_opt三个覆盖窗口会分别在三个主窗口组中打开:Code Coverage Analysis、Instance Coverage 和 Coverage Details(Figure 13-1)。

在 Code Coverage Analysis 窗口中可以做 statement、branch、condition、expression、FSM 和 toggle 六种覆盖分析。窗口中每一行都有图标,标明该行的元素(语句、分支、条件或表达式)是已执行、未执行还是被排除。Table 13-1 是代码覆盖图标说明。
Table 13-1 代码覆盖图标:
| 图标 | 含义 |
|---|---|
| √ | 该行所有语句、分支、条件或表达式均已执行 |
| ✕ | 该行有多种覆盖未执行 |
| True 分支未执行(BC 列) | |
| False 分支未执行(BC 列) | |
| 条件未执行(Hits 列) | |
| 表达式未执行(Hits 列) | |
| 分支未执行(Hits 列) | |
| 语句未执行(Hits 列) | |
| E | 该行应用了有效覆盖排除;行上每一项都被排除,无命中 |
| E□ | 部分被排除项有命中 |
| E□ | 部分项被排除,其余未被排除项全部命中 |
| E× | 部分项被排除,部分未被排除项缺覆盖 |
| E× | 该行应用了自动排除。光标悬停在 EA 上会弹出显示排除原因的 tooltip |
在 Analysis 工具栏(Figure 13-2)中选择要做的分析。

当前打开的是哪种分析,看 Code Coverage Analysis 窗口的标题栏即可(Figure 13-3)。

默认情况下,第一次打开 Code Coverage Analysis 窗口显示 Statement Analysis;之后再打开时显示上次选择的分析窗口。
- 运行仿真。在 VSIM> 提示符输入:
run 1 ms- 以启用代码覆盖的方式加载设计后,Questa SIM 会在 Files 和 Structure (sim) 窗口中添加几个覆盖数据列(Figure 13-4)。用水平滚动条可以看到更多覆盖列(你的结果可能与图中不同)。
Structure (sim) 窗口中的覆盖数据列:
| Name | Specified path | Full path | Type | Stmt Count | Stmt Hits | Stmt % | Stmt Graph | Bran |
|---|---|---|---|---|---|---|---|---|
| sim | vsim.wlf | C:/Tutorial/… | ||||||
| sm.v | sm.v | C:/Tutorial/… verilog | 25 | 22 | 88.000 | |||
| sm_seq.v | sm_seq.v | C:/Tutorial/… verilog | 16 | 15 | 93.750 | |||
| beh_sram.v | beh_sram.v | C:/Tutorial/… verilog | 6 | 5 | 83.333 | |||
| test_sm.v | test_sm.v | C:/Tutorial/… verilog | 77 | 70 | 90.909 |
- 通过 View > Coverage 菜单可以打开和关闭覆盖窗口(Figure 13-5)。

- 所有覆盖窗口都可以缩放、重排和解除停靠:拖动任意边框缩放窗口;拖动标题栏的把手(标题栏中间的三排点)或标签移动窗口;选中窗口后拖出主窗口、或点标题栏右上角的 Dock/Undock 按钮解除停靠;再点一次该按钮可重新停靠。
- 下一步练习里我们会更仔细地看几个覆盖窗口。
查看覆盖数据
看看不同覆盖窗口里显示的数据。
- 在 Structure (sim) 窗口查看覆盖数据:
- 选中 sim 标签,用水平滚动条查看覆盖列中的数据。设计中每个对象都有一份覆盖数据。
- 选 Files 标签切到 Files 窗口并向右滚动。右键任意列名,选 Change Column Visibility,再从弹出列表中选择,即可更改显示哪些覆盖数据列。
Configure Columns 对话框中的列:
| Branch % | Full path |
|---|---|
| Branch Count | Specified path |
| Branch Graph | States % |
| Branch Hits | States Count |
| Condition % | States Graph |
| Condition Hits | Stmt % |
| Condition Count | Stmt Count |
| Condition Graph | Stmt Graph |
| Condition Hits | Stmt Hits |
| Expression % | Stmt Graph |
| Expression Count | Toggle % |
| Expression Hits | Toggle nodes |
| Expression Graph | Toggled graph |
| FEC Condition % | Toggles hit |
| FEC Condition Count | Transitions % |
| FEC Condition Graph | Transitions Count |
| FEC Expression % | Transitions Graph |
| FEC Expression Count | Transitions Hits |
| FEC Expression Graph | Type |
| FEC Expression Hits |
勾选的列显示,未勾选的隐藏。每列的显示/隐藏状态在 Questa SIM 多次启动之间保持不变。 2. 在 Code Coverage Analysis 窗口的 Statement Analysis 视图查看覆盖数据:
- 若 Statement Analysis 视图未显示,在 Analysis 工具栏选 Statement Analysis(Figure 13-7)。

- 在 Files 窗口选择不同文件,Statement Analysis 视图会更新为所选文件的覆盖数据。
- 双击 Statement Analysis 视图中的任意条目,可在 Source 窗口中显示该行。
- 在 Coverage Details 窗口查看 toggle 覆盖细节:
- 在 Analysis 工具栏选 Toggle Analysis,切换到 Toggle Analysis 视图(Figure 13-7)。
- 点击 Details 标签打开 Coverage Details 窗口。若 Details 标签不可见,在主菜单选 View > Coverage > Details。
- 在 Toggle Analysis 中选中任意对象,在 Coverage Details 窗口中查看其覆盖细节(Figure 13-8)。

-
查看实例覆盖数据:
- 点击 Instance 标签切到 Instance Coverage 窗口。若 Instance 标签不可见,在主菜单选 View > Coverage > Instance Coverage。
Instance Coverage 窗口以扁平、非层次视图显示每个实例的覆盖统计。双击任意实例可在 Source 窗口中显示其源代码。
Instance Coverage 窗口内容示例:
| Instance | Design unit | Design unit type | Total coverage | Stmt graph | Stmt count | Stmts hit | Stmts mi |
|---|---|---|---|---|---|---|---|
| /test_sm | test_sm | Module | 52.6% | 77 | 70 | ||
| /test_sm/ill_op | TaskFunction | 100% | 2 | 2 | |||
| /test_sm/rd_wd | TaskFunction | 100% | 8 | 8 | |||
| /test_sm/wt_blk | TaskFunction | 100% | 10 | 10 | |||
| /test_sm/wt_wd | TaskFunction | 100% | 8 | 8 | |||
| /test_sm/ctrl | TaskFunction | 0% | 5 | 0 | |||
| /test_sm/nop | TaskFunction | 100% | 2 | 2 | |||
| /test_sm/sm_seq0 | sm_seq | Module | 65.6% | 16 | 15 | ||
| /test_sm/sm_seq0/… | sm | Module | 85.3% | 25 | 22 | ||
| /test_sm/sram_0 | beh_sram | Module | 45.4% | 6 | 5 |
Source 窗口中的覆盖统计
Source 窗口自带覆盖统计。在 Source 窗口中查看 beh_sram 的覆盖统计:
- 在 Files 窗口双击 beh_sram.v,在 Source 窗口打开源代码视图。
- 滚动 Source 窗口,看到 Figure 13-10 所示的代码。
Source 窗口中的覆盖统计(Figure 13-10):
| 38 | |
|---|---|
| 39 | always @ (negedge clk) |
| 40 | if (rd_ || wr_) begin |
| 41 | if (!rd) |
| 42 | dat_r /test_sm/sram_0/rd; |
| 43 | if (!wr_1 |
| 44 | mem[addr] <= m_dly dat; |
| 45 | end |
| 46 | else |
| 47 | if ((rd_ || wr_) == 0) |
| 48 | stime, , “Error: Simultaneous Reads & Writes no |
| 49 |
Source 窗口包含 Hits 和 BC 两列,分别显示语句命中数和分支覆盖。Figure 13-10 中鼠标悬停在 41 行代码上,这会使 Hits 和 BC 列的覆盖图标变为覆盖数字。Table 13-2 是各种覆盖图标的说明。
Table 13-2 Source 窗口中的覆盖图标:
| 图标 | 含义 |
|---|---|
| 绿色对勾 | 该语句已执行 |
| 绿色 E | 该行已被排除出代码覆盖统计 |
| 红色 X | Hits 列的 X 表示漏测(未执行)的语句(XS)、分支(XB)或条件(XC);BC 列的 X 表示漏测的 true(XT)或 false(XF)分支 |
-
选 Tools > Code Coverage > Show coverage numbers。
Hits 和 BC 列的覆盖图标被替换为每行的执行次数。红色数字表示该行存在漏覆盖;一行上有多个语句时显示省略号(…)。
C:/Tutorial/examples/tutorials/verilog/coverage/beh_sram.v (/test_sm/sram_0) - by file - Default
Hits BC Ln#
7499 38
7499 37498t 1f 39
7498 9372t 28126f 40
9372 41
7498 9376t 28122f 42
9376 43
44
45
46
47
1 0 48
0 49
always @ (negedge clk)
if (rd_ || wr_) begin
if (!rd_)
dat_r <= #M_DLY mem[addr];
if (!wr_)
mem[addr] <= #M_DLY dat;
end
else
if ((rd_ || wr_) == 0)
$display($stime, "Error: Simultaneous Reads & Writes no- 再选一次 Tools > Code Coverage > Show coverage numbers,取消勾选,回到图标显示。
读懂「行号错觉」
Source 窗口里红色 X 或红色数字只说明「这段代码没被执行过」,不一定是 bug——也可能是测试激励根本没覆盖到这条路径(比如上例 48 行的同时读写错误提示)。先补激励、再排代码,不要看到 X 就改 RTL。
Objects 窗口中的翻转统计
翻转(Toggle)覆盖统计每个逻辑节点从一个状态跳到另一个状态的次数。本章前面通过给 vlog、vcom 或 vopt 命令加 -cover x 参数启用了六态翻转覆盖。更多信息见 User’s Manual 的 Toggle Coverage。
在 Objects 窗口查看翻转数据:
- 在 Structure (sim) 窗口选中 test_sm。
- 若 Objects 窗口未打开,选 View > Objects。向右滚动查看各翻转覆盖列(Figure 13-12),或解除停靠并拉大窗口直到所有列都显示。若看不到翻转覆盖列,右键列标题栏,弹出菜单选 Show All Columns。
Objects 窗口中的翻转覆盖列示例:
| Z->1H | nodes | toggled | % Toggled | % 01 | Now | ||
|---|---|---|---|---|---|---|---|
| 0 | 32 | 11 | 34.38% | 34.38% | 11.46% | 0% | |
| 0 | 32 | 6 | 18.75% | 21.88% | 7.292% | 0% | |
| 0 | 1 | 1 | 100% | 100% | 33.33% | 0% | |
| 0 | 1 | 1 | 100% | 100% | 33.33% | 0% | |
| 0 | 32 | 6 | 18.75% | 21.88% | 7.292% | 0% | |
| 8 | 32 | 6 | 18.75% | 21.88% | 47.92% | …4% | |
| 0 | 10 | 4 | 40% | 40% | 13.33% | 0% | |
| 0 | 32 | 0 | 0% | 0% | 0% | 0% | |
| 0 | 32 | 0 | 0% | 0% | 0% | 0% | |
| 0 | 1 | 1 | 100% | 100% | 33.33% | 0% | |
| 0 | 1 | 1 | 100% | 100% | 33.33% | 0% |
把代码行和文件排除出覆盖统计
Questa SIM 允许把某些行和文件排除出代码覆盖统计。可以用 GUI 菜单、名为「exclusion filter file」的文本文件、源代码中的「pragma」,或 coverage exclude 命令来设置排除。pragma 是指示 Questa SIM 忽略括起代码覆盖统计的语句。排除过滤文件和 pragma 的细节见 User’s Manual 的 Coverage Exclusions。
- 在 Code Coverage Analysis 窗口的 Statement Analysis 视图中排除某一行:
- 把 Analysis Type 改为 Statement。
- 在 Statement Analysis 视图右键某行,弹出菜单选 Exclude Selection(也可以选 Exclude Selection For Instance <inst_name>,只为当前实例排除该选择)。
- 取消对已排除语句的排除:右键上一步排除的行,选 Cancel Selected Exclusions。
- 排除整个文件:
- 在 Files 窗口找到 beh_sram.v 文件(VHDL 示例为 beh_sram.vhd)。
- 右键文件名,选 Code Coverage > Exclude Selected File(Figure 13-13)。

- 取消所有文件排除:在 Files 窗口任意处右键,弹出菜单选 Code Coverage > Cancel File Exclusions。
生成代码覆盖报告
可以用 GUI 菜单或在 Transcript 窗口输入命令,生成文本或 HTML 格式的覆盖统计报告;也可以用菜单生成覆盖排除的文本报告。
用 GUI 菜单生成文本覆盖报告,二选一:
- 在主窗口菜单栏选 Tools > Coverage Report > Text。
- 在 sim 或 Files 窗口右键任意对象,弹出菜单选 Code Coverage > Code Coverage Reports。
在 Instance Coverage 窗口右键任意对象,弹出菜单选 Code coverage reports;Instance Coverage 窗口激活时也可在主窗口菜单栏选 Instance Coverage > Code coverage reports。
这会打开 Coverage Text Report 对话框(Figure 13-14),可以选择报告:所有文件、所有实例、所有设计单元、指定设计单元、指定实例或指定源文件。

Questa SIM 会在当前目录创建报告文件(默认名 report.txt),并立即在产品自带的 Notepad 文本查看器/编辑器中显示。「open in」栏允许你改为在 Source viewer 中显示报告,或在用 EDITOR 环境变量指定的编辑器中显示。见 User’s Manual 的 Setting Environment Variables。
生成 HTML 覆盖报告:在主窗口菜单栏选 Tools > Coverage Report > HTML,打开 Coverage HTML Report 对话框,指定 HTML 报告的输出目录路径即可。

HTML 覆盖报告提供浏览器中的动态覆盖视图(Figure 13-16)。HTML Coverage Summary 页面包含一个「List of Design Units included in report…」超链接,点击后跳转到一张表,列出设计中所有设计单元及各覆盖类型的覆盖百分比;这张表可按总覆盖或任一覆盖类型排序。
HTML 覆盖报告示例(Figure 13-16):
| Number of tests run: | 1 |
|---|---|
| Passed: | 1 |
| Warning: | 0 |
| Error: | 0 |
| Fatal: | 0 |
按结构汇总(Coverage Summary by Structure):
| Design Scope | Coverage |
|---|---|
| test sm | 61.33% |
| nop | 100.00% |
| ctrl | 0.00% |
| wt wd | 100.00% |
| wt blk | 100.00% |
| rd wd | 100.00% |
| ill op | 100.00% |
| sm seq0 | 73.72% |
| sram 0 | 50.37% |
按类型汇总(Coverage Summary by Type):
| Coverage Type | Bins | Hits | Misses | Weight | % Hit | Coverage |
|---|---|---|---|---|---|---|
| Statements | 124 | 112 | 12 | 1 | 90.32% | 90.32% |
| Branches | 42 | 37 | 5 | 1 | 88.09% | 88.09% |
| FEC Expressions | 11 | 11 | 0 | 1 | 100.00% | 100.00% |
| FEC Conditions | 2 | 0 | 2 | 1 | 0.00% | 0.00% |
| Toggles | 2094 | 296 | 1798 | 1 | 14.13% | 14.13% |
| FSMs | 31 | 22 | 9 | 1 | 70.96% | 75.45% |
| States | 11 | 10 | 1 | 1 | 90.90% | 90.90% |
| Transitions | 20 | 12 | 8 | 1 | 60.00% | 60.00% |
默认情况下 coverage report 命令生成文本文件,加 -html 参数才生成 HTML。用 notepad <filename> 命令可以在产品自带的 Notepad 查看器/编辑器中显示文本报告。
生成覆盖排除报告:在主窗口菜单栏选 Tools > Coverage Report > Exclusions,打开 Coverage Exclusions Report 对话框,可选择只显示 pragma 排除、只显示用户自定义排除、或两者都显示。

本课收尾
本章到此结束。继续之前需要结束当前仿真,在 VSIM> 提示符输入:
quit -sim自测
自测
vopt +cover=bcesxf test_sm -o test_sm_opt中的bcesxf分别对应哪些覆盖类型?加载设计时还需要加什么参数才能打开覆盖窗口?- Code Coverage Analysis 窗口里的 √、✕ 和 E 图标分别表示什么?Source 窗口的 Hits 列和 BC 列又各显示什么?
- 如何把整个 beh_sram.v 文件排除出覆盖统计?排除后如何取消?除了 GUI 菜单还有哪几种设置排除的方式?
- Toggle 覆盖统计的是什么?某信号 % Toggled 长期为 0% 可能说明什么设计问题?
- 生成覆盖报告有哪些方式?HTML 报告和默认文本报告相比多了什么能力?