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 | 运行可执行文件,输出日志与波形 |

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 对比与选择

| 适用语言 | 纯 Verilog / SV | Verilog + VHDL 混合 |
| 步骤 | 编译 → 仿真 | 分析 → 映射 → 仿真 |
| 编译命令 | vcs(内部自动完成分析+映射) | vlogan/vhdlan + csim |
| 使用频率 | 最常用 | 混合语言时使用 |
二、流程原理
2.1 VCS 为什么是编译型仿真器
VCS 不像解释型工具那样逐行读取执行,而是先把源代码翻译为优化的 C 代码,再编译成独立的可执行文件 simv:

%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_HOME | VCS 安装根目录,Makefile 中引用 $VCS_HOME | 必选 |
| VERDI_HOME | Verdi 安装根目录,Makefile 中引用 PLI 库路径 | 必选 |
| LM_LICENSE_FILE | License 服务器地址 | 必选 |
| SNPSLMD_LICENSE_FILE | Synopsys 专用 License 变量 | 推荐 |
| VCS_PLI_TAB | Verdi PLI 表文件路径,简化 Makefile 编写 | 可选 |
| VCS_PLI_LIB | Verdi 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 编译选项
| -full64 | 64 位模式 | 必选 |
| -sverilog | 支持 SystemVerilog | SV 项目必选 |
| +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 license | License 未配置或服务器异常 | 检查 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
如果觉得本文有帮助,欢迎 👍点赞 ⭐收藏 🔄转发!

