Josh Headapohl

IceStorm Notes

A note from 2021: I originally wrote a draft of this post five years ago and forgot to publish it... until now! Further references to the present tense refer to December 2016.

Project IceStorm provides all the open-source software you need to run code on a handful of FPGAs. Unlike the official Lattice programming tools, it can run on my Mac (or a Raspberry Pi!) I have a project in mind, so I picked up an iCE40-HX8K Breakout Board and started learning how to use it.

Here are a few things that, had I known them, would have let me move a little faster.

Makefile and LED blinking

The IceStorm source code is accompanied by some examples that show how to compile some basic code for the iCEstick dev board and ice40-HX8K Breakout Board.

.pcf pin names

I have never used Verilog before. Part of setting up a project is a .pcf file that defines pin names. I was confused at first about where to find the pin names for the breakout board. Many of the pins for the IOs are printed on the board, but the LEDs are not labeled with the IO pins they are connected to.

The iCE40HX-8K Breakout Board User Guide has a schematic near the end, which shows which LEDs are connected to which IO pins. By comparing the schematic and the .pcf file in the hx8kboard example, I was able to get an idea of what I needed.

iceprog needs -S option to program SRAM

The iCE40HX-8K Breakout Board board has jumpers to decide whether you are programming flash or SRAM. The SRAM is faster to program and has to be reloaded every time you power the board on. The flash stays programmed when you power the board off and on again. To program the SRAM, iceprog needs the -S option! If the jumpers on the board are set for SRAM programming and you forget the -S option, iceprog will just hang forever.

$ iceprog example.bin
init..
cdone: low
reset..
cdone: low
flash ID: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
file size: 135100
erase 64kB sector at 0x000000..

It never finished. This worked much better:

$ iceprog -S switch.bin
init..
cdone: low
reset..
cdone: low
programming..
cdone: high
Bye.

Internal Pull-up Resistors

The iCE40 boards have interal pull-up resistors, but I had some trouble finding documentation and examples of how to use them. There is detailed documentation in the LATTICE ICE Technology Library. There is an example in "Synthesizing Verilog for Lattice ICE40 FPGAs (Paul Martin)" on YouTube, linked from the IceStorm home page, starting at 17m16s. Here's a little bit longer example.

This design lights an LED while a momentary switch is pressed. It will need an external pull-up resistor to keep the switch_pin input high, and a switch that will connect the pin to ground when pressed.

module switch (
  input  switch_pin,
  output led
);

  assign led = !switch_pin;

endmodule

This version uses an internal pull-up:

module led_switch (
  input  switch,
  output led
);

  wire switch_with_pullup;
  
  SB_IO #(
    .PIN_TYPE(6'b0000_01),      // no output, simple input pin
    .PULLUP(1'b1)               // enable pullup
  ) switch_sb_io_instance (
    .PACKAGE_PIN(switch),
    .D_IN_0(switch_with_pullup)
  );

  assign led = !switch_with_pullup;

endmodule