back

用开源工具链玩FPGA

从一块iCESugar开发板开始!

2025-11-15

luisleee


引言

用过 FPGA 的朋友大概都被开发工具折磨过吧?用 Altera 家的被 Quartus 折磨,用 Xilinx 家的被 Vivado 折磨。这些集成开发环境动辄几十个 GB,许可证价格昂贵,配置过程一言难尽,代码编写陈腐如世纪初,语法高亮代码补全一塌糊涂,缺少版本控制,引脚设置每次全靠点点点,交互设计反人类,还动辄崩溃卡死,很难知道它里面都在发生着些什么。我可以很明确地指出,这都是封闭带来的弊病。下面我将展示一种能解决以上所有问题的开源路径。

这里发生了什么?

要用开源工具替代它,我们首先要明白闭源的工具都做了些什么。当你点击编译按钮时,那个几十 GB 的庞然大物在背后表演了这样一场戏法:

开源工具链

幸运的是,我们有一套完整的开源工具链来完成这一流程。

yosys 是一款强大的开源综合工具,能够高效地将 Verilog 代码转换为门级网表,并进行可观的优化。

布局布线上,目前最有希望的项目是 nextpnr。它是一个可移植的、框架性的布局布线工具,其强大之处在于它通过不同的“芯片数据库”来支持多种 FPGA 架构。nextpnr 可以与 yosys无缝衔接,构成 yosys + nextpnr 的核心开源流程。

而位流生成这一步,就比较无计可施了。这一步需要针对特定FPGA芯片进行反向工程或与厂商合作。开源社区已经为一些 FPGA(主要是 Lattice 的某些型号和早期的 Xilinx 芯片)成功破解了位流格式,并开发出了相应的生成工具。

最著名的是 Cliff Wolf 发起的 icestorm 项目,它率先逆向工程了 Lattice iCE40 系列 FPGA 的位流格式,并提供了一整套工具(包括位流生成器 icepack ),为整个开源 FPGA 工具链生态点燃了星星之火。在 iCE40 成功的基础上,社区又催生出了针对更强大芯片的项目:

因此,虽然位流生成这一步壁垒最高,但开源社区正采用“农村包围城市”的策略,从结构相对简单、文档偶尔泄露的低端芯片入手,逐步向中高端芯片推进。这套 yosys + nextpnr + 芯片专属位流工具 的开源组合,已经能够让开发者在不依赖厂商闭源软件的情况下,完全自主地实现从代码到芯片配置的完整流程。这不仅降低了开发门槛和成本,更重要的是,它将 FPGA 开发的底层控制权交还给了工程师。

至于烧录,就非常简单了。烧录器通常支持 JTAG、DAPLink 和 UART 等通用接口,并有成熟的开源软件支持,例如功能强大的 openocd, openFPGALoader 等。

至此一套完整的开源 FPGA 工具链就成型了。这些工具都不是紧耦合的,我们之后可以轻松地享受版本控制和代码高亮补全功能带来的便利,同时也可以用 make 等工具任意掌控构建的细节。

介绍 Lattice iCE40 和 iCESugar 开发板

而我们今天的主角就是最最最入门的一颗 FPGA 芯片:Lattice iCE40。

Lattice iCE40 是 Lattice Semi 公司推出的一系列超低功耗、非易失性的 FPGA。它们因其低成本、丰富的封装选择和活跃的开源工具链支持,在嵌入式系统、消费电子和物联网设备等领域应用广泛。

主要特性包括:

它对我这个教程的最大优点是:简单便宜,可以使用完全开源的工具链。同时市场上有很多比较成熟的适合初学者的开源开发板。国外社区有 icebreaker,icestick 等优秀的开源开发板,也有各种开源 FPGA 项目,例如 PicoRV32、litex 等。但国内社区的相关工作是非常少的,目前我只见到了 iCESugar 开发板这一株独苗。

iCESugar 板载 Lattice iCE40UP5K,提供 5280 个逻辑单元,对于学习研究相当足够。 而且它的板载资源相当丰富,包括 RGB LED、按钮、SPI Flash 存储以及大量的 I/O 引脚,方便连接外设和扩展功能,可以直接用 PMOD 连接,非常方便。

iCESugar 开发板

而且它有一个非常友好的调试器,名为 iCELink,基于 DAPLink,支持拖拽烧录。只需将 FPGA 综合出的配置文件拖动到名为 iCELink 的 U 盘就可以了,非常方便。

本人花 168 块钱全款拿下了它。

一个例子

现在问题只剩一个了:我要怎么用这些开源工具呢,我要怎么配置它呢?

首先我们先把所有所需的工具安装好。我这里用的是 Archlinux, 所以都可以在软件包仓库内找到。在其他系统上,就可能需要从源码编译了。

Archlinux 上可以直接完成安装:

sudo pacman -S yosys nextpnr-git icestorm

对于其他系统,我在下面给出源码的 Git 仓库:

为了简单直观,我们用 iCESugar 开发板上的 RGB LED 做演示,写一个循环轮换灯的例子。事实上这是开发板的官方示例之一。

