I am assuming that you already know about FPGAs if you are reading this. For those who have no clue what it is, imagine it to be a hardware equivalent of Lego that can be programmed.

FPGAs do not have a processor like machinery. They do not have any instruction set. Just a land of something called "Look Up Tables", "IO Blocks" and "Switching Box". FPGAs implement hardware. They implement Digital Circuits!

Let's talk about the tool chain flow and implementing the BLINKY circuit.

Some clarification before we move on. Blinky circuit in the hardware world is equivalent of "Hello, World!". The task here would be to blink an LED. Easy eh?

Step 1: Setup

1. Get an FPGA: In this article we'll be using the Lattice IceStick. One reason is that it is cheap and second, it has an Opensource tool chain. This means you shall have the freedom and power to see under the hood. That also makes it perfect for hacker pursuits ;-) .

2. Install the IceStorm flow: Wondering what it is? It's the Opensource tool chain mentioned in point 1. Folks in the open source community have taken the time and effort to reverse engineer the bit-stream format (more on this in a while) of lattice iCE40 FPGA series (Read more about the entire project IceStorm here).

To install the tool chain you have to be on a linux machine. I am on Ubuntu 17.04 as I write this article. Pull up a terminal and execute the following on the prompt:

sudo apt-get install build-essential clang bison flex libreadline-dev \
                     gawk tcl-dev libffi-dev git mercurial graphviz   \
                     xdot pkg-config python python3 libftdi-dev

This shall install all the required utilities for the components of the tool chain to work. Next execute the following lines, one at a time:

git clone https://github.com/cliffordwolf/icestorm.git icestorm
cd icestorm
make -j$(nproc)
sudo make install

git clone https://github.com/cseed/arachne-pnr.git arachne-pnr
cd arachne-pnr
make -j$(nproc)
sudo make install

git clone https://github.com/cliffordwolf/yosys.git yosys
cd yosys
make -j$(nproc)
sudo make install

Done? Now the final bit. Linux on it's own doesn't allow the user to access the hardware directly. You need something called "super user" permissions. In order that you can program the FPGA without having to switch to the super user mode. Execute the following the terminal window:

sudo nano /etc/udev/rules.d/53-lattice-ftdi.rules

Copy (use Ctrl + c) and Paste (use Ctrl + Shift + v ) the following line on the screen (btw if you did not get it already, you are editing a file "53-lattice-ftdi.rules" to tell the system to grant you the access to the hardware and to be able to program it without being in the super user mode).

ACTION=="add", ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", MODE:="666"

Once done hit Ctrl + o (to save the changes to the file) followed by the Enter key. Then hit Ctrl + x to exit the editor (in the world of nano, Ctrl + o is used to save file and Ctrl + x is used to exit the editor).

If nothing went bad thus far, then you are good to go. Congrats!

Step 2: Design flow

FPGA development is very straightforward. You describe the hardware you want to make in something called Hardware Description Language (in our case we shall use verilog, it's just another languages used to describe hardware, search more about it if you don't already know) in a normal text file (ending in extension .v) and you describe which physical pin of the FPGA is to be associated with the variables used in the code ( you want the code to set and clear some variable, which shall be mapped on the pin the LED is connected to) in yet another text file with extension .pcf, this is called the constraints file.

We feed .v file into the yosys which shall do verilog synthesis for us to produce .blif file. Then we feed .blif and .pcf files to arachne-pnr to produce a .asc file. Arachne-pnr is the place and route tool. It shall layout the structure of how the various blocks within FPGA shall be connected to realise the circuit. The .asc file is the ASCII output of the placement and routing plan. It holds information about which Logic Blocks connect to one another and which Switching Box is used.

Up next, we put the .asc file into icepack which then produces the .bin file which we use to program the FPGA. The .bin has what I referred to earlier as the "bit stream". As the name goes, it just a sequence of bits. When we program an FPGA we send this sequence of bits to the FPGA, the programmer with the FPGA accepts incoming bits and programs the SRAM (don't bother if you don't know what that means :) ).

Finally, we shall hook the FPGA stick into the USB and feed the .bin file into iceprog utility which would program the FPGA (image below shows the block diagram view).

Development flow

Step 3: Describe your hardware. The Blinky circuit.

We shall make two files. These are normal text files and you can use any editor of your choice to do this. One file shall have the .v extension and another one shall have .pcf. file. So in our case these files will be as: led_glow.v and led_glow.pcf.

Put the following in led_glow.v:

module led_glow(clock, led);
    input  clock;
    output led;

    reg [23:0] counter;
	
    always @(posedge clock) begin
        counter <= counter + 1;
    end

    wire [3:0] pwm_input = counter[23]?counter[22:19]:~counter[22:19];
	
    reg [4:0] out;
    always @ (posedge clock) begin
        out <= out[3:0] + pwm_input; 
    end

    assign led = out[4];
endmodule

Don't bother if the code seems daunting. Go ahead and paste the following in the led_glow.pcf file:

set_io led   95
set_io clock 21

If not obvious already then the output variable in the code is led and it is connected to pin 95 of the FPGA (The FPGA has physical pins that are soldered on the board, it's the 95th pin that we are interested in), which by the board's specifications is hooked to the on board Green LED. And the variable clock is connected to the on board oscillator based clock. The clock arrives from pin 21. I'll avoid explaining what the verilog code above does in full detail. At a higher level what we are trying to do is take clock pulse as the input, run a counter base on it and turn on and off the led. Making sense?

Step 4: Build the Binary and Program the FPGA

Open up a terminal and navigate to location where you have the files created above. And then execute the following to build the .bin file:

yosys -q -p "synth_ice40 -blif led_glow.blif" led_glow.v

arachne-pnr -p led_glow.pcf led_glow.blif -o led_glow.asc

icepack led_glow led_glow.bin

And finally, once the .bin file is generated execute the following:

iceprog led_glow.bin
console output post compilation

On executing the command you should see output on the screen as above.

On the board you should now see the Green LED on the board Blinking softly! Much like in the image below.

blinking LEDs on the board

Congrats, you just programmed an FPGA from ground up. Now, explore more about verilog and build digital circuits that you feel like. You could code a CPU in verilog and run it :)