最近由于在一家FPGA公司实习,公司的FPGA仿真和看波形工具是VCS+Verdi,由于这两样工具结合在一起有着极高的效率,也因此真切地感受到,与在学校仅仅使用vivado软件跑整个流程相比,真的是小巫见大巫。

因此便在自己电脑的虚拟机中试着建立VCS+Verdi的仿真环境,写下这篇文章记录自己的使用过程。

参考文章: Linux下VCS与Verdi联合仿真简易教程及例子示范

文章内容主要分两部分:

  1. VCS、Verdi介绍
  2. 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

  1. 首先得在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,有兴趣的朋友可以看看~

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