Go Board – Your First Project

Make an LED blink when you press a Button

At this point – my patient reader – you have got the Go Board, you installed all of the necessary programs, let’s just quickly review what you should have complete at this point. I also created a YouTube video for this project, should you prefer to follow along with that.

  1. Installed iCEcube2 software
  2. Installed Programmer tool
  3. Installed Go Board Drivers

Now it’s time to get cracking! The first project that we are going to do is going to be as simple as possible. All we are going to do is program the FPGA to perform one task: When a button is pushed, one of the LEDs should light up. This is a perfect project to do first, because it will take us through the entire build flow. From coding the VHDL or Verilog, to building the FPGA bitstream, to programming the Go Board, this tutorial will walk you through everything you need to know. Note that this project is 90% the same should you be learning VHDL or Verilog, so I lumped both into the same lesson. The Go Board tutorials build on eachother, so it’s important to do them in order and remember what you learned! Let’s get started!

Go Board First Project Image

The first thing you are going to do is create your VHDL or Verilog code that tells the FPGA what to do. Again, we are going to be creating code that tells the FPGA to light up one of the four LEDs when a particular switch is pushed. The image to the right shows what this looks like. When Switch 1 (SW1) is pushed down on the Go Board, we want D1 to light up. When the button SW1 is released, D1 should turn off. This is a simple FPGA design, but going through the code and the build process will get you comfortable with everything before we get to more complicated designs.

Project Design

No matter which language you decide to use, you should give the project some thought before you begin. As shown in the image above, you have eight signals to deal with. Four of the signals are inputs and four others are outputs. The inputs are your switches, the outputs are your LEDs. How can you design code such that when a button is pushed, an LED is illuminated? Give it some thought, try to write the code on your own. The answers for both Verilog and VHDL are shown below.


Verilog Code – Switches_To_LEDs.v:

module Switches_To_LEDs
  (input i_Switch_1,  
   input i_Switch_2,
   input i_Switch_3,
   input i_Switch_4,
   output o_LED_1,
   output o_LED_2,
   output o_LED_3,
   output o_LED_4);
      
assign o_LED_1 = i_Switch_1;
assign o_LED_2 = i_Switch_2;
assign o_LED_3 = i_Switch_3;
assign o_LED_4 = i_Switch_4;

endmodule

Let’s talk about the Verilog code above. The first keyword you encounter is module. Modules are the blocks of code that perform some functionality. Modules can contain all of the code you need, such as the code above, or they can instantiate other modules. More complicated designs will create levels of hierarchy by having many modules. On the module, you must define the interfaces, which consist of inputs and outputs. In this case, we are creating four inputs and four outputs. You can think of these inputs and outputs of being either a 0 or 1 in binary. The inputs and outputs are going to be connected to specific pins on the Go Board. This connection is done later (and is not part of the Verilog code).

The last keyword introduced in this first project is assign. Assign is used to connect two signals together. There are some rules about this keyword, but for now I’ll just tell you that it must be used outside an always block. Always blocks are for the a later project, so don’t worry about them for now. Once all of the output signals are assigned to the input signals, we have successfully connected all LED outputs to the Switch inputs. Now when i_Switch_1 goes high (to a binary 1) o_LED_1 will also go high. Conversely when i_Switch_1 goes low (to binary 0) o_LED_1 will also go low. You are literally tying the two of them together in your FPGA. There will actually be a physical connection inside the FPGA between these two pins. Neat huh?! You need to remember that the code you are writing is designing a physical circuit inside the FPGA. This particular circuit is pretty simple, but it’s still a circuit!


VHDL Code – Switches_To_LEDs.vhd:

library ieee;
use ieee.std_logic_1164.all;

entity Switches_To_LEDs is
  port (
    -- Push-Button Switches:
    i_Switch_1 : in std_logic;
    i_Switch_2 : in std_logic;
    i_Switch_3 : in std_logic;
    i_Switch_4 : in std_logic;
	
    -- LED Pins:
    o_LED_1 : out std_logic;
    o_LED_2 : out std_logic;
    o_LED_3 : out std_logic;
    o_LED_4 : out std_logic
    );
end entity Switches_To_LEDs;

architecture RTL of Switches_To_LEDs is
begin
  o_LED_1 <= i_Switch_1;
  o_LED_2 <= i_Switch_2;
  o_LED_3 <= i_Switch_3;	
  o_LED_4 <= i_Switch_4;
  
end RTL;

Let’s talk about the VHDL code above. Perhaps the first thing you might notice if you compare the Verilog code to the VHDL code is that the VHDL code is a bit longer. This is a common theme. VHDL generally takes more typing to accomplish the same task. The first two lines of this code tell the tools about which libraries and packages you are using in your code. Take it for granted that these two lines will likely be in every single piece of VHDL you ever write. For now, don’t worry about what they’re actually doing, just put them there.

The next keyword you encounter is entity. The entity of a design can be thought of as the interface to the outside world. Entity and architecture are the two VHDL keywords that define the functionality of some block of code. Together, an entity and architecture make up some piece of functionality in your FPGA design. A single entity/architecture combination can contain all of the code you need, such as the code above, or they can instantiate other entities. More complicated designs will create levels of hierarchy by having many entity/architectures.

Next, you need to specify any signals that are on this interface after using the port keyword. Once you give the signals a name (e.g. i_Switch_1), you need to specify the direction: in, out, or inout (used rarely). After that, give your signals a type. std_logic is the most prevalent type in VHDL and can be thought of as a bit containing 0 or 1 (though it can actually have more values than just that as we will see later). These inputs and outputs are going to be connected to specific pins on the Go Board. This connection is done later (and is not part of the VHDL code).

