数字IC前端设计——前仿篇(VCS,DVE,Verdi)
文章目录
- 引言
- 一、软件介绍
- 1. VCS
- 2. DVE
- 3. Verdi
- 二、VCS的使用
- 1. VCS的编译流程
- 2. 常用的编译选项
- 1)基础编译选项
- 2)调试相关选项
- 3)性能优化选项
- 4)文件和路径选项
- 3. 常用仿真选项
- 1)基础仿真选项
- 2)运行控制选项
- 3)调试和分析选项
- 3. VCS生成物
- 4. 波形文件的生成
- 1)VCD (Value Change Dump)的生成
- 2)VPD (Verilog Procedural Dump)的生成
- 3)FSDB (Fast Signal Database)的生成
- 三、DVE/Verdi波形查看
- 1. DVE查看波形
- 2. Verdi查看波形
- 四、VCS-Verdi lab(入门)
- 1. 文件管理
- 2. VCS编译和仿真
- 1)一步(推荐)
- Verdi查看波形
- DVE查看波形(需要修改tb中的波形生成部分成vpd和vcd)
- 2)两步
- DVE查看波形
- Verdi查看波形
- 3. makefile
- 附录
- 1. ALU代码
- 2. TestBench代码
参考文献
VCS使用教程 (Synopsys VCS Simulator Tutorial)
Linux下VCS与Verdi联合仿真简易教程及例子示范
Verdi的使用
Verdi快速使用技巧
引言
在FPGAer/ICer的实际项目中,仿真无疑占了大量的时间。我想对于仿真工具有人更倾向于使用Vivado、ModelSim、QuestaSim这些编译-仿真-看波形一体化的工具,也有人更倾向于VCS(编译仿真)、Verdi和DVE(看波形)这些独立功能的工具。两者各有优劣。
前者工具链简单易上手,甚至Vivado除了编译、仿真和看波形以外还能实现综合、布局布线等等功能,可谓神器。但是前者也有明显的缺点,比如说综合、编译、仿真速度很慢。
而后者工具链较为复杂,编译和看波形为独立的工具。如果在做ASIC项目中,后者会更加方便和专业。首先,VCS编译和仿真速度极快,效率极高,能够大量节约仿真时间(仿真速度:FPGA>VCS>ModelSim/QuestaSim>Vivado)。而Verdi查看波形也十分方便,支持信号追溯等等功能。
综上所述,为了提高开发效率,下面将以一个简单的ALU的工程来展示如何在Linux下使用VCS和Verdi进行逻辑仿真。此部分只涉及前仿,后仿涉及DC等综合工具。
可以看完第四部分跑完lab后再返回看VCS的详细的选项功能
一、软件介绍
1. VCS
VCS(Verilog Compiled Simulator)是 Synopsys 公司开发的一款高性能仿真工具,它采用编译型仿真技术,将 Verilog/SystemVerilog 代码编译成优化的 C 代码,再编译成可执行文件,从而实现高速仿真。虽然 VCS 本身不直接提供图形化调试界面,但它可以与 Synopsys 的其他工具(如 Verdi)集成,实现高效的调试和波形查看。
同时,VCS 提供了丰富的编译和仿真选项,可以根据设计需求进行灵活配置。VCS 提供了丰富的覆盖率分析选项,包括行覆盖率、条件覆盖率、状态机覆盖率和翻转覆盖率等,有助于Verifier全面评估测试的充分性。
为什么VCS会更快?因为VCS采用了编译型仿真。相较于解释型仿真(传统模式),其优点在于仿真速度极快、内存使用效率高、支持大规模设计以及优化程度高,但是编译时间较长、调试较为复杂并且修改代码需要重新编译。
2. DVE
DVE(Design Verification Environment)是由Synopsys公司开发的一款强大的硬件设计验证工具,主要用于协助工程师分析和调试仿真结果。DVE是集成在了VCS中。
3. Verdi
Verdi 是 Synopsys 提供的一款强大的自动化电子设计自动化(EDA)工具,主要用于功能验证和调试。Verdi 综合了多种调试功能,如波形查看、信号追踪、时序分析和覆盖规划等,为设计验证工程师提供了一个全面的环境进行设计错误的识别和修正。Verdi是比DVE更强大的调试平台,尤其在协议分析、性能分析和根本原因分析(RCA)方面表现出色。
Verdi 工具集包括以下几个组件:
- Waveform Viewer (波形查看器):图形化展示波形数据,支持对仿真数据进行深入分析。
- Signal Spy (信号监视器):实时监测设计中的信号变化,用于调试。
- Time Analysis (时序分析):分析设计中时序问题,帮助识别时序违规。
- Coverage (覆盖率分析器):分析验证的覆盖面,确保测试充分。
- Data Mining (数据挖掘):利用高级算法来发现设计中的潜在问题。
二、VCS的使用
值得注意的是VCS本身不提供图形化界面,因此只能通过terminal来运行。
1. VCS的编译流程
VCS采用两阶段编译模式,提供灵活性和高性能。
RTL源码—>vlogan前端编译—>生成数据库文件—>vcs后端编译—>生成simv可执行文件—>./simv仿真执行—>生成波形和日志
因此,VCS也提供了两种编译方式,分别为一步编译(推荐用于简单项目),两步编译(推荐用于复杂项目)。
# 一步编译
vcs [编译选项] [源文件] -o [输出文件名]
# 两步编译
vlogan [编译选项] [源文件] # 前端编译
vcs [链接选项] [顶层模块] -o [输出文件名] # 后端编译
该文以一步编译模式为主。
2. 常用的编译选项
1)基础编译选项
指令 | 功能 | 示例 | 描述 |
---|---|---|---|
-help | 显示帮助文档 | vcs -help | 查看vcs的可用选项 |
-full64 | 64位编译模式 | vcs -full64 | |
-sverilog | 支持SystemVerilog | vcs -sverilog | |
+v2k | 支持Verilog-2001 | vcs +v2k | |
-timescale | 指定时间精度 | vcs -timescale=1ns/1ps | 也可以tb中指定 |
-o | 输出文件名 | vcs -o my_sim | 默认simv |
-kdb | 输出fsdb文件需要 | vcs -kdb |
2)调试相关选项
指令 | 功能 | 示例 | 描述 |
---|---|---|---|
-debug_access+all | 完全调试访问 | vcs -debug_access+all | 查看所有信号 |
-debug_access+r | 只读调试访问 | vcs -debug_access+r | 只读模式 |
-line | 启用行号调试 | vcs -line | |
+lca | 生成覆盖率数据库 | vcs +lca | 用于覆盖率分析 |
-cm | 覆盖率采集类型 | vcs -cm line+cond+fsm+tgl | 采集line/cond/fsm/tgl覆盖率 |
-cm_dir | 指定存放覆盖率数据库的目录 | ||
-cm_name | 为当次仿真产生的覆盖率数据命名 |
NOTE:收集行覆盖率(line)、条件覆盖率(cond)、有限状态机覆盖率(fsm)和翻转覆盖率(tgl)
覆盖率类型:
代码覆盖率 (Code Coverage):
- line: 每行可执行代码是否被执行。
- cond: if-else、case语句的每个分支是否被走到。
- fsm: 状态机的每个状态和状态转移是否被访问。
- tgl: 每个bit信号是否经历了0->1和1->0的翻转。
功能覆盖率 (Functional Coverage):通过SystemVerilog的 covergroup 定义,衡量设计规格中的功能点是否被测试到。
断言覆盖率 (Assertion Coverage):衡量SVA断言被触发、成功和失败的次数。
3)性能优化选项
指令 | 功能 | 示例 | 描述 |
---|---|---|---|
-Mupdate | 增量编译 | vcs -Mupdate | 只编译修改的文件 |
-j | 并行编译核心数 | vcs -j8 | 8个CPU核心 |
-comp | 优化编译 | vcs -comp | 编译时优化 |
-no_save | 不保存中间文件 | vcs vcs -no_save | 节省可见 |
-fast | 快速模式 | vcs -fast |
4)文件和路径选项
指令 | 功能 | 示例 | 描述 |
---|---|---|---|
-f | 文件列表 | vcs -f filelist.f | 包含源文件路径 |
-v | 库文件 | vcs -v my_lib.v | 单个库文件 |
-y | 库目录 | vcs -y ./lib | 单个库目录 |
+libext+ | 库文件扩展名 | +libext+.v+.sv | 搜索文件类型 |
+incdir+ | include目录 | +incdir+./inc | `include文件路径 |
+define+ | 预定义宏 | +define+SIM_MODE | 编译时宏定义 |
3. 常用仿真选项
1)基础仿真选项
指令 | 功能 | 示例 | 描述 |
---|---|---|---|
-R | 编译后立即运行 | vcs -R tb.v | 一步完成 |
-gui | 启动图形界面 | ./simv -gui=dve | DVE调试界面,也可以-gui=verdi |
-l | 日志文件 | ./simv -l sim.log | 指定仿真日志路径 |
-s | 交互模式 | ./simv -s | 在时间0停止 |
2)运行控制选项
指令 | 功能 | 示例 | 描述 |
---|---|---|---|
+ntb_random_seed= | 随机种子 | ./simv +ntb_random_seed=123 | 确定性随机序列 |
+vcs+lic_wait | 等待license | ./simv +vcs+lic_wait | license不足时等待 |
+vcs+stop+ | 指定停止时间 | ./simv +vcs+stop+1000 | 1000时间单位后停止 |
3)调试和分析选项
指令 | 功能 | 示例 | 描述 |
---|---|---|---|
-ucli | 启动UCLI | ./simv -ucli | 统一命令行界面 |
-vpd_file | VPD文件名 | ./simv -vpd_file sim.vpd | 指定波形文件 |
-cm_name | 覆盖率名称 | ./simv -cm_name test1 | 覆盖率数据库名 |
-cm_dir | 覆盖率目录 | ./simv -cm_dir ./cov | 覆盖率存储路径 |
3. VCS生成物
执行vcs指令后一般会生成一些文件。其中比较关键的是:
- simv:为可执行文件,可以使用./simv来运行仿真。
- sim.log:为vcs的运行日志,名字为用户自己设置。
- csrc:存放vcs生成的C语言源码。vcs将RTL代码转换成C代码后再使用系统的C/C++编译器来创建最终的可执行文件,
- simv.daidir:为vcs的中间数据库目录,包含了设计的层次化信息。
- .vcd/vpd/.fsdb:为波形文件,vcs生成,dve和verdi可以直接打开此类文件查看波形,无需重新编译和仿真。
4. 波形文件的生成
vcs可以生成不同格式的波形文件。常见的有以下三种:
格式 | 优点 | 缺点 | 查看工具 |
---|---|---|---|
VCD | 通用性强,可读 | 文件大,速度慢 | DVE,Verdi |
VPD | 压缩率高,VCS原生 | Synopsys生态 | DVE,Verdi |
FSDB | 压缩率极高,功能强 | Verdi生态 | Verdi |
以上这些波形文件格式的生成代码需要放置再testbench中,指定波形文件格式和保存的内容。
1)VCD (Value Change Dump)的生成
//在Testbench中添加系统任务
initial begin$dumpfile("tb.vcd");$dumpvars(0, top_module_name); // 0表示dump所有层级
end
2)VPD (Verilog Procedural Dump)的生成
//在Testbench中添加 $vcdpluson; 系统任务,并在编译时开启调试选项。
initial begin$vcdpluson();
end
3)FSDB (Fast Signal Database)的生成
//需要Verdi的环境支持,并在Testbench中调用特定系统任务。
initial begin$fsdbDumpfile("tb.fsdb");$fsdbDumpvars(0, "top_module_name");
end
$fsdbDumpfile(fsdb_name[,limit_size])
指定波形文件名,第二个参数可选择用来限制波形的大小(MB)。
$fsdbDumpvars([depth, instance][, “option”])
depth表示要加载波形的层次:
0表示当前instance下的所有变量以及其它module实例的波形;
1表示当前instance中的变量的波形,不包括当前instance中的其它module实例的波形;
2表示包含当前instance以及其中的第一级子instance的波形;以此类推。
instance指定要加载波形的module名。
option加载波形的选项:
+IO_Only – 只加载IO port信号;
+Reg_Only – 只加载reg类型信号;
+mda – 加载memory和MDA信号;
+packedmda – 加载packed MDA;
+struct – 加载structs;
+parameter – 加载parameter;
+fsdbfile+filename – 指定fsdb文件名字。(可覆盖dumpfile操作)
三、DVE/Verdi波形查看
1. DVE查看波形
DVE的启动很简单,只需要在vcs执行完生成vpd/vcd波形文件后,即可用以下指令打开。
dve -vpd vcdplus.vpd &
dve -vcd tb.vcd &
2. Verdi查看波形
Verdi的启动也很简单,只需要在vcs执行完生成vpd/vcd/fsdb波形文件后,即可用以下指令打开。
verdi -f filelist.f -ssf tb.fsdb &
四、VCS-Verdi lab(入门)
1. 文件管理
首先,第一步就是进行文件管理。一般文件管理我采用以下结构,rtl用来放置RTL代码,makefile为运行脚本,sim用来保存vcs仿真的结果和波形,tb用来放置testbench文件。此外,还有一个比较重要的便是设计文件列表filelist.f(注意文件的路径正确)。
2. VCS编译和仿真
1)一步(推荐)
在sim路径下打开terminal并执行以下指令
单步执行的在编译vcs时候加入了-R选项,使得vcs在编译完后直接运行./simv。
# -kdb为生成fsdb所需,否则无法使用verdi打开
vcs -R -full64 -debug_access+all -timescale=1ns/1ps -f filelist.f
执行完后得到一些文件,可见 第3小节文件生成物。值得关注的便是tb.fsdb波形文件。
单步编译后可以直接查看波形。
Verdi查看波形
在sim路径下打开terminal并执行以下指令,启动verdi
verdi -f filelist.f -ssf tb.fsdb &
一开始可以看到没有波形,需要右键选中alu,添加波形。
添加波形后
DVE查看波形(需要修改tb中的波形生成部分成vpd和vcd)
# 使用dve查看波形(vcd,vpd)
dve -vpd vcdplus.vpd &
dve -vcd my_tb.vcd &
2)两步
两步执行的步骤在于先用vcs进行编译得到simv可执行文件,然后再运行./simv文件产生波形文件,./simv可以指定DVE或者Verdi来查看仿真结果。
DVE查看波形
在sim路径下打开terminal并执行以下指令
# 步骤一,编译,生成simv可执行文件
vcs -full64 -debug_access+all -timescale=1ns/1ps -f filelist.f
# 步骤二,仿真并使用dve打开gui界面
./simv -gui=dve &
添加波形
在命令行中运行run,开始仿真
Verdi查看波形
在sim路径下打开terminal并执行以下指令
# 步骤一,编译,生成simv可执行文件
vcs -full64 -debug_access+all -kdb -timescale=1ns/1ps -f filelist.f
# 步骤二,仿真并使用verdi打开gui界面
./simv -gui=verdi &
NOTE:需要注意的是这里vcs的编译需要加-kdb选项,不然会无法打开verdi
3. makefile
可以将上述命令,添加到makefile脚本中,提高工作效率。
附录
1. ALU代码
module alu(input clk,input rst_n,input [7:0] in1,input [7:0] in2,input [1:0] in_ctrl,output [7:0] out
);reg [7:0] A,B;reg [1:0] C;reg [7:0] D;always @(posedge clk or negedge rst_n)beginif(!rst_n)beginA <= 8'd0;B <= 8'd0;C <= 2'd0;endelse beginA <= in1;B <= in2;C <= in_ctrl;endendalways @(posedge clk or negedge rst_n)beginif(!rst_n)D <= 8'd0;else case (C)2'b00 : D <= A + B;2'b01 : D <= ~A;2'b10 : D <= A & B;2'b11 : D <= A | B; default: D <= 8'd0;endcaseendassign out = D;
endmodule
2. TestBench代码
`timescale 1ns/1ps
module tb();reg clk=0;reg rst_n=1;reg [7:0] in1=0;reg [7:0] in2=0;reg [1:0] in_ctrl=0;wire [7:0] out;always #5 clk=~clk;initial begin#10 rst_n=0;#10 rst_n=1;#100repeat(10)begin@(posedge clk) in1 = {$random}%(2**8);in2 = {$random}%(2**8);in_ctrl = {$random}%(2**2);end#100 $finish();endalu alu(.clk(clk),.rst_n(rst_n),.in1(in1),.in2(in2),.in_ctrl(in_ctrl),.out(out));initial begin$fsdbDumpfile("tb.fsdb");$fsdbDumpvars();end
/*initial begin$dumpfile("alu.vcd");$dumpvars(0, tb);end
*/
endmodule