module leds(input clk, output LED_R, output LED_G, output LED_B);
   reg [25:0] counter;

   assign LED_R = ~counter[23];
   assign LED_G = ~counter[24];
   assign LED_B = ~counter[25];

   initial begin
      counter = 0;
   end

   always @(posedge clk)
   begin
      counter <= counter + 1;
   end
endmodule

在编写完 Verilog 之后,保存为leds.v,就可以用 yosys 综合,输出网表的 json 文件了:

yosys -p "synth_ice40 -top led -json leds.json" leds.v

-p后面的是综合的具体命令:对 iCE40 进行综合,顶级模块名称为 leds, 输出到 leds.json,所用到的源文件为 leds.v

对于多个文件的项目,只需要把源文件追加到命令后面即可。

下一步是用 nextpnr 进行布线。这里涉及到一个问题:我们需要配置我们的顶级模块连接的引脚具体是 FPGA 的哪个引脚。我们这里是通过一个 pcf 物理约束描述文件来告诉 nextpnr 你的 Verilog 代码中的顶层模块接口应该对应到 FPGA 芯片的哪个物理引脚上。完整的引脚与外设的对应关系需要具体查阅开发板的电路图和手册。

我在这里给出我这里用到的引脚配置,保存为 constraints.pcf

# For the iCESugar Board (iCE40UP5K-QFN48)

set_io LED_G 41
set_io LED_R 40
set_io LED_B 39

set_io clk   35

这个文件的格式很简单可读,也很容易管理。和刚才生成的网表放在一起,就可以布线了:

nextpnr-ice40 --json leds.json --pcf constraints.pcf --asc leds.asc

leds.asc 即为输出的布线文件。它是一个纯文本文件,打开可以看到它长这个样子,我把它的一部分贴上来:

.io_tile 1 0
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000
000000000000000000

这其实就是 nextpnr 对每一个逻辑开关的配置情况。最后还需要通过 icepack 把它转化成 FPGA 可读的二进制位流:

icepack leds.asc leds.bin

生成的 leds.bin 就可以直接烧录了。我们这块开发板在连接上电脑之后,直接把文件拖拽进去就可以了。

亮了个灯

这套工具还有对设计进行静态时序性能分析的功能。一个简单的示例如下:

icetime -d up5k leds.asc

它会给出这样的输出,计算线路时延,给出该设计理论上能达到的最高时钟频率。

// Reading input .asc file..
// Reading 5k chipdb file..
// Creating timing netlist..

icetime topological timing analysis report
==========================================

Report for critical path:
-------------------------
【省略】

Total number of logic levels: 26
Total path delay: 13.45 ns (74.35 MHz)

我相信至此读者对这套工具链一定有了一点了解了。但是每次构建都这样运行一遍命令肯定很麻烦,所以我在这里提供一个 makefile 供参考:

DEVICE = up5k
PACKAGE = sg48
TOP = leds

SOURCES = src/leds.v
PCF = constraints/icesugar.pcf

BUILD_DIR = build

$(shell mkdir -p $(BUILD_DIR))

build: $(BUILD_DIR)/$(TOP).bin

$(BUILD_DIR)/$(TOP).json: $(SOURCES)
	yosys -p "synth_ice40 -top $(TOP) -json $@" $(SOURCES)

$(BUILD_DIR)/$(TOP).asc: $(BUILD_DIR)/$(TOP).json $(PCF)
	nextpnr-ice40 --$(DEVICE) --package $(PACKAGE) --json $< --pcf $(PCF) --asc $@

$(BUILD_DIR)/$(TOP).bin: $(BUILD_DIR)/$(TOP).asc
	icepack $< $@

clean:
	rm -rf $(BUILD_DIR)

.PHONY: build clean

我的代码可以在这里找到。

结语

更多关于开发板的资料和更多示例可以在这里找到。作者还发布了 nano 和 pro 版本的开发板,感兴趣的朋友可以了解一下

如果想要不烧录就对代码进行测试,可以编写 Test Bench ,并使用 Icarus Verilog 并进行仿真。具体使用可以参照这里

前面也提到了,这块开发板的性能是相当不错的,我们可以在它上面运行各种 SoC,把它变成一台可定制的微型电脑。这对喜欢计算机和数字逻辑设计的朋友来说是非常有吸引力的。开发板的作者有一篇很好的博客,感兴趣的朋友可以了解一下。

以上的内容非常基础,但是包含了你所需要的几乎一切基本工具。这条工具链虽然在对超大规模、高性能设计的优化效果和易用性上,与成熟的商业软件尚有差距,但它代表了一种根本性的转变:我们将设计的控制权从黑盒中夺回,放到了阳光之下。它不仅是可用的工具,更是可审计、可学习、可修改的开放知识体系。对于教育、研究、定制化开发和安全关键领域而言,这种透明性和自主性具有无可替代的价值。

不过仍然很遗憾,虽然对 Lattice iCE40 和 ECP5 系列的支持已经比较成熟,但对于其他厂商的新型 FPGA 芯片,支持往往滞后或尚未覆盖。这仍然是一个有待社区探索的课题。

back