ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vivado IP核导出VCS仿真脚本与Verdi波形调试实战

Vivado IP核导出VCS仿真脚本与Verdi波形调试实战 1. 为什么IP核仿真值得单独折腾一遍做FPGA开发的人大概都有过这种体验RTL代码仿真跑得好好的一旦例化了Xilinx的IP核仿真环境就开始报各种奇怪的错——找不到glbl模块、secureip库缺失、Vivado仿真器跑FFT要等十几分钟。尤其是当你用惯了VCSVerdi这套组合之后再回头用Vivado自带的XSim那种编译速度和波形调试体验的落差确实让人难受。这篇内容要解决的问题很具体如何把Vivado工程里的IP核快速导出成VCS能直接吃的仿真脚本编译跑通后用Verdi看波形。整个流程熟练之后5分钟以内完成一轮从导出到出波形的闭环是完全可行的。适合已经有一定Vivado使用基础、正在往VCSVerdi工作流迁移的数字IC设计或FPGA验证工程师也适合还在用XSim但想试试更高效工具链的朋友。需要提前说清楚的是VCS和Verdi是Synopsys的商业仿真工具本文假设你已经有了可用的授权环境。关于工具本身的获取和安装不在讨论范围内请通过正规渠道解决授权问题。整个流程的核心思路其实就一句话让Vivado帮你生成编译脚本你只需要做少量的路径修正和参数调整然后交给VCS去编译最后用Verdi加载波形数据库。听起来简单但中间有几个关键细节如果不知道很容易卡住。2. 导出前的工程状态检查与IP核编译准备2.1 确认IP核已经生成全部输出产物在Vivado里例化IP核之后很多人只关注综合能不能过忽略了仿真需要的文件是否齐全。IP核在Vivado中需要至少完成一次Generate Output Products而且生成类型要包含Simulation。具体操作是在Sources窗口中找到IP核右键选择Generate Output Products在弹出的对话框里确认Simulation选项被勾选。如果你之前只生成了综合产物仿真目录下会缺少行为级模型文件。这些文件通常在project.srcs/sources_1/ip/ip_name/路径下仿真相关的会放在sim_netlist或者simulation子目录里。对于像FFT、FIR这类复杂IPVivado还会生成*_sim_netlist.v或者*_sim_netlist.vhdl文件这些是VCS编译时必须包含的。提示如果IP核的仿真模型没有生成VCS编译时会报找不到模块定义的错误而且错误信息往往指向IP核内部的某个子模块不容易直接定位到是IP产物缺失的问题。2.2 检查IP核的仿真延迟参数Xilinx的很多IP核在仿真时会引入额外的延迟模型比如FFT IP核在仿真模式下会有较长的计算延迟。如果你发现仿真跑起来之后波形半天没反应不一定是逻辑错了可能是IP核的仿真模型本身就需要那么多周期。这种情况下可以在IP核配置界面里看看有没有Latency或者Simulation Delay相关的选项有些IP允许你选择行为级仿真模型还是周期精确模型。另外像时钟向导Clocking Wizard这类IP仿真时锁相环的锁定时间会直接影响后续逻辑的复位释放时机。建议在testbench里对locked信号做充分的等待不要用固定的延时计数。2.3 确认仿真顶层和库映射关系Vivado导出仿真脚本时会依据当前工程的仿真顶层设置来生成对应的文件列表。你需要在Simulation Settings里确认仿真顶层模块选择你写的testbench模块而不是IP核的示例顶层仿真语言Verilog、VHDL或混合要和你的实际代码一致库映射Xilinx的IP核仿真需要用到unisims_ver、secureip、xpm等库这些在导出脚本里会自动包含但你需要确认VCS的编译选项里正确指定了这些库的路径一个常见的坑是工程里同时有Verilog和VHDL的IP核导出脚本默认只包含一种语言的库。如果混合仿真需要在导出后手动补充另一种语言的库文件。3. Export Simulation脚本的生成逻辑与关键选项3.1 从Vivado菜单导出脚本的完整路径在Vivado中导出仿真脚本的入口在File - Export - Export Simulation。点击后会弹出一个对话框里面有几个关键选项需要留意Simulator选择VCS。Vivado支持导出多种仿真器的脚本选VCS之后生成的脚本会针对VCS的语法和库路径做适配。Script Format通常选Shell或者Makefile。Shell脚本更直接Makefile更适合集成到已有的构建流程里。第一次跑建议选Shell看得清楚每一步在干什么。Output Directory指定一个干净的目录不要和Vivado工程目录混在一起。后续VCS编译会产生大量中间文件单独放一个目录方便清理。Copy Sources如果勾选Vivado会把所有相关的RTL和IP仿真文件复制到输出目录。建议勾选这样脚本里的路径都是相对路径迁移到其他机器上也能用。导出完成后你会在输出目录下看到几个关键文件文件名作用compile.shVCS编译脚本包含所有源文件和编译选项elaborate.sh精化脚本用于生成仿真可执行文件simulate.sh仿真运行脚本调用可执行文件并传入参数*.f文件列表列出所有需要编译的源文件路径*.tclVerdi加载波形用的TCL脚本部分版本会生成3.2 读懂compile.sh里的库路径和宏定义打开compile.sh你会看到类似这样的结构vcs -full64 -sverilog v2k -debug_accessall \ -timescale1ns/1ps \ -Mupdate -line \ defineSIMULATION \ -y $XILINX_VIVADO/data/verilog/src/unisims \ libext.v \ -f ./verilog.f \ -o ./simv这里面有几个参数值得展开说-full64编译64位版本现代服务器基本都是64位环境不加这个可能会遇到内存不足的问题。-debug_accessall打开全部调试访问权限Verdi要能查看信号波形必须加这个。有些老教程写的是-debug_all新版本VCS推荐用-debug_accessall。defineSIMULATION这个宏定义很关键。Xilinx的IP核仿真模型里会用SIMULATION宏来区分仿真行为和综合行为不加的话可能会例化出综合用的黑盒模型导致仿真无波形。-y和libext指定库搜索路径和库文件扩展名。Xilinx的unisims库在Vivado安装目录下脚本里通常用$XILINX_VIVADO环境变量来引用。注意如果你的Vivado安装路径和导出脚本时的路径不一致需要手动修改$XILINX_VIVADO的值或者确保环境变量已经正确设置。3.3 文件列表的组织方式与常见缺失项verilog.f文件里列出了所有需要编译的源文件。Vivado导出的列表通常包含你的RTL设计文件testbench文件IP核的行为级仿真模型Xilinx的全局复位模块glbl.vglbl.v这个文件经常被忽略。它定义了GSR全局置位复位信号很多Xilinx IP核的仿真模型依赖这个信号来初始化内部状态。如果编译时没有包含glbl.v仿真可能会卡在时间0不动或者报GSR未定义的错误。在VCS编译时glbl.v需要和testbench一起作为顶层模块传入。通常的做法是在simulate.sh里指定./simv -l sim.log ntb_random_seed1 \ accessr \ -ucli -do run -all; quit \ testbench glbl这里的testbench glbl就是指定两个顶层模块。VCS会先 elaboration 这两个模块然后从testbench开始仿真。4. VCS编译阶段的参数调优与报错处理4.1 编译速度优化增量编译与并行编译VCS的编译速度受很多因素影响尤其是当设计里包含多个大型IP核时。几个实用的优化手段增量编译加上-Mupdate选项VCS会只重新编译修改过的文件。第一次编译会慢一些后续迭代会快很多。并行编译-jN选项可以指定并行编译的线程数。比如-j8表示用8个线程并行编译。对于多核服务器这个选项能显著缩短编译时间。关闭不必要的调试信息如果当前阶段不需要看波形可以去掉-debug_accessall编译速度会快不少。等需要调试时再加回来重新编译。实测下来一个包含FFT IP核和DDR控制器的中等规模设计第一次全量编译大约需要3到5分钟增量编译可以压缩到30秒以内。4.2 常见编译错误与对应解法错误一找不到secureip库Error: Cannot find library secureip这是因为VCS没有找到Xilinx的secureip库路径。解决方法是在编译脚本里加上-y $XILINX_VIVADO/data/verilog/src/secureip \ libext.vsecureip库包含了一些加密的IP仿真模型比如高速收发器、PCIe硬核等。如果你的设计里没有用到这些理论上可以不加但Vivado导出的脚本默认会包含。错误二timescale冲突Error: Timescale conflict between module xxx and yyyVCS对timescale的要求比XSim严格。如果不同文件的timescale不一致VCS会直接报错。解决方法是在编译选项里加上-timescale1ns/1ps强制统一或者在每个文件开头显式声明相同的timescale。错误三SystemVerilog语法不支持Error: Unsupported SystemVerilog constructVCS默认的SystemVerilog支持级别可能不够高。加上-sverilog v2k -sysv选项可以打开更完整的SystemVerilog支持。如果还是报错检查一下是不是用了VCS版本不支持的新语法特性。4.3 精化阶段的顶层模块指定编译通过之后VCS会生成一个simv可执行文件。但在运行之前还需要做一次精化elaboration确定顶层模块和参数传递。elaborate.sh里通常包含vcs -full64 -debug_accessall \ -timescale1ns/1ps \ -f ./verilog.f \ -top testbench \ -o ./simv-top参数指定了仿真的顶层模块。如果你的testbench模块名不是testbench需要改成实际的名字。另外如果testbench里用了$test$plusargs或者$value$plusargs来接收运行时参数精化阶段不需要特别处理运行时通过plusarg传入即可。5. Verdi波形加载与调试效率提升5.1 从VCS仿真到Verdi的波形数据库生成VCS默认生成的波形文件是VCD格式但VCD文件体积大、加载慢。更好的做法是让VCS直接生成FSDBFast Signal Database格式这是Verdi的原生格式体积小、加载快。要生成FSDB需要在testbench里调用Verdi提供的系统函数initial begin $fsdbDumpfile(wave.fsdb); $fsdbDumpvars(0, testbench); end同时在VCS编译时链接Verdi的库vcs -full64 -sverilog -debug_accessall \ -P $VERDI_HOME/share/PLI/VCS/LINUX64/novas.tab \ $VERDI_HOME/share/PLI/VCS/LINUX64/pli.a \ -f ./verilog.f \ -o ./simv这里的$VERDI_HOME需要指向Verdi的安装目录。novas.tab和pli.a是Verdi的PLI接口文件链接之后VCS才能识别$fsdbDumpfile这些系统函数。提示如果编译时报undefined reference to fsdbDumpfile之类的错误说明PLI库没有正确链接。检查$VERDI_HOME路径是否正确以及novas.tab和pli.a文件是否存在。5.2 Verdi加载FSDB的两种方式方式一命令行直接加载verdi -ssf wave.fsdb -ssf选项表示加载指定的FSDB文件。Verdi启动后会自动打开波形窗口信号树里会列出所有dump的信号。方式二通过TCL脚本加载如果每次都要加载相同的信号分组和显示配置可以写一个TCL脚本# load_wave.tcl database -open wave.fsdb add wave -group Top /testbench/clk add wave -group Top /testbench/rst_n add wave -group IP /testbench/u_fft/*然后启动Verdi时指定脚本verdi -ssf wave.fsdb -play load_wave.tcl 这种方式适合需要反复调试同一组信号的场景省去每次手动添加信号的麻烦。5.3 用nWave做信号分组和总线拆分Verdi的nWave波形查看器有几个很实用的功能能大幅提升调试效率信号分组把相关的信号拖到同一个group里比如把所有AXI接口信号放在一个组所有中断信号放在另一个组。这样波形窗口不会太乱。总线拆分右键点击总线信号选择Expand可以把总线拆成单独的bit显示。对于地址总线、数据总线这种拆分后能更清楚地看到每一位的变化。模拟波形显示对于数据类信号右键选择Analog可以以模拟波形的形式显示适合观察DAC输出、滤波器系数等连续变化的信号。信号搜索在信号树顶部的搜索框里输入关键字可以快速定位到目标信号。支持通配符比如*valid*能匹配所有包含valid的信号。5.4 保存和复用Verdi的调试会话Verdi支持把当前的波形配置保存成.rc文件下次启动时直接加载verdi -ssf wave.fsdb -rc saved_session.rc .rc文件里包含了信号分组、颜色配置、光标位置等信息。对于需要反复调试的项目这个功能能省下大量重复配置的时间。另外Verdi的Signal Event功能可以设置信号触发条件当某个信号满足特定值时自动暂停仿真或者标记时间点。比如设置state 3b101时触发能快速定位到状态机的特定状态。6. 从导出到出波形的完整实操链路6.1 一次完整的5分钟操作流程把前面的步骤串起来熟练之后的完整流程是这样的Vivado端约1分钟确认IP核已生成仿真产物打开Export Simulation选择VCS格式指定输出目录点击导出。脚本修正约1分钟检查compile.sh里的$XILINX_VIVADO路径是否正确确认verilog.f里包含了glbl.v和所有IP仿真文件。VCS编译约2分钟执行compile.sh观察编译日志处理可能的报错。运行仿真约30秒执行simulate.sh等待仿真结束确认wave.fsdb文件已生成。Verdi查看约30秒启动Verdi加载FSDB添加关键信号检查波形是否符合预期。这个时间估算基于中等规模设计10万门级左右和性能正常的服务器。如果设计规模更大或者IP核更多编译时间会相应增加。6.2 把流程固化成可复用的Makefile每次手动改脚本还是麻烦更优雅的做法是写一个Makefile把所有步骤封装起来VIVADO vivado VCS vcs VERDI verdi SIM_TOP testbench FSDB wave.fsdb all: compile simulate compile: $(VCS) -full64 -sverilog -debug_accessall \ -timescale1ns/1ps \ -P $(VERDI_HOME)/share/PLI/VCS/LINUX64/novas.tab \ $(VERDI_HOME)/share/PLI/VCS/LINUX64/pli.a \ -f ./verilog.f \ -top $(SIM_TOP) \ -o ./simv simulate: ./simv -l sim.log fsdbautoflush wave: $(VERDI) -ssf $(FSDB) clean: rm -rf simv* csrc *.log *.fsdb *.vpd这样每次只需要make就能完成编译和仿真make wave打开波形make clean清理中间文件。集成到CI流程里也很方便。6.3 几个容易忽略的细节FSDB文件自动flush仿真过程中如果FSDB文件没有及时写入Verdi打开时可能看不到最新数据。在simv运行时加上fsdbautoflush选项可以让VCS定期自动flush。或者在testbench里调用$fsdbAutoSwitchDumpfile设置文件大小上限和自动切换。仿真时间与波形深度dump所有信号的FSDB文件可能非常大。如果只关心部分信号可以在$fsdbDumpvars里指定层次和信号范围比如$fsdbDumpvars(1, testbench.u_dut)只dump DUT内部第一层的信号。VCS版本与Vivado版本的兼容性不同版本的Vivado导出的仿真脚本可能针对特定版本的VCS做了适配。如果VCS版本和Vivado版本差距太大可能会遇到库文件不兼容的问题。建议使用Vivado官方文档中推荐的VCS版本组合。多时钟域仿真的时间精度如果设计里有多个时钟域timescale的设置要足够小避免时钟边沿对齐时出现精度损失。通常1ns/1ps够用但如果时钟频率超过500MHz建议用1ps/1fs。7. 踩过的坑与排查思路7.1 仿真卡在时间0不动这是最让人头疼的问题之一。仿真启动后时间停在0波形没有任何变化。常见原因有几个glbl.v没有作为顶层模块传入。VCS需要同时elaborate testbench和glbl否则GSR信号无法初始化。IP核的仿真模型没有正确编译。检查verilog.f里是否包含了IP核的*_sim_netlist.v文件。testbench里的时钟没有启动。检查initial块里是否有forever #5 clk ~clk之类的时钟生成逻辑。排查方法在VCS运行时加上-ucli选项进入交互模式后手动执行run 100ns观察是否有信号变化。如果还是没有用scope命令查看当前层次结构确认顶层模块是否正确加载。7.2 Verdi加载FSDB后信号列表为空FSDB文件生成了但Verdi打开后信号树是空的。这种情况通常是$fsdbDumpvars的参数设置有问题。第一个参数是层次深度0表示dump所有层次1表示只dump当前层次。如果写成了$fsdbDumpvars(1)而没有指定模块可能只dump了testbench顶层的信号DUT内部的信号都没有记录。正确的写法是$fsdbDumpvars(0, testbench)其中testbench是顶层模块名。这样会递归dump所有层次的信号。7.3 编译报错指向IP核内部信号有时候VCS会报错说某个IP核内部的信号未定义或者类型不匹配。这通常是因为IP核的仿真模型和Vivado版本不匹配或者仿真模型文件被意外修改过。解决方法是在Vivado里重新生成IP核的输出产物确保仿真模型是最新的。如果重新生成后还是报错检查一下VCS的编译选项里是否包含了defineSIMULATION。有些IP核的仿真模型会根据这个宏来决定是否例化某些内部模块。7.4 仿真速度突然变慢仿真跑了一段时间后速度明显下降可能是FSDB文件太大导致磁盘IO瓶颈。可以设置FSDB文件的大小上限$fsdbAutoSwitchDumpfile(500, wave.fsdb, 10);这表示每个FSDB文件最大500MB最多生成10个文件。超过之后会自动切换到新文件。另一个可能的原因是仿真中产生了大量的事件触发。检查一下testbench里是否有always (*)块在不必要地反复触发或者是否有组合逻辑环路导致仿真器反复迭代。8. 一些提升效率的个人习惯我在实际项目里养成了几个习惯能省下不少时间。第一个是在Vivado工程里专门建一个仿真专用的IP核配置仿真用的IP核可以关闭一些综合优化选项生成更简单的仿真模型编译和仿真都会快一些。第二个是把常用的Verdi信号分组保存成模板新项目直接加载模板再微调不用从零开始拖信号。还有一个很实用的技巧如果只需要验证IP核本身的功能可以先用Vivado自带的IP核示例工程跑一遍仿真确认IP配置没问题之后再把IP核移植到自己的工程里。这样能把IP核配置问题和testbench问题分开排查定位效率高很多。VCS的-l选项可以把编译和仿真日志输出到指定文件配合grep能快速定位错误。比如grep -i error sim.log能过滤出所有错误信息。Verdi的-nologo选项可以跳过启动画面加快启动速度。这些小细节积累起来整个流程的体验会顺畅很多。
返回列表