SpinalHDL Windows 开发环境搭建指南
在快速搭建 FPGA 硬件学术验证 demo 时,SpinalHDL 能大幅提升开发效率。但环境配置本身有不少潜在坑点,尤其在 Windows 上。这份文档是我在配置 Win 新环境时整理的完整步骤。
SpinalHDL 的工具链主要分三个部分:
- 编译运行:JDK + sbt,负责编译和运行 Scala/SpinalHDL 代码
- RTL 生成:SpinalHDL 本身,将 Scala 描述转换为 Verilog
- 仿真验证:包括轻量化的 iverilog(个人常用)、主流的 Verilator(编译为 C++,速度更快),以及波形查看器 GTKWave
其中需要注意的一点是,调用 SpinalSim 进行协同仿真时需要 g++ 编译 VPI 插件,而 Windows 下走 WSL 调用 Verilator 等工具链会比较麻烦,所以这里选择了 MSYS2 路线来统一解决 C++ 工具链的问题。
这个文档的目标是快速搭建一套适合学术 demo 的 SpinalHDL 环境,支持中小规模设计的仿真性能需求,不一定适合大规模业务体系。工具安装统一使用 Scoop——命令行部署方便快捷,包管理也很省心。
另外,本文也包含一个完整的 demo 工程搭建步骤,可以依据此测试整套工具链是否跑通。
最终搭建的工具链如下:
| 环节 | 工具 | 说明 |
|---|---|---|
| 编译运行 | JDK 17 + sbt | 编译运行 Scala/SpinalHDL 代码 |
| RTL 生成 | SpinalHDL 1.12.0 | Scala → Verilog |
| 仿真 | iverilog + SpinalSim | Verilog 仿真,支持 Scala 协同仿真 |
| 高性能仿真 | Verilator | 编译为 C++,速度更快 |
| 波形查看 | GTKWave | 打开 VCD/FST 波形文件 |
| 编译工具链 | MSYS2 (g++ / Boost) | SpinalSim VPI 插件编译所需 |
一、前置依赖
安装工具链之前需要确认以下基础环境已就绪:
| 依赖 | 说明 | 检查命令 |
|---|---|---|
| Scoop | 包管理器 | scoop --version |
| Git | Scoop 依赖 Git 来管理 bucket | git --version |
安装 Scoop
Scoop 默认安装到 ~\scoop\(即 C:\Users\<用户名>\scoop\)。如需自定义路径(比如装到 D 盘),安装前设置环境变量:
$env:SCOOP = 'D:\Scoop'安装 Scoop(PowerShell 执行):
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex验证:
scoop --version所有工具统一安装在
apps/子目录下。
安装 JDK 17、sbt 和 Iverilog
scoop bucket add java
scoop install openjdk17 sbt iverilogMSYS2 工具链
scoop install msys2
$bash = "$env:USERPROFILE\scoop\apps\msys2\current\usr\bin\bash.exe"
& $bash -lc "pacman -Syu --noconfirm"
& $bash -lc "pacman -Su --noconfirm"
& $bash -lc "pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-boost mingw-w64-x86_64-verilator perl-Pod-Parser"配置 PATH
$msys2bin = "$env:USERPROFILE\scoop\apps\msys2\current\mingw64\bin"
$currentPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
[System.Environment]::SetEnvironmentVariable('Path', "$currentPath;$msys2bin", 'User')重新打开终端后验证:
java -version && sbt --version && iverilog -V && gtkwave --version && g++ --version && verilator --version二、项目结构
mkdir -p src/main/scala src/test/scala projectproject/build.properties
sbt.version=2.0.6build.sbt
ThisBuild / version := "0.1.0"
ThisBuild / scalaVersion := "2.13.16"
ThisBuild / organization := "com.example"
val spinalVersion = "1.12.0"
lazy val root = (project in file("."))
.settings(
name := "spinal-project",
libraryDependencies ++= Seq(
"com.github.spinalhdl" %% "spinalhdl-core" % spinalVersion,
"com.github.spinalhdl" %% "spinalhdl-lib" % spinalVersion,
compilerPlugin("com.github.spinalhdl" %% "spinalhdl-idsl-plugin" % spinalVersion),
"com.github.spinalhdl" %% "spinalhdl-sim" % spinalVersion,
"org.scalatest" %% "scalatest" % "3.2.19" % Test,
),
Test / fork := true,
Test / javaOptions += "-Dspinal.sim.defaultBackend=iverilog",
)src/main/scala/Adder.scala
import spinal.core._
import spinal.lib._
case class Adder(width: Int) extends Component {
val io = new Bundle {
val a = in UInt(width bits)
val b = in UInt(width bits)
val result = out UInt(width bits)
}
io.result := io.a + io.b
}
object AdderMain extends App {
SpinalVerilog(Adder(8))
println("Verilog generated!")
}src/test/scala/AdderSim.scala
import spinal.core._
import spinal.core.sim._
import scala.util.Random
object AdderSim extends App {
SimConfig
.withIVerilog // 指定 iverilog 后端(注意大写 V)
.withWave // 生成 VCD 波形
.withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = SYNC)))
.compile(Adder(8))
.doSim { dut =>
dut.clockDomain.forkStimulus(10)
for (_ <- 0 until 100) {
val a = Random.nextInt(256)
val b = Random.nextInt(256)
dut.io.a #= a
dut.io.b #= b
dut.clockDomain.waitRisingEdge()
assert(dut.io.result.toLong == ((a + b) & 0xFF),
s"FAIL: $a + $b != ${dut.io.result.toLong}")
}
println("ALL 100 TESTS PASSED!")
}
}三、编译与运行
# 生成 Verilog
sbt "runMain AdderMain"
# SpinalSim 仿真(sbt 2.x 语法)
sbt "Test / runMain AdderSim"
# 查看波形
gtkwave simWorkspace\Adder\test\wave.vcd最后更新于