This article is part of a series documenting my first foray into FPGA programming. You might find it helpful to read the summary article1 first.

Project IceStorm

Whilst it is true that Lattice provide their own tools2 for programming their FPGAs, they don’t run natively on the Mac. I suspect they’re also rather large, complicated, GUI beasts. Instead, I’ve been using Project IceStorm3, a third-party, open-source toolchain.

The Toolchain

The core toolchain comes in three parts:

Whilst IceStorm and Arachne-pnr seem to be rather focussed tools, Yosys is called a suite for good reason. I think you could use it for many other tasks where logic needs to be manipulated.

Installation walkthrough

Note: These relate to installing the tools on MacOS in early 2018, using homebrew7.

All of these are quite easily installed from GitHub, though first we must install some build tools. Essentially we just follow the instructions on the IceStorm website8.

The shell snippets below all install under $ROOT_DIR, so you should either define that or edit the scripts appropriately.

Dependencies

The set below could easily be incomplete. Please let me know if you find any omissions.

$ brew install python3 libffi libftdi0 readline
    pkg-config bison flex git mercurial

IceStorm

$ cd $ROOT_DIR
$ git clone https://github.com/cliffordwolf/icestorm.git icestorm
$ cd icestorm
$ make
$ make install

Arachne-PNR

$ cd $ROOT_DIR
$ git clone https://github.com/cseed/arachne-pnr.git arachne-pnr
$ cd arachne-pnr
$ make
$ make install

Arachne-PNR has an implicit dependency on chip databases included with IceStorm, so if you modify those you should reinstall Arachne-PNR.

Yosys

$ cd $ROOT_DIR
$ git clone https://github.com/cliffordwolf/yosys.git yosys
$ cd yosys
$ make
$ make install

Homebrew actually includes a formula for yosys9 which can be installed directly:

$ brew install yosys

I built the stock version from GitHub for consistency with the rest of the toolchain. The formulaic version10 makes a couple of tweaks:

A Makefile

It obviously makes sense to control the build with a Makefile. For simple projects, like the blinky demonstrations, I’ve used this general file:

TARGET_STEM = blink

PINS_FILE = pins.pcf

YOSYS_LOG  = synth.log
YOSYS_ARGS = -v3 -l $(YOSYS_LOG)

VERILOG_SRCS = $(wildcard *.v)

BIN_FILE  = $(TARGET_STEM).bin
ASC_FILE  = $(TARGET_STEM).asc
BLIF_FILE = $(TARGET_STEM).blif

all:    $(BIN_FILE)

$(BIN_FILE):    $(ASC_FILE)
    icepack    $< $@

$(ASC_FILE):    $(BLIF_FILE) $(PINS_FILE)
    arachne-pnr -d $(ARACHNE_DEVICE) -P $(PACKAGE) -o $(ASC_FILE) -p $(PINS_FILE) $<

$(BLIF_FILE):    $(VERILOG_SRCS)
    yosys $(YOSYS_ARGS) -p "synth_ice40 -blif $(BLIF_FILE)" $(VERILOG_SRCS)

prog:    $(BIN_FILE)
    $(PROG_BIN) $<

timings:$(ASC_FILE)
    icetime -tmd $(ICETIME_DEVICE) $<

clean:
    rm -f $(BIN_FILE) $(ASC_FILE) $(BLIF_FILE) $(YOSYS_LOG)

.PHONY:    all clean prog timings

Each project needs only to define the FPGA chip and programming command, then include the standard file above:

ARACHNE_DEVICE = 1k
PACKAGE      = tq144

ICETIME_DEVICE   = hx1k

PROG_BIN     = iceprog

include ../std.mk

Note that arachne-pnr and icetime both need the device type, but sadly in an inconsistent way.

Then you can build the code:

$ make

or flash it:

$ make prog

or generate a timing profile:

$ make timings

Regrettably, there’s no test infrastructure in the Makefile: a serious omission for all but the most trivial project.

Other tools

You should regard the following as things which people have claimed to be useful, but I’ve little or no direct experience of them.

Icarus Verilog

This can be handy for simulations. Waveforms can be viewed with GtkWave. Both are in homebrew:

$ brew install icarus-verilog
$ brew cask install gtkwave

Verilator

Verilator11 is another Verilog simulator.

ice40_viewer

This displays a configuration graphically in the browser. You can grab the code from GitHub12, or just run it online13.