主要讲解如何在Linux环境下使用VCS对verilog或systemverilog进行编译,并使用VCS自带的DVE实现仿真和波形查看。

同时为了方便操作,介绍如何使用makefile实现自动化操作。

VCS+Verdi 仿真流程

1. VCS

全称Verilog Compiler Simulator,是Synopsys家的

其实就类似于windows环境下的questasim或modelsim,只不过vcs是linux环境下的工具。

可参考
《vcsmx user guide》
《vcsmx unified command line interface(ucli) user guide》
《VCS_DVE中文用户手册》
VCS+Verdi 仿真教程
[VCS]VCS常用命令詳解
Linux 运行vcs仿真命令,VCS使用以及命令行调试

1.1. Elaborate / Complie Design

首先是编译,主要完成语法检查和文件联编,并生成可执行的仿真文件

可直接在Linux终端执行,格式如下:

vcs [选项] [文件]

其中选项是可选的,下面给出一些常用选项

-full64:			支持64位系统
-l [文件名]:		创建文件,用于记录编译日志
-f [文件名]:		在某文件中索引要编译的文件路径,以及其他编译选项
-o [文件名]:		重命名仿真文件
-debug_acc+all:	支持UCLI调试
+incdir+[目录]:		为`include指定索引目录
+define+[]:		宏定义
-notice:			更加冗长的编译信息,便于调试
-timescale=1ns/1ps:时间单位和时间精度
+v2k:				开启verilog 2001架构
-sverilog:			开启systemverilog 架构

注意*.v中的`include均是以Makefile文件 或 输入vcs命令为起点目录!!!
而不是*.v文件所在的目录!!!
啥意思?看例子!

例子

首先在sequence_check目录下,有一个files.f和目录exercise,目录exercise下有sequence_check_tb.v和sequence_check.v

请添加图片描述
在这里插入图片描述
各文件内容如下:

//*************files.f*******************
./exercise/sequence_check_tb.v

//****************sequence_check_tb.v******************
`timescale 1ns/1ps
`include "./exercise/sequence_check.v"			//注意这里不能写成`include "sequence_check.v"
module sequence_check_tb();
//...
endmodule

//*******************sequence_check.v*************
module sequence_check();
//...
endmodule

然后执行编译,在sequence_check目录下写入

vcs -full64 -debug_acc+all -sverilog -l comp.log -f files.f

运行之后显示信息

在这里插入图片描述
并且在sequence_check目录下,多出来好几个文件,这里面的文件comp.log就是编译的日志,文件simv就是用于仿真的文件

请添加图片描述

1.2. Simulate with DVE

之后就可以使用DVE进行仿真

命令格式

simv [选项]

选项如下

-l [文件]:			仿真日志
-gui:				开启GUI界面,否则就在linux终端显示transcript的内容
-ucli:				在linux终端使用TCL控制仿真进程
-i [文件名].tcl:	启动DVE后,在UCLI要启动的TCL命令

-gui

开启图形界面模式,要看波形必须得开这个,这个界面就很类似于questasim了

在这里插入图片描述
那么怎么看波形呢,首先需要add dump一下,才能看数组、结构体这种

在这里插入图片描述
将选中信号,然后add wave→new wave就开启DVE看波形了,对波形的简单操作如下

在这里插入图片描述

-ucli

这样就可以在linux终端下使用tcl命令控制仿真,在图形界面中的下面也可以使用ucli模式对仿真进行控制

请添加图片描述

在ucli中一些tcl命令如下

scope: 显示当前的顶层模块

scope u1: 就表示进入到当前顶层模块中的u1模块,同时将u1模块设置为顶层模块

scope -up: 回到目前顶层模块的上一层。

show: 显示当前顶层模块的信号以及子模块

show -value 信号 -radix hex/bin/dec:显示信号的值 以特定的进制显示。

run:运行仿真run 一直运行,直到遇到$stop或者设置的断点

run time: 运行多少时间停止(不推荐)

run -posedge: 信号 运行到信号的上升沿停止

run -negedge: 信号 运行到信号的下降沿停止