After the architecture, you need to use the <= assignment symbol. An assignment is used to connect two signals together. Note that if you try to just use a normal assignment like = as used in C, you’ll get a tool error. Once all of the output signals are assigned to the input signals, we have successfully connected all LED outputs to the Switch inputs. Now when i_Switch_1 goes high (to a binary 1) o_LED_1 will also go high. Conversely when i_Switch_1 goes low (to binary 0) o_LED_1 will also go low. You are literally tying the two of them together in your FPGA. There will actually be a physical connection inside the FPGA between these two pins. Neat huh?! You need to remember that the code you are writing is designing a physical circuit inside the FPGA. This particular circuit is pretty simple, but it’s still a circuit!


Building your FPGA design

Once you have the coding done, it’s time to build the design! Open iCEcube. Click File then New Project. You will be greeted with an intimidating window asking for a bunch of specific information about your FPGA board. I’ll be nice and tell you how to set those values:

Picture of Project settings required for Nandland Go Board

Go Board Project Settings

Picture of how to add files to your project

These are the settings that you will be using for every single Go Board project, so keep that in mind. Click Next when you’re done here. This next dialog box prompts you to add the Verilog or VHDL source file that you created previously. You can do that now. Or alternatively you can skip this step by clicking Finish. Instead you can expand Synthesis Tool and right click on Design Files to add your file to your project. The Verilog or VHDL that you add is used for Synthesis.

What is Synthesis?

It’s probably worth taking a minute to discuss the first phase of your FPGA build process. The iCEcube2 tool takes the code that you wrote and goes through a process called synthesis. Synthesis converts the VHDL or Verilog code into physical elements that are available on your particular FPGA. An FPGA has dedicated pieces of logic on it. It has wires, it has Look-Up Tables, it has Registers, and it has some Memory. It can have other things, but these are by far the most targeted elements during synthesis. It’s OK if you aren’t comfortable with each of these right now, we’ll talk about them each individually. Since this design is very simple, it will use very little of your FPGA resources in the synthesis process, just a few wires to route signals. After the design is done with Synthesis, it goes to Place and Route (P&R).

What is Place and Route?

Place and Route is the second phase of the FPGA build process. Synthesis converts the code to physical components available to your FPGA. Place and Route takes those components and places them on your FPGA. You can think of an FPGA as a large grid of these components. Place and Route will assign which component gets used where. It is a particularly important step of the FPGA build process for designs that use clocks. This particular design does not require the use of a clock, so Place and Route is not as important. We will see in future projects how clocks play a pivitol role in FPGAs, and you’ll understand more about Place and Route then.

One very important thing that Place and Route does is it assigns the signals at the top level of your FPGA design to physical pins on the device. You need to tell the tools how to map each signal in your design to a physical pin on the device! This is a very important step and if you do not tell Place and Route how to assign the pins, it will just choose them on its own and it will be wrong. Does i_Switch_1 go on Pin 1 or Pin 100? This gets set in a Constraints File. Again, I’ll be nice and give you the constraints file needed for the Go Board. This provides the mapping for all of your pins on the projects that we will encounter. You’ll notice in the constraint file that there’s more signals than we created in the code above. That’s OK, we’ll use those extra signals eventually.

Ding Ding Ding! Come and get your Constraint File!

Here’s a link to the Go_Board_Constraints.pcf. Save this file in your project directory and add it to your project in iCEcube. This is done under P&R Flow then expand Add P&R Files then add it under Constraint Files.

Building the FPGA Bitstream File

We’re geting close, I promise. Everything is set. You created your project. The code has been added to your project. The constraints have been added. Now it’s time to build the bitstream! This is the file that is used by your FPGA to program itself. Click Tool then Run All. This should go through the entire build process, from Synthesis, through Place & Route, to Generating your bitstream file. (Just a note here, you’ll see Bitmap in iCEcube2, Bitmap is the program that creates the bitstream). You should see some nice green check marks appear. Take a minute to look at the Output from the build process, the tools give you some neat information about what’s happening behind the scenes.

Programming the FPGA

Open the Diamond Programmer tool. You should be greeted with this screen. If you do not see that the Cable has been detected successfully, you may need to install the FTDI Drivers.

Picture of Diamond Programmer first screen

Diamond Programmer First Screen

Now the way the Go Board works is that there is an integrated circuit that turns the USB connection to a SPI interface, which is used to program a Flash chip that’s installed on the Go Board. The purpose of using Diamond Programmer is to load this Flash over the USB. Once the flash has been loaded, the FPGA will boot up from the flash and you’ll see the fruits of your labor! Since you’re going to a SPI Interface, the Programmer will be unable to detect the FPGA. That’s OK, you will need to tell the Programmer about what FPGA you do have on the Go Board. Select Device Family and Device as shown in the figure below.

Picture of Diamond Programmer setup

Diamond Programmer First Screen

Now double click under Operation and next to Access Mode select SPI Flash Programming. That will bring up the picture as shown below. You will need to select your programming bitstream that you built. This is located in your iCEcube2 project directory /sbt/outputs/bitmap/. Make sure to select Family and Vendor as shown in the figure below.

Picture of Go Board SPI Flash Settings

Go Board SPI Flash Settings

Now click Design and select Program. If everything was done correctly, you should see Operation Successful. This means that your SPI Flash has been programmed and your FPGA is running! Try pushing a button! LEDs blink! Congratulations, you’ve built your first FPGA project! Once you set this up, you should save your Diamond Programmer settings so that you only need to go through this once!

Gif of results

Go Board Project 1 Completion!


For the next project, we will learn about a fundamental FPGA component: Look-Up Tables