摆脱Vivado单独建仿真环境的终极解决方案

做FPGA样机和做芯片的思路其实是有差异的。为了追求好的性能,节省成本,降低功耗(PPA),芯片设计者往往把事情做到极致,去做验证时把各种覆盖率尽可能做到100%,把每个模块电路结构优化到面积最小,通过Power Gating和Clock Gating等技术把功耗降到最低,争取把每次流片(烧钱)的风险降到最低;相比芯片设计流程,FPGA样机的开发人员往往不太注重上述要求,虽然有着与做芯片相同的目标和追求,但往往因为FPGA的可编程性,即便后续发现问题,也可以通过修改代码再次烧写bit文件的方式来弥补,出错成本相对低了很多。但如果按照做芯片的方式来做FPGA样机,肯定会带来更好的结果,甚至可以大幅度的降低FPGA开发时间。在这个过程中,就需要把常规的做FPGA的方式进行修正,比如经常采用的跟FPGA编译工具联合仿真的办法就不太适合做芯片的验证了。本文就探讨如何把Vivado与ModelSim联合仿真修改为单独采用ModelSim进行仿真。

在本公众号上一篇文章(【干货】推荐一款FPGA仿真调试鸟枪换炮的工具!)中就曾提到,隔行如隔山,做芯片的人永远无法理解只做FPGA样机的人在某些情况下不做仿真就直接上板的做法,非芯片设计出身只做FPGA样机的人也不知道这个世界上还存在更为高效的Verilog或VHDL语言的仿真工具和仿真方法,也不理解为了把一个芯片做到极致,必须严格要求代码规范的做法。为了能够使用上一篇文章中高效的Verdi或者SimVision仿真调试工具,脱离Vivado等仿真工具单独搭建仿真环境的就成为比较急迫的需求了。

本公众号之前也曾经发布过一篇相关的文章,用Modelsim独立仿真带Vivado IP核的仿真工程,也是实现采用ModelSim单独搭建仿真环境的一种方法,但文中所述方法仍未彻底摆脱Vivado的环境,适用的场景也受到限制,某些工程中还会出错。因此,本文从最原始文件搭建仿真环境的思路出发,尝试着研究脱离Vivado单独建仿真环境的过程中都会遇到什么问题,采用什么样的方法比较容易解决,笔者试了好几个工程,总结出一套相对完善的解决思路,来分享给大家。

FPGA开发最不理解的芯片设计中的操作

1、做芯片的仿真最后都不用图形界面
与刚开始做FPGA开发时都在图形界面下操作的仿真方法不同,做大规模芯片设计时的仿真常常不调用图形界面,都是采用命令行的形式做的仿真。

上图就是采用简单的windows下的批处理调用modelsim进行的一个仿真过程,这个简单的批处理,就是脚本。也是本文最终要实现的目标。

set PROJECT_PATH=%cd%
::vsim  -do  sim.do
vsim -c -do  sim.do  

脚本,是芯片设计人员必须要掌握的基本技能。在芯片设计的各个阶段,脚本的作用是非常巨大的。代码仿真,可以使用脚本来进行仿真环境的搭建,综合的约束文件,必须采用脚本来提前对综合过程中的各种要求进行说明,后端就更不用说了。因为整个芯片的设计流程,每个流程的所有中间信息都是靠文本来储存的,RTL代码,netlist,后端的颜色文件,流片用的GDSII等等,对文本进行随意的操作处理就是一名IC设计人员的基本技能。

如下图就是一个简单的采用NCVerilog进行仿真的脚本。

#!/bin/sh
echo "\`include \"../testcase166/$1.v\"" > testcase.v
sed "s/\/wave.shm/\/wave$1.shm/g" ../testbench/testbench.v > testbench.tmp
cp ../testbench/testbench.v ../testbench/testbench.bak
cp testbench.tmp ../testbench/testbench.v
rm -f testbench.tmp

ncverilog -f ../filelist/filelist.v +access+rwc  -l ../log/log/$1.log

mv ../testbench/testbench.bak ../testbench/testbench.v

rm -f testcase
~

而下图则是一个采用TCL语言描述的Design Complier综合脚本的开头部分。

sh date
remove_design -designs 
##########################
#set library             #
##########################
set search_path [list /tools/lib/smic25/feview_s/version1/STD/Synopsys \
                      /tools/lib/smic25/feview_s/version1/STD/Symbol/synopsys]
