本文主要介绍VCS进行verilog代码debug的基本方法
一、使用系统函数
首先我们在编写verilog模块的testbench时,可以在里面使用一些verilog的系统函数,在运行simv文件跑仿真时,进行一些控制。例如:
函数 | 含义 |
---|---|
$time | 代表当前的仿真时间 |
$display | 类似C语言的printf函数,仿真时在终端上打印一些信息,比如一些变量的值 |
$monitor | 和$ display类似,不同的是$ display在被调用的时候打印一些信息,$monitor可以自动监测变量,当变量值发生变化时,便打印出信息 |
$stop | 调用时使仿真产生一次中断 |
$finish | 调用时使仿真结束 |
$readmemb | 用于存储器建模时的初始化,将一个文本文件里的数据,写入存储器 |
$readmemh | 以十六进制数写入 |
$readmemb | 以二进制数的形式写入 |
二、使用UCLI (用户命令行接口)
使用 UCLI 进行Debug其实是非常低效的,使仿真在错误的地方停止,用命令打开一个一个“黑盒子”(module) 并查看内部信号与预期是否一致。在实际使用VCS的时候基本不用,在此简单介绍,不做过多赘述。
三、使用DVE
在前面我们已经使用命令 ./simv -gui 。以图形化界面的方式运行仿真。以下介绍一种更为常用的方式
module addertb;
reg [7:0] a_test, b_test;
wire [7:0] sum_test;
reg cin_test;
wire cout_test;
reg [17:0] test;
add8 u1(a_test, b_test, cin_test, sum_test, cout_test);
initial begin
`ifdef DUMP_VPD
$vcdpluson();
`endif
end
initial
begin
for (test = 0; test <= 18'h1ffff; test = test +1) begin
cin_test = test[16];
a_test = test[15:8];
b_test = test[7:0];
#50;
if ({cout_test, sum_test} !== (a_test + b_test + cin_test)) begin
$display("***ERROR at time = %0d ***", $time);
$display("a = %h, b = %h, sum = %h; cin = %h, cout = %h",
a_test, b_test, sum_test, cin_test, cout_test);
$finish;
end
#50;
end
$display("*** Testbench Successfully completed! ***");
$finish;
end
endmodule
在 addertb.v 中新增了一个 initial 块。表示如果在编译时,定义了 DUMP_VPD 这个宏,那么在仿真时,打开 $vcdpluson() 这个开关选项
使用上图命令编译源码后仿真,+define+DUMP_VPD表示在编译时定义 DUMP_VPD 这个宏,即在仿真时,打开了$vcdpluson() 这个开关选项。
我们可以看到,在仿真完成后,生成了 vcdplus.vpd 这个文件。这个文件记录了仿真过程中所有信号的波形,可以使用 dve 打开
通过 dve & 命令打开 dve, "&"的用途是后台打开dve,以免终端被占用。我们可以看到 dve 打开后界面为空白
File -> Open Database
选择 vpd 文件并打开
在Hierarchy 部分,可以查看顶层模块里面的子模块,右键 -> Add to Waves 查看对应模块的波形图。
在上述方法中,在编译时通过定义一个宏,打开 testbench 中 $vcdpluson() 这个开关选项,在运行 simv 进行仿真时,VCS便把所有的波形记录下来,生成一个 .vpd 文件 (波形文件)。在dve中打开文件,即可查看仿真波形,方便之处在于波形可以发给他人查阅。
几点补充:
1.在编译时,将 -debug_all 选项 更改为 -debug_pp
。打开生成 VPD 文件的功能,关掉UCLI的功能,节约编译时间。
2.在编译时,使用 +define+macro1 将宏macro1传给源代码。使用+define+macro1=value+macro2=value 将macro1和macro2 传给源文件中同名的宏。
3.在编译时,使用 +vpdfile+filename 可以更改生成 VPD 文件的文件名,默认为 vpdplus.vpd。
4.可直接使用命令: dve -vpd vcdplus.vpd & 后台打开 dve 并加载 vpd 文件,代替上面图7~图9的过程。
5.调用 $ vcdpluson() 时可以加入一些参数,如果什么都不加,则默认记录顶层模块下所有子模块的信号波形。参数格式:$vcdpluson(level_number, module_instance, … , … )。比较重要的参数为前两个。数字设计里面的 module 是层次化/结构化的,类似于一层一层的黑盒子不断包含下去。module_instance 表示从哪一个module开始记录波形,level_number表示查看 module_instance 下子模块多少层的波形。下面使用一些例子来说明。
本文介绍了VCS 进行 debug 的三种方式,其中第三种是最常使用最有效的。
在实际工程中,通常使用VCS生成 fsdb 格式的波形文件,将其导入另一个软件 Verdi 查看波形,代替DVE进行联合仿真
参考:
https://zhuanlan.zhihu.com/p/129034106
https://www.bilibili.com/video/BV1oF411Y7hh?spm_id_from=333.999.0.0