[FPGAs] Introduction to the ICEStick40

FPGAs are arguably the best way to get into hardware reverse engineering for many reasons. The most obvious one according to me is the experience in what I've to term "raw clockiness" (or the practice of making a real hardware backed clock; do exactly what you want). There is a certain romanticism of  freshly broken set theory and deep repressed proof theory sins that comes to bare for me when I'm exposed to this kind of computing. All other kinds tend to veil this shaky, sometimes deeply COUNTER intuitive means of problem solving :)

Basically what I mean to say here is that if you can get over the hurdle with FPGAs (which is not a big deal at all if you know basic set theory) you've mastered many things that repeatedly form the base of the problems you'll need to solve in reverse engineering hardware questions like:

  • What is this thing doing with that oscillator? What on earth can it possibly be doing? There are only so many combinatoric things that can happen based on the context and components / traces handling a signal or input - the more experience you have with raw signal programming the better you get to know these limitations and nuances. They are the most important rules of the game a lot of the time. 
  • Which one of these input/output signals is the clock / data etc etc based on what components are doing with it in context? Like an argument to a function in assembly you are trying to type based on its place in other functions and contexts. 
  • How does this thing receive its programming or settings? from where? how often? FPGAs are often volitile, they don't "store" their programming for ever it is constantly reprogrammed for use, programming is usually done via a micro-controller or anything that can squawk some bit stream into the chip really. 
  • OMG is that an FPGA on the board? Sometimes things you are trying to identify can literally just straight up be FPGAs hehe

Anyway enough philosophical waxing (jokes everything is a kind of soft philosophy to me now); lets get into a quick example with the ICEStick. The reason I really really like this project is because its completely open source, you can get the ICEStick for super cheap on amazon and various other places; so its super easy to get started! All you need to do is download a couple things, write a make file and start pumping out bit streams that do the awesome things. In this post I'll cover all you need to do, to get that going.

Basic Workflow 

Here are the basic steps:

  1. Write some verilog modules (*.v files) -  obvious any text editor will do but vi(m) is always the best choice always. 
  2. Define a constraints file for your board (*.pcf files) - this tells the other tools where to find what component when place n routing when producing the bitstream. You only need to do this once depending on which components you're using on which board. 
  3. Synthesize them into a bitstream  (*.bin files) - for this we will use yosys
  4. Produce some place n' route files (*.txt files) - our place n route tool here will be arachne-pnr (pnr stands for "place n route"
  5. Program/flash the FPGA board with iceprog

Preparing the Environment

You need to grab a couple tools to get this all setup (most of the posts I link below mention other steps for various platforms) for this one I'm sticking to simple Ubuntu 18 LTS machine with nothing fancy installed except git. All you need to do is download a couple repositories and make + install them.
  1. install / make dependencies
  2. install / make  yosys, arachne-pnr, iceprog
  3. Test build
I've whipped up a simple script that does all this for you, available on gist:

All you need to do is run this and it should sort everything. Could take a couple minutes.
Once that's all done, make yourself a test folder and stick this convenient Makefile in their:

To use the make file you simply do the following:
  1. Replace the VER variable with the name of the Verilog module you'd like to synthesize.
  2. make (make everything).
  3. make prog (program the most recent bitstream).
Last thing you need to do, before writing some Verilog; is define a constraints file (*.pcf).  You might notice that the tools we use here are not specifically for a particular board, they support a range of them. In order to make sure (when you synthesize a bitstream) that you're targeting the right board - you need to state some configurations for IOPins, clocks and other goodies you'd like the FPGA to interact with on the board, here's what the ICEStick40's .pcf file looks like:

LED Blinker with ICEStick40

Once you've got everything up and running, you'll be able to whip up a simple LED Blinker like so:

Good thing here is that this works pretty much like any other LED blink counter, it just maps some reg's to the LEDs, and flips them on and off using a clock pre-scaler that reduces it to 1Hz (using a 21 bit reg array). If you're confused about these words its totally cool, I have some blog posts on the way that explain how they work in full. For now just make sure you can get your environment working, making sure you understand the code is a workable problem, but only if you can actually hit the FPGA with the right stuff.

If you compile this using my Makefile (or not), you should see something like the following output (luckily because yosys and the pnr tools are pretty verbose, you will be able to trace quite a bit of activity if things are going funky):

Last step is actually programming the FPGA with the bitstream we just generated, here's what the output is meant to look like:

>sudo make prog
iceprog example.bin 
cdone: high
cdone: low
flash ID: 0x20 0xBA 0x16 0x10 0x00 0x00 0x23 0x64 0x34 0x65 0x04 0x00 0x22 0x00 0x32 0x27 0x12 0x16 0xFE 0x6A
file size: 32220
erase 64kB sector at 0x000000..
cdone: high

That's it for this one folks.

References and Reading

  1. https://appcodelabs.com/getting-started-with-lattice-icestick-using-open-source-tools-on-macos-linux
  2. Various ICEStick posts from hackaday https://hackaday.com/tag/icestick/ 
  3. http://www.clifford.at/icestorm/