Jamie.zhen头像

IC前端 - VCS


title: IC前端设计——VCS
date: 2026-06-11
tags: IC前端设计, VCS, 仿真验证, Verilog, SystemVerilog
categories: IC设计

IC前端设计——VCS

VCS(Verilog Compiler Simulator)是 Synopsys 的高性能编译型仿真器,其仿真流程根据语言构成分为两步法和三步法两种。本文将系统讲解这两种流程的用法与原理,并提供实战速查。


一、两步法与三步法

1.1 两步法

两步法适用于纯 Verilog / SystemVerilog 项目,只需两步:

步骤命令做了什么
编译vcs语法检查 + 中间代码生成 + 链接映射,一步产出 simv
仿真./simv运行可执行文件,输出日志与波形

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=images%2F02_two_step_flow.png&pos_id=i在这里插入图片描述
mg-as8YnCZk-1781142960194)

# Step 1: 编译
vcs -full64 -sverilog -debug_all -timescale=1ns/1ps \
    -P $VERDI_HOME/share/PLI/VCS/LINUX64/novas.tab \
    $VERDI_HOME/share/PLI/VCS/LINUX64/pli.a \
    -f filelist.f -l compile.log

# Step 2: 仿真
./simv -l sim.log +fsdb+autoflush

1.2 三步法

三步法适用于 Verilog + VHDL 混合语言项目,将编译拆为分析与映射两步:

步骤命令做了什么
分析vlogan / vhdlan各语言独立语法分析,产出中间库
映射csim链接所有中间库,产出 simv
仿真./simv运行可执行文件,输出日志与波形

在这里插入图片描述

# Step 1a: 分析 Verilog
vlogan -full64 -sverilog +v2k -timescale=1ns/1ps \
    -work work -l analyze_vlog.log -f verilog_filelist.f

# Step 1b: 分析 VHDL(必须自底向上!)
vhdlan -full64 -work work -l analyze_vhdl.log -f vhdl_filelist.f

# Step 2: 映射
csim -full64 -top work.tb_top -l elaboration.log -o simv

# Step 3: 仿真
./simv -l simulation.log +fsdb+autoflush

1.3 对比与选择

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=image在这里插入图片描述

两步法三步法
适用语言纯 Verilog / SVVerilog + VHDL 混合
步骤编译 → 仿真分析 → 映射 → 仿真
编译命令vcs(内部自动完成分析+映射)vlogan/vhdlan + csim
使用频率最常用混合语言时使用

二、流程原理

2.1 VCS 为什么是编译型仿真器

VCS 不像解释型工具那样逐行读取执行,而是先把源代码翻译为优化的 C 代码,再编译成独立的可执行文件 simv:

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=images在这里插入图片描述
%2F01_vcs_principle.png&pos_id=img-LkvjW31F-1781142960195)

这种"先编译、后执行"的模式,使大规模设计的仿真速度比解释型工具快数十倍甚至上百倍。代价是编译需要时间,但仿真阶段极为高效——这在需要反复运行的回归测试中优势尤为明显。

2.2 两步法为什么能一步完成编译+映射

vcs 命令内部实际上包含了分析(vlogan)和映射(csim)两个阶段,只是对用户透明——当项目仅含 Verilog/SV 时,所有源文件使用同一个分析器,编译器可以一次性完成语法分析并直接链接映射,无需拆分。

2.3 三步法为什么要拆分为分析+映射

根本原因:不同语言需要不同的分析器。

  • Verilog 用 vlogan 分析
  • VHDL 用 vhdlan 分析

两者产出各自格式的中间库文件,不能由单一命令同时处理。因此必须先分别分析,再用 csim 统一链接。

此外,VHDL 的语言特性要求分析必须按依赖顺序自底向上——底层包和元件声明必须先于上层实体分析,否则会报 “entity not found” 错误。拆分为独立的分析步骤,使工程师可以精确控制分析顺序。

2.4 为什么两步法不能处理混合语言

vcs 命令内部只能调用 vlogan,不具备调用 vhdlan 的能力。当项目中存在 .vhd 文件时,vcs 无法识别和分析它们,会直接报错。此时必须切换为三步法,由用户手动分别调用两种分析器。


三、Makefile 自动化构建

将仿真流程固化为 Makefile,一条命令完成编译/仿真/调试,提升效率。

3.1 环境变量配置

Makefile 中的编译选项依赖正确的环境变量,需在 ~/.bashrc 中预先配置:

# =====================================================================
#  VCS + Verdi 环境变量配置
#  添加到 ~/.bashrc,执行 source ~/.bashrc 生效
# =====================================================================

# ===================== VCS =====================
# VCS 安装根目录
export VCS_HOME=/opt/synopsys/vcs
# 将 VCS 可执行文件加入 PATH
export PATH=$VCS_HOME/bin:$PATH

