最近由于在一家FPGA公司实习,公司的FPGA仿真和看波形工具是VCS+Verdi,由于这两样工具结合在一起有着极高的效率,也因此真切地感受到,与在学校仅仅使用vivado软件跑整个流程相比,真的是小巫见大巫。
因此便在自己电脑的虚拟机中试着建立VCS+Verdi的仿真环境,写下这篇文章记录自己的使用过程。
参考文章: Linux下VCS与Verdi联合仿真简易教程及例子示范
文章内容主要分两部分:
- VCS、Verdi介绍
- Linux下VCS+Verdi仿真demo演示
1. VCS、Verdi介绍
VCS是编译型Verilog模拟器,它完全支持OVI标准的Verilog HDL语言、PLI和SDF。VCS具有目前行业中最高的模拟性能,其出色的内存管理能力足以支持千万门级的ASIC设计,而其模拟精度也完全满足深亚微米ASIC Sign-Off的要求。 VCS结合了节拍式算法和事件驱动算法,具有高性能、大规模和高精度的特点,适用于从行为级、RTL到Sign-Off等各个阶段。VCS已经将CoverMeter中所有的覆盖率测试功能集成,并提供VeraLite、CycleC等智能验证方法。VCS和Scirocco也支持混合语言仿真。VCS和Scirocco都集成了Virsim图形用户界面,它提供了对模拟结果的交互和后处理分析。
Verdi最初是由Novas Softwave公司设计的,后属于了SpringSoft公司,最终SpringSoft被Synopsys公司收购,Verdi正式属于Synopsys。可以调用第三方工具进行编译仿真产生波形文件并可以查看、可查看源代码对应的电路图,最强大之处在于可以在源代码、原理图、波形图和状态图之间进行即时跟踪,协助工程师debug。
相信大家都用过Vivado,Quartus等,这里以Vivado为例,他包含了RTL,编译,仿真,综合,看波形,烧板子等,集大成为一体。相比之下,VCS和Verdi就很专一了,VCS专注于编译及仿真,Verdi专注于看波形,仅此而已,安分守己。那Vivado这种功能这么全,工业界直接全用一个Vivado走天下不就行了,为何要大费周折用VCS和Verdi呢?
按我公司老板的话来讲,Vivado其实只能算个写Verilog的(而且还很慢),只不过集成了综合,仿真,看波形等功能,如果要真正做Asic设计,还是得在各个步骤用上用更加专业的软件,用那些在领域中做到顶峰的EDA,对,那就是Synopsys的VCS,Verdi这种(毕竟Vivado的优化大多也只针对于自家FPGA)。首先VCS编译仿真速度极快,效率极高,为大家节约时间,Verdi看波形也十分方便debug,它支持信号追溯,无缝增加信号波形等功能。虽然上手比Vivado难,但学习之后能感受到其美丽之处的。
2. Linux下VCS+Verdi仿真demo演示
环境:Linux
编写Verilog:gvim
编译仿真:VCS
波形查看:Verdi
- 首先得在Linux下配置好VCS和Verdi的环境,这个方面我就不再这里赘述了,默认大家VCS和Verdi环境都已经配好,你可以在命令行输下vcs和verdi看有没有信息,有信息的话就说明已经安装。
- 终端输入vcs显示如下:
- 终端输入verdi,会直接打开Verdi的GUI界面
要想在Linux下使用VCS进行编译仿真并使用Verdi观察波形,需要有4个文件:RTL设计文件,也就是利用Verilog设计的.v文件,或者利用Systemverilog设计的.sv文件;testbench文件,产生激励信号提供给设计模块,用来对设计模块的功能进行验证,也是.v文件;filelist.f文件,用来列写出testbench文件和RTL文件,这样比较方便,不用对所有的文件一个一个的在shell中敲出来,它可以自己根据列表文件自己去找;makefile文件,通过makefile脚本的编写,可以极大的节省效率,编译仿真VCS时可以不用一次又一次的敲命令,直接通过Linux内置的make命令来执行编译控制命令。
2.新建一个src、tb和sim的文件夹,并把脉冲计数器的.v文件和testbench的.v文件分别放在src和tb文件夹
mkdir pulse_counter
cd pulse_counter
mkdir src tb sim
3. 分别在对应文件夹建立.v文件
gvim /src/pulse_counter.v
`timescale 1ns/1ps
module pulse_counter(
input i_clk,
input i_rst_n,
input i_pulse,
input i_en,
output reg[15:0] o_pulse_cnt
);
reg[1:0] r_pulse;
wire w_rise_edge;
//
//脉冲边沿检测逻辑
always @(posedge i_clk)
if(!i_rst_n) r_pulse <= 2'b00;
else r_pulse <= {r_pulse[0],i_pulse};
assign w_rise_edge = r_pulse[0] & ~r_pulse[1];
//
//脉冲计数逻辑
always @(posedge i_clk)
if(i_en) begin
if(w_rise_edge) o_pulse_cnt <= o_pulse_cnt+1;
else /*o_pulse_cnt <= o_pulse_cnt*/;
end
else o_pulse_cnt <= 'b0;
endmodule
gvim /tb/tb_pulse_counter.v
`timescale 1ns/1ps
module tb_pulse_counter();
//参数定义
`define CLK_PERIORD 10 //时钟周期设置为10ns(100MHz)
//接口申明
reg clk;
reg rst_n;
reg i_pulse;
reg i_en;
wire[15:0] o_pulse_cnt;
//对被测试的设计进行例化
pulse_counter uut_pulse_countern(
.i_clk(clk),
.i_rst_n(rst_n),
.i_pulse(i_pulse),
.i_en(i_en),
.o_pulse_cnt(o_pulse_cnt)
);
//复位和时钟产生
//时钟和复位初始化、复位产生
initial begin
clk <= 0;
rst_n <= 0;
#1000;
rst_n <= 1;
end
//时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;
//测试激励产生
integer i;
initial begin
i_pulse <= 1'b0;
i_en <= 1'b0;
@(posedge rst_n); //等待复位完成
@(posedge clk);
repeat(10) begin
@(posedge clk);
end
#4;
i_en <= 1'b1;
for(i=0; i<50; i=i+1) begin
#500;
i_pulse <= 1'b1;
#300;
i_pulse <= 1'b0;
end
i_en <= 1'b0;
#10_000;
i_en <= 1'b1;
for(i=0; i<69; i=i+1) begin
#500;
i_pulse <= 1'b1;
#300;
i_pulse <= 1'b0;
end
i_en <= 1'b0;
#10_000;
i_en <= 1'b0;
for(i=0; i<15; i=i+1) begin
#500;
i_pulse <= 1'b1;
#300;
i_pulse <= 1'b0;
end
i_en <= 1'b0;
#10_000;
$stop;
end
//dump fsdb
initial begin
$fsdbDumpfile("fifo.fsdb");
$fsdbDumpvars(0);
end
endmodule
4. 编写filelist.f
目录切换到sim目录,并新建一个filelist,f文件
cd sim
gvim filelist.f
在filelist.f文件中输入如下内容
../src/pulse_counter.v
../tb/tb_pulse_counter.v
5.编写makefile文件
新建一个makefile文件
gvim makefile
在makefile文件中输入如下内容
#************parameter input*************
#※prepare the source list file and then make add the soucefile name
#for example ,the Verilog source file's name is vlog_list.f then :make norsim src_list=file_list
src_list = filelist
simv_name = simv
vpdpluse_name = vcdpluse
cov_file_name = coverage
vdb_name = $(simv_name)
#************constant command************
#compile
NOR_VCS = vcs -full64 -sverilog +v2k -timescale=1ns/1ns \
-debug_all \
+notimingcheck \
+nospecify \
+vcs+flush+all \
-o $(simv_name) \
-l compile.log \
-f $(src_list).f
#coverage compile switch
COV_SW = -cm line+cond+fsm+branch+tgl
#verdi dump wave compile option
VERDI_SW = -P /tools/synopsys/verdi/Verdi3_L-2016.06-1/share/PLI/VCS/linux64/novas.tab \
/tools/synopsys/verdi/Verdi3_L-2016.06-1/share/PLI/VCS/linux64/pli.a
#run option
RUN_GUI = -R -gui -l run.log
RUN_VPD = -R +vpdfile+$(vpdpluse_name).vpd -l run.log
RUN_COV = -R $(COV_SW) -cm_name $(vdb_name) -cm_dir ./$(cov_file_name) -l run.log
RUN_VER = -R +fsdb+autoflush -l run.log
#************command************
#normally sim
norsim:
$(NOR_VCS) $(RUN_GUI)
#post-process
postsim:
$(NOR_VCS) $(RUN_VPD)
dve -vpd $(vpdpluse_name).vpd
#coverage
covsim:
$(NOR_VCS) $(COV_SW) $(RUN_COV)
dve -covdir $(cov_file_name).vdb
#verdi
#versim:
run_vcs:
$(NOR_VCS) $(VERDI_SW) $(RUN_VER)
vd:
verdi -sv -f $(src_list).f -ssf *.fsdb -nologo
#rm
clr:
rm -rf *csrc ./*.daidir $(simv_name) *simv* DVE* ucli* *.vpd *.vdb *.log *.fsdb *novas* *.dat *Log *rc *conf
6. 调用vcs仿真并调用Verdi查看波形
万事俱备,现在开始调用两个文件并进行仿真,在终端中输入
make run_vcs
终端显示下图,表示VCS已经仿真完成,并在文件夹中建立了fsdb文件
之后输入如下命令来打开Verdi查看波形
make vd
鼠标点击图中位置,并按住滚轮拖动到如图箭头所指位置
接着就会出现对应的波形
接下来便可以利用Verdi快乐的查看波形并进行debug啦!
至此,我们利用VCS+Verdi进行编译仿真并查看波形就大功告成,开心!
总结
十分感谢能够看到这里,这样整个教程就已经告一段落,教程中对于makefile文件的编写,以及vcs和Verdi的一些常用指令并没有详细的介绍,如果大家想深入了解具体的内容,欢迎移步到synopsys的官方指导文档,同时如果想了解Verdi的详细使用方法,这里也推荐一个我看后觉得很有收获的一个up主Verdi基础使用自学记录_哔哩哔哩_bilibili,有兴趣的朋友可以看看~