基于脚本的ModelSim自动化仿真(Xilinx FPGA篇)

基于脚本的ModelSim自动化仿真(Xilinx FPGA篇)

    • 一、为什么要用脚本仿真?
      • [1.1 传统GUI仿真的痛点](#1.1 传统GUI仿真的痛点)
      • [1.2 脚本仿真的核心价值](#1.2 脚本仿真的核心价值)
      • [1.3 Xilinx FPGA的特别需求](#1.3 Xilinx FPGA的特别需求)
    • 二、准备工作------仿真环境搭建
      • [2.1 软件环境要求](#2.1 软件环境要求)
      • [2.2 编译Xilinx仿真库](#2.2 编译Xilinx仿真库)
      • [2.4 验证库配置成功](#2.4 验证库配置成功)
    • 三、脚本编写实战
      • [3.1 项目目录结构](#3.1 项目目录结构)
      • [3.2 编写待测模块](#3.2 编写待测模块)
      • [3.3 编写Testbench](#3.3 编写Testbench)
      • [3.4 编写仿真脚本](#3.4 编写仿真脚本)
      • [3.5 编写批处理命令](#3.5 编写批处理命令)
      • [3.6 编写波形文件](#3.6 编写波形文件)
      • [3.7 执行仿真](#3.7 执行仿真)
      • [3.8 修改代码后重新仿真](#3.8 修改代码后重新仿真)
    • 四、高级脚本技巧
      • [4.1 do文件实现 ``define`](#4.1 do文件实现 ``define`)
      • [4.2 设置仿真时间精度](#4.2 设置仿真时间精度)
      • [4.3 状态机添加到波形](#4.3 状态机添加到波形)
      • [4.4 设置显示格式(Radix)](#4.4 设置显示格式(Radix))
      • [4.5 波形颜色设置](#4.5 波形颜色设置)
      • [4.6 波形分组设置](#4.6 波形分组设置)

一、为什么要用脚本仿真?

1.1 传统GUI仿真的痛点

在FPGA开发中,仿真验证是不可或缺的环节。传统的ModelSim图形界面操作流程通常是:启动软件 → 创建工程 → 添加文件 → 编译 → 加载仿真 → 添加波形 → 运行。每次修改代码后,这套流程都要重复一遍,存在三个明显问题:

  • 重复操作耗时:每次修改代码都要重新点击一遍流程
  • 容易遗漏步骤:尤其是Xilinx仿真库的设置,经常被忽略导致报错
  • 无法版本控制和团队复用:GUI操作无法被Git追踪,换个电脑就要重新配置

1.2 脚本仿真的核心价值

使用Tcl脚本进行自动化仿真,可以解决上述所有问题:

  • 一键式自动化 :一个do命令完成全部流程
  • 可复现性强:脚本保存为文件,团队成员可直接使用
  • 便于回归测试:修改代码后快速重新仿真,适合频繁迭代

掌握脚本仿真方法后,每次仿真只需双击一个.bat文件,可以把更多精力放在代码设计和功能验证上。

1.3 Xilinx FPGA的特别需求

Xilinx FPGA开发中经常使用IP核(PLL、RAM、FIFO等),这些IP核的仿真需要专用的仿真库(unisim、simprim、xilinxcorelib等)。手动配置这些库比较繁琐,而脚本方式可以统一管理库的映射,一次配置永久使用。本文聚焦Xilinx + ModelSim这一组合。

二、准备工作------仿真环境搭建

2.1 软件环境要求

  • ModelSim SE 2020.4,Modelsim 安装破解步骤如下:
    1. 复制MentorKG.exe,mgls64.dll以及patch64_dll.bat这三个文件到Modelsim安装目录的win64文件夹下,如E:\modeltech64_2020.4\win64
    2. 双击win64文件夹内粘贴过去的patch64_dll.bat文件,会生成LICENSE.TXT,另存到安装目录
    3. 设置系统环境变量,变量值为LICENSE.TXT的路径 变量名:LM_LICENSE_FILE 变量值:E:\modeltech64_2020.4\LICENSE.TXT
    4. 完成。
  • Xilinx Vivado 2021.1官网下载链接

2.2 编译Xilinx仿真库

这是使用Xilinx IP核仿真的前置条件,编译一次即可重复使用

  1. 生成库文件

    打开Vivado,点击 Tools → Compile Simulation Libraries:

    • Simulation simulator:选择 ModelSim
    • Library language:选择 Verilog 或 VHDL(根据项目)
    • Compilation:选择器件系列(选择自己需要,选择太多后续加载库慢)
    • Output directory:指定库输出目录(路径建议不含空格和中文)

    点击Compile,等待编译完成即可。

    在Vivado2020.2之后的版本中,需要指定GCC路径,可以指定Vivado自带的GCC路径:D:\Xilinx\Vivado\2020.2\tps\win64\msys64\mingw64\bin

  2. 从库文件夹里的 modelsim.ini 文件中复制如下内容

  3. 将 modelsim 根目录下 modelsim.ini 文件属性只读关闭

  4. 粘贴刚刚复制的内容到该文件的如下位置,然后保存,勾选只读

2.4 验证库配置成功

打开ModelSim,在Library窗口中应能看到unisim、simprim、xilinxcorelib等库,说明配置成功。

三、脚本编写实战

3.1 项目目录结构

在开始实践前,先建立规范的目录结构:

复制代码
project/
├── sim/              # 仿真脚本
├── src/
│   ├── ip/           # IP核文件
│   ├── rtl/          # RTL源文件
│   ├── tb/           # Testbench文件

3.2 编写待测模块

以计数器模块为例,在src/rtl/目录下创建counter.v

verilog 复制代码
// 计数器模块
module counter (
  input        clk,
  input        reset,
  output [7:0] cnt_out
);
//------------------------------------
//             Local Signal
//------------------------------------
  reg [7:0] cnt = 0;
//------------------------------------
//             User Logic
//------------------------------------
  always @ (posedge clk)
    if (reset)
      cnt <= 8'd0;
    else
      cnt <= cnt + 8'b1;
//------------------------------------
//             Output Port
//------------------------------------
  assign cnt_out = cnt;

endmodule

3.3 编写Testbench

src/tb/目录下创建tb_counter.v

verilog 复制代码
`timescale 1ns/1ns

module tb_counter;

//*************************** Parameters ***************************
  parameter PERIOD_CLK = 10;
//***************************   Signals  ***************************
  reg        clk = 0;
  reg        reset = 1;
  wire [7:0] cnt;

//*************************** Test Logic ***************************
  always # (PERIOD_CLK/2) clk = ~clk;

  initial
    begin
      #100
      reset = 0;
      #1000;
      $stop;
    end
//***************************    Task    ***************************

//***************************  Instance  ***************************
// 计数器模块
  counter u_counter(
    .clk     (clk),
    .reset   (reset),
    .cnt_out (cnt)
  );

endmodule

3.4 编写仿真脚本

sim/目录下创建sim.do

tcl 复制代码
# 1. 清除之前的工作
quit -sim
.main clear
 
# 2. 设置库路径
set VIVADO_DIR "D:/software/Xilinx/Vivado/2021.1/data"
set VIVADO_LIB_DIR "D:/software/modeltech64_2020.4/vivado_lib_2021_1"
set IP_DIR "../src/ip"
set RTL_DIR "../src/rtl"
set TB_DIR "../src/tb"

# 3. 创建库
# unisim 库 提供Xilinx FPGA所有基本硬件原语(LUT/FDCE/RAMB36E1/BUFG/MMCM/IO原语等)的行为级和结构级仿真模型
vlib unisim
# unimacro库 提供复杂功能模块(如FIFO/移位寄存器/DSP宏)的仿真模型
vlib unimacro
# secureip 库 提供Xilinx加密IP核(如PCIe/GTX收发器)的仿真模型
vlib secureip
# xpm 库 提供Xilinx CDC/XPM_MEMORY/XPM_FIFO参数宏的仿真模型
vlib xpm_lib
# xil_defaultlib 库 存放Vivado自动生成的IP核仿真模型(如FIFO/DDR控制器等)
vlib xil_defaultlib
# work 库 为用户自定义库
vlib work

# 4. 映射库
vmap unisim "$VIVADO_LIB_DIR/unisim"
vmap unimacro "$VIVADO_LIB_DIR/unimacro"
vmap secureip "$VIVADO_LIB_DIR/secureip"
vmap xpm_lib "$VIVADO_LIB_DIR/xpm"
vmap xil_defaultlib ./xil_defaultlib
vmap work ./work

# 5. 编译库文件
# vcom -2008: 编译VHDL(支持2008标准)
# vlog : 编译 Verilog/SystemVerilog
  # 编译 glbl 模块
  vlog -work xil_defaultlib "$VIVADO_DIR/verilog/src/glbl.v"
  # 编译 xpm 模块
  # vlog -work xpm_lib "$VIVADO_DIR/ip/xpm/xpm_fifo/hdl/xpm_fifo.sv"
  # 编译 Xilinx IP
  # vlog -work xil_defaultlib "$IP_DIR/blk_mem_gen_0/blk_mem_gen_0_sim_netlist.v"
  # 编译设计文件
  vlog -work work +define+SIM "$RTL_DIR/counter.v"
  vlog -work work "$TB_DIR/*.v"

# 6. 启动仿真
vsim -t 1ns -voptargs="+acc" -L unisim -L unimacro -L secureip -L xpm_lib -L xil_defaultlib -L work xil_defaultlib.glbl work.tb_counter

# 7. 添加波形
do wave_counter.do

# 8. 运行仿真
run -all
wave zoom full

3.5 编写批处理命令

这是本节的重点------无需手动打开ModelSim,通过Windows批处理命令一键启动仿真。

sim/目录下创建run_sim.bat

bash 复制代码
vsim -do sim.do

3.6 编写波形文件

sim/目录下创建wave_counter.do

TCL 复制代码
add wave -noupdate /tb_counter/u_counter/clk
add wave -noupdate /tb_counter/u_counter/reset
add wave -noupdate /tb_counter/u_counter/cnt_out

3.7 执行仿真

双击run_sim.bat执行。

3.8 修改代码后重新仿真

修改代码后不需要关闭软件,只需要在modelsimTranscript窗口输入do sim.do`,然后回车即可,软件会自动执行仿真进程。

四、高级脚本技巧

4.1 do文件实现 ``define`

在编译文件时增加 +define+SIM,相当于在.v文件增加``define SIM`的功能。

tcl 复制代码
 vlog -work work +define+SIM "$RTL_DIR/counter.v"

4.2 设置仿真时间精度

增加-t 1ns设置仿真时间精度为1ns。

tcl 复制代码
vsim -t 1ns -voptargs="+acc" -L unisim -L unimacro -L secureip -L xpm_lib -L xil_defaultlib -L work xil_defaultlib.glbl work.tb_counter

4.3 状态机添加到波形

tcl 复制代码
# 定义虚拟类型(将二进制值映射为状态名)
virtual type { 
    {IDLE   2'b00} 
    {READ   2'b01} 
    {WRITE  2'b10} 
    {DONE   2'b11} 
} state_type

# 将实际信号转换为虚拟类型
virtual function {(state_type)/tb_cmos_init/u_cmos_init/cmos_init_state} cmos_init_state_named

# 添加到波形(显示为状态名)
add wave -noupdate /tb_cmos_init/u_cmos_init/cmos_init_state_named

4.4 设置显示格式(Radix)

格式 命令参数 说明
二进制 -radix binary 显示为0/1
十六进制 -radix hex 显示为0-F
十进制 -radix decimal 显示为整数
无符号十进制 -radix unsigned 显示为正整数
八进制 -radix octal 显示为0-7
ASCII -radix ascii 显示为字符
符号化 -radix symbolic 显示为状态机名称
默认 -radix default 使用原类型默认格式
tcl 复制代码
# 以无符号十进制显示
add wave -radix unsigned /tb_top/uut/data_bus

4.5 波形颜色设置

tcl 复制代码
# 为不同信号设置颜色
add wave -color "Red" /tb_top/uut/error_flag

# 可用颜色:Red, Green, Blue, Yellow, Cyan, Magenta, White, Black

4.6 波形分组设置

可以在 -group 前增加 -expand 用来展开分组,默认不展开。

tcl 复制代码
# ===== 添加分隔线 =====
add wave -divider {===== Top Level Signals =====}

# ===== 时钟和复位 =====
add wave -expand -group "Clock_Reset" \
    -color "Yellow" \
    /tb_top/clk \
    /tb_top/rst_n

# ===== 状态机 =====
add wave -group "FSM" \
    -radix symbolic \
    /tb_top/uut/current_state \
    /tb_top/uut/next_state

# ===== 内部计数器(十六进制)=====
add wave -group "Counters" \
    -radix hex \
    /tb_top/uut/cnt_8bit \
    /tb_top/uut/cnt_16bit

# ===== 错误标志 =====
add wave -group "Error_Flags" \
    -color "Red" \
    /tb_top/uut/parity_err \
    /tb_top/uut/timeout_err
相关推荐
汽车仪器仪表相关领域1 天前
Kvaser Hybrid Pro 2xCAN/LIN 双通道可编程CAN/LIN通讯接口:一机双模可编程,汽车车身混合总线测试专用设备
人工智能·功能测试·安全·fpga开发·汽车·压力测试
szxinmai主板定制专家1 天前
电力设备RK3568/RK3576+FPGA,多系统混合部署Linux+RTOS RT-THREAD,强实时性
linux·运维·服务器·人工智能·嵌入式硬件·fpga开发
ALINX技术博客1 天前
【黑金云课堂】FPGA技术教程Vitis开发:PS端DP接口解析
fpga开发·fpga
FakeOccupational1 天前
fpga系列 HDL:跨时钟域同步 shift register同步(CDC)毛刺滤除&解码前去抖动滤波模块
fpga开发
小眼睛FPGA1 天前
【紫光HiYou开源入门轻量级PCIE开发板PG2L25G】实验例程6-基于UDP 的以太网传输实验例程
fpga开发
高速上的乌龟1 天前
Lattice LFCPNX-100 HSB+Fpga开发详解: MAC+PCS以太网SFP光口传输
单片机·嵌入式硬件·fpga开发
ALINX技术博客1 天前
【黑金云课堂】FPGA技术教程Linux开发:电压温度检测/USB/eMMC
linux·fpga开发
小眼睛FPGA1 天前
【紫光HiYou开源入门轻量级PCIE开发板PG2L25G】实验例程3-基于紫光FPGA 的UART 串口通信
fpga开发
liuluyang5301 天前
SV 时钟移位示例代码解析
fpga开发·sv