之前一直在用terminal做所有的仿真和测试,看波形的机会没有很多,偶尔看过几次也是用gtkwave看的。但是说实话verdi还是有必要学一下的,毕竟是业界标准仿真工具(


why verdi

通过$display+gtkwave的方式对于小模块来说完全够用,但是当设计比较复杂的时候,信号线会有很多,想要找到他的驱动源光看waveform还是比较困难。

verdi是synopsys的一个调试平台,这个软件是把波形,源码,原理图等联合到一起,可以从一根有问题的信号线出发,快速定位到他的驱动逻辑。在业界verdi是很常用的debug工具,一般会配合Synopsys VCS/Cadence NC来做simulation.

verdi要读取三类文件:design(.v/.sv), testbench(.v/.sv), waveform(.fsdb).
其中.fsdb是compiler生成的synopsys系的波形文件。


open project

首先是学会通过verdi打开整个工程。这里选择打开week4中RAL模型的最后一组代码。

如果只需要打开波形文件,最简单的启动方式是:

1
verdi -ssf <waveform.fsdb> &

如果需要同时加载RTL代码,可以先给整个工程添加一个filelist.f用来管理代码文件:

filelist.f:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
dma.sv
dma_interface.sv
dma_seq_item.sv
dma_sequence.sv
read_sequence.sv
write_sequence.sv
dma_sequencer.sv
dma_driver.sv
dma_monitor.sv
ctrl.sv
intr.sv
io_addr.sv
mem_addr.sv
dma_reg_model.sv
dma_reg_seq.sv
dma_adapter.sv
dma_agent.sv
dma_model_env.sv
dma_sfr_defines.sv
dma_model_base_test.sv
dma_reg_test.sv
testbench.sv

然后我们可以通过以下命令打开verdi:

1
verdi -sv -f filelist.f -ssf dump.fsdb &

对于包含.sv文件的项目来说,-sv很重要,如果不写,明确指出对systemverilog的支持,有时会出现很多问题。

如果当时生成的不是synopsys的专用格式,可以通过verdi打开GUI之后通过File->Export->FSDB转成.fsdb,也可以通过vcd2fsdb input.vcd -o output.fsdb进行转化。完整的命令是:

1
vcd2fsdb input.vcd -o output.fsdb -top <top_module> -timescale=1ns

-top指定顶层模块,有时是必须的。

VCD本身信息有限,没有层次优化信息,还可能缺少dump的信号,如果想要使用verdi还是直接生成FSDB更好一点。

生成fsdb格式的waveform:

1
2
3
4
initial begin
$fsdbDumpfile("output.fsdb");
$fsdbDumpvars(0,top);
end

还要在编译的时候加上-debug_access+all.


from compile

可以从一个小体积的设计感受用法。

DUT

写一个简单的计数器。

counter.sv:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module counter(
input logic clk,
input logic rst_n,
input logic en,
output logic [7:0] cnt,
output logic overflow
);

always_ff @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt<='0;
else if(en)
cnt<=cnt+1;
end

assign overflow = (cnt == '1) && en;

endmodule

testbench

再写一个测试。

tb_counter.sv:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
module tb_counter;

logic clk;
logic rst_n;
logic en;
logic [7:0] cnt;
logic overflow;

counter u_counter(
.clk(clk),
.rst_n(rst_n),
.en(en),
.cnt(cnt),
.overflow(overflow)
);

always #5 clk=~clk;

initial begin
clk=0;
rst_n=0;
en=0;

#20 rst_n=1;
#10 en=1;

#3000;
en=0;
#200;

en=1;
#500;
$finish;
end

initial begin
$fsdbDumpfile("counter.fsdb");
$fsdbDumpvars(0, tb_counter);
end
endmodule

在某些版本中,可能不会完整dump logic,可以改成$fsdbDumpvars(0, "+all");或者$fsdbDumpvars(0, tb_counter, "+struct");

run.sh

还需要写一个编译并运行的脚本。

run.sh:

1
2
3
4
5
6
7
8
vcs -full64 -sverilog -debug_access+all \
-fsdb -timescale=1ns/1ps \
counter.sv \
tb_counter.sv \
-o simv_counter \
2>&1 | tee compile_counter.log

./simv_counter 2>&1 | tee sim_counter.log

after run…

将以上三个文件放到一个目录下运行,我们会得到counter.fsdb文件。

如果编译报错:最常见的问题是找不到FSDB相关的库。检查:

  • $VERDI_HOME/share/PLI/VCS/LINUX64 目录是否存在
  • 尝试加上 -P $VERDI_HOME/share/PLI/VCS/LINUX64/novas.tab $VERDI_HOME/share/PLI/VCS/LINUX64/pli.a

open via verdi

我们可以通过指定RTL文件(+tb文件)和.fsdb文件打开项目:

1
verdi -sv counter.sv tb_counter.sv -ssf counter.fsdb &
  • -sv:告诉Verdi用SystemVerilog模式解析(兼容Verilog)
  • counter.v tb_counter.v:加载源码(Verdi需要源码来做信号追踪)
  • -ssf counter.fsdb:加载波形文件
  • &:后台运行,不占用终端

也可以像之前说的一样写一个filelist.f:

1
2
counter.sv
tb_counter.sv

然后用指定filelist.f的方式打开:

1
verdi -sv -f filelist.f -ssf counter.fsdb &

刚打开应该是这样的:

open verdi!


windows

现在看到的这个界面,主要需要关注的应该是三个窗口。

windows name description
nTrace Source Browser 这个窗口用来看源码,点击信号名可以追踪
nWave Waveform Viewer 用来看波形
nSchema Schematic Viewer 看电路原理图,追踪信号连接关系的

显然在上面的图中,下方的黑色框框就是nWave,上面右侧有代码的部分就是nTrace.

open waveform

如果没有自动打开nWave,我们可以通过Tools->new waveform,或者是第二栏常用工具的waveform标志打开。

不过一般通过命令行打开,带有-ssf,或者是vcs编译过程中有-verdi -gui,一般nWave是会自动打开的。

add signals

刚打开的nWave是一个什么都没有的黑框,需要手动添加信号到波形窗口。

首先我们可以在菜单栏第二栏常用工具中打开signal_list小窗口,这样我们点击最左侧的Instance下的模块,在signal_list下就会出现对应的信号:

signal list

此时我们直接双击signal_list下的信号,就会显示到下面的nWave中。

当然还有其他添加方式,比如说可以通过在code中右键添加到nWave,还可以拖动信号直接到下面的nWave.

然后我们就可以在nWave窗口中观察这些信号的波形。

shortcut

关于波形,有一些常用的快捷键:

shortcut description
F 缩放到全局,看全部仿真时间范围
Z 放大视野观看
shift + Z 缩小视野观看
左键选择区域 框选放大
<- / -> 移动视图

其余按键和按钮可以自己多多探索。

signal trace

这个是真正重要的功能,也是verdi比gtkwave好用的地方。当我们需要人工debug的时候需要知道现在关注的信号是哪里来的,这个信号驱动了什么其他信号。

trace driver (alt + shift + D)

我们尝试追踪驱动源。在nWave窗口中,如果我想要找到是什么信号驱动了cnt,我们可以选中cnt,右键找到Show OneTrace Signals

trace

或者是上方第二行常用工具的蓝色左箭头D,

然后点击Driver,就会自动在源码中跳转到驱动cnt那行:

driver

trace load (alt + shift + L)

如果我们改成点击Load,就会显示cnt被谁,在哪一行代码中读取了:

load

trace connectivity (alt + shift + C)

如果选择点击connectivity,就会显示完整的driverload关系:

connectivity

nSchema

首先点击工具栏的Schematic,新建一个nSchema window.

然后我可以在左侧hierarchy双击一个实例模块,u_counter,可以看到nSchema中展示了一个counter模块的原理图:

Schematic

  • 我们可以在这里添加模块的信号到nWave,查看某信号的driver和load;

  • 双击某个模块可以跳转到它的代码定义;

  • 鼠标左键向四个方向拖动实现不同的功能。

find

当设计很大的时候手动找信号会比较慢,可以在signal_list下按ctrl + F开启搜索功能找到信号,支持通配符查找。

waveform compare

如果想要对比两个testcase的波形差异,可以:

  • 打开两个nWave窗口
  • 分别加载不同的.fsdb文件
  • 并排放置,对同一信号做视觉比较

waveform compare

assert / condition

可以打开最上方的window -> assertion debug mode进入assertion调试界面:

assertion debug mode

在这里的Property Statistics面板中,可以看到一条断言20_counter_sv_assert,scope是tb_counter.u_counter,但是这里的Failure, Success, Incomplete都是0,说明断言没有被触发到(因为我们代码里面其实没有进行断言)。

而且其实需要在代码中写一个assert有些东西才会显示。

在verdi中,assert是按需出现的(至少在2018.9版本中)。简单来说,想要让verdi出现assert功能,最好满足以下条件:

  1. 代码里面要有SVA,类似:
1
assert property (@(posedge clk) en |-> #1 cnt !=0);

如果代码里没有写assert,verdi只有临时添加assert.

  1. 编译的时候打开asserion
1
2
3
4
5
vcs -sverilog -assert enable_diag ...

# or

vcs -sverilog -assert svaext ...
  1. 打开KDB并且指定-dbdir:

编译时添加:

1
vcs -kdb ...

运行时添加:

1
./simv_counter -dbdir simv.daidir
  1. 仿真时记录assertion信息
1
./simv +assertfile +fsdb+assert +fsdb+all

我们可以在counter.sv中加一些简单的断言,重新编译,看看结果如何。

counter.sv:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

module counter(
input logic clk,
input logic rst_n,
input logic en,
output logic [7:0] cnt,
output logic overflow
);

always_ff @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt<='0;
else if(en)
cnt<=cnt+1;
end

assign overflow = (cnt == '1) && en;

// reset -> cnt == 0
property p_rst_cnt_zero;
@(posedge clk) !rst_n |-> (cnt == 8'h00);
endproperty
a_rst_cnt_zero: assert property (p_rst_cnt_zero)
else $error("cnt not zero during reset!");

// en = 0 -> cnt not been changed
property p_no_change;
@(posedge clk) disable iff (!rst_n)
!en |=> (cnt == $past(cnt));
endproperty
a_no_change: assert property (p_no_change)
else $error("cnt changed while en=0!");

// overflow condition
property p_overflow;
@(posedge clk) disable iff (!rst_n)
overflow |-> (cnt == 8'hFF) && en;
endproperty
a_overflow: assert property (p_overflow)
else $error("unexpected overflow!");

endmodule

修改tb_counter.sv:

1
2
3
4
5
initial begin
$fsdbDumpfile("counter.fsdb");
$fsdbDumpvars(0, tb_counter);
$fsdbDumpSVA; // new line
end

run.sh:

1
2
3
4
5
6
7
8
9
10
vcs -full64 -sverilog -debug_access+all \
-assert enable_diag -kdb \
-fsdb -timescale=1ns/1ps \
counter.sv tb_counter.sv \
-o simv_counter \
2>&1 | tee compile_counter.log

./simv_counter 2>&1 | tee sim_counter.log

./simv_counter +fsdb+assert +fsdb+all +assertfile +fsdb+sva_sucess -gui=verdi -dbdir simv_counter.daidir

这样打开的界面是这样的:

with code assertion

可以发现多了一个tcl console.

我们也可以通过tcl console进入assertion mode,输入verdiWindowWorkMode -assertionBrowser,返回0说明执行成功。

force/release

如果想要使用VCS的交互模式(-gui),可以通过交互模式启动:

1
2
3
4
vcs -full64 -sverilog -debug_access+all -fsdb \
counter.sv tb_counter.sv -o simv_gui

./simv_gui -gui & disown

在这里可以在仿真过程中强行改变信号值。

save/recover waveform

如果调好了波形的显示(顺序,颜色,格式等)可以保存:

  • nWave -> File -> Save Signal List -> save as .rc file

下次打开可以通过File -> Load Signal List恢复。

-gui

verdi + UVM

在跑UVM环境中,dump FSDB的方式有所不同。

当然也要在tb中加入:

1
2
3
4
5
initial begin
$fsdbDumpfile("test_name.fsdb");
$fsdbDumpvars(0, tb_top);
$fsdbDumpSVA;
end

编译要加上UVM开关:

1
vcs -ntb_opts uvm

感觉这一段有点多余

no relationship

一段无关紧要的内容。在之前我们安装过synopsys 2018.09版本的工具和6.17b版本的cadence virtuoso.

但是当时安装的时候走过不少弯路,而且版本也有点旧了,所以这里再安装一次2024.06版本的vcs和verdi.

preparation

首先准备一个已经装好rocky8.10的机子,打开之后,如果是使用virtual box的虚拟机,还需要额外安装一个vboxaddition来打开共享文件功能。

依旧是先安装运行vboxaddition安装程序的必要工具:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

sudo dnf update -y # update dnf env

sudo dnf install -y gcc make perl bzip2 tar elfutils-libelf-devel kernel kernel-devel kernel-headers
# compile env.

# 检查内核版本是否匹配
uname -r
rpm -q kernel-devel-$(uname -r)

# 如果不匹配就需要更新内核
sudo dnf update -y kernel kernel-devel kernel-headers
sudo reboot

然后安装vboxaddition:

1
2
3
4
cd /
sudo mount /dev/cdrom mnt
cd mnt
sudo ./VboxLinuxAdditions.run

安装之后重启,确认开启vbox shared以后,将当前用户添加到vboxsf组:

1
sudo usermod -aG vboxsf $(USER)

重启之后就可以让当前用户访问/media/sf_shared.

env

安装之前,还需要下载一些图形化依赖,因为synopsys的set_up.sh脚本是图形化安装。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo dnf groupinstall "Development Tools" -y
sudo dnf install libXScrnSaver.x86_64 -y
sudo dnf install -y \
libXScrnSaver \
xcb-util \
xcb-util-wm \
xcb-util-image \
xcb-util-keysyms \
xcb-util-renderutil \
libXext \
libXrender \
libXtst \
libXi \
libXrandr

全部安装完成之后,可以进入下一步软件的安装。

EDA install

我相信synopsys2024.06的相关软件资源大家都是可以在网上找到的,这里就不多说了。

安装方式也很简单,首先进入Installer_5.8文件夹下,运行./SynopsysInstaller_v5.8.run,获取set_up.sh.
这个set_up.sh可以启动下载器。对于个人使用,直接bash set_up.sh安装就行;如果有和他人分享软件的需要,可以将软件下载到/opt/synopsys下,运行set_up.sh的时候需要多加一个-install_as_root.

打开下载器之后,source选择scl_2024.06, vcs_all_vW-2024.09-SP1, verdi_vW-2024.09-SP1, 分别下载scl(证书管理), vcs(编译器), verdi(图形化工具).
目标下载目录选择/opt/synopsys即可。

下载完成之后,对于破解,首先需要将Patch_tools下的内容复制到对应的安装目录,比如:

1
2
3
sudo cp Patch_tools/* /opt/synopsys/scl/2024.06
sudo cp Patch_tools/* /opt/synopsys/verdi/W-2024.09-SP1
sudo cp Patch_tools/* /opt/synopsys/vcs/W-2024.09-SP1

之后进入每个文件夹,运行:

1
sudo ./pubkey_verify -y && sudo ./synopsys_checksum -y && sudo ./SynopsysMonoSlayer -a

完成补丁修正。

Synopsys.dat

我们需要转到windows实现破解。首先在linux机子上运行:

1
2
hostname
ip a

记住本机的hostname和MAC地址。

在windows上通过pubkey工具完成破解。对于2024.06版本的license,因为证书有过格式修改,所以还需要额外进行一步fix.bat Synopsys.dat进行修正。

active(?)

获得可用的Synopsys.dat之后,将这个证书放到<install_path>/scl/2024.06/admin/license下,然后打开文件,修改第二行的:

1
DAEMON snpslmd

为:

1
DAEMON snpslmd <install_path>/scl/2024.06/linux64/bin/snpslmd

这样就完成了证书的准备。

然后在~/.bashrc写好配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export SNPSLMD_LICENSE_FILE=27000@localhost.localdomain



# vcs
export VCS_HOME=/opt/synopsys/vcs/W-2024.09-SP1
export PATH=$PATH:$VCS_HOME/bin
export LD_LIBRARY_PATH=$VCS_HOME/linux64/lib:$LD_LIBRARY_PATH
export VCS_NO_LINUX_CHECK=1

# verdi
export VERDI_HOME=/opt/synopsys/verdi/W-2024.09-SP1
export LD_LIBRARY_PATH=$VERDI_HOME/share/PLI/VCS/linux64
export PATH=$PATH:$VERDI_HOME/bin

# scl
export SCL_HOME=/opt/synopsys/scl/2024.06
export PATH=$PATH:$SCL_HOME/linux64/bin
export VCS_ARCH_OVERRIDE=linux

#license
export LM_LICENSE_FILE=/opt/synopsys/scl/2024.06/admin/license/Synopsys.dat
alias lmg="lmgrd -c /opt/synopsys/scl/2024.06/admin/license/Synopsys.dat"

完成之后更新source ~/.bashrc,之后运行一次lmg,如果证书没有问题,可以尝试打开verdi,如果打开不闪退,说明安装成功。

这个方法其实也是有点问题的,因为会出现有时能够破解成功有时不行的问题,一些可能可行的建议如下:

  • 尝试使用实体机。我装了两次,第二次实体机成功了,猜测可能是新版scl的MAC验证方式更新有关。但是也有人虚拟机安装成功,也不好说。

  • user问题,如果无法运行可以尝试切换成root运行lmg.

  • 也可能是linux版本问题,我第二次装的是rocky8.10.

  • 可能是隐性的缺库,可以通过ldd查看。

  • proxy可能会影响license验证。

如果出现奇怪的抽风,而且license相关文件没有修改过,可以用以下方式尝试杀进程重新开始:

1
2
3
4
5
lmutil lmdown

ps aux | grep lmgrd

kill -9 <process id>

另:我这次在archlinux上也装好了。

verdi 2026.09

verdi 2026.09 2

2024的看着确实好看很多。

如果是在arch上装的话,下载依赖就应该改成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo pacman -S --needed \
base-devel \
libxss \
xcb-util \
xcb-util-wm \
xcb-util-image \
xcb-util-keysyms \
xcb-util-renderutil \
libxext \
libxrender \
libxtst \
libxi \
libxrandr \
lsb-release

从零开始的DFT工程师! homepage

project homepage is here.