Opensource FPGA: First Steps with the IceStorm Toolchain

Opensource FPGA: First Steps with the IceStorm Toolchain

This blog post gets you started with Project IceStorm, a fully open source Verilog-to-Bitstream flow for iCE40 FPGAs. First we will cover installation of the toolchain on Linux and Mac OS X. Then a simple blinky program is synthesized, routed and programmed on a Lattice iCEStick. At the end some further resources are collected.

Work in progress!

Overview

FPGA stands for "Field Programmable Gate Array", it is essentially a huge array of logic gates which can be arbitrarily connected to make a circuit of your choice.


![flow](/content/images/2017/04/fpga-programming-flow-2-1.svg)

Installation

Four tools need to be installed:

  1. yosys: Verilog RTL synthesis
  2. Icarus Verilog: Verilog simulation and synthesis tool
    • iverilog: The compiler
    • vvp: Simulation runtime engine
  3. arachne-pnr: Place and route tool for FPGAs
  4. icestorm: Tools for generating and manipulating iCE40 bitstreams
    • icebox
    • icebram
    • icecompr
    • icefuzz
    • icemulti
    • icepack
    • icepll
    • iceprog
    • icetime
    • chip databases

If you want to compile and install all four yourself and install in the default /usr/local location, then you can use Dimitri del Marmol's excellent icetools set of scripts. Just run icestorm.sh and you're set.

If you also want to visualize simulated waveforms you have to install a fifth tool GTKWave.

Linux

You can also install the tools

apt-get install verilog
apt-get install icestorm
apt-get install fpga-icestorm

Optional:

apt-get install gtkwave

Mac OS X

If you use Mac homebrew it is not a good idea to install into /usr/local. You can use the following steps to install all four:

Prerequisites

brew install bison gawk pkg-config git mercurial graphviz python python3 libftdi0 libffi

Yosys and Icarus-Verilog

Fortunately yosys and iverilog are already packaged in homebrew:

brew install yosys icarus-verilog

Unfortunately, arachne-pnr and icestorm are not available on homebrew, yet, so we have to build them ourselves.

Icestorm

git clone https://github.com/cliffordwolf/icestorm.git
cd icestorm
PYTHONPATH=`brew --prefix`/lib/python$PYTHONVERSION/site-packages/ make -j

I don't want to install the tools in /usr/local because that's owned by homebrew. Instead I'd like to use $HOME/.local:

# dry run. Remove the -n to actually install
make -n install DESTDIR=$HOME/.local PREFIX=

Arachne-pnr

Arachne-pnr consists of the executable and three chip databases that contain the details of the topologies. Again, I choose to install into .local instead of the default /usr/local:

git clone https://github.com/cseed/arachne-pnr.git 
cd arachne-pnr
make -n PREFIX=$HOME/.local 
make -n PREFIX=$HOME/.local install

libftdi0

The iceprog programmer is responsible for burning the bitstream onto the device. iceprog uses the libgtdi0 library which cannot be used while the official FTDI USB serial driver is installed. To check whether FTDI's driver is installed run

kextstat | grep FTDIUSBSerialDriver

Then, if necessary, uninstall the FTDI driver.

sudo kextunload -b com.FTDI.driver.FTDIUSBSerialDriver

The driver can be re-installed with the opposite command:

sudo kextload -b com.FTDI.driver.FTDIUSBSerialDriver

Optional: GTKWave

brew install caskroom/cask/gtkwave

Blinky

Blinky is the "Hello World" for FPGAs. The goal is to get the green LED of the iCEStick board to blink continuously.

Verilog

blinky.v

// blinky.v
// Blink the green LED with frequency 12e6/2^24 = 0.7Hz approx.
module top (clk_in, led_green_out, led_red_out);
    input clk_in;
    output led_green_out;


    reg [23:0] counter;
    assign led_green_out = counter[23];
    assign led_red[3:0] = 4'b0;

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

endmodule

Pin assignment blinky.pcf:

set_io clk_in 21
set_io led_green_out 95
set_io led_red[0] 96
set_io led_red[1] 97
set_io led_red[2] 98
set_io led_red[3] 99
yosys -p "synth_ice40 -top top -blif build/blinky.blif" blinky.v
arachne-pnr -d 1k -P tq144 -o build/blinky.asc -p blinky.pcf build/blinky.blif
icepack build/blinky.asc build/blinky.bin
iceprog build/blinky.bin

Here's a Makefile for this workflow:

all: build/blinky.bin

build/blinky.bin: build/blinky.asc
	icepack $< $@

build/blinky.asc: blinky.pcf build/blinky.blif
	arachne-pnr -d 1k -P tq144 -o $@ -p $^

build/blinky.blif: blinky.v
	yosys -p "synth_ice40 -top top -blif $@" $^

prog: build/blinky.bin
	iceprog build/blinky.bin

clean:
	rm build/*

.PHONY: prog clean

The default target is build/blinky.bin. To write this to flash invoke the prog target. Finally, clean the build directory with the clean target.

Simulation

Time->Zoom->Zoom Full

GTKWave User's Guide

Resources

Other Build scripts

PlatformIO

"PlatformIO is an open source ecosystem for IoT development"

Platform.io support a few iCE40 boards.

Verilog