set target_library  { smic25_tt.db }
set link_library    { smic25_tt.db  }
set symbol_library  { smic25.sdb }


##########################
#Paths    variables      #
##########################
     set main_dir ../..

     set RTL_ROOT_PATH $main_dir/hdl
     set NETLIST_PATH  $main_dir/sim/syn/netlist
     set RPT_PATH      $main_dir/sim/syn/log
     set DB_PATH       $main_dir/sim/syn/db
     set SDF_PATH      $main_dir/sim/syn/sdf

##########################
#void warning Info       #
##########################
suppress_message  VER-130
suppress_message  VER-129
suppress_message  VER-318
suppress_message  ELAB-311
suppress_message  VER-936


################################
#read&link&Check design#
################################

2、做芯片的仿真最后都不看波形

在做芯片仿真时,无论是采用自己搭建的简单仿真环境还是UVM的仿真环境,最后的形式常常是把所有的testcase都集中到仿真环境中,只需敲一个命令,回车,所有的testcase就能够全部运行下去。而仿真过程的错误,也都被记录到log文件中,无论是运行的对与错,都可以在log文件中看到。如下图就是所有的testcase截图,每个case运行的结果也会保存到另外一个log目录下。

而FPGA开发人员,则不会去建立如此完善的仿真环境,往往是简单的搭建一个某种功能模式下的仿真环境仿一下过了,就上板了。

采用ModelSim单独仿真

1、整理RTL代码及仿真代码

如果要用ModelSim单独仿真,并且需要搭建类似于上面描述的采用脚本形式来仿真的仿真环境,那么第一步就需要从Vivado工程中把相应的Verilog代码整理出来。

Vivado跟Quartus在仿真时采用的思路是不一样的,对于Quartus而言,你可以很容易就能脱离开Quartus单独搭建一个ModelSim或者VCS的仿真环境,因为Quartus所有的IP核或者原语库之类的内容全部都是以verilog或者VHDL文件存储的,建仿真环境时,只需要到Quartus的安装路径下找一个叫EDA的目录下找sim_lib的子目录下找相应的.v文件添加到仿真工程里就可以了,常见的库文件主要有三个,220model.v,altera_mf.v和cyclone_atoms.v(或者是别的FPGA型号)。见本公众号之前的文章有详细描述:用Quartus II和ModelSim做后仿真(时序仿真)。

在Vivado中也有类似于Quartus中的库文件,在Vivado工程目录下,如下图所示。

然后,整体拷贝ip文件夹到自己想搭建的modesim仿真环境目录下:

上图中rtl文件夹就是自己原来的设计文件,tb则是一些仿真用的.v文件。

2、编写脚本sim.do文件

一个比较简单的modelsim脚本文件如下。

vlib work
vlog -f  ./rtl.f
vsim -novopt work.tb_crossbar_top
do wave.do
run 10us

上面的脚本的具体含义,大家都可以百度搜索找到。需要说明的是所有工程中的文件的路径是需要写到一个rtl.f的文件夹下的,具体源代码可以参考本公众号之前的文章:如何快速生成Verilog代码文件列表?(内附开源C代码),需要注意的是,生成的文件路径地址中的斜杠与modelsim脚本中要求的斜杠刚好相反,可以直接采用文本编辑器替换掉,也可以添加以下子函数到C代码中简单修改一下。

