QuestaSim仿真Vivado工程:Xilinx仿真库编译与挂载指南

📅 发布时间:2026/10/5 19:04:56
QuestaSim仿真Vivado工程:Xilinx仿真库编译与挂载指南
直接说结论QuestaSim本身不认Xilinx的仿真库刚装好就拿来仿真Vivado工程百分之百会报错。这不是软件没装好而是你缺了一个很关键的环节——把Xilinx的库编译成QuestaSim能用的格式并且在工程里正确挂载。这篇文章就专门讲这个事怎么把Vivado/ISE那一套库unisim、secureip、xpm等在QuestaSim里编译好、配置好以及功能仿真和时序仿真分别该怎么设置。我翻了大量网上的提问发现很多人卡在同一个地方Vivado导出的仿真文件里带了glbl.v、unisim、xpm这些依赖但QuestaSim不知道去哪找于是一堆Unknown type、Cannot find module报错。所以本文会把“编译库—挂库—功能仿真—时序仿真—排查报错”这条线整个走一遍适合刚转QuestaSim的FPGA工程师也适合被库问题折磨了很久的老手。1. 先搞明白Xilinx库为什么不能直接拿去仿真1.1 两大EDA工具的“库世界观”不一样Vivado自带的仿真器是XSimXSim编译出来的库格式和QuestaSim完全不同。Vivado安装目录下的data/verilog/src里存的是Xilinx提供的原始Verilog/VHDL源码unisim、secureip、unimacro、xpm等但QuestaSim不能直接把这些源码当成自己的“编译后库”来用。这里我打个比方Vivado的库像是一堆刚刚从菜市场买回来的新鲜蔬菜XSim有自己的厨房能直接加工而QuestaSim是另一家餐厅它不会直接进你的厨房做菜它需要你先在自己的灶台上把这些蔬菜“过一遍火”——这个“过火”的过程就是编译。所以核心思路就一句话用QuestaSim自己的编译器vlog/vcom去编译Xilinx的库源码生成QuestaSim的库格式再告诉QuestaSim“以后这些库名字对应哪个文件夹”。这一步跑通了后头功能仿真和时序仿真才会顺。1.2 需要编译的库有哪些Xilinx在Vivado里按用途把库分成了几块各有各的用处unisim仿真Xilinx原语比如BUFG、IBUFDS、FDRE、SRL16等大部分RTL仿真都绕不开它。secureip存放受保护的IP内核仿真模型比如高速收发器、部分DSP、PCIe硬核等这些模型以加密形式存在。unimacro一些Xilinx宏模块CARRY4、MUXF7等的“拼装”封装有些设计会直接例化这些宏。xpmXilinx参数化宏现在新的IP核非常依赖xpm库比如FIFO、RAM、CDC、异步复位同步释放等。xpm分xpm_cdc、xpm_memory、xpm_fifo等子库。simprim主要是时序仿真后仿真时要用的单元库包含带延迟信息的原语模型。glbl严格来说不算独立库而是一个glbl.v文件里面是全局复位/时钟的虚拟驱动逻辑时序仿真和很多原语仿真必须把它编译进去。如果你用的还是老一点的ISE流程那还有一个unisim_comp和simprim_comp的VHDL版本思路一模一样只是编译命令换成vcom。1.3 消息里常见的“Cannot find unit”是什么意思QuestaSim里出现** Error: (vcom-1136) Cannot find unit xxx或者vlog: Cannot find module xxx本质就是编译器在当前的work库和映射库里翻了个遍找不到那个顶层模块或单元。Xilinx的IP核在sim_1目录下生成的仿真文件例化了一大堆unisim/xpm里的东西这些东西不在work库里你没有提前编译并映射这些库QuestaSim当然一脸懵。所以真正要解决的工程问题只有两个库编译到哪里、仿真时怎么让QuestaSim找到这些库。2. 编译Xilinx库的完整操作2.1 准备工作确认版本和文件路径在动手编译之前先确认三件事Vivado安装路径默认在C:\Xilinx\Vivado\2021.1不同版本后头的版本号不同注意替换。QuestaSim版本建议使用10.7c以上或者2021.x之后的版本否则对新版Vivado如2022.2的xpm和secureip支持不友好。操作系统位数QuestaSim和Vivado尽量都用64位不然仿真大工程时内存容易爆。注意版本太老的QuestaSim比如10.2编译新版Vivado的UNISIM会有大批语法报错这不是你操作的问题是工具版本的问题。如果遇见接二连三的语法错误优先怀疑版本不匹配而不是怀疑自己配置写错了。2.2 手工编译方式用Questasim的compile脚本在QuestaSim的安装目录下有一个专门用于编译Xilinx库的Tcl脚本位置通常在这C:\questasim64_xxx\modelsim.ini C:\questasim64_xxx\tcllib\vendor\mentor\compile_xilinx_libs.tcl这个脚本支持多个Xilinx版本用法是在QuestaSim的命令窗口里执行vsim -c -do source C:/questasim64_10.7c/tcllib/vendor/mentor/compile_xilinx_libs.tcl; quit但更常见的做法是直接调脚本的Tcl过程。比如compile_xilinx_libs -family vivado \ -version 2021.1 \ -src_dir C:/Xilinx/Vivado/2021.1/data \ -lib_dir C:/xilinx_sim_lib/2021.1-family vivado指定是Vivado平台-src_dir指向Vivado安装目录下的data文件夹-lib_dir是你想把编译好的库输出到哪个目录。执行完之后C:/xilinx_sim_lib/2021.1下面会生成unisim_ver、secureip、xpm等一堆文件夹每个文件夹里都是QuestaSim格式的编译产物_info、.dat等。如果你懒得折腾Tcl脚本直接用QuestaSim的GUI菜单也行。在主界面菜单栏上打开Tools - Compile Xilinx Simulation Library它会弹个向导让你选Vivado版本、库目录、输出目录点完成后就开始批量编译。这个向导本质上就是在帮你调那个脚本好处是不用手敲路径缺点是自动化不够换台机器还得重新点一遍。2.3 关键参数选择为什么有时要单独编译xpm脚本默认会编译unisim和secureip但xpm库有时候不会自动选上。很多网上的教程其实漏了这一步导致仿真时一遇到新版Xilinx FIFO IP就报xpm_cdc模块找不到。如果你用到的IP核比较新请务必在向导里勾上xpm或者手动编译vlib xpm vlog -work xpm C:/Xilinx/Vivado/2021.1/data/ip/xpm/xpm_cdc/hdl/xpm_cdc.sv vlog -work xpm C:/Xilinx/Vivado/2021.1/data/ip/xpm/xpm_memory/hdl/xpm_memory.sv vlog -work xpm C:/Xilinx/Vivado/2021.1/data/ip/xpm/xpm_fifo/hdl/xpm_fifo.sv乱不乱不乱。其实就是把Xilinx的SystemVerilog源码一条条帮你在QuestaSim里编译一遍。如果脚本能自动全编最好不能全编就手动补齐。2.4 编译完成后必须做的事配置modelsim.ini库编译出来只是第一步你的工程不会自动知道这些库在哪。需要把库路径写进modelsim.ini里。先说一下modelsim.ini这个文件的作用。它是QuestaSim的全局配置文件里面有一个[Library]区域块格式是[Library] unisim_ver C:/xilinx_sim_lib/2021.1/unisim_ver secureip C:/xilinx_sim_lib/2021.1/secureip xpm C:/xilinx_sim_lib/2021.1/xpm ...你可以在QuestaSim里敲命令来写入映射vmap unisim_ver C:/xilinx_sim_lib/2021.1/unisim_ver vmap secureip C:/xilinx_sim_lib/2021.1/secureip vmap xpm C:/xilinx_sim_lib/2021.1/xpmvmap不单是写文件它还会建立逻辑库名和物理路径的映射关系。映射写好后modelsim.ini里会多出这些条目以后每次启动QuestaSim它只要读到这个ini文件就自动知道unisim_ver对应哪个文件夹。提示vmap命令对当前工程生效其实是修改当前工作目录下的modelsim.ini。如果你在某个工作目录里敲这个命令它会把映射写进那个目录的ini文件里。所以一定要搞清楚当前目录在哪别到时候换了个目录又发现库全丢了。3. 在工程里挂载Xilinx库并做功能仿真3.1 搭一个最小仿真工程我习惯用.do脚本把工程流程固定下来这样每次重新拉代码、重新仿真都不用手点。一个最小脚本大概这样# compile_and_run.do vlib work vlib xil_defaultlib # 编译Xilinx基础库 vlog -work unisim_ver C:/xilinx_sim_lib/2021.1/unisim_ver/*.v vlog -work xpm C:/xilinx_sim_lib/2021.1/xpm/*.sv # 编译自己的源码 vlog -work xil_defaultlib ../rtl/fifo_wrapper.v vlog -work xil_defaultlib ../rtl/axis_fifo.v vlog -work xil_defaultlib ../sim/tb_fifo.v # 启动仿真 vsim -L unisim_ver -L xpm -L xil_defaultlib work.tb_fifo这里有个细节很多人不太注意vsim启动时加了一堆-L参数。-L的意思是允许QuestaSim在指定库里查找模块因为仿真时testbench顶层模块里引用的FIFO IP并不是直接编译到work库里的而是在xpm或unisim_ver库里已经编译好的单元。你不把库列出来它搜不到。3.2 把Vivado导出的仿真文件挪到QuestaSimVivado里打开一个IP核Sources选项卡里有Simulation Sources右键选Generate Output Products然后在sim_1目录下会生成一个.f文件File list里面列了这个IP核仿真依赖的所有源文件路径。常见路径是这样的C:/project/project.srcs/sources_1/ip/fifo_gen_0/sim/fifo_gen_0.v C:/project/project.srcs/sources_1/ip/fifo_gen_0/sim/fifo_gen_0_sim_netlist.v如果你不想自己手动拉一堆文件可以直接用vlog -f参数把.f文件喂给QuestaSimvlog -f C:/project/project.srcs/sources_1/ip/fifo_gen_0/sim/fifo_gen_0.f这是一条偷懒捷径但有个前提.f文件里的路径要和你本机的相对路径对得上。如果Vivado工程挪过位置.f里的路径全是旧路径得先在文本编辑器里清理一遍。3.3 常见功能仿真流程功能仿真不需要管延迟信息只验证逻辑功能正确性。完整流程可以浓缩成四步我直接把这四步写成一个run_sim.do脚本方便以后一键跑# 清除之前的编译产物 if {[file exists work]} { vdel -all -lib work } vlib work vlib xil_defaultlib # 1. 编译Xilinx原语库很多IP例化原语时要用 vlog -work unisim_ver C:/xilinx_sim_lib/2021.1/unisim_ver/unisim_comp.v vlog -work secureip C:/xilinx_sim_lib/2021.1/secureip/secureip_comp.v # 2. 编译glbl时序仿真时代码里会例化它 vlog -work unisim_ver C:/Xilinx/Vivado/2021.1/data/verilog/src/glbl.v # 3. 编译设计代码和testbench vlog -work xil_defaultlib ../rtl/*.v vlog -work xil_defaultlib ../tb/tb_top.v # 4. 启动仿真把库都挂上 vsim -L unisim_ver -L secureip -L xil_defaultlib -L xpm \ -t 1ps \ work.tb_top \ work.glbl # 添加信号到波形 add wave -r /* run -all这个脚本里的work.glbl不能丢。很多人后仿真报错就是因为忘了把glbl模块一并加载进去。glbl提供全局置位/复位信号glbl.gsr、glbl.gtsamba总线和不少原语仿真要靠它来驱动统一的全局信号少了它仿真行为会变得很奇怪甚至直接退出。3.4 GUI方式一步步点出来的灵活配置如果你不太熟悉命令行也可以全在GUI里操作。流程是这样先选好工作目录启动QuestaSim。File - New - Project填写工程名和目录。Add Existing File把RTL文件和testbench加进去。右键工程里的文件选Compile All或者直接CtrlShiftL。打开Library面板如果之前vmap做得好能看到unisim_ver、xpm这些逻辑库名称。在命令行里输入vsim -L unisim_ver -L xpm work.tb_top回车启动仿真。打开Objects窗口选中信号拖进Wave窗口再点Run -all。GUI的坑在于很多人以为库只要在Library面板里“看得到”就完事了结果vsim一启动还是报找不到模块。原因就是少了-L参数QuestaSim默认只认work库你在Library面板里看到的库只是“挂载”了不代表仿真器自动搜索。切记vsim启动时得显式列出所有需要搜索的库。4. 时序仿真后仿真里库的设置细节4.1 后仿真和功能仿真的差别后仿真时序仿真比功能仿真严苛得多因为设计里已经加入了门级延迟、布线延迟、单元延迟等信息仿真时要把这些延迟背靠背地“标定”到仿真模型上这就是SDF反标。Vivado生成的SDF文件一般在工程目录里长这样C:/project/project.runs/impl_1/top_design.sdf后仿真第一步把综合后或实现后的网表文件编译进来。Vivado导出的网表是top_design.v里面例化了大量的基本门和Xilinx原语这些原语几乎都不在work库里全靠simprim或unisim_ver库来提供模型。所以后仿真时库的挂载有点不一样通常要同时挂这三个vsim -L simprim_ver -L unisim_ver -L secureip -L xil_defaultlib \ -sdftyp /tb_top/dut../impl_1/top_design.sdf \ work.tb_top \ work.glbl-sdftyp /tb_top/dut../impl_1/top_design.sdf的意思是把SDF文件里的延迟信息反标到路径/tb_top/dut这个实例上。/tb_top/dut是testbench里被测试设计模块的层次路径必须写成绝对层次路径写错就不会反标成功。4.2 SDF反标失败时怎么检查反标不成功时QuestaSim通常会在transcript窗口打印类似这样的警告** Warning: (vsim-SDF-324) Failed to find timing annotation for cell type: LUT6 ** Warning: (vsim-SDF-325) Failed to find timing annotation for cell type: FDRE看到这种警告先别慌这是常事很多情况下是因为有些单元没有时序模型可标不影响功能正确性只是延迟信息不完整。但如果整片全是这个警告那多半是simprim_ver没挂对或者SDF路径写错了。排查方法很简单在QuestaSim的命令行里执行check -sdf它会列出所有SDF文件的加载状态哪些反标成功哪些失败。再看-sdftyp的层次路径有没有打错用find /tb_top -dut之类的指令确认一下例化名字是不是叫dut。4.3 为什么后仿真要单独编译simprim功能仿真用的unisim_ver库库里的模型是不带延迟的主要用于验证逻辑功能。但后仿真希望看到“最接近真实硬件”的表现延时、竞争、毛刺都应该出现所以Xilinx单独维护了一个simprim_ver库里面全是带延迟行为描述的模型。所以如果你后仿真时只挂了unisim没挂simprim最常见的现象是仿真结果看起来和功能仿真一模一样根本没有延迟效果。那不是你设置成功而是时序信息压根没被用上。标准做法是专门编译一次simprimvlib simprim_ver vlog -work simprim_ver C:/Xilinx/Vivado/2021.1/data/verilog/src/simprims/*.v如果Vivado没有专门的simprims目录部分新版本把它挪到了别的位置可以在data/verilog/src下面搜一下simprims相关文件夹找到路径即可。VHDL工程则需要编译simprim的VHDL库。注意后仿真的库挂载顺序尽量不要乱。业界惯例是先simprim_ver再unisim_ver再secureip最后xil_defaultlib。顺序不对有时候也能跑但出问题排查起来很头疼按标准来最省心。5. 常见报错和疑难杂症排查速查表我把这几年自己和同事踩过的坑整理成了下面的速查表每一条都是真实遇到过的问题。真遇到类似情况建议照着表顺序排查很多问题其实都在前三条。报错信息原因解决方法Cannot find module glbl没编译glbl.v或仿真是没加载work.glbl编译Vivado安装目录下的glbl.vvsim时加上work.glblCannot find unit xpm_cdc_sync_rst没编译xpm库编译xpm源文件并在vsim时-L xpmFailed to find timing annotation for cell typeSDF反标失败或simprim库没挂全检查-sdftyp路径确保simprim_ver库已挂载Error: (vlog-1902) Option -L is not a legal optionvlog命令不支持-L-L只用于vsim库搜索路径放在vsim阶段编译阶段用-work指定目标库# ** Fatal: (vsim-3445) Invalid library mappingmodelsim.ini里的库路径变了或失效重新执行vmap确认路径存在vsim: cannot open unisim_ver as an alternative library逻辑库名映射丢了用vmap unisim_ver 物理路径重设** Error: Could not find compiled library xpm没在modelsim.ini中映射xpm用vmap或在GUI里Library - Add Existing添加** Warning: (vsim-3736) Module not found in library某个例化的原语不在当前库搜索范围检查IP依赖的库补充-L参数SDF file not foundSDF路径写错或相对路径不对用绝对路径重写-sdftyp仿真结果全是X态但功能仿真正常后仿真的glbl或全局复位没正确驱动确认glbl已加载检查testbench复位时序编译IP核文件报大量语法错误QuestoSim版本与Vivado版本不兼容升级QuestaSim或换低一点的Vivado版本这类表格放在手边出现问题对照着看比反复百度强多了。6. 一个自动化的库管理习惯随手就能用最后分享一个我自己的小习惯。因为Xilinx库编译一次时间不短快则十几分钟慢则半小时以上换台电脑又要重来所以我一般会在自己常用的目录下放一个setup_libs.do内容就是编译库和映射的全套脚本。换电脑后执行一次后续所有工程都复用这套编译产物。# setup_libs.do set VIVADO_ROOT C:/Xilinx/Vivado/2021.1 set LIB_OUT C:/xilinx_sim_lib # 建库 file mkdir $LIB_OUT vlib unisim_ver vlib secureip vlib xpm vlib simprim_ver # 编译 vlog -work unisim_ver $VIVADO_ROOT/data/verilog/src/unisims/*.v vlog -work simprim_ver $VIVADO_ROOT/data/verilog/src/simprims/*.v vlog -work secureip $VIVADO_ROOT/data/verilog/src/secureip/*.v vlog -work xpm $VIVADO_ROOT/data/ip/xpm/xpm_cdc/hdl/xpm_cdc.sv vlog -work xpm $VIVADO_ROOT/data/ip/xpm/xpm_memory/hdl/xpm_memory.sv # 映射到当前model sim.ini vmap unisim_ver $LIB_OUT/unisim_ver vmap secureip $LIB_OUT/secureip vmap xpm $LIB_OUT/xpm vmap simprim_ver $LIB_OUT/simprim_ver # 编译glbl vlog -work work $VIVADO_ROOT/data/verilog/src/glbl.v quit -f执行方法很简单在QuestaSim命令窗口里敲do setup_libs.do之后创建新工程时直接vmap一下就能引用。我现在维护的绝大多数工程仿真脚本也不过是把这个setup_libs.do跑一遍再跑自己的run_sim.do全程无脑省掉了大量重复劳动。我自己实际操作中踩过最大的一个坑是贪方便直接拿Vivado生成的IP核.f文件一股脑全编译结果有些文件是XSim专用的有些是综合用的混在一起就会冒出奇奇怪怪的语法报错。后来学乖了只拿simulation目录下的文件和.f综合目录的文件一概不碰。另一个经验是QuestaSim版本升级后最好重新编译一遍Xilinx库别偷懒沿用旧库因为不同版本对SystemVerilog语法的支持程度不太一样老库在新工具里偶尔会出一些莫名其妙的时序反标警告。把这些前置工作做扎实后头的仿真就是水到渠成的事。