Abstract: This ’blog describes my first experiments using a ValentF(x) LOGI-Pi FPGA board. After a short overview of LOGI-Pi and its Xilinx Spartan-6 FPGA, we show how to download two examples. The first is a pre-tested LED demo from ValentF(x) and the second is created from Verilog source code using Xilinx tools.
Disclaimer: This ’blog is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. Incorrect board connections and/or an incorrect FPGA bitstream could cause damage to an FPGA and/or its connected circuitry, or cause a system to malfunction. Users must agree that the author has NO LIABILITY for any damages.
For a LOGI-Bone version of this ’blog, see First Experiments with the ValentF(x) LOGI-Bone.
The ValentF(x) LOGI-Pi is a new FPGA development board for the Raspberry Pi Models A, B, and B+. Its chief advantage over other FPGA boards is that RasPi GPIO pins connect directly to the FPGA so you have a flexible high-speed, low-latency connection. LOGI-Pi also has expansion sockets compatible with 3.3V Arduino UNO, DUE, and DUEM shields as well as four Digilent Pmod™ sockets. These connectors provide many options for add-on boards with all sorts of analog and digital capabilities. By going with standard connectors ValentF(x) doesn’t have to design and support those add-on boards themselves.
Here is the annotated layout of LOGI-Pi, from ValentF(x)’s LOGI-Pi User Guide, copied with permission:
In addition to the FPGA and expansion sockets LOGI-Pi has a 32 MB SDRAM, two LEDs, two push buttons, and two DIP switches, all of which are connected to FPGA pins for your use.
The heart of LOGI-Pi is a Xilinx Spartan-6 LX9 FPGA in a TQ144 package. This is a modern, high-performance FPGA which is currently the Xilinx price/performance “sweet spot”. Here are the main features of the LX9:
- Programmable array of logic cells with 5720 6-input Look-Up Tables (LUTs), 11,440 flip-flops, and carry-chain logic. Each 6-input LUT can be treated as two 5-input LUTs with shared inputs, and 1/4 of them can be used as high-speed 64-bit distributed RAM cells with various single- and multi-port configurations.
- 32 Block RAMs, each 18Kb for a total of 576 Kb (64KB with 9-bit bytes). Each Block RAM has two independing read/write ports which can have different data widths.
- 16 DSP slices, each with an 18x18 multiplier, adder, and accumulator.
- 2 clock managers with PLLs.
- 16 fast low-skew global clock distribution networks.
This same FPGA is used by a number of other FPGA development boards including Gadget Factory’s Papilio Pro and their upcoming Papilio DUO, Embedded Micro’s Mojo V3, XESS Xula2-LX9 (1.0mm pitch BGA), and Scarab Hardware’s upcoming miniSpartan6+ (also BGA). These boards have prices similar to LOGI-Pi but do not plug into RasPi headers.
Spartan-6 Configuration Options
Spartan-6 is an SRAM-based FPGA, which means that when you first turn on power the FPGA is unconfigured and remains so until you write a configuration bitstream into it. A bitstream is a 340KB file that defines the configuration of logic cells, routing, I/O pads, clocks, and block memory contents. Each of the 2.7 million bits in the file sets an SRAM bit in the FPGA -- some people describe an SRAM FPGA as an large SRAM with some logic attached to it.
There are several ways to write a bitstream to LOGI-Pi’s FPGA. By default, RasPi writes the bitstream by running logi_loader, which uses SPI to transfer the bitstream’s data bits and some GPIO pins for various FPGA control signals that don’t need to be fast. Xilinx calls this Slave Serial mode since an external master -- in this case RasPi -- is treating the FPGA as a slave device.
You can modify LOGI-Pi to configure itself from a serial Flash chip that’s included on the board. This is called Master Serial/SPI mode because the FPGA is in control of its own configuration. You would typically use this mode for a stand-alone LOGI-Pi application that only uses RasPi for development.
But wait! There’s more! You can also use JTAG to configure the FPGA if you solder a 6-pin header onto LOGI-Pi. JTAG can overwrite the bitstream configured by either of the other two modes. For JTAG you need an external JTAG module that typically plugs into a PC USB port. You can use the JTAG port to program LOGI-Pi if you don’t have a RasPi.
In this ’blog we will be using the default Slave Serial mode with RasPi writing the bitstream.
Installing and Powering LOGI-Pi
LOGI-Pi is designed to plug directly onto a RasPi Model A or B Expansion header P1, as shown in this photo from FPGA Development Board for the RASPBERRY PI.
The two boards are aligned except for a small LOGI-Pi overhang on the RasPi HDMI side.
LOGI-Pi is best suited to the RasPi Model A/B rev 2.0 PCB which has alignment holes in the same positions as LOGI-Pi mounting holes so you can screw the two boards together with nylon standoffs and screws (provided). LOGI-Pi also plugs into a RasPi 1.0 PCB just fine, but the 1.0 PCB doesn’t have alignment holes so you don’t get the standoffs’ mechanical security. LOGI-Pi has a rubber bumper to keep its pins from shorting into RasPi’s Ethernet jack, but they’re still pretty close and I recommend sticking electrical tape on RasPi’s Ethernet and USB connectors to make sure they don’t short to LOGI-Pi.
LOGI-Pi should also plug onto a RasPi Model B+ Expansion header J8, but the boards won’t be aligned as well and the RasPi B+ mounting holes aren’t compatible with LOGI-Pi.
The exact procedure for installing a LOGI-Pi is described in Logi-Pi - Out-Of-Box - Step by Step. When you plug LOGI-Pi into RasPi, do so with the power off and make sure the connectors are aligned correctly. If they aren’t, you could damage one or both boards. For the RasPi Model B+, I think the proper way to align it is to plug LOGI-Pi into pins 1-26 of B+ Expansion header J8, i.e., the end labeled “J8”. However, I’ve never tried it myself so I recommend checking that it’s correct before turning on power.
Once LOGI-Pi is installed, it can be difficult to view and probe RasPi, depending on what case you have. In particular, the RasPi Status LEDs are covered up unless you can peek in from the side. I use a home-made open-frame chassis with an opaque faceplate, so I can only see the glow of LEDs through a LOGI-Pi mounting hole. (I have a 1.0 PCB so I can’t use LOGI-Pi’s standoffs.)
Another consideration with RasPi is heat distribution. The RasPi BCM2835 SoC and LAN9512/14 USB/Ethernet chips both get warm with normal use, and if they don’t have some airflow they can get quite hot, especially with some Model B 1.0 PCBs. My vertical-mount chassis gets airflow across both sides of RasPi, which keeps the two chips from overheating. LOGI-Pi leaves quite a bit of space between the two boards, so you probably won’t have problems. My vertical-mount chassis works beautifully.
Alternatively, you can plug a 26-pin cable between RasPi and LOGI-Pi. This allows you to use many standard RasPi cases. I don’t know how long the cable can be before it causes signal integrity problems, especially with SPI.
By default, LOGI-Pi is powered from RasPi’s 5V rail, which usually comes from RasPi’s Micro USB power jack. For small to medium experiments, RasPi provides enough power for LOGI-Pi without causing 5V to drop to the point that it causes RasPi power issues as described in the RasPi Hardware Wiki. If you run into problems, power all your attached USB devices from an externally-powered USB hub so RasPi has more current available for LOGI-Pi. Replacing the Micro USB power cable may also help: see Raspberry PI:- USB power cables, crashing and other problems. If you don’t mind modifying your RasPi, you can replace its polyfuse with a single-blow fuse, which has lower resistance and therefore a lower voltage drop.
Your primary tool for diagnosing power problems is to measure the 5V level as described in the RasPi Troubleshooting Wiki. You may need to probe LOGI-Pi instead of TP1 and TP2 on RasPi. Be very careful probing the GPIO connector, because if you accidentally short 5V to 3.3V or to a signal you can kill your RasPi and/or LOGI-Pi.
Some RasPi Model B users back-power RasPi from an externally-powered USB hub. This may provide higher 5V than going through the Micro USB cable. I back-power my modified 1.0 Model B from a Motorola Atrix Lapdock which provides solid 5V power.
LOGI-Pi also has holes for optional headers if you want to provide it with its own power, e.g., for stand-alone applications. If RasPi is also powered, don’t power LOGI-Pi separately unless you know what you’re doing. In particular, make sure that if only one of the boards is powered this is not going to damage unpowered chips on the other. You could use one of these headers to provide power to both LOGI-Pi and RasPi. Be careful doing this, because it bypasses all of RasPi’s 5V protection circuits. Be sure to check both the RasPi and LOGI-Pi schematics first.
For this ’blog I’m powering LOGI-Pi from RasPi’s Expansion header as usual.
LOGI-Pi has linear regulators to convert 5V to 3.3V for FPGA I/O and from 3.3V to 1.2V for FPGA core logic. These regulators could get hot if the FPGA is doing a lot. Some newer FPGA boards like Papilio Pro and DUO have switching regulators for these voltages which can save a lot of power.
Preparing Raspbian GNU/Linux for LOGI-Pi
To develop FPGA designs using LOGI-Pi, you will need two computers: an x86 PC to run Xilinx FPGA software, and your RasPi with LOGI-Pi installed. The Xilinx software generates bitstreams, which you then transfer from the PC to your RasPi, and then you’ll run a program on RasPi to write bitstreams to LOGI-Pi. There are various ways to do this, but for this ’blog I’ll concentrate on what I do with my RasPi setup.
I have a 256MB RasPi Model B running 2014-09-09 Raspbian Wheezy, downloaded from raspberrypi.org. I use a Motorola Atrix Lapdock as my keyboard, mouse, and display. I can also use a GNU/Linux PC running Ubuntu 12.04 LTS to talk to RasPi over Ethernet using a Terminal window with ssh (secure shell). The Terminal window is convenient for LOGI-Pi development since I can use the PC’s display, keyboard, and mouse for everything once RasPi has booted. The Lapdock display is useful for seeing if RasPi is booting and shutting down properly.
To talk to RasPi from the PC, you need to know the user name and password of a RasPi user who has superuser privileges. I’m going to call this user george. You can also use the default user pi if you don’t want to create a separate user.
You also need to know RasPi’s IP address. It’s normally assigned automatically using DHCP by a router or the PC. My RasPi’s IP address is 192.168.0.106, which I found by giving the ifconfig command on RasPi using Lapdock. For various ways to connect to RasPi so you can get its IP address, see Logi-Pi Quick Start Guide,
Next, george needs a subdirectory for storing LOGI-Pi bitstreams. I’ll assume this subdirectory is called LOGI with full RasPi path /home/george/LOGI or ~george/LOGI.
Finally, you need to enable RasPi’s SPI (Serial Peripheral Interconnect) device drivers and obtain or build LOGI-Pi’s FPGA loader logi_loader. One way to do this is to load a pre-configured RasPi OS image from ValentF(x), as described in LOGI-Pi Quick Start Guide.
If you prefer to use an official RasPi release from raspberrypi.org, you will need to do a fairly simple procedure to enable SPI and build logi_loader. It’s described in another section of LOGI-Pi Quick Start Guide.
I found that with 2014-09-09 Raspbian Wheezy I could leave out a few steps. First, check whether the SPI device drivers are already present. You can tell by listing /dev on a RasPi terminal:
See if there are device drivers /dev/spidev0.0 and /dev/spidev0.1. If not, SPI is “blacklisted” and you will need to enable it by editing /etc/modprobe.d/raspi-blacklist.conf. First, change to the system directory /etc/modprobe.d and make a backup copy of raspi-blacklist.conf:
sudo cp -p raspi-blacklist.conf raspi-blacklist.orig
Next, edit raspi-blacklist.conf using nano or a different text editor. You’ll need to use sudo. The original file looks something like this:
# blacklist spi and i2c by default (many users don't need them)
Comment out the bcm2708 lines so that SPI and I²C will be enabled next time you reboot:
# blacklist spi and i2c by default (many users don't need them)
Then save the file (ctl-X on nano). Finally, reboot RasPi to apply the changed raspi-blacklist.conf:
After RasPi reboots, /dev/spidev0.0 and /dev/spidev0.1 should be present.
Next we need to build logi_loader. First see if it’s already in /usr/bin. Otherwise you need to rebuild it from source code at GitHub. 2014-09-09 Raspbian Wheezy already has gcc, make, and git so you don’t need to install them.
First, decide where you want to build logi-tools, e.g., in your LOGI directory created earlier. With the Internet attached to your RasPi via Ethernet, enter these commands on a RasPi terminal:
This downloads the source code and makefiles for all LOGI tools. Next, build logi_loader:
This compiles logi_loader from C source code. Finally, copy logi_loader to /usr/bin:
sudo make install
The executable file /usr/bin/logi_loader should now exist. You are now ready to write FPGA bitstreams to your LOGI-Pi.
Experiment 1: Writing a Pre-tested Bitstream to LOGI-Pi
Now let’s try writing a bitstream to LOGI-Pi. ValentF(x) has a nice blinking LED demo which they describe in the ValentF(x) Wiki. However, they don’t provide a LOGI-Pi bitstream file for it. You can build the bitstream using the instructions in LOGI-Pi Quick Start Guide but this is pretty complex for a first exercise. So I’ve compiled the example and put the bitstream file logipi_blink.bit in LOGIdemo.zip.
The procedure in this section uses GNU commands entered in two PC Terminal windows, one for the PC and one for RasPi. If you prefer GUIs and/or your PC is running Windows, ValentF(x) has other procedures with GUI equivalents for ssh and scp: SSH Guide, SCP Guide. You can also enter RasPi commands on your attached RasPi keyboard and display instead of using ssh.
Here are the commands I use on my RasPi setup. The commands should be similar on other setups. If you need help, please ask questions in the comments. As with most GNU/Linux commands, use man to get reference information. For example, the command “man ssh” describes how to use ssh.
To keep things clear, I will prefix commands entered on the PC with “PC$” and those entered on RasPi with “RasPi$”. I’ll use 192.168.0.106 as my RasPi IP address and george as my user name -- you’ll need to substitute your own.
- With power off, plug LOGI-Pi onto your RasPi as described earlier.
- Plug in your RasPi. The RasPi and LOGI-Pi power LEDs should turn on and you should see lots of flashing on the RasPi Activity LED as the operating system boots (assuming the LED is visible with LOGI-Pi installed).
- Connect an Ethernet cable between RasPi and your router or Ethernet switch, or directly to your PC. Once RasPi has booted the RasPi Link LED should come on.
- After giving RasPi time to boot, open a Terminal window on your PC and ping RasPi so you know you can talk to it:
PC$ ping 192.168.0.106
ping should show a series of successful data transfers and you should see RasPi’s Ethernet activity LED blink as the pings occur.
- Log onto RasPi using ssh and the IP address you verified in the last step. On your PC, give the command:
PC$ ssh email@example.com
The first time I did this ssh asked me to confirm that this was correct. Then ssh asks for george’s RasPi password. If the RasPi user name is the same as your PC user name you can simply write:
PC$ ssh 192.168.0.106
Once ssh has accepted the password, you’re in a command shell on RasPi and you can enter GNU commands exactly as if you were on a RasPi serial port or directly-attached display and keyboard.
- You are now in george’s home directory on RasPi. Let’s change to the LOGI directory:
RasPi$ cd LOGI
- Back on the PC, open another Terminal for PC commands. Let’s assume the PC also has a subdirectory LOGI and that we’ve downloaded logipi_blink.bit to that directory. Let’s change to the PC’s LOGI directory:
PC$ cd ~/LOGI
- You are now ready to transfer logipi_blink.bit from the PC to RasPi. Use scp (secure copy) which in turn uses ssh for data transfers and authentication. Here’s the PC command:
PC$ scp logipi_blink.bit firstname.lastname@example.org:LOGI/.
This copies logipi_blink.bit from the current PC directory to ~george/LOGI on RasPi, keeping the same file name. scp will ask for george’s password to authenticate the transfer.
- On RasPi, make sure the file arrived by listing LOGI’s .bit files:
RasPi$ ls -l *.bit
Spartan-6 LX9 .bit files are approximately 340KB.
- The last step is to write logipi_blink.bit to LOGI-Pi’s FPGA:
RasPi$ sudo logi_loader logipi_blink.bit
- If the transfer is successful, you should see a pretty blinking pattern on LOGI-Pi’s LED1 and LED0.
If you look carefully, you will also see that LOGI-Pi’s Done LED is on. It’s near pins 23 and 25 of the RasPi expansion connector. The LED turns on very faintly for logipi_blink.bit. This is because it’s pulled up by a weak FPGA resistor instead of being driven high by a transistor.
- When you are done playing with RasPi, be sure to shut it down properly so you don’t corrupt the file system:
RasPi$ sudo shutdown -h now
Experiment 2: Creating and Downloading a New Bitstream
In this experiment, I create a new bitstream using Xilinx tools and download it to LOGI-Pi using the same procedure as Experiment 1. I’m not going to tell you how to install or use the Xilinx tools since that’s a long procedure and can be found elsewhere, for example Logi-Pi Quick Start Guide. Gadget Factory also has some tutorials: Install ISE WebPack and Papilio Xilinx ISE WebPack VHDL Getting Started.
Experiment 2 creates a 4-bit binary counter that displays its two LSbs using LOGI-Pi LEDs and its two MSbs using external LEDs driven by two Pmod pins. The 4-bit counter is easy. The difficult part is dividing LOGI-Pi’s 50 MHz oscillator down to a value visible by humans, in this case 4 Hz.
Here’s the Verilog code for the clock generator. Instead of dividing by 12,500,000 using a single 24-bit counter, I first divide by 1000 using a 10-bit counter and then divide by 12,500 using a 14-bit counter.
module ClockDiv(Mclk, clk4Hz);
input Mclk; // 50 MHz master clock.
output clk4Hz; // 4 Hz clock-enable pulse.
reg [9:0] P; // Divide by 1000 prescaler.
wire [10:0] nextP = P + 1;
wire Pcarry = nextP; // Prescaler carry out, pulses at 50 KHz.
reg clk50KHz; // Glitch-free 50 KHz clock enable pulse.
reg [13:0] Q; // Divide by 12,500 counter.
wire [14:0] nextQ = Q + clk50KHz;
wire Qcarry = nextQ; // Low-freq carry out, pulses at 4 Hz.
always @(posedge Mclk)
// Divide by 1000: when nextP has carry out, set
// P = -1000 = 1024-1000 = 24. Pcarry is sync reset.
if (Pcarry) P <= 10'd24; else P <= nextP[9:0];
clk50KHz <= Pcarry;
// Divide by 12,500: when nextQ has carry out, set
// Q = -12,500 = 16,384-12,500 = 3,884. Qcarry is sync reset.
if (Qcarry) Q <= 14'd3884; else Q <= nextQ[13:0];
clk4Hz <= Qcarry;
This is a rather unusual way to express counters, but maps well to Xilinx logic. People usually make a divide-by-n counter by resetting it to 0 and then detecting when it reaches n-1. However, this requires logic to compare to n-1. So instead, we preset the counter to −n and increment it until it reaches all ones, which we detect using the carry out of the counter’s adder chain.
Now that we have a 4 Hz pulse stream, it’s easy to make the 4-bit counter:
module UpCounter(Mclk, reset, up, K);
input Mclk; // 50 MHz master clock.
input reset; // Asynchronous reset.
input up; // Counter enable.
output [3:0] K; // 4-bit counter;
reg [3:0] K;
wire clk4Hz; // 4 Hz demo clock enable pulse.
wire [4:0] nextK = K + up;
ClockDiv cd(Mclk, clk4Hz); // Instance of ClockDiv module.
always @(posedge Mclk or posedge reset)
if (reset) K <= 0; else if (clk4Hz) K <= nextK[3:0];
The counter includes asynchronous reset which we’ll connect to LOGI-Pi’s PB0, and an enable input which we’ll connect to PB1. Normally the counter increments at 4 Hz. If you press PB0, the counter resets to 0 and stays there. If you press PB1, the counter holds its current value.
Finally, here’s the root module that connects counter bits K[3:0] to the LEDs and connects PB0 and PB1 with the proper polarities:
module UpCountPi(Mclk, PB0, PB1, LED0, LED1, LED2, LED3);
input Mclk; // 50 MHz master clock.
input PB0; // Press to reset = active-low.
input PB1; // Press to hold = active-high enable.
output LED0, LED1; // LSbs are active high.
output LED3, LED2; // MSbs are active low.
wire [3:0] K; // 4-bit counter;
UpCounter uc(Mclk, !PB0 /*reset*/, PB1 /*up*/, K);
assign LED0 = K;
assign LED1 = K;
assign LED2 = !K;
assign LED3 = !K;
Now that we have the Verilog code for Experiment 2, we can compile it using Xilinx ISE (Integrated Software Environment). I’m using the ISE 12.4 free-as-in-beer WebPACK Editon on Ubuntu 12.04 LTS, which mostly works except for some graphical tools I don’t need. I’ve created an ISE project named LOGIdemo in LOGI, so the many files ISE generates -- including the bitstream -- will be in LOGI/LOGIdemo.
The design synthesizes without any errors or warnings on ISE 12.4. It may generate warnings in other versions.
Now, before implementing the design you need to tell ISE how to assign signals to pins. There’s a graphical tool to do this in ISE, but IMO it’s a lot easier to create and edit a User Constraint File. The name of the UCF normally matches the root module’s name, so here’s UpCountPi.ucf:
NET Mclk LOC="P85" | IOSTANDARD=LVTTL | PERIOD=20ns;
NET PB0 LOC="P102" | IOSTANDARD=LVTTL; # PB0 = press to reset
NET PB1 LOC="P101" | IOSTANDARD=LVTTL; # PB1 = press to hold
NET LED0 LOC="P105" | IOSTANDARD=LVTTL; # LED0
NET LED1 LOC="P104" | IOSTANDARD=LVTTL; # LED1
NET LED2 LOC="P5" | IOSTANDARD=LVTTL; # PMOD1-1
NET LED3 LOC="P2" | IOSTANDARD=LVTTL; # PMOD1-2
I found the pin numbers in the LOGI-Pi R1.0 schematics. The LOGI-Pi Quick Start Guide shows you how to find them. In the 4/23/2014 LOGI-Pi R1.1 schematics the PMOD1 and PMOD2 connections appear to be exchanged on sheet 4. That’s OK because they’re also exchanged on sheet 6 so the errors cancel out.
Once I have added UpCountPi.ucf to root module UpCountPi using ISE’s Add Source command, I can run the ISE implementation tools. This takes less than a minute on my PC. There should be no errors and no significant warnings.
When placement and routing is done, I recommend checking the Pinout Report to make sure the pins agree with UpCountPi.ucf.
The last step is to generate the bitstream. The default options are mostly OK, but we’re going to set the Drive Done option so the Done LED is more visible. Watch the ISE console log to see when it’s done generating the bitstream.
When ISE is done, we can copy UpCountPi.bit to RasPi and LOGI-Pi. This is basically the same as steps 7-11 in Experiment 1:
- On the PC, change to the directory that contains UpCountPi.bit, in my case LOGI/LOGIdemo.
PC$ cd ~/LOGI/LOGIdemo
- Transfer UpCountPi.bit from the PC to RasPi using scp:
PC$ scp UpCountPi.bit email@example.com:LOGI/.
- On RasPi, make sure the file arrived by listing LOGI’s .bit files:
RasPi$ ls -l *.bit
- Write UpCountPi.bit to LOGI-Pi’s FPGA using logi_loader:
RasPi$ sudo logi_loader UpCountPi.bit
- If the transfer is successful, you should see a binary counting pattern on LED1 and LED0. If you attach LEDs to PMOD1 pins 1 and 2 you get the two MSbs of the 4-bit counter. These are active-low LEDs, so connect their cathodes to PMOD1 pins and their anodes to +3.3V (PMOD1 pin 6) through suitable resistors, e.g., 560Ω.
If you push PB0, the counter resets to 0000. If you push PB1, the counter holds its current value.
You should also clearly see the Done LED, since it’s now driven high by an FPGA transistor.
The Experiment 2 source files LOGIdemo.v and UpCountPi.ucf are available in LOGIdemo.zip, along with UpCountPi.bit.
This was my first experience with LOGI-Pi and it went very smoothly. The board is well-designed and well-made, and provides many useful capabilities. Since I’ve done a lot of designs with other FPGAs and I’ve used ISE a lot, I had more trouble learning about device driver blacklists and git than the FPGA-specific tasks.
This is a simple introduction to using LOGI-Pi, intended to help you see results with minimal effort and frustration. LOGI-Pi is a very powerful board, capable of myriad interesting projects. I plan to show a few of these in upcoming ’blogs in this series.
[This document is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. To view a copy of this license, visit creativecommons.org/licenses/by-sa/3.0/. No warranty is expressed or implied. Raspberry Pi is a trademark of the Raspberry Pi Foundation.]