CONTENTS

Home
Updates
Software
Electronics
Music
Resume
Contact


YouTube
BlueSky
GitHub
LinkedIn


Open-Source FPGA Development

Posted: April 15, 2025
Updated: June 14, 2026

Introduction

This was originally instructions on how to build the open source dev tools for doing development with the Tang Nano board but has been updated for:

  • GOWIN GW2AR-LV18QN88C8/I7 (Sipeed Tang Nano 20K)
  • GOWIN GW2A-LV18PG256C8/I7 (Sipeed Tang Primer 20K)
  • Lattice ice40 (ice40)
  • MachXO2
  • ECP5

The open source tool to complile are yosys / nextpnr. Yosys is required for all FPGA families. Nextpnr needs to be compiled for each specific family.

To make sure I didn't forget how to do this I'm writing it all down here. The page is organized as:

  • Setup Docker
  • Compile yosys
  • Compile nextpnr for Gowin (optional)
  • Compile nextpnr for ice40 (optional)
  • Compile nextpnr for MachXO2 (optional)
  • Compile nextpnr for ECP5 (optional)
  • Save Docker Image
  • Starting Docker Image
  • Examples of command line options for yosys and nextpnr for building project on each FPGA family.

Related Projects @mikekohn.net

FPGA: FPGA VGA, Nexys2, Glow In The Dark Memory, Intel 8008, F100-L, RISC-V, x86 / 68000, MIPS, MSP430, PowerPC, W65C832, Apollo 11, PDP-11

Setting Up Docker

The first steps are to set up a docker container to hold all the development tools. This allows the tools to be build and installed without modifying (and possibly leaving files all over) the host's operating system.

If docker isn't installed, on Ubuntu it can be done with:

sudo apt install docker.io

After it installs, it might be good to add your username to the docker group so it doesn't have to be run with sudo.

First step after docker is installed is to pull the lastest debian image with docker:

docker pull debian:latest

Next the docker container can be started:

docker run --rm -it debian:latest /bin/bash

Building Yosys

The next step is to build Yosys in the docker container. Yosys is the first step of building an FPGA project. To build it follow these steps:

apt update apt install git g++ cmake \ build-essential clang lld bison flex \ libreadline-dev gawk tcl-dev libffi-dev git \ graphviz xdot pkg-config python3 libboost-system-dev \ libboost-python-dev libboost-filesystem-dev zlib1g-dev

Next clone and build Yosys:

cd mkdir source cd source git clone https://github.com/YosysHQ/yosys.git cd yosys git submodule update --init --recursive mkdir build cd build cmake .. make

NOTE: Doing a git pull occasionally to get the latest yosys sometimes needs an update to the abc submodule. Usually typing "make" after that just works, but I ran into this issue where it would not build. I did "rm -rf abc" to remove the abc directory and "git submodule update --init --recursive" to get the latest and that fixed the issue.

Building nextpnr for GOWIN FPGA Support

Need to install some prerequisites for nextpnr-himbaechel:

apt install \ libboost-dev \ libboost-filesystem-dev \ libboost-thread-dev \ libboost-program-options-dev \ libboost-iostreams-dev \ libboost-dev apt install libeigen3-dev apt install pip pip install --break-system-packages apycula

There have been times when I've updated yosys / nextpnr without updateing apycula, which broke the builds from working properly... so apycula should be updated often. To udpate apycula at a later time:

pip install --upgrade --break-system-packages apycula

Next need to clone and build nextpnr-himbaechel:

cd cd source git clone https://github.com/YosysHQ/nextpnr.git cd nextpnr git submodule update --init --recursive mkdir build_gowin cd build_gowin cmake .. -DARCH="himbaechel" -DHIMBAECHEL_UARCH="gowin" make

Now all the dev tools should be built. The last thing missing is openFPGAloader. That didn't appear to be a part of Ubuntu either so it seems it needs to be built from source. This one is probably better though to build on the host and not in the container.

Building nextpnr For Ice40 FPGA Support

Some extra things can be done to have this container hold a devkit for ice40 too. First is to clone and build icestorm:

apt install libftdi1-dev cd cd source git clone https://github.com/YosysHQ/icestorm.git cd icestorm make make install