# ===================== Verdi =====================
# Verdi 安装根目录(波形调试工具)
export VERDI_HOME=/opt/synopsys/verdi
# 将 Verdi 可执行文件加入 PATH
export PATH=$VERDI_HOME/bin:$PATH

# ===================== License =====================
# Synopsys License 服务器地址(端口号@主机名或IP)
export LM_LICENSE_FILE=27000@license_server
# Synopsys 专用 License 变量(优先级高于 LM_LICENSE_FILE)
export SNPSLMD_LICENSE_FILE=27000@license_server

# ===================== 库路径 =====================
# VCS PLI 库路径(用于 FSDB 波形生成,Makefile 中引用)
export VCS_PLI_TAB=$VERDI_HOME/share/PLI/VCS/LINUX64/novas.tab
export VCS_PLI_LIB=$VERDI_HOME/share/PLI/VCS/LINUX64/pli.a

# ===================== 可选:多版本管理 =====================
# 如果安装了多个版本,可通过别名切换
# alias vcs2023='export VCS_HOME=/opt/synopsys/vcs2023; export PATH=$VCS_HOME/bin:$PATH'
# alias vcs2024='export VCS_HOME=/opt/synopsys/vcs2024; export PATH=$VCS_HOME/bin:$PATH'

环境变量速查表:

变量作用是否必选
VCS_HOMEVCS 安装根目录,Makefile 中引用 $VCS_HOME必选
VERDI_HOMEVerdi 安装根目录,Makefile 中引用 PLI 库路径必选
LM_LICENSE_FILELicense 服务器地址必选
SNPSLMD_LICENSE_FILESynopsys 专用 License 变量推荐
VCS_PLI_TABVerdi PLI 表文件路径,简化 Makefile 编写可选
VCS_PLI_LIBVerdi PLI 库文件路径,简化 Makefile 编写可选

验证环境是否就绪:

# 检查 VCS 是否可用
vcs -V

# 检查 Verdi 是否可用
verdi -V

# 检查 License 是否正常
lmstat -a -c $LM_LICENSE_FILE

# 检查 PLI 库文件是否存在
ls -l $VCS_PLI_TAB $VCS_PLI_LIB

配置完成后,Makefile 中的 $(VERDI_HOME) 等变量即可正确展开。若 Makefile 运行报 VERDI_HOME: undefined,说明环境变量未在当前 shell 中生效。

3.2 两步法 Makefile

# =====================================================================
#  VCS 两步法 Makefile
#  适用场景:纯 Verilog / SystemVerilog 项目
# =====================================================================

# ===================== 用户可配置参数 =====================
# 顶层模块名(可通过命令行覆盖:make TOP_MODULE=tb_fifo)
TOP_MODULE ?= tb_top
# 源文件列表
FILE_LIST  := filelist.f
# 仿真可执行文件名
SIMV       := simv.$(TOP_MODULE)

# ===================== 目录定义 =====================
WORK_DIR   := ./work          # 工作目录(存放中间文件)
LOG_DIR    := ./log           # 日志目录
WAVE_DIR   := ./wave          # 波形目录
COV_DIR    := ./cov           # 覆盖率目录

# ===================== VCS 编译选项 =====================
VCS_OPTS   := -full64             \  # 64 位模式编译
              -sverilog            \  # 启用 SystemVerilog 支持
              +v2k                 \  # 启用 Verilog-2001 标准
              -debug_all           \  # 保存全部调试信息(支持 Verdi/DVE 调试)
              -timescale=1ns/1ps   \  # 时间单位 1ns,精度 1ps
              -lca                 \  # 低编译时间优化
              -o $(SIMV)           \  # 指定输出可执行文件名
              -l $(LOG_DIR)/compile.log  # 编译日志

# Verdi PLI 库(用于生成 FSDB 波形,配合 Verdi 调试)
VCS_OPTS   += -P $(VERDI_HOME)/share/PLI/VCS/LINUX64/novas.tab
VCS_OPTS   += $(VERDI_HOME)/share/PLI/VCS/LINUX64/pli.a

# 覆盖率选项(验证阶段启用,调试阶段可注释掉以加速编译)
VCS_OPTS   += -cm line+cond+fsm+tgl+branch    # 收集的覆盖率类型
VCS_OPTS   += -cm_dir $(COV_DIR)/$(TOP_MODULE).vdb  # 覆盖率数据库路径
VCS_OPTS   += -cm_hier cm_hier.file            # 指定覆盖率收集层次

# ===================== 仿真选项 =====================
SIM_OPTS   := -l $(LOG_DIR)/sim.log            # 仿真日志
SIM_OPTS   += +fsdb+autoflush                  # 自动刷新 FSDB 波形文件
SIM_OPTS   += +ntb_random_seed=$(shell date +%N)  # 随机种子(每次仿真不同)

