Windows 下 iCE40 FPGA 开源开发环境配置

2021-02-26 15:31:35 浏览数 (1)

导语:之前有分享过开源FPGA板卡-OpeniCE,链接如下《开源FPGA开发板-OpenICE 介绍及抽奖》及《开源FPGA开发板-OpeniCE例程更新说明》、《基于开源FPGA-OpeniCE的NES游戏机》。今天收到高老哥的投稿,是在Windows下开发ice40相关开发板的配置,一篇“保姆级”的教程,令我汗颜。

Windows 下 iCE40 FPGA 开发环境配置

收到碎碎思寄来的基于 iCE40UP5k 的 OpeniCE 板,经过一番尝试,我可以在 Windows 系统进行 FPGA 开发,在此将一些经验分享给大家。

开源 FPGA 工具链

相比 FPGA 厂商的开发工具,开源工具链有以下几个优点:

  • 不需要厂商许可证。开源工具链的中所有组件均有源代码提供,可以自行编译或者使用已经构建好的二进制文件,不需要任何厂商许可证。
  • 体积小,下载安装方便。包含了 Lattice iCE40 系列、ECP5 系列 FPGA 支持的工具链压缩包大小在 100 MB 左右,而厂商提供的安装包有几个到几十个 GB。
  • 速度快,节省上板调试时间。以笔者测试用的几个小工程为例,完成代码综合、布局布线并下载到 FPGA 中仅需几秒钟的时间。
  • 跨平台支持。开源工具链不仅支持 Windows,Linux 和 Mac OS 等操作系统,而且支持 x86 之外的处理器平台。
  • 更容易与其他工具整合。

准备工作

你需要具备一下条件:

  • 装有 Windows 系统的 PC 机
  • 一块 iCE40 FPGA 开发板,OpeniCE 或者其他 iCE40 FPGA 开发板
  • fpga-toolchain 软件
  • zadig 软件

下载和安装

