做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、做芯片的仿真最后都不用图形界面 上图就是采用简单的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) strcpy(buf,s); for(i=0;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、覆盖率分析 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,仿真验证就是器! |
|