Intel Cyclone V SE (FPGA-SOC) Development Notes

Introduction

The CycloneV SE FPGA, such as that on the Terasic DE10-Nano has enough Fabric Resources to support reasonably complex FPGA designs, while also containing 800MHz Dual Core ARM processors capable of running Linux.

This allows for the best-of-both-worlds in software development. Realtime signal processing can be implemented in FPGA Fabric with high performance and deterministic time responses.

The interfaces on the other-hand can be Implemented in a standard Linux Environment. This means high level interfaces such as USB and Ethernet with advanced functions are trivial. Even webservers using technologies such as Node.js can be run on the same Silicon as the deterministic algorithms reducing the number of chips required to implement a design, and for those designs to be created faster.

In addition, I have frequently used this connection between fabric and FPGA as a prototyping platform. When bringing up a new design this also makes it trivial to pass chips with I2C and SPI busses to the Linux system to test chip hardware chip communication and verify algorithms. Once the chips and algorithms are known good/close in C, the algorithms can THEN be moved into VHDL with NO HARDWARE CHANGES. This reduces the number of revisions needed in fabric to develop algorithms and replacing the hardware bring-up and the initial proof of concept algorithms to be designed using Python or C.

Unfortunately, as these are new and very rapidly evolving devices, I have continually run into issues with poor, limited, or out-of-date tutorials.

This is further complicated by the fact that when using these devices, one must use everything from low level digital design all the way through to the full stack of Linux Development (kernel development, kernel drivers, device trees and userspace programs) in addition to some SOC-FPGA specific routines.

This means that if you are responsible for doing the full stack of development, it’s frequently quite awhile between when I need to do a procedure on the NEXT project, by which time I have forgotten some of the details….

Project Setup

Hardware development can be done using Quartus II on the OS of choice.

Parts of the Linux side development be done in on a Linux system. I use Ubuntu in a VirtualBox instance, but other systems including WSL are likely usable (I just came up with my procedures when WSL was in its infancy).

VHDL Development

Most of the FPGA development is standard. It’s however very advantageous, to start with an Intel Golden System Reference Design (GSRD) and build your files into that.

This is due to some really annoying and trivial complexities in setting up the SOC system, finding all the right checkboxes, etc, and its just not worth it. Just start with the GHRD, make sure it works stock, and then start modifying it….

AXI Peripheral Development

The major difference from standard FPGA design is creating the interfaces between the ARM processor running Linux and the FPGA fabric. This is however surprisingly trivial and I have a standard format that I just modify for all my projects.

To instantiate the peripheral, use the Nios II Embedded Design Suite.

Building the uBoot Pre-loader

The pre-loader is the first step of the boot. It generally exists on a raw partition of the SD card at a fixed address. This is responsible for setting up certain things like SOC clocks, loading the FPGA bitstream from a file elsewhere on the SD card, load the device tree overlay, and booting the Linux operating system.

The uBoot pre-loader only needs to be rebuilt when clocks change on the SOC side (eg: infrequently). Try to remember to check the message log when you think it MIGHT be needed and the build will tell you if its needed or not. I find building the preloader to be annoying and prone to errors, so I try to avoid it whenever possible.

Device Tree Overlay File

The Device Tree Overlay file is a means to inform Linux on bootup as to what peripherals are available, what drivers to load for such peripherals, and what memory addresses they are located.

This means, this file is how you inform Linux that you created a custom (or instantiated something common like a SPI peripheral) and added it to the chip using the Nios II Embedded Design Suite.

This file as such is created by EDS, often then modified by hand, and compiled using the Linux tool “dts”.

Linux Memory Mapped Devices

Once a peripheral is known to exist in Linux, it can be accessed using mmap(), assuming the user is running as root. This is often a good first step to getting everything working.

Linux Driver Development

Once everything has been proven using a memory mapped device, it is sometime desirable to create proper Linux drivers for the device. This allows for improved device security, possible stability enhancements and greater ease of use through abstraction of the hardware interfaces.