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.
- Installed iCEcube2 software
- Installed Programmer Standalone
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!
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:
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 Programmer Standalone tool. You should be greeted with this 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 Programmer Standalone 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.
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.
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 Programmer settings so that you only need to go through this once!
For the next project, we will learn about a fundamental FPGA component: Look-Up Tables
Hey there! I just received a Go board and have started watching the tutorials. I have an issue. I tried the first 2 projects – switches to LEDs and the LUT. They don’t work after downloading the bitstream files. I’ve followed the tutorials, went back through to make sure I didn’t miss anything. The Verilog files synthesize properly; the P&R works and the bitstream is generated. I program them and the programmer says success. I see download activity on the Go board, so I know that the Go board is receiving the file and yet when I try it out, the Go board doesn’t work. On the Switches to LEDs, when the switch is pressed, the LED doesn’t light up. On the second project, when the SW1 and SW2 are simultaneously pressed, LED 1 doesn’t light up. The other 3 LEDs are on so I know that the bit file was downloaded correctly. Is there anything I might have missed? I went back over my steps, but I couldn’t find step I messed up with. Any help would be appreciated! I’ve enjoyed going over the tutorials and I’m anxious to get these projects to work! Again, thanks for a great product. Jim
Hi Jim. I’m guessing that you forgot to include the constraints file. This maps the signals from your design to the physical pin on the FPGA. If you don’t include that, then the tools will guess (incorrectly) which pins to assign.
hello , i have a problem with diamond programmer device setting , i don’t see in the drop down list the spi-m25p10-a, any idea ?
In Device Properties:
Family: SPI Serial Flash
Vendor: Micron
Device: M25P10
Package 8-pin SOIC
Hi , i have solved my problem, i have downgraded from version 3.13 to 3.9 of diamond programmer and it works fine.
Salut Luigino, peux tu envoyer le lien pour cette cersion 3.9 ?
Is there a I2C or SERDES project for the GO board?
Hi! Russell,
After watching the video, I did not find the link to download the virtual comm port drivers. I only got the constraints file link there, Thanks for that. I tried on the Google to load the virtual comm port drivers, but the link was not free.
Please provide me the link to load the virtual comm port drivers.
At this point they come standard with Windows. You don’t need to install them.
I was able to download the free TeraTerm virtual com port drivers at this link:
github.com/TeraTermProject/TeraTerm/releases
When you go to the URL, scroll down and look under “Assets” for Tera Term 5.2. This is the latest version.
Click on “teraterm-5.2.exe” to download the software to your computer.
Once you have downloaded the software to your computer, look in your Downloads folder and double click on the file “teraterm-5.2.exe”
This will launch the Setup program to install the Tera Term on your computer.
I just wanted to correct my error in my earlier comment. Tera Term is the terminal emulator.
For the Vitual COM port drivers, go to the FTDI website and download the VCP drivers from:
https://ftdichip.com/drivers/vcp-drivers/
I see that iCEcube2 software is used to generate the binary file. But then a separate piece of software called Diamond seems to be needed to actually load the binary file onto the Go Board. What would you call the Diamond software? Do all FPGAs require 2 separate software tools (1 to generate the bitstream and a 2nd to actually get the binary file onto the board)?
This is common for all FPGA/SoCs, The IDE and Synthesis Tool and then the programmer. In production there isn’t a need for synthesizing the code, just uploading the bitstream to the device and this typically is a much simpler task and the program takes less space and resources. Installing the entire development environment just to upload the bitstream is overkill for the task
Hi Russell
I started your tutorials a while ago, everything was going fine – have had a break due to my job and now I’m back, but I find that my icecube2 license has expired. How do I go about renewing it please?
See here: https://www.latticesemi.com/iCEcube2#_12092ABF818047B59CC430396492212C
Hi
I did not found the virtual comm port drivers link in the notes, as you mentioned in video. Can you please send here in the reply of this comment?
Russell, I got the link from the previous comments. Loaded and run it successfully, but why my port in device manager is coming with warning exclamatory sign?
If it’s running successfully then you should be good!
If there’s a question mark, maybe the drivers aren’t able to found? Try grabbing the VCP drivers here:
https://www.ftdichip.com/old2020/Drivers/CDM/CDM21228_Setup.zip
Hi when I try to add the constraints file, pcf is not included in the file types, so when I add it it doesn’t go in the constraints.
Make sure you’re adding the .pcf to the Place and Route constraints and not the Synthesis constraints. The Synthesis constraints are looking for a .sdc file which is why you might be having trouble.