本文转载自:Xilinx技术社区微信公众号
本文来自Grace Sun, Xilinx Senior Tools Applications Engineer
用户在用第三方仿真器对Vivado设计做仿真的时候,面临的第一个任务就是做仿真库的编译。事实上,后续相当一部分碰到的问题都与仿真库编译相关。今天,我们就来梳理一下关于仿真库编译的方方面面。
为什么需要单独编译仿真库?
一般来说,你的设计里不免会调用器件原语或是例化 Xilinx IP,这些原语及IP的仿真模型是以一系列组织为库的源文件给出,如果不事先把这些源文件编译成目标仿真器识别的格式,那跑仿真的时候就会出现找不到对应模块的错误。
有人也许会问,那我预先不编译,实际用到哪个原语就把模型源文件添加到编译列表实时编译到对应的库不行吗?当然也是可以的,只是设计越复杂,涉及到的仿真模型越多,逐一添加既繁琐又容易遗漏和出错,同时也增加编译开销,不如打包预编译来得省心。
仿真库和仿真模型从哪里找?
Xilinx提供的仿真库列表如下:

其中,unisim,unimacro,unifast 可以在 Vivado 安装目录下的 data/
XPM 源文件可以在安装目录的 data/ip/xpm 下找到,跟其他IP(data/ip/xilinx)一样,都支持预编译。
simprim 库比较特别,你在data/verilog(vhdl)下是找不到其对应入口的。这个库只用于Verilog Timing Simulation(VHDL Timing Simulation不支持),逻辑库的名称为simprims_ver。其模型的行为描述跟Verilog unisim库完全一样,只是多了 specify 语句的延时信息。举个简单的例子,以下是 data/verilog/src/unisims/BUFG.v 的内容:
`timescale 1 ps / 1 ps `celldefine module BUFG `ifdef XIL_TIMING #( parameter LOC = "UNPLACED" ) `endif ( output O, input I ); // define constants localparam MODULE_NAME = "BUFG"; `ifdef XIL_TIMING reg notifier; `endif // begin behavioral model buf B1 (O, I); // end behavioral model `ifndef XIL_XECLIB `ifdef XIL_TIMING specify (I => O) = (0:0:0, 0:0:0); $period (negedge I, 0:0:0, notifier); $period (posedge I, 0:0:0, notifier); specparam PATHPULSE$ = 0; endspecify `endif `endif endmodule `endcelldefine
在编译仿真库的时候,XIL_TIMING 定义的那部分内容只有编译 simprims_ver 库的时候才生效,剩下的代码 unisims_ver 和 simrpirms_ver 是共享的。
怎样编译仿真库?
Tcl 命令行方式和 GUI方式都可实现,有AR和文档都做了记录,在此不再赘述。
https://www.xilinx.com/support/answers/64083.html
UG900,搜索 Compiling Simulation Libraries 章节。
需要提及的是,编译仿真库并不是一个一劳永逸的过程,当你的 Vivado 或者第三方仿真器版本做了更改时,必须重新编译仿真库。
编译仿真库的常见错误解析
从以往报告的问题统计来看,大约有一半的编译库失败是由于用户环境设置以及第三方仿真器版本不兼容所致。
在此敲黑板划重点,在编译之前,一定要参照文档选择合适的仿真器版本,不兼容的版本未经验证,在编译一些加密的IP库文件时尤其容易出错。
UG900,搜索 Supported Simulators,下表是 Vivado 2020.1 兼容的第三方仿真器:

或者 UG973,搜索 Compatible Third-Party Tools。
理论上来说,版本是前向兼容的,也就是更新的版本也能支持。不过,考虑到只有所列举的版本才做过完整测试,以及新版本可能会做的改动影响,强烈建议按照官方所列的选取版本。
举例来说,Questasim 10.7版本里面编译选项-novopt已经移除了,而 Vivado 2018.1之前在启动 compile_simlib 给 Questasim 做仿真库预编译时会自动添加-novopt选项,如果不用兼容的 10.6b而用10.7,就会出错。
在成功编译了仿真库的前提下,其产生的初始化文件同样不可忽视。各个第三方仿真器的初始化文件如下图,一般安装目录随带有默认的初始化文件。

compile_simlib 启动后,会从对应仿真器的安装目录拷贝默认的初始化文件,放至预编译库目标文件夹,并且修改此文件,添加预编译库的映射地址。因此,你需要确保默认的初始化文件存在且有读写权限。
以 Questasim为例,你会看到 compile_simlib生成的 modelsim.ini 有类似如下的改动和添加:原始默认modelsim.ini

预编译库文件夹下生成的 modelsim.ini


注,仅截取一部分库做说明。
其中,others 引用的是安装路径下的 std 等标准库映射,后面增添部分就是预编译库的逻辑名称以及物理地址。
这个生成的初始化文件需要拷贝到你跑仿真的文件夹下,以便仿真器可以正确读入和引用预编译库。
仿真库编译的高阶配置及分析
最后对 compile_simlib 的高阶应用略作展开。
本质上来说,compile_simlib 会自动对目标仿真器生成编译脚本,并调用目标仿真器来编译Xilinx的仿真库。用户一般是不用去关心和控制底层命令的。
如确有需要去修改某些自动生成的编译选项,可借助 Tcl 命令 config_compile_simlib 进行配置,例如:config_compile_simlib-cfgopt {vcs_mx.verilog.unisim:-kdb}
其用法描述请参考帮助手册 config_compile_simlib help。
还有一些编译特定库出错的情况下,compile_simlib.log 无法反映错误全貌,需要去到预编译库的文件夹下查看具体的编译脚本和日志。
还是以 Questasim 预编译结果中的一个IP库为例,查看选项需包含隐藏文件:

Windows 系统的.cmd即为具体的编译命令,.log为此IP的编译报告。
用户可依据.cmd,根据log提供的具体错误信息,尝试手动修改脚本并调试。
总结来说,仿真库的编译不可少,正常使用的话,抓住版本兼容和初始化文件两个要点就够了。希望对大家有所帮助哦。