run -change: 信号 信号有变化时停止

stop: 设置断点stop 显示断点

stop -posedge: 信号 在信号的上升沿设置断点

stop -negedge: 信号 在信号的下降沿设置断点

stop -condition {信号表达式}: 信号表达式为真的地方设置断点

stop -delete 断点值: 删除断点值的断点

restart: 重新开启ucli调试模式

call {系统任务}:调用verilog系统任务,

finish:结束仿真

force:信号强制赋值

release:解除信号强制赋值

get:获取信号数值

step:单步执行

do *.do:可将很多这些UCLI命令整合到一个*.do文件内,然后以打包运行

命令 –h:显示命令的帮助

以上这些命令完全可以配合一般的tcl命令一起使用,例如

set i 0;
while {$i < 20} {
	force top.clk 1;
	run 10ns;
	force top.clk 0;
	run 10ns;
	incr i 1;
}
release top.clk;

Tool Command Language(TCL)

2. Verdi

一开始我还不理解,人家VCS既能编译,又能仿真出波形,还要Verdi干嘛?

后来才了解到,Verdi是在编译、仿真出波形之后,用来分析工程的。

除了原理图,波形,状态机图和波形比较等基本功能,Verdi还可以自动跟踪信号活动、基于断言的调试、功耗感知调试以及事务和消息数据的调试和分析等等。

下面介绍一下常见功能

2.1. 启动

首先是启动,依据*.v和testbench建立工程

可直接在Linux终端执行,格式如下:

verdi [选项] [文件]

其中选项是可选的,下面给出一些常用选项

-f [文件名]:		在某文件中索引工程包含的文件路径
-top [名称]:		工程名称,建议用testbench的名字
-nologo:			无欢迎界面
-ssf [文件名].fsdb:	指定已有的波形文件

2.2. 打开波形 nWave

先是打开波形。Verdi识别*.fsdb波形文件,所以在使用VCS执行仿真的时候,要输出*.fsdb波形文件

如何输出呢?在UCLI使用call的TCL语句调用系统函数,比如

call {$fsdbDumpon}:							打开波形保存功能
call {$fsdbDumpoff}:						关闭波形保存功能
call {$fsdbDumpfile("dump.fsdb")}:			指定波形文件名为dump.fsdb
call {$fsdbDumpvars(0,addr4_tb,"+all")}:	addr4_tb为指定的testbench,0表示输出所有层次的波形,1表示只输出第一层的波形,以此类推,"+all"表示输出结构体等数据结构

然后再启动verdi时指定那个fsdb文件就可以打开波形了

2.3. 信号追踪 nTrace

2.4. 架构查看 nScheme

3. Makefile

作用也是整合linux命令,将所有命令写到一个名为Makefile的文件下,然后在终端输入make xxx即可运行对应的命令

例如有个Makefile文件内容如下,注意使用\表示同一组代码

在这里插入图片描述
在该Makefile的目录下执行以下命令及含义为:

make all:等价于make clean之后再make comp
make comp:执行后面的linux命令,表示使用vcs编译,并生成仿真文件
make run: 运行仿真
make rung:以gui形式运行仿真
make clean:看到rm -rf就是删除文件,其实就是清除上一次编译仿真留下来的文件

当然Makefile也支持变量替换,如同TCL那样

#############################
# User variables
#############################
TB       = apb_tb
SEED     = 1
TESTNAME ?= apb_single_transaction_test
VFILES  += apb3_pkg_ref/{apb_pkg.sv,apb_tb.sv}


#############################
# Environment variables
#############################
VCOMP    = vlogan -full64 -ntb_opts uvm-1.2 -sverilog -timescale=1ps/1ps -nc -l comp.log +incdir+apb3_pkg_ref
ELAB     = vcs -full64 -ntb_opts uvm-1.2 -debug_all -l elab.log -sim_res=1ps 
RUN      = $(TB).simv -l run.log -sml +ntb_random_seed=$(SEED) +UVM_TESTNAME=$(TESTNAME)

