最近在Windows上重新搭数字电路仿真环境,第一件事就是装Verilator。很多做FPGA或者数字IC验证的朋友都遇到过这个尴尬:官网不提供直接的Windows安装包,GitHub上虽然有release,但想要拿到好用版本要么自己啃源码编译,要么装个WSL绕一圈。实际上Windows下有一个非常顺手的路子——MSYS2,它自带软件包管理,一条pacman命令就能把Verilator连同GCC、Make、Perl这些依赖全部装齐。配合国内镜像源加速,整个安装过程真的可以做到“一键完成”,这篇就手把手记录一次完整的实操流程,包括镜像配置、安装步骤、第一个仿真Demo,以及我踩过的坑。
1. 为什么是MSYS2而不是源码编译
1.1 Verilator到底是个什么东西
Verilator是一个开源的Verilog/SystemVerilog仿真器,它和Icarus Verilog这类解释型仿真器最大的区别在于:它会把RTL代码转成C++模型,然后用C++编译器编成本地可执行文件,仿真速度非常快,在大型RTL工程和CI回归里特别吃香。正因为它是“编译型”仿真器,所以天然依赖一套完整的C++工具链,Windows下最难搞的就是这堆依赖。
如果你只装个Verilator二进制,它跑不起来,因为它生成C++代码之后,还需要调用g++去编译最终的可执行测试程序,还需要perl来执行驱动脚本,还需要make来自动化构建。这三样在Windows上凑齐并且版本兼容,手动折腾一次就知道了,相当费劲。
1.2 各安装方案的对比
Windows下装Verilator,其实有几种常见路子:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 官网源码编译 | 版本可控,能自己调编译选项 | 依赖perl、flex、bison、g++、make等,Windows下手动配齐极其痛苦 |
| Cygwin | 提供完整的Unix风格环境 | 包管理配置相对老旧,生成的程序依赖Cygwin DLL,分发和调用都不方便 |
| WSL | 最接近Linux原版体验 | 需要开启虚拟化,重一点,文件IO跨系统也经常说不清 |
| MSYS2 | 轻量、pacman包管理、更新快,生成的程序直接调MinGW工具链 | 需要理解不同终端环境的区别,镜像源默认在国外,需要手动加速 |
我自己用下来的体验是:MSYS2是最省心的选择。它本质上是一套在Windows上运行的POSIX兼容环境,但提供了原生的MinGW-w64工具链,Verilator在MSYS2仓库里已经维护得很好,版本跟进也快,装上去就能直接用。
1.3 整体安装流程
完整流程其实就三步:
- 安装MSYS2基础环境;
- 把pacman软件源替换成国内镜像;
- 用pacman安装Verilator及依赖。
后面再写一个简单的Verilog计数器模块,编译成仿真可执行文件跑一下,验证整个环境没问题。
2. MSYS2环境准备与国内镜像加速
2.1 下载安装包的两个办法
MSYS2的安装包可以从官网下载,但如果你直接走官方地址,下载速度全看网络心情。这里更推荐从清华镜像源的MSYS2发行目录里,挑一个最新的msys2-x86_64-xxxx.exe安装包下载,速度会稳定很多。
如果下载exe安装包本身也嫌麻烦,或者你遇到网上很多朋友说的“安装器卡在50%”这种问题,还有一个更隐蔽的办法:从同一个镜像目录下载msys2-base-x86_64.tar.xz,这个压缩包是绿色解压版,用7-Zip或者Windows 10自带的tar命令解压到C:\msys64,再手动配置镜像源,一样能用一个完整的MSYS2环境。
注意:不管用哪种方式装的MSYS2,路径尽量保持默认的
C:\msys64,这样后面很多教程里的路径都能直接对上,减少理解成本。
安装完成后,系统开始菜单里会出现几个入口,重点关注两个:MSYS2 MSYS和MSYS2 MinGW64。前者是基础环境,更新系统包和配置镜像源时用;后者是MinGW-w64环境,我们编译RTL仿真时要在这个终端里操作,因为只有这个终端会把C:\msys64\mingw64\bin加进PATH。
2.2 配置pacman国内镜像源
MSYS2的软件源分为好几个仓库,说白了就是好几条“列表”,每个列表文件对应一套环境。我们主要用的是mingw64仓库,所以至少需要配置/etc/pacman.d/mirrorlist.mingw64。另外整个MSYS2基础系统本身也会更新,/etc/pacman.d/mirrorlist.msys这个文件最好也一起换掉,否则pacman -Syu更新基础包时照样龟速。
先启动MSYS2 MSYS终端,打开镜像列表文件。这里我习惯先把原始文件备份到.bak,万一配错了还能快速恢复:
cp /etc/pacman.d/mirrorlist.mingw64 /etc/pacman.d/mirrorlist.mingw64.bak cp /etc/pacman.d/mirrorlist.msys /etc/pacman.d/mirrorlist.msys.bak然后直接向这两个文件写入国内镜像。清华源、中科大源、上海交大源都维护了MSYS2镜像,挑稳定的一到两个放进去就行。我个人习惯清华源排第一、中科大源排第二,备用效果好。
echo "Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64/" > /etc/pacman.d/mirrorlist.mingw64 echo "Server = https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/" >> /etc/pacman.d/mirrorlist.mingw64MSYS基础源的文件内容同理:
echo "Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch/" > /etc/pacman.d/mirrorlist.msys echo "Server = https://mirrors.ustc.edu.cn/msys2/msys/$arch/" >> /etc/pacman.d/mirrorlist.msys提示:
$arch是pacman的变量,会自动替换成当前系统架构,比如x86_64。写配置文件时不要把它写成固定路径,否则换架构或换机器时容易出问题。
2.3 首次更新系统包
镜像源配好之后,先执行一次系统整体更新,让MSYS2的内核包和pacman工具都处于最新状态:
pacman -Syu这一步的坑很多。新版MSYS2在更新一部分核心包之后,会弹出一个提示,大意是“当前终端即将关闭,请重新打开再继续更新”,这是正常的,不是报错。你需要把所有MSYS2窗口全部关掉,重新打开一个新的MSYS2 MSYS终端,再跑一次pacman -Syu,直到提示所有软件包都是最新状态。
如果更新过程中长时间卡住不动,最常见的罪魁祸首就是网络源没生效,比如你之前没做镜像配置、当前pacman还在走官方源。这时可以按Ctrl+C中断,检查镜像文件内容,确保Server行没有拼错,再重新执行。
3. 用pacman一键安装Verilator及依赖
3.1 一条命令装齐所有东西
环境更新好之后,真正安装Verilator的时间到了。打开MSYS2 MinGW64终端,执行这条命令:
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-verilator make这条命令别看长,它就是整个安装的“本体”。它会帮你处理全部依赖关系,包括Perl、Make、GCC工具链、Verilator本体。全程需要下载的包大约一两百兆,国内镜像源加速下基本几十秒到几分钟就能完成,对比手动编译源码,简直是一个非常舒服的过程。
这里简单拆解一下为什么是这三个包:
mingw-w64-x86_64-verilator:核心包,提供verilator命令和头文件;mingw-w64-x86_64-gcc:提供g++编译器,因为Verilator会把Verilog代码转成C++模型,最终还需要编译成本地程序;make:MSYS环境下的构建工具,Verilator生成C++代码后会调用make来自动完成后续编译。
为什么不装flex和bison?因为MSYS2的Verilator包是预编译好的,不需要你自己从源码解析语法,所以这两个开发工具就不需要手动出现了,这也是“一条命令搞定”的魅力所在。
3.2 一定要在MinGW64终端里操作
安装完成后,先验证一下命令是否可用:
which verilator verilator --version如果终端里输入verilator提示command not found,优先怀疑你是不是还开在MSYS2 MSYS那个环境里。Verilator是打包在mingw64仓库里的,它的可执行文件在/mingw64/bin目录下,只有MSYS2 MinGW64终端会把这条路径加进PATH。
正常安装后,verilator --version会输出类似Verilator 5.028 2024-xx-xx rev v5.028的字样。看到版本号,安装阶段就算彻底完成了。
3.3 顺带装个波形查看工具
做数字电路仿真,光看终端打印不够直观,会想看波形。GTKWave是一个轻量免费的VCD波形查看器,MSYS2仓库里也有,建议顺手装上:
pacman -S mingw-w64-x86_64-gtkwave装好之后,后面仿真导出的.vcd文件就能用GTKWave打开,肉眼确认时序关系。这个工具虽然界面朴素,但胜在轻量,对学习和小型工程完全够用。
4. 跑通第一个Verilator仿真Demo
4.1 准备RTL文件和测试台
环境装好只是一半,真正让人踏实的是亲手跑通一次仿真。我在C:\msys64\home\当前用户名\下面建了一个verilator_demo目录,准备用一个简单的8位计数器来验证全链路。
RTL文件counter.v,就是一个标准时序逻辑计数器:
module counter #(parameter WIDTH = 8) ( input wire clk, input wire rst_n, output reg [WIDTH-1:0] count ); always @(posedge clk or negedge rst_n) begin if (!rst_n) begin count <= 0; end else begin count <= count + 1; end end endmodule测试台用C++写,因为Verilator生成的就是C++模型,仿真测试程序也自然用C++来驱动。这个文件命名为tb_counter.cpp:
#include "Vcounter.h" #include "verilated.h" #include <cstdio> int main(int argc, char** argv) { VerilatedContext* ctx = new VerilatedContext; ctx->commandArgs(argc, argv); Vcounter* dut = new Vcounter{ctx}; for (int cycle = 0; cycle < 10; cycle++) { dut->clk = 1; dut->rst_n = (cycle < 2) ? 0 : 1; dut->eval(); dut->clk = 0; dut->eval(); printf("cycle=%d count=%u\n", cycle, dut->count); } dut->final(); delete dut; delete ctx; return 0; }简单解释一下:Verilator生成的顶层类叫Vcounter,实例化之后每个时钟周期给clk和rst_n赋值,调用eval()让组合逻辑和时序逻辑完成一次求值,然后读取count输出并打印。前两个cycle让rst_n拉低,观察复位值;之后释放复位,观察计数器递增。
4.2 编译RTL并生成仿真程序
在MSYS2 MinGW64终端里进入demo目录,执行Verilator的编译命令:
cd /c/msys64/home/你的用户名/verilator_demo verilator --binary --build -j 0 -Wall counter.v tb_counter.cpp --top-module counter这条命令里的参数我拆开说一下:
--binary:编译成单独的可执行仿真程序,而不是生成库文件;--build:自动调用make完成底层编译;-j 0:让make自动判断并行度,编译更快;-Wall:开启Verilator的代码检查,能提前发现RTL里很多常见问题;--top-module counter:显式指定顶层模块为counter。
命令执行后,Verilator会先生成obj_dir目录,里面是转换后的C++代码和编译产物,最后生成一个名为Vcounter的可执行文件。这一步如果能看到编译输出正常结束,说明整个工具链已经完全打通了。
运行仿真程序:
./obj_dir/Vcounter输出大概长这样:
cycle=0 count=0 cycle=1 count=0 cycle=2 count=1 cycle=3 count=2 cycle=4 count=3 cycle=5 count=4 cycle=6 count=5 cycle=7 count=6 cycle=8 count=7 cycle=9 count=8前两拍count保持0,是因为复位还没释放;第三拍开始计数递增。这个结果说明RTL到C++模型的转换、C++编译、仿真执行,全链路都工作正常。
4.3 导出VCD波形用GTKWave查看
如果只想验证功能,上面的打印就够了。但很多时候我们需要看信号时序,那就得导出VCD波形文件。需要在测试台里加入波形转储代码:
#include "verilated_vcd_c.h" // 在main中 VerilatedVcdC* tfp = new VerilatedVcdC; ctx->traceEverOn(true); dut->trace(tfp, 99); tfp->open("wave.vcd"); // 每个时钟周期仿真结束后调用 tfp->dump(cycle); // 仿真结束 tfp->close();修改后再跑一次Verilator编译,运行后目录下会生成wave.vcd,然后启动GTKWave打开它,就能看到clk、rst_n、count这些信号的时序波形了。traceEverOn(true)这个设置很关键,没有它Verilator在时间推进时会跳过一些信息采样,可能导致波形不完整。
5. 常见问题与排查技巧实录
5.1 安装与运行问题速查表
| 症状 | 常见原因 | 解决办法 |
|---|---|---|
| MSYS2安装器卡在50%左右 | 基础包下载走官方源,速度太慢或被中断 | 从清华镜像下载base压缩包解压,或先彻底退出安装器后重试 |
| pacman更新报“unable to lock database” | 上次pacman异常退出,锁文件残留 | 删除/var/lib/pacman/db.lck后重试 |
| pacman -Syu中途窗口自动关闭 | 核心包升级后需要重启终端继续 | 关闭所有MSYS2窗口,重开终端再执行一次pacman -Syu |
| verilator: command not found | 在MSYS2 MSYS终端里运行,或PATH不对 | 确认打开的是MSYS2 MinGW64终端 |
| 编译报错显示g++找不到 | 未安装MinGW GCC工具链 | 执行pacman -S mingw-w64-x86_64-gcc |
| 编译报错显示make找不到 | 缺少make工具 | 执行pacman -S make |
| 运行生成的Vcounter时报缺失DLL运行库 | 某些依赖库不在PATH中 | 确认在MSYS2 MinGW64终端内运行,或把C:\msys64\mingw64\bin加入系统PATH |
| 仿真输出count一直是0或X | 复位时序处理不当 | 检查测试台,确保复位信号先有效、释放后才有时钟有效沿 |
| 打开VCD波形后发现没有信号 | 没有调用traceEverOn,或在dump前就结束 | 测试台里显式调用ctx->traceEverOn(true),并确保波形文件正常关闭 |
5.2 几个值得展开的坑
第一个坑是“安装器卡在50%”。这个现象高频出现,尤其安装包解压到一半需要联网下载基础组件时,如果走的是国外源,很容易长时间卡住。我踩过一次之后就不再依赖安装器的在线初始化了,直接下载msys2-base-x86_64.tar.xz绿色版,解压后自己配置镜像源。这样全程离线也能完成基础环境搭建,可控性高了非常多。
第二个坑是pacman -Syu更新到一半提示要关闭终端。很多新手看到终端自己退出就慌了,以为安装失败,然后强行重启电脑或者删除目录,反而把环境搞坏。其实这是MSYS2的预期行为:更新了pacman自身和C运行时库之后,旧进程已经被占用,必须重启终端让新版本接管。正确做法就是关掉所有MSYS2相关窗口,重新打开,再执行一遍更新命令,通常第二次就会顺利完成。
第三个坑是终端选错。MSYS2里有两个常用环境,MSYS2 MSYS更像是“Unix环境模拟层”,MSYS2 MinGW64才是编译原生Windows软件的主力环境。我见过很多人在MSYS终端里执行pacman -S mingw-w64-x86_64-verilator,装是装上了,但输入verilator又找不到命令。原因很简单:mingw64仓库的可执行文件装在了/mingw64/bin,这个目录只存在于MinGW64终端的PATH里。以后凡是遇到“装了但找不到”这种问题,先看看自己是不是用错了终端。
5.3 一些使用上的经验建议
版本方面,MSYS2仓库里的Verilator更新算勤快的,基本能跟上主线。如果你需要某个固定版本,也可以去Verilator官方仓库下载源码放到MSYS2里编译,但我建议非必要不搞源码编译,仓库版本对绝大多数项目都够用。
路径方面,如果你以后想在VS Code或自己写脚本里直接调用verilator命令,可以把C:\msys64\mingw64\bin和C:\msys64\usr\bin追加到Windows系统PATH。但要注意,这会让Windows系统自带的某些Unix工具被MSYS2版本覆盖,比如find、sort这些命令的行为会和原生命令不太一样。我自己是只在MSYS2终端里用,因为这种隔离带来的麻烦少于便利。
环境方面,我习惯每装完一套新环境后,把下面这条检查命令存进备忘录:
pacman -Syu && pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-verilator make && verilator --version下次无论换电脑还是帮同事搭环境,照着跑一遍,基本不会翻车。
最后说点个人体会。MSYS2这套方案我用了蛮久,最大的感受是Verilator在Windows下的安装终于不再是“劝退题”了。它没有虚拟机那么重,也没有源码编译那么多依赖,一条pacman命令就能拉起一个原生Windows仿真环境。后续如果需要在Windows下做更复杂的验证流程,可以再研究一下把Verilator接到CMake工程里,或者配合GTKWave做自动化波形检查,这些都是可以继续深入的方向。希望这篇记录能帮你在Windows下尽早跑通第一个Verilator仿真,省下来的时间不如多写两行RTL。