FPGA Page
Introduction
FPGA stands for Field-programmable gate array. I wish I had wrote this up last time but hey on the way now.
First Project
My first project was from Digikey videos [[1]] which I struggle with in several ways. So lets write them down so I do not forget
Python
We us apio which is a python apt to make things easy. It loads the tools required to build a binary.
mkdir <project_name>
cd<project_name>
virtualenv venv
source venv/bin/activate
Install Apio
Install apio. He installed 0.6.3 but I mine worked on 0.9.5
pip apio
Before project A
Before creating the blink example we need to make sure we are configured for the correct board. For me this was the ice40up5k-b-evn which I believe it the marketing name. It was quite hard to track the chip down and therefore the pinout. I eventually found
- FPGAUG0200110.pdf which lists my board at the bottom once.
- iCE40UP5K-SG48 is the chip and listed under features
- iCE40UltraUltraPlusSG48PinMigration.xlsx is the pinout really poorly named
Before project B
We need to install gtkwave with
sudo apt install gtkwave
Fix up the tcl install as mine moaned about not have specific version. It first created a link for the /usr/local/lib with
sudo ln -s /usr/share/tcltk/tcl8.6 /usr/local/lib/
Then changed the init.tcl
#package require -exact Tcl 8.6.14
package require -exact Tcl 8.6.12
Create project
So we create a project using the examples provide with this command
apio examples -d icestick/leds
My default this creates a files called
- apio.ini
- led.pcf
The apio.ini contains the board and top module to use. For the board we need to fix this and we do so with
# To list the boards
apio boards --list
# And for us we use
apio init --board iCE40-UP5K
This then produces the following apio.ini file
[env]
board = iCE40-UP5K
top-module = main
We need to replace the main with the name of the first module which is leds
[env]
board = iCE40-UP5K
top-module = leds
Now we need to modify the project constraints file. This is a file which on the left has the name of the pin used in the project and on the right has you pin number. Because we used a icestick example the pins will be different. Here is the corrected file for the iCE40UP5K-SG48 based off the xls spreadsheet
# -----------------------------------------------------------------------------
#- Leds example for the iCEstick board
#- Constraint file (.pcf)
# -----------------------------------------------------------------------------
# -- Pinout: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/images/icestick_pinout.png
# -- Guide: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/icestickusermanual.pdf
# ------------ User Leds ------------------------------------------------------
set_io D1 23
set_io D2 25
set_io D3 26
set_io D4 27
set_io D5 32
Now we are ready. No idea what some of these commands do and will not doubt file this in when I understand. Maybe just the sim I struggle with
# Parse the syntax
apio verify
# Simulate with gtkwave
apio sim
# Build
apio build
# Upload
apio upload
And here is a picture for fun.
First Edited Project
So this was my real first project as I copied the code but knew what it did. Made a pcf with the 5 leds and 4 buttons
# Leds
# ====
#set_io led_0 25
#set_io led_1 23
#set_io led_2 26
set_io led_3 27
#set_io led_4 32
# Buttons
# =======
set_io -pullup yes pmod_0 38
set_io -pullup yes pmod_1 36
set_io -pullup yes pmod_2 28
set_io -pullup yes pmod_3 42
And then wrote some logic
// Verilog module called and_gate
module main (
// Inputs
input pmod_0,
input pmod_1,
// Outpu
output led_3
);
assign led_3 = ~pmod_0 & ~pmod_1;
endmodule
Does not do a lot, the important bits were the pullup resistor for the buttons. For the logic it merely sets led_3 on when both buttons are pressed
Second Edited Project
So it probably will seem basic looking back but rock and rolling along. We are building this
- If button 0 is pressed LED 0 and LED 1 come on
- If button 0 and 1 are pressed all 3 leds come on
This shows us how to define out inputs/outputs in arrays and what a wire is. First the pcf file. Pretty simple, just like arrays
set_io led[0] 25
set_io led[1] 23
set_io led[2] 26
set_io led[3] 27
set_io led[4] 32
set_io -pullup yes pmod[0] 38
set_io -pullup yes pmod[1] 36
set_io -pullup yes pmod[2] 28
set_io -pullup yes pmod[3] 42
Now the module. Not as simple but added comments to help remember. Replicate seemed to be the thing to remember. To me the wire is just a named resource but I am sure there is more to come.
module main (
// Inputs
input [1:0] pmod,
// Outpu
output [2:0] led
);
// Named connection we are going to use
wire not_pmod_0;
// Continuous assignment
// Connect the pmod[0] to this named connection
assign not_pmod_0 = ~pmod[0];
// Replicate twice the value of not_pmod, starting a led[0]
assign led[1:0] = {2{not_pmod_0}};
// Now switch on the led[2] if not pmod_0 and not pmod[1]
assign led[2] = not_pmod_0 & ~pmod[1];
endmodule