This installs chipdb in /usr/local/share/icebox. And then from nextpnr:

cd cd source/nextpnr mkdir build_ice40 cd build_ice40 cmake .. -DARCH=ice40 make

If no other FPGA families are needed, skip to the section on how to save the docker image.

Building nextpnr For ECP5 and MachXO2 Support

To do either ECP5 or MachXO2, first libtrellis has to be installed. That can be done with:

cd cd source git clone https://github.com/YosysHQ/prjtrellis cd prjtrellis/libtrellis cmake . make make install cd /usr/local/share/trellis git clone https://github.com/YosysHQ/prjtrellis-db.git rm -rf database ln -s prjtrellis-db database

To Build nextpnr with MachXO2:

cd cd source/nextpnr mkdir build_machxo2 cd build_machxo2 cmake .. -DARCH=machxo2 make

To Build nextpnr with ECP5:

cd cd source/nextpnr mkdir build_ecp5 cd build_ecp5 cmake .. -DARCH=ecp5 make

Saving The Docker Container Image

Before doing that, it would probably be a good idea to "commit" the container so instances of it can be started later without rebuilding the devkits. To save the container first the container id needs to be found. That can be done with:

docker ps

In my case, the container id is d20cae9d3ad2 so to save a new image based on a snapshot of this container with the image name fpga_dev:

docker commit d20cae9d3ad2 fpga_dev

This can take some time. After it finishes, this container can be exited. To start a new container based on the new fpga_dev image:

Starting The Docker Container

docker run --rm -it -v /path/to/fpga/project:/fpga fpga_dev /bin/bash

The -v part is used to mount a directory from the host system /path/to/fpga/project to /fpga inside the container. This will allow the Verilog project to be built in the container leaving the resulting binary on the host system. Also all files can be edited on the host rather than inside the container.

Inside the container some environment variables should be set:

export PATH=$PATH:/root/source/yosys/build:/root/source/nextpnr/build:/root/source/icestorm/icepack

Building For Tang Nano

A sample Makefile for a blink program for the Tang Nano could look like this:

PROGRAM=blink default: yosys -q \ -p "synth_gowin -top $(PROGRAM) -json $(PROGRAM).json -family gw2a" \ src/$(PROGRAM).v nextpnr-himbaechel -r \ --json $(PROGRAM).json \ --write $(PROGRAM)_pnr.json \ --freq 27 \ --vopt family=GW2A-18C \ --vopt cst=tangnano20k.cst \ --device GW2AR-LV18QN88C8/I7 gowin_pack -d GW2A-18C -o $(PROGRAM).fs $(PROGRAM)_pnr.json

To flash the board with the blink.fs file, build openFPGALoader on the host and do:

sudo build/openFPGALoader --scan-usb sudo build/openFPGALoader --ftdi-serial 2023030621 ~/source/fpga/gowin_blink/blink.fs

Replace 2023030621 with the serial number for the specific Tang Nano board.

Building For Tang Primer 20k

To build a project with the Tang Primer 20k FPGA board, the following can be done:

yosys -q -p "synth_gowin \ -top $(PROGRAM) \ -json $(PROGRAM).json \ -family gw2a" \ $(SOURCE) nextpnr-himbaechel -r \ --json $(PROGRAM).json \ --write $(PROGRAM)_pnr.json \ --freq 27 \ --vopt family=GW2A-18C \ --vopt cst=tangnano20k.cst \ --device GW2A-LV18PG256C8/I7 gowin_pack -d GW2A-LV18PG256C8/I7 -o $(PROGRAM).fs $(PROGRAM)_pnr.json

Building For ice40

An example of building for an iCE40-HX8K:

default: yosys -q -p "synth_ice40 \ -top $(PROGRAM) \ -json $(PROGRAM).json" \ $(SOURCE) \ src/mips.v nextpnr-ice40 -r \ --hx8k \ --json $(PROGRAM).json \ --package cb132 \ --asc $(PROGRAM).asc \ --opt-timing \ --pcf icefun.pcf icepack $(PROGRAM).asc $(PROGRAM).bin

Copyright 1997-2026 - Michael Kohn