这一篇在干嘛?
波形窗口只能告诉你「信号什么时候变了」,却说不清「是谁让它变的」。这一篇介绍两个按连通性思考的调试视图:Schematic(增量原理图)窗口和 Dataflow 窗口。你将学会从某个信号出发,逐级展开它的驱动者与读者(drivers/readers),像侦探一样反向追溯一个意外跳变、甚至一个 X(未知态)到底从哪条路径传播而来。示例设计是一个带 cache 模块和处理器读写请求的 test bench,分 Verilog 和 VHDL 两个版本。
Schematic 窗口:增量原理图调试(原文第 9 章)
Schematic 窗口的 Incremental(增量)视图可以按「进程到进程」的方式展开设计的物理连通性,显示某个信号、net、寄存器、进程、模块或 architecture 的驱动者/读者。
编译并加载设计
本课示例文件路径:
- Verilog –
<install_dir>/examples/tutorials/verilog/schematic - VHDL –
<install_dir>/examples/tutorials/vhdl/schematic
本课以 Verilog 版本为例,有 VHDL license 的读者可改用 VHDL 版本,操作步骤一致。
- 新建一个目录,把
<install_dir>/examples/tutorials/verilog/schematic下的所有文件复制进去(VHDL 用户复制vhdl/schematic目录)。 - 启动 Questa SIM 并切换到练习目录:
- 在 UNIX shell 输入
vsim,或 Windows 下双击 Questa SIM 图标;若弹出 Welcome to Questa SIM 对话框,点 Close。 - 选择 File > Change Directory,切换到第 1 步建的目录。
- 在 UNIX shell 输入
- 修改 WildcardFilter 设置,在 Questa SIM> 提示符下执行:
set WildcardFilter "Variable Constant Generic Parameter SpecParam Memory Assertion Endpoint ImmediateAssert"这条命令把默认列表中的「CellInternal」去掉了,让 cell 内部的所有信号也会被仿真器记录,从而在调试环境中可见。
- 执行本课 DO 文件:在 Questa SIM> 提示符输入
do run.do。该 DO 文件依次完成:- 创建工作库 —
vlib work - 编译设计文件 —
vlog或vcom - 优化设计 —
vopt +acc top -debugdb -o top_opt - 加载设计 —
vsim -debugdb top_opt - 把信号加入 Wave 窗口 —
add wave /top/p/* - 记录设计中所有信号 —
log -r /* - 运行仿真 —
run -all
- 创建工作库 —
- 把数值基改为符号制:输入
radix -symbolic并回车。
FPGA 语境
-debugdb优化选项保留了调试数据库,这是 Schematic/Dataflow 视图能工作的前提。在安路 TD 这类 FPGA 流程里,如果你习惯给网表加-O5之类的高优化等级,调试时记得退回保留可见性的选项,否则内部信号会被优化掉看不到。
探索连通性
- 打开 Schematic 窗口:选菜单 View > Schematic,或在 Transcript 窗口的 VSIM 提示符下执行
view schematic。窗口打开后默认处于 Incremental 视图。 - 向 Schematic 窗口添加一个信号:
- 确认 Structure (sim) 窗口中选中了实例 initial69。
- 把 strb 信号从 Objects 窗口拖到 Schematic 窗口(Figure 9-2)。

增量视图以橙色高亮显示 strb 信号。鼠标悬停在任何设计对象上都会弹出 tooltip 信息框,图中展示的是 initial69 模块(青色方框)的详情。每个信号 net 两端会显示当前值;Schematic 窗口获得焦点时,按键盘上的 v 键可以开关信号值显示。
- 查找 p 模块内部 strb 信号的读者:
- 在 p 模块内右键高亮的 strb 信号,选 Expand Net To > Readers(Figure 9-3)。
Readers 菜单"/>

- 查找 p 模块外部 strb 信号的读者。鼠标悬停到信号 pin 上时,光标会变成右箭头、左箭头或双向箭头:右箭头表示双击可展开到读者(fanout),左箭头表示双击可展开到驱动者,双向箭头则同时展开两者。

- 如图 9-5 所示,把光标移到 strb 信号上看到右箭头后双击。

- 所有读者随即被「长」出来(Figure 9-6)。

- 查找 p 模块中 NAND 门上 test 信号的驱动者:
- 点击 Show Wave 按钮,打开 Schematic 窗口内嵌的 Wave 查看器(窗口太小时可先拉大)。
- 在原理图中选中 NAND 门,该门输入输出信号的波形会载入 Wave 查看器,门本身高亮。

- 在 Wave 查看器中选中 test 信号,原理图中对应的 test 输入随之高亮(Figure 9-7)。

注意:内嵌 Wave 查看器激活时窗口标题是「Schematic -Default (wave)」,增量视图激活时是「Schematic -Default (schematic)」。
- 在原理图中点击高亮信号 test 的 pin,让原理图视图重新激活。
- 点击 Expand net to all drivers 图标。
- 从 Figure 9-8 可以看到,test 信号的驱动进程是 p 模块内的一个 i0 模块。

- 展开 c 模块中进程 always155(VHDL 版本标为 line_84)上信号 oen 的读者:
- 点击 oen 的 pin 使其激活。
- 在原理图任意处右键弹出菜单,选 Expand Net To > Readers,结果见 Figure 9-9。

oen 展开到读者时停在 s0–s3 实例的边界上。想看实例内部,双击实例内的 oen net,会「长」出一个三态器件(Figure 9-10)。

- 继续用上面任一方式探索设计:双击信号 pin 或 net、使用工具栏按钮、或用右键弹出菜单。
- 如果 net 两端的信号值叠在一起看不清(Figure 9-11):

- 点击 Regenerate 按钮重绘原理图,所有设计元素、信号值和 pin 名会清晰显示(Figure 9-12):
| clk | St0->St1 | St0->St1 | clk |
|---|---|---|---|
| St1 pstrb | St1 | St1 | pstrb |
| prw | St1 | St1 | prw |
- 结束时,按住 Delete Content 按钮不放,直到弹出菜单:

- 点击 Show Wave 按钮

关闭内嵌 Wave 查看器。
从原理图查看源代码
Schematic 窗口可以显示任何设计对象的源代码预览。
- 向 Schematic 窗口添加一个信号:
- 确认 Structure (sim) 窗口选中实例 p。
- 把 t_out 信号从 Objects 窗口拖到 Schematic 窗口。
- 双击 NAND 门,会弹出 Code Preview 窗口(Figure 9-13),所选对象的源代码被高亮。

Code Preview 窗口提供四键工具栏:在 Source Editor 中打开源码;把选中的代码重新居中显示;复制选中代码;在窗口底部打开 Find 工具栏搜索代码。
- 试着把几个工具栏按钮都点一遍。
- 结束时关闭 Code Preview 窗口,然后按住 Delete Content 按钮直到弹出菜单出现,选 Delete All 清空原理图视图。
折叠与展开实例
复杂实例的内容在增量视图中默认折叠(隐藏),以节省屏幕空间、提高可读性。
- 显示一个折叠实例:
- 在 Structure 窗口展开 c 模块的层次。
- 把 c 模块中的 s2 实例从 Structure 窗口拖到 Schematic。

折叠实例由带虚线边框的深蓝色方块表示(Figure 9-14);鼠标悬停时 tooltip 会显示 FOLDED。
- 展开这个折叠实例:
- 在折叠实例内部右键打开弹出菜单。
- 选择 Fold/Unfold,实例展开为 Figure 9-15。

因为我们只是把它拖进增量视图、并没有把任何信号追踪到它内部,所以此时看不到 s2 的内容。
- 显示 s2 实例的内容:双击 s2 内部的 addr net,相连的门和内部实例就会出现(Figure 9-16)。

- 重新折叠 s2:
- 左键点击 s2 实例边框使其高亮。
- 右键打开弹出菜单,选 Fold/Unfold 折叠实例。

- 试试其他折叠实例(s0、s1、s3)。结束后用 Delete Content 按钮清空原理图。
追踪事件
Schematic 窗口可以把事件追溯到它的起因。在增量视图任意处右键,选 Event Traceback 即可打开相关选项(Figure 9-18)。

事件追踪从当前「active time」开始,该时间由以下三者之一决定:Wave 窗口中选中的光标、Schematic 窗口内嵌 Wave 查看器中选中的光标、或 Schematic 窗口的 Current Time 标签。
打开 Current Time 标签
本例使用内嵌 Wave 查看器光标设定的时间。Current Time 标签默认打开,以下步骤用于在增量视图中开关它:
- 增量视图激活时,选 Schematic > Preferences 打开 Incremental Schematic Options 对话框。
- 在 Show 区勾选 Current Time label,点 OK 关闭对话框。

Current Time 标签出现在增量视图右上角。

追踪一个事件
- 向原理图添加对象:
- 确认 Structure (sim) 窗口选中实例 p。
- 把 t_out 信号从 Objects 窗口拖到原理图窗口。
- 打开 Schematic 窗口的 Wave 查看器:点击工具栏的 Show Wave 按钮。
- 在内嵌 Wave 查看器中显示某进程的信号:在原理图中选中 NAND 门,其输入输出波形即载入 Wave 查看器。
- 在 Wave 查看器中放一个光标指定 Current Time:
- 把光标拖到 Wave 查看器中 strb 波形 465 ns 处的跳变上。
- 在 Wave 查看器中选中 strb 的信号路径,原理图中 strb net 随之高亮(Figure 9-21)。

原理图右上角的 Current Time 标签此时显示光标所在时间 465 ns。 5. 追溯事件的起因:
- 在原理图中右键高亮信号打开弹出菜单。
- 选择 Event Traceback > Show Cause,会打开一个 Source 窗口,直接驱动进程被高亮(Figure 9-22)。
C:/Tutorial/examples/tutorials/verilog/schematic/top.v (/top) - Default
Ln# 1/2 Driver Lines
wire [15:0] sdata;
initial begin
clk = 1'b0;
end
always #20 clk = ~clk;同时 Transcript 窗口显示追踪结果(Figure 9-23):
find drivers -source -time {465 ns} -cause /top/p/strb
# Multiple active drivers exist at time 460 ns for signal sim:/top/p/strb:
# PROCESS: #ALWAYS#29 SIGNAL: /top/clk FILE: top.v:29
# PROCESS: #INITIAL#25 SIGNAL: FILE: top.v:26
#
# ----
# *PARTIAL* causality trace results for signal "sim:/top/p/strb":
#
# Time | Type | Scope | Signal | Source File
# ---- | ---- | ---- | ---- | ----
# 460 ns | Gate | /top/p | strb_r | proc.v:25
# 460 ns | PROCESS | /top/p | clk | proc.v:69
# 460 ns | Gate | /top | clk | top.v:29- 想看路径细节:按住 Event Traceback 工具栏按钮不放,弹出菜单出现后选 View Path Details,打开 Active Driver Path Details 窗口。它显示导致所选事件的时序进程信息:信号名、因果路径上每个进程的时间、以及因果进程在代码中的位置。

- 在 Schematic 窗口中查看 assign251 进程上 strb_r 的路径细节:
- 点击 Active Driver Path Details 窗口顶行,选中 strb_r 的驱动者。
- 点击对话框 View Path Details 区的 Schematic Window 按钮(Figure 9-25)。

这会打开一个专属的 Schematic (Path Details) 窗口,显示所选驱动者的路径细节(Figure 9-26)。其 Wave 查看器区还会显示 Trace Begin 和 Trace End 两个光标。

可以继续用同样方式追踪其他事件、在专属 Schematic 和 Wave 窗口中查看路径细节。 7. 继续之前清空 Schematic 窗口:
- 关闭 Active Driver Path Details 窗口。
- 关闭 Schematic (Path Details) 窗口。
- 点击 Schematic 标签切回原 Schematic 窗口。
- 用 Delete Content 按钮清空 Schematic Viewer。
- 点击 Show Wave 图标关闭原理图窗口的 Wave 视图。
本课收尾
- 在 VSIM> 提示符输入:
quit -sim把 WildcardFilter 恢复出厂默认:
set WildcardFilter "default"Dataflow 窗口调试(原文第 10 章)
Dataflow 窗口同样用于探索设计的「物理」连通性、追踪在设计中传播的事件、找出意外输出的原因。窗口中显示进程、信号/net/寄存器以及互连关系。
编译并加载设计
本课示例文件路径:
- Verilog –
<install_dir>/examples/tutorials/verilog/dataflow - VHDL –
<install_dir>/examples/tutorials/vhdl/dataflow
- 新建目录,把
<install_dir>/examples/tutorials/verilog/dataflow下所有文件复制进去(VHDL 用户复制vhdl/dataflow目录)。 - 启动 Questa SIM 并切换目录:
- UNIX shell 输入
vsim,或 Windows 下点 Questa SIM 图标;欢迎对话框出现则点 Close。 - 选 File > Change Directory 切到练习目录。
- UNIX shell 输入
- 修改 WildcardFilter 设置:
set WildcardFilter "Variable Constant Generic Parameter SpecParam Memory Assertion Endpoint ImmediateAssert"同样是去掉默认列表中的「CellInternal」,让 cell 内所有信号被记录、在调试环境中可见。
4. 执行 DO 文件:在 Questa SIM> 提示符输入 do run.do。它依次:创建工作库、编译设计文件、优化设计、加载设计、把信号加入 Wave 窗口、记录设计中所有信号、运行仿真。
5. 打开 Dataflow 窗口:在 VSIM> 提示符输入 view dataflow 并回车。
6. 改基为符号制:在 VSIM> 提示符输入 radix -symbolic。
探索连通性
- 向 Dataflow 窗口添加信号:
- 确认 Structure (sim) 窗口选中实例 p。
- 把 strb 信号从 Objects 窗口拖到 Dataflow 窗口(Figure 10-1)。

- 探索设计:
- 点击 Expand net to all readers 图标。

视图展开,显示与 strb 相连的进程(Figure 10-2)。

- 查找进程 nand50(VHDL 版本标为 line_71)上 test 信号的驱动者: i. 点击 Show Wave 图标打开 Wave 查看器(必要时拉大 Dataflow 窗口)。 ii. 在 Dataflow 查看器中选中 nand50 门(VHDL 版本标为 t_out_asgn),其输入输出波形载入 Wave 查看器,门高亮。 iii. 在 Wave 查看器中选中 test 信号,Dataflow 查看器中 test 输入随之高亮(Figure 10-3)。

iv. 在 Dataflow 查看器中选中该高亮信号(使 Dataflow 窗口的这一部分激活),然后点击 Expand net to all drivers 图标。
Figure 10-4 中绿色高亮标出你在设计中走过的路径。

- 选中进程 always155(VHDL 版本标为 line_84)上 oen 信号的 net,点击 Expand net to all readers 图标。

想继续探索随意。结束时按住 Delete Content 按钮不放,出现下拉列表后选 Delete All 清空 Dataflow 查看器。
追踪事件
另一个实用功能是追踪造成意外输出值的事件。借助 Dataflow 窗口的内嵌 Wave 查看器,可以从一次跳变反向追溯到导致该意外输出的进程或信号。
- 设置默认行为:在 Wave 窗口双击信号时在 Dataflow 窗口显示驱动者。
- 点击 Wave 窗口标签使其激活。
- 选 Wave > Wave Preferences,打开 Wave Window Preferences 对话框。
- 在「Double-click will:」菜单中选 Show Drivers in Dataflow,点 OK(Figure 10-6)。

- 向 Dataflow 窗口添加对象:
- 在 Wave 窗口中双击 t_out 波形任意处。Source 窗口会打开并显示该信号的源代码。
- 点击 Dataflow 标签打开 Dataflow 窗口。
- 若尚未打开,点击 Show Wave 图标打开 Wave 查看器(必要时拉大窗口)。
- 点击 nand50 门,在 Wave 查看器中显示其输入输出(Figure 10-7)。

- 追踪 NAND 门的输入:
- 在 Dataflow 查看器中双击进程 nand50(VHDL 版本标为 line_71)。显示跳到 proc.v 的源代码视图,蓝色箭头指向 NAND 门的声明处(Figure 10-8)。
C:/Tutorial/examples/tutorials/verilog/dataflow/proc.v (/top/p) - Default
Ln#
49 nor (test2, _rw, test_in);
50 nand (t_out, test, strb);
51
52 task write;
53 input [`addr_size-1:0] a;
54 input [`word_size-1:0] d;
55 begin
56 if (verbose) $display("%t: Writing data=%h to addr=%h", $time
57 addr_r = a;- 点击 Dataflow 标签回到 Dataflow 窗口。
- 在 Wave 查看器中滚动到 t_out 的最后一次跳变。
- 点击 t_out 最后一次跳变的右侧,光标会吸附到 2785 ns(Figure 10-9)。

- Dataflow 查看器中 t_out 应为红色高亮。点击该高亮信号使其激活,然后选 Tools > Trace > Trace next event 追踪第一个相关事件。
Questa SIM 会在 Wave 查看器加一个光标,标出最后一个事件——2745 ns 处 strobe 跳到 St0——正是它使 t_out 输出 St1(Figure 10-10)。

- 再选两次 Tools > Trace > Trace next event,观察光标跳到下一个事件。
- 选择 Tools > Trace > Trace event set。
Dataflow 流程图长出前一级进程,显示 strb 信号的输入驱动者(Figure 10-11)。同时 Wave 查看器也会显示新选中进程的输入输出信号。

可以照此方式继续在设计中追踪事件:反复选 Trace next event 直到 Wave 查看器中出现你感兴趣的跳变,再选 Trace event set 更新 Dataflow 流程图。
- 结束时选 File > Close Window 关闭 Dataflow 窗口。
追踪 X(未知态)
Dataflow 窗口可以轻松追踪未知值(X)在设计中传播的过程。它与 Wave 窗口动态联动:先在 Wave 窗口看信号,再用 Dataflow 窗口追问题的源头;在 Dataflow 中遍历时,相关信号会自动加进 Wave 窗口。
-
在 Wave 和 Dataflow 窗口中查看 t_out:
- 在 Wave 窗口滚动到能看到 /top/p/t_out。
t_out 在 2066 ns 变为未知态 StX,之后一直 1 与未知之间来回跳(Figure 10-12)。波形的红色表示未知值。

双击波形后源代码视图再次打开并指向 t_out;同时会自动打开一个 Dataflow 窗口,显示 t_out、相关进程和它的波形。
- 点击 Dataflow 标签激活 Dataflow 窗口。
因为上次关闭窗口时 Wave 查看器是打开的,它会再次在 Dataflow 窗口内打开,且 t_out 处于高亮(Figure 10-13)。

- 把光标放在 t_out 为未知的时间上(例如 2728 ns)。
-
追踪未知态:
- 在 Dataflow 查看器中点击高亮信号使查看器激活(激活后查看器四周出现黑框;信号被选中时呈橙色)。
- 选菜单 Tools > Trace > ChaseX。
设计展开,显示 t_out 未知态的来源(Figure 10-14):本例中输入信号 test_in 为 HiZ 值(VHDL 版本为 U)、输入信号 _rw(VHDL 版本为 bar_rw)为 St0,使 test2 输出解算为未知态(StX),未知态再传播到 t_out。

FPGA 语境
X 态传播是 FPGA 仿真里最常见的「玄学问题」来源:安路 TD 综合后的寄存器没有复位初值、或异步复位未覆盖全部寄存器时,上电仿真经常满屏 X。学会用 ChaseX 反向追到第一个产生 X 的源头(往往是未复位的寄存器或未驱动的输入),比盯着波形猜要高效得多。
- 继续之前清空 Dataflow 窗口:
- 点击 Delete All 图标清空 Dataflow 查看器。
- 点击 Show Wave 图标关闭 Dataflow 窗口的 Wave 视图。
在 Dataflow 窗口显示层次
可以用层次实例的方式在 Dataflow 窗口中显示连通性——前提是在添加对象之前先改好选项。
- 修改选项以显示层次:
- 在主窗口菜单选 Dataflow > Dataflow Preferences > Options(窗口未停靠时,在 Dataflow 窗口菜单栏选 Tools > Options),打开 Dataflow Options 对话框(Figure 10-15)。

- 选 Show: Hierarchy,点 OK。
- 向 Dataflow 窗口添加信号 t_out:在 VSIM> 提示符输入:
add dataflow /top/p/t_outDataflow 窗口会显示 t_out 及所有层次实例(Figure 10-16)。

本课收尾
- 在 VSIM> 提示符输入:
quit -sim恢复 WildcardFilter 出厂默认:
set WildcardFilter "default"自测
自测
- 在 Schematic 增量视图中,鼠标悬停信号 pin 时出现的三种箭头(右箭头、左箭头、双向箭头)分别对应什么展开行为?
- 为什么要先执行
set WildcardFilter "Variable Constant Generic Parameter SpecParam Memory Assertion Endpoint ImmediateAssert"再加载设计?- Schematic 窗口的事件追踪(Event Traceback > Show Cause)从哪个「active time」开始?它由哪三种方式设定?
- 在 Dataflow 窗口中,Trace next event 与 Trace event set 两个操作各做了什么、通常怎样配合使用?
- ChaseX 追踪 t_out 的未知态后,发现根源是什么?这个功能对调试 FPGA 上电仿真中的 X 态有什么帮助?