ARTICLE DETAIL

资讯详情

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

Vivado+VCS+Verdi联合仿真AXI VIP:从环境搭建到波形调试实战

Vivado+VCS+Verdi联合仿真AXI VIP:从环境搭建到波形调试实战 做数字IC验证或者FPGA工程的人几乎都绕不开这三样东西Vivado、VCS、Verdi。我之前有段时间做AXI总线相关的IP验证天天跟这三件套打交道。当时最头疼的不是RTL逻辑本身而是怎么把高速仿真跑起来再把波形以最舒服的方式打开快速定位到问题。Vivado自带仿真器不是不能用但一到大数据量回归或者要跟UVM、VIP配合的时候效率差异就很明显了。这篇文章我想把自己在实际项目里“Vivado VCS Verdi”联合仿真AXI VIP的完整流程、踩过的坑、以及调波形时的一些小心得整理出来。文章偏工程实践不讲太多空泛的原理重点放在“怎么把这些工具真正串联起来”上。无论你是刚接触AXI协议验证的在校生还是已经在FPGA岗位上想提升仿真效率的工程师这篇内容应该都能给你一些直接可用的参考。1. 为什么是这三件套而不是只用Vivado Simulator很多刚开始学AXI验证的人会有一个疑问Vivado里面明明自带了仿真器XSimSynthesis和Implementation也都集成得很好为什么还要绕一圈去用VCS、Verdi这种第三方工具链先说结论Vivado Simulator适合做小规模、短时长的功能仿真。一旦你的测试用例涉及大量AXI事务、随机激励、断言检查甚至整套UVM验证环境XSim的编译速度和仿真性能就会明显拖后腿。VCS作为编译型仿真器对SystemVerilog和UVM的支持更成熟编译、elaboration和运行效率都更稳定是工业界最主流的仿真工具之一。而Verdi则解决了另一个问题——波形调试效率。VCS负责“跑得快”Verdi负责“看得清”。两者通过fsdb格式波形紧密配合。Vivado在中间扮演的角色是IP集成和RTL生成你需要在Vivado里配置和生成AXI VIP、例化AXI Interconnect、完成地址映射与时钟复位设计然后把导出的RTL、IP核源码、约束交给VCS做仿真。从工具协作的角度看三者的分工非常清晰工具核心职责输出VivadoIP生成、SoC集成、约束管理RTL网表、IP核源码、XCI配置VCS编译、仿真、回归测试simv可执行文件、运行日志、fsdb波形Verdi波形查看、信号追踪、协议分析FSDB波形分析、NTrace事件窗口这种方式下Vivado不再是一个“仿真器”而是一个“IP供应商和集成环境”。你的仿真流程跑在VCS上调试看波形的重活交给VerdiVivado则专注做它最擅长的事情把Xilinx的IP正确配置出来、生成对应的行为模型和仿真库。这套组合在我做的AXI VIP验证工作中效果非常直接原来在XSim里跑一个含有几百笔AXI事务的用例可能要数十分钟切到VCS以后时间大幅缩短波形排查也更顺手。有的朋友可能会问那直接用VCSVerdi不就行了问题是AXI VIP这种Xilinx官方IP往往会依赖一些特定的原语库和仿真模型直接从VCS编译RTL文件会报各种找不到库、找不到原语的错误。只有通过Vivado正确导出仿真文件再配合编译好的Xilinx库VCS才能顺利完成编译和仿真。所以这个流程里Vivado不是可有可无的前置步骤而是保证工具链顺畅的必要环节。2. 环境准备编译Xilinx仿真库并生成AXI VIP2.1 版本匹配是第一个隐藏门槛很多人在第一步就卡住往往不是因为不会敲命令而是因为工具版本不匹配。VCS、Verdi、Vivado是由不同公司维护的独立工具链它们之间的兼容性需要通过仿真库的编译来桥接但版本差异仍然会造成大量莫名其妙的编译报错。我用的组合是Vivado 2021.2搭配VCS 2020.12和Verdi 2021.04实测下来还算稳定。Vivado 2020.x和2022.x配合VCS 2018~2021的表现也都比较常见。需要特别注意的是VCS版本太老可能不支持新版Vivado导出的SystemVerilog语法VCS太新又可能有License或编译选项上的差异。建议入门时选一套经过社区和项目验证的组合不要追求“全都最新”。另外确保VCS和Verdi的环境变量已经配置好尤其是VERDI_HOME和VCS_HOME。两者之间的PLI库路径也要能互相访问。检查的方式很简单在shell里分别敲vcs -ID和verdi -ID能看到版本信息就说明基本环境OK。2.2 用compile_simlib编译Xilinx仿真库Xilinx的IP在仿真时会依赖unisim、unimacro、secureip这些库。VCS不认识这些库文件必须先把它们编译成VCS能加载的格式。这一步可以在Vivado的GUI里操作也可以用命令行。GUI方式打开Vivado在Tools菜单下选择Compile Simulation Libraries在里面设置Compiled library location选择Simulator为VCS然后点击Compile。整个过程会持续一段时间取决于机器性能和IP库里包含的原语数量。编译完成后你会在目标目录下看到类似xilinx_vcs_libs的文件夹里面包含了编译好的unisim、secureip等库。命令行方式更适合脚本化集成。可以先用Vivado的Tcl模式执行vivado -mode batch -source compile_libs.tclcompile_libs.tcl里主要是调用compile_simlib命令大致内容如下compile_simlib -simulator vcs \ -family all \ -language all \ -library unisim \ -library unimacro \ -library secureip \ -dir /path/to/xilinx_vcs_libs编译完成后我建议立即用VCS手动跑一个最简单的primitive仿真来验证库是否正确。比如编一个包含BUFG原语的顶层用VCS编译跑一遍看是否能找到lib。这个“小冒烟测试”能帮你排除大半后续的库路径问题。2.3 在Vivado中正确生成AXI VIP接下来进入核心环节生成AXI VIP。在Vivado的IP Catalog里搜索“AXI Verification IP”双击打开配置界面。这里有几个关键配置项需要根据你的验证目标来选择接口类型可以选择AXI4、AXI3、AXI4-Lite或AXI4-Stream。如果验证的是普通内存映射接口不要选Stream否则协议检查的信号规范完全不同。接口模式Master模式用于发起事务Slave模式用于响应事务。如果你要验证的是DUT的AXI Slave接口VIP设为Master如果你要验证DUT的AXI Master接口VIP设为Slave。数据位宽通常配成和DUT一致。项目里常用的是64位或128位配置不匹配会在仿真阶段出现协议错误。协议检查开关VIP支持启用内置的协议检查器我建议默认打开。它会在波形里产生额外的错误指示信号非常有助于定位协议违例。生成IP后会在工程目录下生成对应的xci文件和一系列仿真源文件。从IP Sources标签页里可以看到该VIP的仿真模型其中包括axi_vip_pkg、axi_vip_if等SystemVerilog文件。这些文件才是VCS后续真正要编译的对象。与此同时我会单独用Export Simulation导出RTL和仿真文件。在Sources标签页右键点击IP选择Export SimulationVivado会整理出一份干净的仿真文件列表避免手动收集时漏掉某个子模块。这个列表就是后面filelist的基础。3. AXI VIP的结构与驱动机制拆解3.1 AXI协议关键点快速回顾在进入VIP使用细节之前有必要把AXI协议的几个核心点过一遍因为后续调试波形时你会反复看到这些信号。AXI4是高性能内存映射接口包含五个通道写地址通道AW、写数据通道W、写响应通道B、读地址通道AR、读数据通道R。每个通道都通过VALID/READY握手来传输信息只有当VALID和READY同时为高时一笔传输才真正发生。AXI4相较于AXI3的一个显著特点是支持outstanding传输也就是master可以在没有收到前一笔响应的情况下连续发出多笔事务。每个事务又可以有多个beat由ARLEN/AWLEN决定burst长度ARSIZE/AWSIZE决定每拍数据宽度。VIP的最大价值就是把这些复杂握手、乱序返回、突发传输等行为用封装好的方法实现让你不用手动去逐个翻转信号而是直接调用API发起完整的事务。3.2 Xilinx AXI VIP的内部结构和两种模式Xilinx AXI VIP从代码结构上看是一个基于SystemVerilog的接口封装核心是axi_vip_if接口类和相应的master/slave驱动类。这套VIP既支持直接使用也支持嵌入到UVM环境中。简单模式Example Design模式下你可以在testbench中实例化VIP接口然后直接通过接口对象调用事务API。比如master端可以执行master_0_if.AW_ADDR.put(32h0000_1000); master_0_if.AW_LEN.put(8d3); master_0_if.AW_BURST.put(2b01); master_0_if.W_DATA.put(64hDEAD_BEEF_0123_4567);每一行都是在往对应的通道monitor/fifo中“放入”一笔握手所需的数据。VIP内部会自动按AXI协议时序把这些packet驱动到总线上包括生成VALID、等待READY、计算WSTRB等。对于Slave模式VIP则更像一个自动响应器。当DUT的master发起读写事务时VIP会按照预设的响应策略返回ready信号甚至可以根据配置产生延迟和错误响应。这种模式对验证AXI Master模块非常有用因为不需要自己写一堆乱序返回逻辑。3.3 VIP的接受度、背压和协议检查在实际调试中理解VIP的“接受度”配置很重要。AXI VIP内部每个通道都有FIFO用来缓存待发送或已接收的事务。如果在配置界面里把acceptance值设得比较小VIP接收事务的速率就会受限波形上表现为READY长期拉不高DUT端甚至可能出现卡死现象。我最初踩过这个坑。把VIP的写通道acceptance设为1结果DUT一次只能发出一笔事务整条链路的性能和预期差很多。后来定位到是VIP配置的问题而不是DUT逻辑问题。所以在做性能类验证时尽量把acceptance调大比如16或32才能真实模拟master的outstanding能力。VIP的另一个强大功能是协议检查。它会实时监测每个通道的握手时序一旦出现AWVALID和AWREADY同时在时钟上升沿拉高但AWADDR没有正确保持等情况VIP会触发断言失败并在FSDB波形里留下标记。运行结束后查看log里有没有UVM_ERROR几秒钟内就能定位到违反协议的位置。4. VCS Verdi联合仿真完整实操4.1 构建filelist注意SystemVerilog和库路径进入VCS仿真前先整理filelist。AXI VIP的接口代码是SystemVerilog必须以.sv后缀放进filelist才能被正确识别。如果你在Vivado导出的文件列表里看到后缀是.v但实际上含SystemVerilog语法建议重命名为.sv或者VCS编译时用-sverilog选项兜底。一份最小可用的filelist大概长这样# rtl_and_vip.f # Xilinx VIP package /path/to/axi_vip/axi_vip_pkg.sv /path/to/axi_vip/axi_vip_if.sv # DUT RTL ./rtl/axi_dut.sv # Testbench ./tb/tb_top.svVCS编译时要额外指定Xilinx库路径和PLI库路径。Xilinx库路径用-y和libext查找PLI库路径用-P指定Verdi的novas.tab文件。命令大致是vcs -sverilog \ -f filelist.f \ -y /path/to/xilinx_vcs_libs/unisim \ libext.v.sv \ -P $VERDI_HOME/share/PLI/VCS/LINUX64/novas.tab \ $VERDI_HOME/share/PLI/VCS/LINUX64/pli.a \ -debug_accessall \ -l compile.log \ -o simv这里有几个点值得解释-debug_accessall是为Verdi打开各类调试访问权限。如果你漏掉这个选项可能在Verdi里看不到某些中间信号或者无法进行源码级的TBATime Based Analysis操作。它等价于老版本里的-debug_all新版本推荐用-debug_accessall。-P选项指定PLI库这是VCS和Verdi通信的关键。很多新手在这漏配置导致fsdb dump时直接报$fsdbDumpvars not found。注意不同Verdi版本路径可能稍有不同老版本可能在share/PLI/VCS/LINUX64新版本可能变成share/PLI/VCS/LINUX64/novas.tab和libnovas.so最好先确认实际路径。4.2 testbench中打开fsdb波形testbench中打开fsdb波形的代码非常简洁但位置和选项很关键。常见的写法是initial begin $fsdbDumpfile(axi_vip_test.fsdb); $fsdbDumpvars(0, tb_top, all); end第一个参数0表示dump全部层级这在早期调试中是够用的但波形文件会非常大。我测试过一个几百笔事务的AXI测试用例全部层级dump可能产生几个GB的fsdb文件Verdi加载和缩放都会变慢。所以在功能验证阶段建议指定关键模块$fsdbDumpvars(0, tb_top.dut, all); $fsdbDumpvars(0, tb_top.axi_vip_0, all);注意fsdbDumpvars必须发生在仿真时间0。如果你在时钟已经跑了很久之后再调用前面那段时间的波形是抓不到的。我习惯把这段代码放在tb_top里最靠前的位置。此外还可以用$fsdbAutoSwitchDumpfile做分卷dump让波形文件按大小自动分割方便管理$fsdbAutoSwitchDumpfile(500, axi_vip_test.fsdb, 10);表示每个分卷500MB最多10个文件写满后自动切换到下一个文件。这个选项对长时间仿真实用性很高避免单个文件过大拖慢IO。4.3 Verdi打开波形并高效定位信号仿真跑完后进入Verdi有两种常用方式。第一种是先启动Verdi再加载fsdb第二种是直接用命令行一次性打开源码和波形verdi -f filelist.f -top tb_top \ -ssf axi_vip_test.fsdb \ -nologo 启动后你会看到nWave窗口里面以层次树的形式展示所有信号。传统做法是从左侧的Hierarchy树里手动找到某个模块然后把信号拖到nWave窗口。模块多了以后这个方法很累我后来习惯直接在nWave窗口里输入信号名过滤Verdi支持通配符和正则输入araddr所有带araddr的信号立刻出来。对于AXI总线信号建议把同类信号打成一个Group。nWave里选中多个信号后右键选择Group可以起名“AXI_READ_CH”。这个操作的意义不只是好看当你同时对比几十个AXI信号时折线分组合并使用不同的颜色显示比零散摆放清晰太多。你还可以把当前屏幕的显示布局保存为Session文件下次加载fsdb时直接恢复省去每次重新拖信号的时间。4.4 波形和源码的联动追踪Verdi最让我舒心的一点是波形和源码之间的双向定位。在nWave中双击某个信号的跳变沿会自动跳转到对应的SystemVerilog源码位置显示该信号是在哪一行被驱动的。反向操作也可以在源码里右键某个信号选择Add to Waveform它能精确地把信号加到当前波形视图中。AXI VIP验证中我通常一边看ntrace的事件列表一边看nWave里的数据通道。当出现协议错误时Verdi的Message窗口会直接显示断言失败位置。点击错误消息它会把当前视图跳转到对应仿真时间点并高亮显示冲突信号。这个机制比手动在波形里left到right找沿高效得多尤其是事务数量多、总线频率高的时候人工排查几乎不可行。5. AXI事务调试的实战技巧与波形分析思路5.1 抓取并分析一笔完整的写事务拿到一段AXI波形后首先要找的是一笔完整事务的“起点”和“终点”。以写事务为例起点是AWVALID和AWREADY同时拉高那一拍此时AWADDR、AWLEN、AWBURST都属于有效数据。接着在W通道等WVALID和WREADY同时为高此时看WDATA和WSTRB。写数据结束后等待BVALID和BREADY握手拿到写响应BRESP。用Verdi操作时我会先把这些信号全部拉到nWave并分组AW通道组、W通道组、B通道组。然后找到AWVALID上升沿用鼠标右键选择“Mark Time”接着定位到最后一次WVALID拉高的沿“Mark Time”两者之间的周期数就是这次写事务的耗时。注意这里有个常见误区一笔写事务的最后一次WVALID拉高不一定是BVALID出现的时刻由于VIP的响应策略和DUT内部流水线BVALID可能会晚很多。所以分析整笔事务延迟时要把B通道也算进去。5.2 处理乱序返回读通道常见难题AXI4支持乱序返回也就是多笔读事务按不同ID发出响应却不按原有顺序返回。这给调试带来了很大麻烦。我第一次遇到乱序问题时简单地把RARADDR和RDATA放在一起观察结果怎么都对不上。后来发现必须按ARID对应的RDATA来组合数据。在Verdi里最好的办法是用“Bus”模式把ARID和RID信号做成组然后观察相同ID下的RLAST和RDATA。也可以用nWave的Find功能查找RVALIDRREADYRLAST同时为高的那一拍那就是一笔读事务真正的结束点。此时记录下RDATA和RID再回到前面的AR通道找对应ID的最后一次请求完成事务匹配。这一套手工流程熟练后一般几分钟能定位到乱序返回是否异常。5.3 定位总线上“卡死”的问题AXI总线常见的“卡死”现象是某个通道的VALID长时间拉高但READY不来整个链路阻塞。这时候不要盯着VALID看要往上游查READY为什么不来。比如AWVALID一直拉高但AWREADY长期为低说明slave端没有能力接收新事务。紧接着你会看到WVALID可能也正常但B通道没有完成前一笔事务。这时问题很可能在slave或DUT内部的响应逻辑。用Verdi把FIFO的watermark信号、内部状态机状态信号拉出来看通常能快速定位是哪一段逻辑堵住了。如果DUT内部有FIFO还要看FIFO的写使能和读使能是否正常。FIFO满时读使能如果没拉高那问题可能是下游模块在等待某种条件。用Verdi的层次树逐步下钻从总线层信号一直追到状态机内部是我最常用的排障路径。5.4 利用协议检查器定位违例Xilinx AXI VIP内置的协议检查器会输出多个状态信号。在Vivado配置VIP时有一项是Enable Protocol Checker。打开后仿真中一旦检测到协议违例会通过$error或$warning报告并在fsdb中产生特定信号。Verdi的Message窗口会列出这些违例的时间和类型点击即可跳转到波形。这一功能对于初学者尤其友好省去了手动对照协议的繁琐过程。比如VIP可能报出“Write data burst length mismatch”实际写拍数与AWLEN不符或“Write strobe is low while WVALID is high in last beat”。这些消息本身已经把人脑需要做的分析完成了大半接下来只需要看波形确认根因。5.5 波形更新率为零先查这两个开关很多人在VCS跑完后发现fsdb文件里没有波形或者只在仿真结束时出现一个点。绝大多数情况下不是Verdi的问题而是dump配置或编译选项有误。grep一下compile.log里有没有fsdb函数的warning。如果没有报错但波形依然空尝试把-dumpvars的层级参数从0改成1并且确认tb_top的名字完全匹配注意大小写。另外在仿真过程中如果进程被kill -9强制终止来不及刷新缓冲fsdb也可能不完整。建议在tb里加上自动finishinitial begin #20000; $display(TIMEOUT!); $finish; end保证仿真会在规定时间主动结束避免长时间挂起。6. 常见问题与排查技巧实录6.1 VCS编译时报找不到unisim原始库现象编译RTL时提示Could not find BUFG / IBUF / FDRE primitive或者unknown module。原因VCS没有加载Xilinx的unisim库或者库路径没有正确指向。解决确认vcs命令中包含-y选项指向compile_simlib生成的库目录并且使用libext.v.sv让VCS自动搜索。如果仍然找不到检查库目录里是否有对应模块的源文件。6.2 Verdi报$fsdbDumpvars未定义函数现象仿真启动时出现类似Failed to find $fsdbDumpvars的报错或者仿真能跑但波形文件根本没有生成。原因PLI库没有正确链接。解决检查vcs命令中的-P选项是否包含novas.tab和pli.a的完整路径。另外有些新版本Verdi将PLI路径改到了$VERDI_HOME/share/PLI/VCS/LINUX64如果libpli.a没有找到也可以尝试改用$VERDI_HOME/share/PLI/VCS/LINUX64/novas.tab和$VERDI_HOME/share/PLI/VCS/LINUX64/libnovas.so的组合。不同版本略有差异需要稍微试一下。6.3 fsdb波形文件奇大无比现象仿真跑完发现fsdb文件占用数十GB磁盘Verdi加载后卡顿严重。原因$fsdbDumpvars(0)把整个testbench的所有层级信号全部dump了包括大量中间变量。解决修改dump层级只dump感兴趣的模块例如指定tb_top.dut和tb_top.axi_vip_0。如果确实需要深度调试可以用all配合mask文件限制只导出指定模块的信号。6.4 AXI事务发起后DUT没有反应现象master端发起写事务但slave端信号没有任何变化总线一直处于空闲状态。原因常见于testbench中忘记连接AXI VIP接口或者接口信号名和DUT端口不匹配。还有一个容易被忽略的原因是VIP接口在仿真开始时可能处于复位状态需要等它的内部初始化完成后再发起事务。解决检查testbench中VIP接口的例化连接确认AW、W、B、AR、R各条通道都正确连到DUT的对应端口。同时在发送事务前加足够长时间的复位和初始化稳定周期通常几十纳秒到几百纳秒。6.5 Verdi中文注释显示乱码现象源码里有中文注释Verdi打开后乱码影响可读性。原因Verdi默认编码和源文件编码不一致。很多EDA工具默认使用UTF-8或ASCII而Windows下生成的源文件可能是GB2312或者GBK。解决统一源码编码为UTF-8。如果源文件已经是UTF-8但仍有乱码可以在Verdi中通过Setup界面调整默认字体和编码或者用File-Change Encoding手动指定源文件编码。最稳妥的方式是从项目一开始就用UTF-8保存所有.v/.sv文件避免后面反复转换。6.6 VCS仿真进程一直不结束现象仿真跑到一定时间后既不退出也不报错看起来像是挂住了。原因testbench中没有设置仿真总时长和自动finish机制。AXI_VIP的某些等待操作可能会因为协议错误而不停阻塞。解决在testbench顶部增加一个超时看门狗initial begin #1_000_000; $display(TIMEOUT, simulation failed!); $finish; end一旦超过设定时间主动结束仿真再通过波形分析和log定位具体原因。面对大量回归用例时这种超时机制能帮你快速筛出卡死的用例。7. 从一套工具链到一套方法论做AXI VIP验证这段时间我最大的感受是工具链本身只是一个放大器真正起作用的还是你对协议的理解和对调试路径的规划。Vivado VCS Verdi这套组合解决了两个核心问题仿真性能和波形可读性。VCS让复杂事务集可以快速跑完Verdi则让出错时能够迅速定位到几十纳秒窗口内的异常点Vivado在整个链路里是IP供给和系统集成的底座。对于刚开始接触这套流程的工程师我的建议是先不要贪多。用官方示例环境跑通一个最基础的单笔读写事务确认fsdb波形能正常生成Verdi能正确加载然后再逐步增加到数十笔、数百笔事务。这样任何一步出了问题都能缩小范围快速定位。最后分享一个我自己的小习惯每次配置完VIP后我都会先用最简单的事务跑一遍冒烟测试再去做复杂的随机约束场景。这套“最小闭环优先”的方法看似慢实际上在长期项目中节省了大量兜底排查时间。AXI协议虽然复杂但只要把通道握手、事务ID、beat数量这几个要素刻在脑子里配合VCS和Verdi的联合调试你会发现绝大部分问题都有很清晰的排查路径。
返回列表