comp:
	$(VCOMP) 
	$(VCOMP) $(VFILES)
elab: comp
	$(ELAB) -top $(TB) -o $(TB).simv
run:
	$(RUN) 
rung:
	$(RUN) -gui
clean:
	rm -rf AN.DB DVEfiles csrc *.simv *.simv.daidir *.simv.vdb ucli.key
	rm -rf *.log* *.vpd *.h urgReport

所以可以用cd ./vcs && ./run_vcs.sh来切换目录并启动新目录下的命令

通过下一节工程目录结构,查看写法。

4. 工程目录结构

这里给出一个典型的工程目录结构,以使层次更加分明

rtl目录

用于存放各种*.v文件,除了testbench文件

tb目录

用于存放各种*.sv格式的testbench文件

tb文件就不用再include涉及到的*.v文件了

vcs目录

用于只存放编译文件,必要文件有

file.list

列出编译所需的全部rtl和tb文件,注意…表示以rtl目录的上级目录

例如

//rtl files
../rtl/uart_tx.v
../rtl/uart_rx.v
../rtl/uart.v

//tb files
../tb/uart_tb.sv

macro.list

主要包括宏定义、库文件的Verilog模型路径,文件搜索路径信息等。

//macro
+define+UART_HIGH_BPS
+define+UART_FIFO_DEPTH = 4096

//指定库文件,建议包含路径
//-v <filename>

//指定库文件,IP等Verilog模型路径
//-y <directory>

//指定要包含的文件目录
//+incdir+<directory>

run_vcs.sh

用于启动VCS编译,注意将刚才的file.list和macro.list添加进去

注意使用\换行

-top 命令后接的是tb文件的Module名字

vcs -full64 -notice -debug_all+acc -j8 \
+plusarg_save +libext+.v+.V+.sv+.svh -sverilog +memcbk \
-P ${Verdi_HOME}/share/PLI/VCS/LINUX64/novas.tab \
${Verdi_HOME}/share/PLI/VCS/LINUX64/pli.a \
-cpp /usr/bin/g++-4.4 -cc /usr/bin/gcc-4.4 \
-f ./file.list -f ./macro.list -top uart_tb \
-l ./compile.log

sim目录

此处添加仿真、波形生成命令,并开启Verdi进行调试

wave_gen.tcl

这个是打开DVE之后,要输入的UCLI命令,整理在这里然后自动调用

call {$fsdbDumpfile("dump.fsdb")}
call {$fsdbDumpvars(0, uart_tb, "+all")}		//uart_tb是tb文件的module名字,不是乱起的!!!!
call {$fsdbDumpon}
run

run_sim.sh

启动仿真。由于编译后生成的simv和sim.daidir在vcs目录下,所以这里需要搞个快捷方式

ln -sf ../vcs/sim* .
simv -ucli -i ./wave_gen.tcl -l ./sim.log +fsdb+function

run_verdi.sh

启动verdi

verdi -f ../vcs/file.list -f ../vcs/macro.list -top uart_tb -ssf ./dump.fsdb -nologo &

Makefile文件

方便终端直接运行各目录下的文件,而不用在目录之间跑来跑去,所写的Makefile如下

all: clean comp run verdi

comp:	
		cd ./vcs && ./run_vcs.sh
run:	
		cd ./sim && ./run_sim.sh
verdi:
		cd ./sim && ./run_verdi.sh
clean:
		rm -rf ./vcs/simv.* ./vcs/simv* ./vcs/csrc ./vcs/*.log
		rm -rf ./sim/*.log ./sim/*.vpd ./sim/ucli.key ./sim/*.fsdb

要注意一切文件中的一切路径,都以指令所在目录为原点

例如tb目录下的uart_tb.sv中要访问外部数据,执行$readmemh('init_mem.hex',uart_tb.u_uart.mem);,那么这个init_mem.hex文件应该放在哪里?
应该放在sim目录下,因为仿真是在该目录下启动,所以就以sim为目录原点搜索init_mem.hex

clean是为了删除全部的自动生成文件

写完之后,在makefile目录下执行对应的命令即可

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