# ===================== 目标定义 =====================
.PHONY: all compile sim verdi cov urg clean

# 默认目标:编译 + 仿真
all: compile sim

# ----- Step 1: 编译 -----
compile: | $(LOG_DIR)
	vcs $(VCS_OPTS) -f $(FILE_LIST) -top $(TOP_MODULE)

# ----- Step 2: 仿真 -----
sim:
	./$(SIMV) $(SIM_OPTS)

# ----- Verdi 查看波形 -----
verdi:
	verdi -sv -f $(FILE_LIST) -ssf $(WAVE_DIR)/*.fsdb \
	      -nologo -top $(TOP_MODULE) &

# ----- 覆盖率报告 -----
cov:
	urg -full64 -dir $(COV_DIR)/$(TOP_MODULE).vdb \
	    -report $(COV_DIR)/report -format both

# ----- 清理 -----
clean:
	rm -rf $(SIMV) $(SIMV).daidir csrc *.log *.vpd *.vcd *.key
	rm -rf $(WORK_DIR) $(COV_DIR) *.vdb
	rm -rf novas.* ucli.key

# ----- 创建目录 -----
$(LOG_DIR):
	mkdir -p $(LOG_DIR)

3.3 三步法 Makefile

# =====================================================================
#  VCS 三步法 Makefile
#  适用场景:Verilog + VHDL 混合语言项目
# =====================================================================

# ===================== 用户可配置参数 =====================
TOP_MODULE := work.tb_top       # 顶层模块名(三步法需带库名前缀)
FILE_LIST  := filelist.f        # Verilog/SV 源文件列表
VHDL_LIST  := vhdl_filelist.f   # VHDL 源文件列表
SIMV       := simv              # 仿真可执行文件名

# ===================== 目录定义 =====================
WORK_DIR   := ./work            # 编译工作库目录
LOG_DIR    := ./log             # 日志目录
WAVE_DIR   := ./wave            # 波形目录
COV_DIR    := ./cov             # 覆盖率目录

# ===================== vlogan 选项(Verilog/SV 分析) =====================
VLOGAN_OPTS := -full64              \  # 64 位模式
               -sverilog            \  # 启用 SystemVerilog
               +v2k                 \  # 启用 Verilog-2001
               -timescale=1ns/1ps   \  # 时间单位与精度
               -work work           \  # 指定工作库名
               -l $(LOG_DIR)/analyze_vlog.log  # 分析日志

# 覆盖率选项(验证阶段启用)
VLOGAN_OPTS += -cm line+cond+fsm+tgl+branch
VLOGAN_OPTS += -cm_dir $(COV_DIR)/$(TOP_MODULE).vdb

# ===================== vhdlan 选项(VHDL 分析) =====================
VHDLAN_OPTS := -full64              \  # 64 位模式
               -work work           \  # 指定工作库名(与 vlogan 一致)
               -l $(LOG_DIR)/analyze_vhdl.log  # 分析日志

# ===================== csim 选项(映射/链接) =====================
CSIM_OPTS  := -full64              \  # 64 位模式
              -top $(TOP_MODULE)    \  # 指定顶层模块
              -debug_all            \  # 保存调试信息
              -o $(WORK_DIR)/$(SIMV) \  # 输出可执行文件路径
              -l $(LOG_DIR)/elaboration.log  # 映射日志

# Verdi PLI 库(映射阶段添加,使 simv 支持 FSDB 波形输出)
CSIM_OPTS  += -P $(VERDI_HOME)/share/PLI/VCS/LINUX64/novas.tab
CSIM_OPTS  += $(VERDI_HOME)/share/PLI/VCS/LINUX64/pli.a

# ===================== 仿真选项 =====================
SIM_OPTS   := -l $(LOG_DIR)/simulation.log    # 仿真日志
SIM_OPTS   += +fsdb+autoflush                  # 自动刷新 FSDB
SIM_OPTS   += +ntb_random_seed=$(shell date +%N)  # 随机种子

# ===================== 目标定义 =====================
.PHONY: all analyze elaborate simulate verdi cov urg clean

# 默认目标:分析 + 映射 + 仿真
all: analyze elaborate simulate

# ----- Step 1: 分析 -----
#    Verilog 和 VHDL 分别用各自的分析器处理
#    VHDL 必须按依赖顺序自底向上分析!
analyze: | $(LOG_DIR) $(WORK_DIR)
	vlogan $(VLOGAN_OPTS) -f $(FILE_LIST)
	vhdlan $(VHDLAN_OPTS) -f $(VHDL_LIST)

# ----- Step 2: 映射 -----
#    链接所有中间库,生成可执行仿真文件
elaborate:
	csim $(CSIM_OPTS)

# ----- Step 3: 仿真 -----
simulate:
	cd $(WORK_DIR) && ./$(SIMV) $(SIM_OPTS)

# ----- Verdi 查看波形 -----
verdi:
	verdi -sv -f $(FILE_LIST) -ssf $(WAVE_DIR)/*.fsdb \
	      -nologo -top $(TOP_MODULE) &

# ----- 覆盖率报告 -----
cov:
	urg -full64 -dir $(COV_DIR)/$(TOP_MODULE).vdb \
	    -report $(COV_DIR)/report -format both

# ----- 清理 -----
clean:
	rm -rf $(WORK_DIR) $(LOG_DIR) $(COV_DIR)
	rm -rf csrc *.log *.key *.vpd novas.* ucli.key

# ----- 创建目录 -----
$(LOG_DIR) $(WORK_DIR):
	mkdir -p $@

3.4 使用方式

# ===== 两步法 =====
make              # 一键编译 + 仿真
make compile      # 仅编译
make sim          # 仅仿真
make verdi        # 打开 Verdi 查看波形
make cov          # 生成覆盖率报告
make clean        # 清理所有中间文件

# 指定顶层模块(覆盖默认值)
make TOP_MODULE=tb_fifo

# ===== 三步法 =====
make              # 一键分析 + 映射 + 仿真
make analyze      # 仅分析(vlogan + vhdlan)
make elaborate    # 仅映射(csim)
make simulate     # 仅仿真
make cov          # 生成覆盖率报告
make clean        # 清理

四、常用指令与选项

4.1 编译选项

选项功能必选程度
-full6464 位模式必选
-sverilog支持 SystemVerilogSV 项目必选
+v2k支持 Verilog-2001推荐
-debug_all保存全部调试信息调试时必选
-timescale=1ns/1ps指定时间单位/精度必选
-f filelist.f从文件读取源文件列表推荐
-R编译后立即运行仿真快速验证
-cm line+cond+branch启用覆盖率收集验证阶段

4.2 波形调试

VCS 支持 VPD(DVE 查看)和 FSDB(Verdi 查看)两种格式,推荐 FSDB——文件更小、加载更快。

// testbench 中添加
initial begin
    $fsdbDumpfile("wave.fsdb");
    $fsdbDumpvars(0, tb_top);   // 0 = dump 所有层次
end
# 编译时添加 Verdi PLI 库
vcs ... -P $VERDI_HOME/share/PLI/VCS/LINUX64/novas.tab \
        $VERDI_HOME/share/PLI/VCS/LINUX64/pli.a

# 查看波形
verdi -sv -f filelist.f -ssf wave.fsdb -nologo &

精细控制波形记录范围,避免文件过大:

initial begin
    #100; $fsdbDumpon;     // 开始记录
    #500; $fsdbDumpoff;    // 停止记录
    #400; $finish;
end

4.3 覆盖率指令

编译时启用:-cm line+cond+fsm+tgl+branch+assert

类型含义
line行覆盖率——代码是否被执行
cond条件覆盖率——条件分支是否被触发
fsm状态机覆盖率——状态跳转是否完整
tgl翻转覆盖率——信号 0↔1 是否都发生
branch分支覆盖率——if/else 是否都走到
assert断言覆盖率——SVA 断言是否被触发

指定收集范围(排除 TB 噪声):-cm_hier cm_hier.file

// cm_hier.file
+tree tb.u_chip_top.u_digital_top

多用例合并:

urg -full64 -dir ./case1/simv.vdb ./case2/simv.vdb -dbname merged.vdb

覆盖率提升闭环:
在这里插入图片描述

100% 代码覆盖率 ≠ 没有 Bug,需结合功能覆盖率(covergroup)和断言覆盖率构建完整验证体系。

4.4 +define+ 宏定义

# 无值宏(条件判断)
vcs +define+DEBUG ...

# 有值宏(传递参数)
vcs +define+A=300 ...

# 多宏
vcs +define+DEBUG,MAX_COUNT=100 ...

命令行 +define+ 优先级最高,会覆盖代码内部同名宏。


五、常见问题

问题原因解决
Cannot checkout VCS licenseLicense 未配置或服务器异常检查 LM_LICENSE_FILE,lmstat 验证服务状态
Timescale 冲突多模块 timescale 不一致使用 -override_timescale=1ns/1ps 强制统一
VHDL 分析报 entity not found分析顺序错误按自底向上顺序分析 VHDL 文件
两步法报 Unknown module type项目含 VHDL 文件切换为三步法
波形文件未生成未添加 dump 函数或 PLI 库检查 $fsdbDumpvars 和编译选项
仿真速度慢波形记录范围过大用 $fsdbDumpon/$fsdbDumpoff 控制范围

参考资源:Synopsys VCS User Guide · Verdi User Guide · URG Coverage Report Guide

如果觉得本文有帮助,欢迎 👍点赞 ⭐收藏 🔄转发!

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/qq_33133587/article/details/161882404

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--