首先下载 fpga-toolchain(https://github.com/YosysHQ/fpga-toolchain) Windows 平台每日构造包,如下图所示:

成文时,nightly-20210129 为最新的每日构建版本,笔者下载了 fpga-toolchain-windows_amd64-nightly-20210129.7z 进行安装配置。读者可以根据情况选择最新的版本。

在硬盘上创建一个目录,然后将下载好的压缩包解压缩到此目录中。笔者在 D 盘创建了一个文件夹 OpeniCE,并将下载的文件解压到此目录,然后进入到 fpga-toolchainbin 子目录下:

你可以找到构建 iCE40 bit-file 最重要的几个文件:

  • yosys,用来将 verilog RTL 综合生成网表文件
  • nextpnr-ice40,根据网表文件和约束文件进行布局布线
  • icepack,将生成的中间文件转换成 binary 格式的 bit-file
  • iceprog,下载 binary 格式的 bit-file,需确认是否支持你的开发板
  • icetime,检查并生成时序报告

此外,我们看到 fpga-toolchain 里面还有包含了其他工具,例如构建工具 make、支持 formal verification 的 SymbiYosys(https://github.com/YosysHQ/SymbiYosys)、支持 ECP5 FPGA 的 Project Trellis(https://github.com/SymbiFlow/prjtrellis) 套件等等,此处不做深入介绍。

使用上述几个程序就可以一步步的构建、生成并下载 iCE40 的 bit-file,不过频繁构建文件时,这些操作就变得非常繁琐,通常情况下我们会使用一些辅助工具来简化这一过程。

安装驱动

需要注意的是,此处描述针对 OpeniCE 单板,读者需根据单板厂家提供的文档来安装驱动。

先在 zadig(https://zadig.akeo.ie/) 官网下载 zadig 2.5 程序。

插入 OpeniCE 单板后,运行 zadig,选中 List All Devices。

然后在主界面列表里面选中 “OpenICE II v1.0A -B06- (Interface 0)”:

驱动列表中有 WinUSB、libusb-win32 和 libusbK 三个选项供选择。在笔者的环境中,安装 libusb-win32 驱动后无法正常下载,安装 libusbK 驱动后 FPGA 下载有时不稳定,所以,笔者最终安装了 WinUSB 驱动。

辅助工具

fpga-toolchain 中已经包含了构建构建工具 make,大多数情况下,我们还需要其他的工具进行一些操作,例如 rm 工具来清理中间文件,或者构建之前对某些文件进行预处理等等。

为了便于以后扩展,笔者选择使用 msys2(https://msys2.org) 来作为辅助 FPGA 开发。读者也可以选择 windows-build-tools(https://github.com/xpack-dev-tools/windows-build-tools-xpack)。

msys2 的最新安装文件可以从清华大学开源软件镜像站(https://mirrors.tuna.tsinghua.edu.cn/)的 msys2 镜像处进行下载:

下载完毕后,将 msys2-x86_64-latest.tar.xz 也解压缩到 D:OpeniCE 目录下:

进入 msys64 目录,执行 msys2.exe 程序。第一次执行时,msys2 会进行一些初始化工作,初始化完成后,会看到类似下面的界面:

可以执行一次下面的命令来更新包信息:

代码语言:javascript复制
pacman -Syuu

再执行之前,笔者建议将 /etc/pacman.d 文件夹下的 mirrorlist.mingw32、mirrorlist.mingw64 和 mirrorlist.msys 三个文件中的包含 https://mirrors.tuna.tsinghua.edu.cn 的条目放置在其他条目之前以加快包同步和下载速度。

更新完毕后,可以执行下面的命令安装 make 包:

代码语言:javascript复制
pacman -S make

安装构建工具 make 后,我们就有一个类 Linux 的命令行环境了,然后我们可以编写代码并进行测试了。

测试代码

在 D:OpeniCE 创建 workspaceledflash 目录,然后在 ledflash 下创建 proj 目录和 rtl 目录。

在 proj 目录下创建一个文件,文件名为 Makefile,内容如下:

代码语言:javascript复制
PROJ := ledflash

VSRC := ../rtl/ledflash.v 
      ../rtl/mod_n_counter.v

TOP := $(PROJ)
EXTRA_OPT := #-abc2
EXTRA_OPT  = #-retime

DEVICE := up5k
PACKAGE := sg48
FREQ   := 12
PCF     := openice.pcf

ADD_CLEAN := abc.history


include common.mk

Makefile 中主要定义了项目名称,verilog 代码文件以及设备相关的属性。感兴趣的读者可以查阅 yosys 和 nextpnr-ice40 手册,了解相应参数的含义。读者需要根据自己 FPGA 的信号确定是否要进行修改。

在 proj 目录下创建一个文件,文件名为 common.mk,内容如下:

代码语言:javascript复制
all: $(PROJ).rpt $(PROJ).bin

%.json: $(VSRC)
yosys -ql $*.log -p 
'synth_ice40 $(EXTRA_OPT) -top $(TOP) -json $@' 
       $(VSRC)

%.asc: $(PCF) %.json
nextpnr-ice40 --$(DEVICE) 
$(if $(PACKAGE),--package $(PACKAGE)) 
$(if $(FREQ),--freq $(FREQ)) 
--json $(filter-out $<,$^)     
--pcf $< --asc $@

%.bin: %.asc
icepack $< $@

%.rpt: %.asc
icetime $(if $(FREQ),-c $(FREQ)) -d $(DEVICE) 
-mtr $@ $<

prog: $(PROJ).bin
iceprog -S -k $<

prog_flash: $(PROJ).bin
iceprog $<

clean:
rm -f $(PROJ).{json,asc,bin,rpt,log} $(ADD_CLEAN)

.SECONDARY:
.PHONY: all prog prog_flash clean

common.mk 主要定义了常见的规则,通常情况下,读者可以不加修改直接使用。其中包含的目标项有:

  • all,缺省目标,生成 binary bit-file 及时序报告文件
  • prog,下载 bit-file 到 FPGA,要先设置 OpeniCE 上的 JP16
  • prog_flash,将 bit-file 下载到 FLASH,需先设置 OpeniCE 上的 JP16
  • clean,清除所有的中间文件

在 proj 目录下创建一个文件,文件名为 openice.pcf,内容如下

代码语言:javascript复制
# 12 MHz input clock
set_frequency i_clk 12

# input clock
set_io -nowarn i_clk            35

# RGB LEDs
set_io -nowarn o_led_blue_n     39
set_io -nowarn o_led_red_n      40
set_io -nowarn o_led_green_n    41

openice.pcf 中定义了输入的时钟频率以及所有的输入和输出引脚。读者需要查阅自己 FPGA 开发板的文档进行修改。

在 rtl 目录下创建一个文件,文件名为 ledflash.v,内容如下:

代码语言:javascript复制
//
// A flashing LED
//


`default_nettype    none


module ledflash
#(
   parameter   N   = 12_000_000
)
(
   input   wire                i_clk,
   output  wire                o_led_blue_n
);

   wire    w_en;
   wire    w_tick;

   assign w_en = 1'b1;

   mod_n_counter
   #(
      .N          ( N             )
   )
   u_mod_n_counter
   (
      .i_clk      ( i_clk         ),
      .i_en       ( w_en          ),
       /* verilator lint_off PINCONNECTEMPTY */
      .o_counter  (               ),
       /* verilator lint_on PINCONNECTEMPTY */
      .o_tick     ( w_tick        )
   );

   reg     r_led;

   initial r_led = 1'b0;
   always @ (posedge i_clk)
       if (w_tick)
           r_led <= ~r_led;

   assign o_led_blue_n = r_led;

endmodule

ledflash.v 中例化了一个计数分频模块和一个带使能反转的寄存器。输入时钟为 12MHz 时,W 取 12000000,FPGA 加载完毕后,LED 会亮 1 秒钟,灭 1 秒钟,然后不断重复亮灭。

然后在 rtl 目录下创建一个文件,文件名为 mod_n_counter.v,内容如下:

代码语言:javascript复制
//
// A mod-N counter with an enable signal
//
// o_tick asserts when i_en asserts and counter counts up to
// the limit
//


`default_nettype    none


module mod_n_counter
#(
   parameter   N       = 50,
   parameter   WIDTH   = $clog2(N)
)
(
   input   wire                    i_clk,
   input   wire                    i_en,
   output  wire    [WIDTH - 1 : 0] o_counter,
   output  wire                    o_tick
);

   reg     [WIDTH - 1 : 0] r_counter;
   wire    [WIDTH - 1 : 0] r_counter_next;

   initial r_counter = {WIDTH{1'b0}};
   always @ (posedge i_clk)
       if (i_en)
           r_counter <= r_counter_next;

   wire    w_tick;

   assign w_tick         = (r_counter == (N[WIDTH - 1 : 0] - 1'b1));
   assign r_counter_next = w_tick ? {WIDTH{1'b0}} : (r_counter   1'b1);

   assign o_tick    = i_en & w_tick;
   assign o_counter = r_counter;

endmodule

mod_n_counter.v 实现了一个模 N 计数器,每 N 个周期产生一个时钟周期的高电平脉冲。需要注意的是,当 N 为 2 的次幂时,这种实现不是最优的。

上板调试

完成上述文件之后,用 USB 线将 OpeniCE 连接到 PC 机,将跳线帽设置成 iCE 编程模式,双击 D:OpeniCEmsys64msys2.exe 运行 msys,然后输入:

代码语言:javascript复制
export PATH=$PATH:/d/OpeniCE/fpga-toolchain/bin

将 fpga-toolchain 工具加入到 PATH 环境变量:

进入到 /d/OpeniCE/workspace/ledflash/proj 目录,输入 make prog 然后回车执行。如果前面的准备工作都正常,读者应该能看到类似下图的结果:

在笔者的环境中,整个过程大概花费两秒左右。然后,观察 OpeniCE 单板,会发现 RGB LED 的蓝色 LED 灯在闪烁。

总结

按照本文的说明,读者硬件可以比较容易地在 Windows 上构建一个 iCE40 FPGA 的开发环境。

由于使用了 msys2 作为辅助开放工具,读者可以在 msys2 中安装 verilator 作为仿真工具以及 Lint 工具,可以安装 gtkwave 来查看反正波形,还可以使用 Symbiyosys 来进行 formal verification,敬请期待。

本文版权归原作者所有

0 人点赞