VSC用途:
仿真事件队列指的就是,VCS仿真工具是如何处理我们所写代码。(其他的仿真工具可能并非如此,不同公司的仿真工具除了遵循一些共同的标准之外,还会有自己特定的算法,最后得到了各自的仿真工具,因为存在各自不同的算法,不同的工具对同一个东西的仿真结果可能就会有所不同。)
对于仿真事件队列而言,它遵循IEEE 1364 标准:Verilog 语言的仿真基于分层的事件队列;只要在同一层的事件,什么执行顺序都是可以的。
(对于单核 CPU 言,代码是串行执行的。但是相比于软件,实际的的硬件电路具有并发性。那么如何通过软件模拟硬件的并发性?)
VCS处理仿真代码的过程(仿真的基本流程)如下:
读取所有的 initial、always 、assgin 等语句,按照空间顺序放在队列里面。首先执行没有延时的语句(如变量的初始化赋值等)
执行完没有延时的语句之后,将时间 t 设为 0,称之为 current time。
然后,首先进入 active region。
在该区域内,VCS执行的操作包括:
① 原语(或门、非门、CMOS逻辑、PMOS逻辑、上拉、下拉 …);
② $display;
③ 不包含任何延时信息的 assgin 语句;
④ 阻塞赋值( = );
⑤ 非阻塞赋值( <= )只计算右边的表达式,不进行赋值操作
进入 inactive region
执行带有 #0 的语句。
虽然没有延时,但是对于VCS而言,这种语句会比没有使用 # 设置延时的语句的执行时间晚一些。
进入 Nonblocking assgin region
对非阻塞赋值语句进行赋值操作
monitor region
monitor 系统函数是只有在变量发生变化的时候才会执行。
future region
执行其他语句
视频里面有一个示例,说明了同一个代码,使用不同的仿真器得到了不同的结果。这里只给出了代码,这段代码本身也存在一定的问题,不够严谨。
仿真事件队列:
VCS (verilog compile simulator) 是一个编译型仿真工具,其工作过程主要分为两部分:
(1)编译(Complie):把源码“翻译”为可执行文件
(2)仿真(Simulate)
VCS 遵循 IEEE-1364 标准,具有PLI(Programming Language Interface)接口,verilog、SV等可以借助PLI调用 C\C++ 程序
支持多个抽象层次的仿真
(1)行为级描述(验证)
(2)RTL级描述(设计)
(3)门级描述(综合之后得到的,和工艺相关)
整体上分为编译和执行,具体过程如下:
(1)将 Verilog/SV 翻译为 C 语言中间文件
(2)将 C 语言文件编译为对象文件(.o)
(3)连接后形成可执行文件
基本命令
vcs source_files [compile_time_options]
source_files
:DUT的源文件,Verilog 或 SystemVerilog格式,多个源文件之间用空格隔开
compile_time_options
:告诉 VCS 如何对源文件进行编译
使用该命令之后会生成一个用于仿真的二进制可执行文件 simv
。
-Mupdate
:增量编译(Incremental compilation),只对修改过的文件进行重新编译,然后链接即可。
-R
:Run after compilation,编译后立即进行仿真(不需要通过 ./simv
来执行仿真 )
-gui
:Starts the DVE gui at runtime (仿真时使用 DVE 调试)
-debug_all
:产生vpd文件,可以用 DVE 进行后续的调试(enable DVE for post-processing)
-l
: set log file name,编译时的信息写到 log 文件
-sverilog
:提供对SystemVerilog的支持
+v2k
:支持 Verilog 2001 标准
-v lib_file
:lib_file 是 Verilog 文件,包含了引用的 module 的定义,可以是绝对路径,也可以是相对路劲。
-y lib_dir
:lib_dir是参考库的目录(就是 lib_file 所在的位置),vcs从该目录下寻找包含引用的 module 的V erilog文件,这些文件的文件名必须和引用的 module 的名一样
+libext+.v+.vhd+...
:vcs 在参考库目录下寻找以 .v 和 .vhd 为扩展名的文件。 多个扩展名之间用“+”连接。(如果用到的库文件很多的时候,就可以使用命令和 -y
命令的组合,而不用使用 -v
命令逐个添加)
+incdir+dir1+dir2+…
:vcs从 dir1 和 dir2 等目录下寻找源代码中 `include 指示的文件。
-f filelist
:如果源文件很多的时候,在 source_files 中用空格隔开是不明智的,这里就可以使用 -f
指令。filename中包含了源文件和部分编译选项。
-o bin_name
:默认生成的可执行文件名称是 simv,该选项是修改可执行文件的名称。
+define+macro1=value+macro2=value+…
将宏 macro1 传给源代码。将macro1和macro2,…传给源文件中同名的宏,如果value是字符串的话,要用双引号括起来。
基本命令
./simv [run_time_options]
run_time_options
是可选的,可有可无,根据需求选定即可。
-l log_file
:记录 DVE 或 VCS 仿真过程的 log 文件
-s
:Stop simulation at time 0
DesignWare 是 Synopsys 公司提供的一个库,主要包含的是 RTL 代码,和具体的工艺无关,存在于 VCS 的安装目录之下,可以在代码中直接调用库单元,如下所示:
此时,在仿真的时候,就要制定库文件,具体的实现是通过 -y
命令指定库文件的路径,然后使用 +libext+.v+
指定读取的库文件的后缀名是 .v 。
测试电路时用 1bit 加法器(fa.v)搭建的 8bit 加法器。
写好源代码和tb代码之后,直接使用 vcs
命令进行编译。编译过程如下:
编译后生成的内容如下,其中 simv 就是用于仿真的可执行文件。
然后执行仿真,命令如下。其中最后的 &
表示的是后台执行,后面紧跟着的一行内容是进程号。(这样当前控制台不会被占用,可以继续执行其他操作)
打开的 DVE 界面如下:
下图这里的内容是对应的,选中addertb(testbench模块),右边就会显示 addertb中的所有信号。
如果选中u1(实例化的待测模块),就可以看到该模块中的变量:
打开波形窗口:
打开之后如下:
(这里不是自己的,自己的忘记没有截图了)
因为还没有开始仿真,所以看不到任何波形。
按 F5 开始仿真,得到结果如下;
波形显示信息的调整:
第一次编译的时候,没有使用 -debug_all
选项,在仿真的时候,尝试调用 gui 的时候出现如下错误。
(1)也就是说,如果想要仿真是在图形化界面进行的,就必须在编译的时候由相关选项
(2)从提示也可以看出,工具是一直在更新的,新版本的工具用的也是新的指令,这里就先把基础的搞明白,后续有时间可以看看新版本的工具手册。
执行 vcs add*.v fa.v +v2k -debug_all
命令后的文件内容:
csrc
:C source file , C 语言文件,内容如下:
使用如下命令,就可以将编译过程显示在终端的内容写到文件中
vcs add*.v fa.v +v2k -debug_all -l complie.log
执行该命令之后,会在当前目录下,生成一个 complie.log 文件,文件内容如下:
命令如下:
vcs add*.v fa.v +v2k -debug_all -l complie.log -R -gui
使用 -R
命令之后,编译结束后会直接打开图形化界面,然后停在仿真时间为 0 的时候(和自己打开图形化仿真界面的情况是一样的),F5 之后开始仿真。
编译命令
vcs add*.v fa.v +v2k -debug_all -l complie.log -o simv_adder
verilog代码中定义了宏,分别使用如下两种情况来启用宏。
第一种是直接在代码中使用 `define 命令定义,第二种是将 define 定义的内容单独写在一个文件中,然后使用 include 命令包含该文件。
对于第一种情况,直接编译即可。
但是对于第二钟情况,直接编译就会报错,虽然 global_define.vh 和源文件 fsm_moore.v 是在同一个目录之下
这个时候需要使用如下命令:
vcs ./tb/fsm_tb.v ./rtl/fsm_moore.v +v2k -debug_all +incdir+./rtl/global_define.vh -o simv_fsm_moore
必须要指出去哪里寻找 include 指示的文件。
还有一种方法是在编译的时候,通过参数去定义宏,编译命令如下:
vcs ./tb/fsm_tb.v ./rtl/fsm_moore.v +v2k -debug_all +define+INC_COUNTER+ -o simv_fsm_moore