ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Vivado中AXI VIP配置与仿真实战:从报错到跑通全流程解析

Vivado中AXI VIP配置与仿真实战:从报错到跑通全流程解析 写这篇文的时候我正盯着Vivado 2023.1的波形窗口发呆。那根红线的reset_n拉起来之后master才慢悠悠地抬了一拍然后老老实实地把TLVALID/TREADY按AXI协议该有的样子推起来。第一次在项目中完整跑通AXI VIP仿真整个过程没有报错没有波形中断没有地址对不上——那一刻的舒畅感比拿到新板子还带劲。我得承认走到这一步之前我在AXI VIP上栽的跟头是真不少。最开始的版本老是报[XSIM 43-3282]、[XSIM 43-3309]这种看不懂的莫名错误甚至一度怀疑是Vivado安装有问题差点去重装2023.2。后来一点点排查才搞清楚原来不是工具坏而是AXI VIP的初始化顺序、接口使能、示例生成方式每一步都有讲究。这篇文章我就把从配置到成功仿真的完整路径拆开讲透重点记录那些真正坑过我的报错以及我能确认管用的解决办法。整个流程基于Vivado 2023.1版本AMBA AXI4接口用XSim做仿真。如果你用的是2023.2、2024.1多数地方也能直接套用但GUI菜单位置可能有细微差别。1. AXI VIP到底能干什么——配置之前先认清这东西很多朋友第一次碰AXI VIP看名字以为是“验证IP”以为它跟UVM Testbench里面那种通用验证组件差不多装上就能用。实际不是这么回事。Xilinx Xilinx VIP或者说AXI Verification IP是AMD官方提供的一套行为级模型专门挂在AXI总线上扮演Master或Slave角色用来在仿真环境里替代你真实的Master组件或Slave设备。说得直白一点你设计了一个AXI Slave模块想验证它的“从设备”行为是否规范总不能把CPU核搬进仿真里吧这时候在总线上挂一个AXI VIP Master它就模拟CPU那侧发起读写的动作盯着你的Slave回不回应。1.1 AXI VIP的核心能力边界AXI VIP的官方定位是用于协议级验证不是性能验证。它能帮你做的基本集中在三类事情发起事务Master模式的VIP能执行读、写、读改写Read-Modify-Write、独占访问Exclusive Access、突发传输Burst以及乱序完成Out-of-Order等不同的AXI事务序列。响应事务Slave模式的VIP可以接收Master发来的读请求、写请求按照配置好的内存模型、延时参数等给出响应甚至能主动注入错误响应比如返回SLVERR/DECERR。协议检查VIP内部有协议检查器能发现总线上的违例比如握手信号时序不对、突发长度超限、地址未对齐等并以Report的方式弹出来。它能验证的是功能正确性、协议合规性但测不出你的设计时序余量是多少——那是时序分析Timing Analysis和真实硬件测试的事。搞清楚了这个边界你就不会在仿真阶段期待不属于它的功能也不至于把它当“普通测试代码”随便乱配。1.2 配置它为什么容易报错我见过很多朋友在IP Catalog里找到AXI Verification IP双击打开Generate之后拉到Block Design里连了两根线就跑仿真然后就开始报错。这里头核心原因有四个接口数量多。AXI VIP一个IP里可配置多个Master接口和多个Slave接口每个接口还有独立的协议支持选项AXI4/AXI3/AXI4-Lite一旦接口配置和你后续连线的接口名字对不上编译直接失败。参数化程度高。地址宽度、数据宽度、突发类型支持、超时计数、协议检查开关每一项都直接影响仿真行为少了哪一项都可能在仿真中途爆出协议错误。示例工程生成机制特殊。Xilinx AXI VIP在Block Design里并不像普通IP那样Generate Output Products之后就能直接仿真还得额外生成示例工程否则主测试文件可能不存在或不完整。依赖仿真环境设置。XSim与VIP模块之间的编译顺序、库文件路径、时间精度设置稍有偏差就会报出一堆看不懂的错误。咱们这篇文的思路就是把这四类问题一个个拆掉按顺序走完后面成功率会高出很多。2. 正式配置前的关键准备——省得后面反复返工正式开始之前先花十分钟把环境和版本问题处理掉。我最早就是跳过了这一步结果后面在仿真阶段连续折腾了两天才发现问题根源居然在工程目录路径和库版本上。2.1 Vivado版本与工程路径我这个流程基于Vivado 2023.1。其他2023.2、2023.3、2024.1版本基本兼容但有一点必须确认你手上的Vivado版本是完整版包括Vivado Lab Solutions和XSim仿真器而不是只装了硬件服务器版本。工程路径方面强烈建议工程路径全部用英文不要出现空格、中文、特殊符号。AXI VIP内部会产生非常长的对象路径一旦工程路径有空格XSim跑仿真时非常容易触发路径解析类报错表现就是一会儿编译失败一会儿又找不到指定的仿真文件。注意如果工程路径、IP输出路径、仿真输出路径中出现中文实测会出现某些随机性报错排查起来非常折磨人。走通一遍流程之后再回来看这段话你会感谢我的。2.2 Block Design还是纯HDL选哪一个这两条路线我都走过。简单说结论官方推荐、我建议新手直接用Block Design简称BD方式。AXI VIP在BD里能非常直观地连接接口、配置地址映射还能用连接自动化Connection Automation帮你自动接线和创建互联。纯HDL方式虽然更“干净”但你需要手动例化所有的AXI Interconnect和协议接口信号报错时定位也更麻烦。在本文剩余部分我全程围绕Block Design流程来讲。下面先创建一个名为axi_vip_test的RTL工程器件选择Artix-7 xc7a35ticsg324-1L你按自己的板子选也行不影响并且建好一个顶层文件top.v——先不写内容留着待会儿放实例化。2.3 需要额外配置的环境项Vivado 2023.1中编译仿真库Compile Simulation Libraries这一步不用手动做启动仿真时XSim会自动编译。但有一点要特别注意如果你多个Vivado版本混装过或者C盘空间严重不足仿真库可能损坏。这种情况下的典型报错是[Vivado 12-1306]找不到Unix DB文件。早做准备的方式很简单在Vivado的Tcl Console里执行catch { compile_simlib -simulator xsim -family all -dir C:/xilinx_simlib }跑一次全系列编译目录放到非系统盘后面仿真就少一个故障源。3. AXI VIP配置的完整实操步骤——每一步都写清楚万事俱备下面进入重头戏在Block Design中把AXI VIP配起来并把仿真跑通。这部分我会按实际操作顺序展开每一步对应着什么意图也一并说明不是单纯罗列菜单。3.1 创建BD并添加AXI VIP IP打开工程后在Flow Navigator选择Create Block Design输入设计名称比如axi_vip_test_bd。创建完成会进入BD画布界面。在Diagram空白处右键或者点击界面上方的号添加IP搜索框输入AXI Verification IP双击添加。此时BD画布上会出现一个AXI VIP的图形组件默认以一个MASTER_VIP和一个SLAVE_VIP块的形式存在注意它默认是例化了一个Master一个Slave各一不是只有一个模块。3.2 VIP配置界面逐个参数讲清楚双击VIP组件打开配置界面。你会看到三块主要区域Master Interface主接口、Slave Interface从接口、General Options通用选项其中每个接口标签页下还有具体的协议参数。先说Master Interface命名为M00_AXI这类Protocol选择AXI4还是AXI4-Lite。如果你的被测设计是常见的寄存器读写从机选AXI4-Lite足够用而且仿真速度快如果要测高带宽突发传输必须选AXI4。Data WidthAXI4下可选32/64/128/256/512AXI4-Lite只能是32。Address Width根据自己的地址空间选我习惯保持32。Enable Read Path、Enable Write Path默认都勾选代表Master支持读和写两种事务。后面配置测试序列时读和写对应的动作命令不一样。Enable Protocol Checks默认勾选。它会监测到协议违例立即报错一旦你测试代码里事务触发姿势不对这个开关会立刻把问题暴露出来。建议保留。Enable Coverage可选。开启后VIP会收集协议覆盖率数据在仿真实用但会明显拉慢速度。验证功能阶段建议关闭。Enable Transaction Recording默认勾选为好。它能记录transaction级日志便于ploc波形时对照总线上实际跑的事务。然后是Slave Interface命名为S00_AXI之类的一样有Protocol、Data Width、Address Width选项。多了Support Narrow Burst、Support Unaligned Access之类的选项。若你的测试场景会涉及窄传输和未对齐访问这里需要打勾否则保持默认即可。Memory Model这里可以选BRAM、DRAM、Register等。我通常选Register模式仿真速度快地址读写能直接映射到内部寄存器变量。你如果希望VIP模拟一个内存控制器就选BRAM。最后是General OptionsSystemC Simulator、C Modeling这类选项保持默认即可。Simulation Options里的Output Waveforms默认开启生成波形文件。IPCores Compilation可以根据你的CPU核心数设置并行编译个数我一般设4太多反而容易内存爆掉。配好之后点OK退出。此时BD画布上的组件会刷新显示你配置好的接口名称和数据宽度。3.3 自动连接以及地址映射还没完。AXI VIP在BD里只是个孤零零的组件得跟你自己的设计连接起来。拿我的工程举例我在BD里另外添加了一个自己写的AXI Slave IPmy_axi_slave_0这名字无所谓你知道怎么弄就行然后把VIP的Master接口M00_AXI连到Slave的S_AXI接口俗称“总线上两个口对接”。接着需要设置地址映射。在BD画布上方菜单栏选择Address Editor能看到主行有M00_AXI下面列出了从机my_axi_slave_0对应的S_AXI给这个S_AXI分配一个地址段比如0x0000_0000开始大小64K。为什么要做地址映射因为AXI VIP发起读写事务时你必须给它一个目标地址。如果地址映射没配VIP仿真时不知道往哪儿发请求底层会返回错误。配好之后后续代码里操作的就是这段地址命名空间。3.4 Generate Output Products的坑这一步很多人踩坑我专门说一下。在BD画布右键VIP组件选择Generate Output Products。这里有个别的IP没有的行为它会询问你是否要生成示例工程Generate Example Design。选择“是”。示例工程会生成一个包含VIP Master/Slave实例的顶层top.v在工程目录下会生成一个*_example文件夹里面自动调用了VIP的驱动方法甚至包含一个简单的读写测试事件。这一步特别重要——如果你不生成示例后面在仿真里光靠Testbench自己写调用很容易漏掉例化的初始化代码。很多朋友直接生成到仿真阶段就报uvm相关错误基本都是因为少了这一步。生成的示例文件放到工程的project/project.srcs/sources_1/ip/axi_vip_0_example/目录下通过Sources窗口加到工程里Add Sources - Add or create design sources。你不需要改动它先让它原样跑起来。4. 仿真运行与波形调试——从跑出波形到看懂波形配置就绪下面开始仿真。这一步也是报错高发区但按正确的顺序操作能大幅降低失败概率。4.1 启动行为仿真Vivado左侧Flow Navigator里选择Run Simulation - Run Behavioral Simulation。第一次跑XSim会编译所有仿真源文件包括IP库和示例工程。这个编译过程可能耗时一两分钟屏幕下方会有一大堆编译信息别慌。如果一切顺利仿真窗口会自动打开弹出一个默认的波形窗口。你会看到几个初始信号CLK、reset_n、以及M00_AXI接口上相关的握手信号。此时仿真还未必开始跑因为示例工程里普遍会自己跑若干个测试序列用run -all命令可以一次性跑完。我在Tcl Console直接执行run -all然后等仿真结束波形窗口就能看到VIP的行为。你会看到M00_AXI上的AXI4-Lite写事务以AWVALID-WVALID-BVALID顺序出现读事务以ARVALID-RVALID顺序出现。到这个层面恭喜AXI VIP配置已经成功了一大半。4.2 如何确认事务真的是成功的波形窗口里能看但因为信号名太长太密光肉眼找容易漏。更靠谱的方法是看XSim的Tcl Console输出和仿真日志。示例工程默认会打印一些事务日志里面有AXI4-Lite Write Transfer、Read Transfer、Response OKAY之类的关键词。你也可以在Testbench里用$display打印VIP事务完成后的返回值。标准做法是调用axiprotocol_0.agent.sequence.write()或.read()这类方法然后检查返回的Response值是不是AXI4-LITE_OKAY。这些在示例里已经写好了你只需要看Console输出里出现了多少条OKAY。实操心得我建议在跑完示例后在波形窗口里打开M00_AXI总线接口的所有子信号专门找AWREADY、WREADY、BVALID、ARREADY、RVALID这五个握手信号。仿真结束时这五个信号全部出现高电平且手上事务的响应类型为OKAY基本可以判定整个链路是通的。4.3 自定义测试场景的方法示例工程跑通之后就该轮到改造成自己的测试序列了。这里说一个最常见也最基础的用法如何让你的AVIP Master发起一笔自己指定地址和数据的写操作。在示例工程的Testbench里通常是tb_top.sv找到对VIP驱动句柄的引用比如axiprotocol_0。接下来在initial块中利用VIP的sequence调用类似这样// 在testbench中 initial begin // 等待系统复位释放 (posedge axi_vip_0.agent.rst_n); repeat(5) (posedge axi_vip_0.aclk); // 发起一笔写传输 axi_vip_0.agent.sequence.write( .addr(32h0000_0000), .data(32hDEAD_BEEF), .resp(trans) ); // 发起一笔读传输 axi_vip_0.agent.sequence.read( .addr(32h0000_0000), .data(rdata), .resp(trans) ); $display(Read data 0x%08x, rdata); end这只是示例工程风格的片段不是给你直接复制到任何工程都能跑的万能脚本。但核心思路是调用VIP的.sequence.write()/.read()方法传地址和数据任务结束后数据要么写进从机要么从从机里读回来响应状态由resp变量携带。4.4 波形窗口使用要点与调试步骤跑仿真的时候可以打开Waveform Configuration窗口添加以下几组信号AXI总线整体总线接口右键M00_AXI信号选择Add to Wave Window。顶层时钟和复位信号确保aclk与aresetn在波形窗口中有且能确认复位释放时机。自定义被测设计的内部寄存器信号加内部信号方便看数据有没有真的落到对应寄存器上。调试时建议这样操作在波形窗口点击“重新启动仿真”按钮然后配合run -10us跑10微秒观察局部行为。用run -all跑完整测试反而容易在大量信号中迷失。真实调试中最常见的情况是VIP发起写事务后BVALID迟迟不拉高。不要急着怀疑VIP先看你的Slave设计对WVALID/WREADY握手的响应是否正常。如果Slave一直不拉高AWREADY那就说明VIP没配置成对应的“接受握手”模式或者在地址译码上出了问题。5. 高频报错与排查清单实录这部分我直接上干货把我在实战中遇到过、也帮外地朋友远程排查过的AXI VIP报错按出现频率排个序。每个都写了当时的症状和最终的修正手段你可以当速查表用。5.1 仿真库/编译类报错这类报错通常出现在第一次Run Simulation时特征比较明显。[Vivado 12-1306] ... failed to compile simprims library仿真库损坏或不全。处理方式Tcl Console执行前面提过的compile_simlib重新编译全套库特别注意路径不能有中文或空格。ERROR: [XSIM 43-3321] ... could not find design unit axi_vip_pkg说明你的工程缺少AXI VIP的仿真库或者包文件引用。检查Settings - Simulation - Verilog Compile Order确认axi_vip_pkg、xil_defaultlib等包文件在前面。也可以尝试把示例工程的所有文件删掉重新Generate Output Products。Error: [Synth 8-448] ... instance u_axi_vip of design unit axi_vip ... is not defined这是综合阶段的错误说明IP核没有被正确例化到顶层。在Block Design中检查你的VIP实例化名字和BD名字是否一致然后在顶层代码中检查是否例化了axi_vip_test_bd这个wrapper而不是VIP本身。5.2 协议级报错仿真中途爆出的红字当你成功进入仿真却在中途发现Tcl Console里不停刷协议错误这类基本上属于测试场景配置问题。[XSIM 43-3305] AXI4-Lite Write Transfer is illegal ... Burst length must be 1说明使用AXI4-Lite却试图发起非单拍的burst传输。AXI4-Lite协议规定突发长度恒为1检查example sequence是不是用了AXI4的burst命令改成AXI4-Lite适应的命令即可。[XSIM 43-3309] Address (0x...) is outside the configured range of ...地址越界。Block Design里的地址映射与Testbench里访问的地址不一致。回到Address Editor重新核对保证测试代码访问的地址落在映射范围内。[XSIM 43-3282] Response is not OKAY ... SLVERR从机报错。说明你的Slave设计功能有问题或者访问了不支持的地址。此时不要折腾VIP回到你设计的RTL代码里排查译码逻辑。AXI protocol violation: AWVALID low when not allowed协议上时序违例往往出现在你改了示例工程的burst模式或等待条件之后。仔细检查你的事务发起是否遵循了“VALID必须在READY就绪前拉高且一旦VALID拉高不能随意拉低”的规则。5.3 仿真卡死或没反应这是听别人描述最多的状态跑了run -allConsole半天不输出波形窗口信号全是低电平也没有红色报错。这种大概率不是配置问题而是仿真死锁deadlock。死锁常见原因是握手环节没有“相互等待”的支持。比如你的VIP Master在等READY而Slave设计在等VALID两边互不相让总线直接冻结。排查方法在波形窗口只保留AWVALID/AWREADY/WVALID/WREADY/BVALID/BVALID这几组信号看哪个一直为低。哪个拉不起来就去查哪一侧的逻辑。还有一个常见死锁原因复位信号的时序。仿真一开始就跑示例测试序列但复位还没释放或者释放时间晚于第一个transaction的发起时间。处理方法在Testbench的initial块中先让复位信号置低至少5个时钟周期再拉高同时确保测试序列从复位释放后才开始启动。Xilinx的示例工程默认有这段逻辑但自己写的时候容易漏。5.4 打印日志太多看不过来吐槽这个的兄弟太多了。AXI VIP默认在仿真中会打出大量transaction级打印信息尤其当你跑的数据量大时Console里一行接一行无法直视。这点其实可以在VIP配置中关掉但是在配置界面找不到因为你需要用Tcl命令控制。在Tcl Console执行set_property -name {ip_property.axiprotocol_0.agent.enable_transaction_recording} -value 0 -objects [get_bd_cells /axi_vip_0]这样能关闭transaction recording。如果你想连打印都一并关掉可以再在Testbench里实例化一个uvm_config_db机制来屏蔽日志或者直接改VIP生成的example文件注释掉uvm_report_info的显示级别。不过我个人建议保留必要的事务级打印毕竟报错时你还得靠它定位。6. 能榨干AXI VIP的最后几个实用技巧跑通是第一阶段用得顺手是第二阶段。最后分享几个我实际在项目里反复用的小技巧。6.1 用Vivado的Address Editor规划多设备地址空间如果你在一个BD里同时挂了多个AXI Slave测试时往往需要分别访问不同地址。建议在Address Editor里给每个Slave都分一个独立的地址段不要都塞到同一个基地址下。比如Slave0分0x0000_0000–0x0000_0FFFSlave1分0x0000_1000–0x0000_1FFF。这样后续在Testbench里发起事务时直接按照地址段访问代码可读性和维护价值会高很多。6.2 利用VIP的Slave模式做回环测试如果你的验证对象是一个DMA引擎或一个要求从丛机侧主动发起中断的设备建议同时挂一个AXI VIP Slave。Slave模式的VIP内部维护了可随时读写的寄存器或内存缓冲Master和Slave搭配使用可以快速做回环测试Master往Slave区写数据再读回相同地址比对数据一致性。这个流程在master验证浮点运算模块、导航控制模块时特别有用比上板测快得多。6.3 掌握VIP的UVM集成方法AXI VIP底层实现是基于UVM的。这也意味着如果你的验证平台本身就直接用UVM写法甚至可以在VIP里通过标准的UVM API直接报名和启动sequence而不用像示例工程那样把初始化逻辑都丢在initial块中。这个方向需要你先补一下UVM基础知识但一旦掌握你的验证环境就真正脱离Testbench的脚本式写法进入规模化验证的阶段。具体做法大概是这样在UVM环境里例化VIP的agent设置成master模式注册成UVM component之后你就可以像标准UVM环境一样通过seq.start(agent.sequencer)来发起事务。此处注意在UVM集成时VIP内部已经定义了protocol.txn这种派生事务类你不用自己重写事务类继承扩展就行。6.4 遇到“仿真空转”先检查接口名字很多时候看起来像没跑起来实际是总线接口的Sample Data Mode或者接口时钟反转配置错了。AXI VIP里面有专门对S_AXI_ACLK和S_AXI_ARESETN的连接要求一旦在BD里把reset_n接到了其他低有效信号上仿真空转根本不报错。检查一下VIP的接口连接看reset_n是否连接到了正确的“低有效复位”信号这个很低级但踩的人极多。6.5 保存一份成功的工程配置作为模板一旦某一轮工程完整跑通整个BD设置和示例的Top文件基本上就别再大改了。把它复制一份作为后续项目的起点。后续换芯片、换接口宽度时在这个基础工程上做增量修改比从零配置快得多报错率也会大幅下降。最后再送一个实战小建议AXI VIP真正上手之后你会发现它的报错大多不是Vivado坏了也不是VIP没配好而是因为你还没给它一个“清晰、合规、符合AXI协议规则”的访问场景。每次报错回去看三步第一步地址映射对不对第二步Protocol型号对不对第三步Testbench里的事务参数到底写没写对。把这三步看完起码80%的问题都能自答。从配置界面的一脸懵到示例工程跑出第一条OKAY响应再到自己写出第一段自定义读写sequence整个过程其实是FPGA验证能力提升的一次缩影。我在实际项目中体会最深的一点是AXI VIP不是用来替代你动脑去理解AXI协议的它更像是逼着你去理解协议细节的一个导师——你越是认真地遵循协议去配置它它越是服服帖帖地为你服务。这套流程走完之后建议你再看看AXI协议规范文档把先地址后数据的AXI读操作、写操作握手流程、以及不同burst模式的区别都过一遍那时候你回头再看VIP配置界面几乎每个参数都能对上协议里的一句话。能把协议理解和工具配置对上号你就真正入门了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进