void xiegang(char* s)
{
int i,j,k;
char buf[800]=" ";
char buf1[800]=" ";
memset(buf,0,800);
memset(buf1,0,800);

strcpy(buf,s);
strcpy(buf1,s);

for(i=0;i {
if(buf[i]=='\\')
{
buf1[i]='/';
}
}

strcpy(s,buf1);
}

上面的C代码实现文件列表的程序,其实也是脚本。

3、注意事项

在实现的过程中,发现Vivado并没有把所有用到的库文件都写成.v的形式,而是以编译库的形式存在。这样就需要在仿真时把对应的库文件包含进去。上面的脚本需要修改为:

vlib work
vlog -f  ./rtl.f
#vsim -novopt work.tb_crossbar_top
vsim -gui work.tb_crossbar_top -voptargs="+acc" -L C:/modeltech64_10.5/vivado_17_2/simprims_ver -L C:/modeltech64_10.5/vivado_17_2/unisims_ver 
do wave.do
run 10us

C:/modeltech64_10.5/vivado_17_2/simprims_ver

C:/modeltech64_10.5/vivado_17_2/unisims_ver

两个库都是Vivado与ModelSim联合仿真时ModelSim预先编译好的仿真库,这里面很多都是FPGA上用到的BUFG、PLL等内容。但添加完这些库文件后,还是有错误,具体如下:

经过上网查找原因,发现这是xilinx全局复位的模块。该模块在C:\Xilinx\Vivado\2015.1\data\verilog\src路径其实在上面Error提示的一部分。

于是,自己copy一份glbl.v到当前工程,进行编译。

但还是弹出相同的错误提示。

最后,在tb.v中添加该模块的调用才最终解决问题。

在笔者尝试多个工程之后,发现找Vivado 对应的库实在是太麻烦了,那么多的编译出来的库,每个库也找不到具体解释含义的说明文档。无奈之下,想到了彻底摆脱Vivado的终极解决方案。

出现了找不到某个模块定义的错误之后,就需要尝试着去添加上图中不知道含义的库看能不能解决问题,一个一个的试,一个一个的试,试到怀疑人生。

终极方案

这个终极解决方案就是采用ASIC的思路来替换掉所有的IP。如果考虑最后要做ASIC,那么就需要把设计代码中所有的FGPA IP核或者原语之类的内容全部替换掉,比如FIFO都要修改成控制逻辑加RAM的形式,一些BUFG之类的改善时序或驱动的原语也全部删掉。如果只考虑做仿真,则只需要自己手写一个RAM的行为逻辑,定义一个数组类型,根据输出的时候是否打拍随意的调整。一些FIFO也可以很容易的在网上找到源代码,同步的,异步的,首字置出的FIFO都有。替换干净之后,就跟Vivado没有任何关系了!甚至也跟ModelSim也没有任何关系了,可以随意的更换仿真工具,比如VCS和NC等,彻底的解决问题。

写到此处,想起了一个有趣的事情。据说有一种永远不让代码中出现BUG的终极解决方案。猜猜看是什么。

答案是:不要写一行代码!

这个跟摆脱Vivado单独建仿真环境的终极解决思路竟然高度一致!彻底摆脱Vivado建仿真环境的方法也是,仿真代码中不要用到Vivado中的任何一个IP核!!!

4、覆盖率分析
有了脚本的支持,也脱离掉了Vivado的束缚,就可以做很多自己想做的事情,把仿真环境做成可回归的形式之后就可以做覆盖率分析。这时的脚本就修改成如下的样子。

vlib work
vlog -f  ../filelist/filelist_sim.v
vlog -f  ../filelist/filelist_hdl.v  -cover bcesxf
vsim -novopt -coverage work.TESTBENCH -L C:/modeltech64_10.5/vivado_17_2/simprims_ver -L C:/modeltech64_10.5/vivado_17_2/unisims_ver 
run -all

大家可能注意到,上面脚本中把filelist分成了两种,一种是仿真的,不用看覆盖率,另外一种则是可综合代码部分,需要看覆盖率,单独写到了filelist_hdl.v的文件里面。

运行结束后,就可以在图形界面上看到覆盖率分析的结果。

随着测试例的运行,上面设计代码的覆盖率也会逐渐提高,最后可以通过选择达不到覆盖率要求的模块进行详细的分析,查看测试例没有运行到的语句。有了充分的仿真验证后,再上板就顺利的多了。至少99%的逻辑BUG都被解决掉了,剩余的就是一些时序方面的问题,这样就可以大大节约FPGA调试的时间。

用做芯片的思路去做FPGA,不是杀鸡用牛刀,而是一种正确的思路。搭建一个完善的仿真验证环境固然麻烦,但一旦做好之后,事半功倍,效率会大幅度的提升。本文中提到的仿真环境仅仅是一种最简单的只有Verilog代码的仿真环境,在验证复杂度和便捷性等方面都差的很远远。公司里面目前采用的办法,往往是大牛们用SV搭建好一个UVM框架后,下面做具体实现的人只需要往对应框里面填数字就可以了。

工欲善其事,必先利其器!做FPGA,仿真验证就是器!

本文在写作工程中还参考了以下网址上的内容,也解决了问题,特此感谢。

https://www.cnblogs.com/demosaic/p/5529870.html


文章来源:网络交换FPGA的博客
*本文由作者授权转发,如需转载请联系作者本人

最新文章