FPGA-based processors such as NIOS/MicroBlaze are capable of doing pretty amazing stuff. I’m surprised that so far it’s not very popular amongst the electronic enthusiasts. The strength of FPGA-based embedded system is that it’s so flexible. It allows you to configure each individual peripheral for your system, define address ranges … etc, BUT this is also the weakness because it IS intimidating and exhausting if you come from microcontroller world where the hardware is already verified and stable when it’s shipped to programmers.
In this post I will attempt to convince Arduino/Atmega users to try out FPGA-based processor system.
First off, you need to know that FPGA chip is a special type of chip that contains a sea of gates and flip-flops. The gates are used to calculate logic functions the flip-flops are used to store the results. So essentially, this is all we need to make digital circuit. Of course, we still need the wires that route signals between them. Therefore, FPGA can make ANY digital circuit including a complete CPU.
Have a look at this video where Dave compares FPGA and microcontroller
We will focus on how to use an FPGA that has already been configured as a microcontroller system. But before that, we need to understand some basic concepts of how a blank FPGA is configured to run as Embedded MicroProcessor System. I’m going to demonstrate with NIOSII processor because it’s free and I know that it’s quite an awesome processor with powerful tools chain. You, of course, can pick any processor from here www.opencores.org and configure your FPGA to run it. This video shows steps to setup an FPGA-based Embedded System. Some jargons before you start:
- Cyclone : Name of a family of FPGA manufactured by Altera (which belongs to Intel now)
- SOPC/QSys: a piece of GUI tool that allows you to configure the system your self
- Quartus: compilation tool that generates binary image to configure your FPGA
The following flow chart summarizes the concept which is similar for both Xilinx FPGA and Altera FPGA
This post focuses on the software flow by giving you the hardware description file (.sopcinfo) and hardware configuration file (sof). I’m going to demonstrate with the BEMICRO MAX10 board because this is one of the best value-for-money development kit that I’ve ever used. Brace your self for a series of boring instructions that need to be done before we can see something interesting.
Import Hardware Description File and Start a new software project
- You should have A “BEMICRO MAX10” board.
- Download the hardware description file (niossii.sopcinfo) and hardware configuration file (niosii.sof) that I’ve already prepared here.
- Download and install Quartus Prime Including NIOS-II Eclipse UI from here.
- Then open SDK Eclipse GUI. If you can’t find it from “Start Menu” it is located at altera_installation/nios2eds/bin/eclipse-nios2
- Create new Hello Nios Project and BSP
- Select the correct hardware description file (niosii.sopcinfo) then click FINISH
After this step, the tool will create a BSP project and an application called “hello_niosii”. The “Hello_niosii” project has only 1 main.c file which will print out a text message “Hello from NIOSII!”. You can use this same process to create a new program for your own application. If the BSP already has been created, you don’t have to create a new BSP and you can share the BSP between multiple Applications.
Although the preconfigured BSP seems to be correct, it’s good to have a look at important BSP’s settings. You can see the BSP settings by right-clicking the BSP project and select NIOSII–> BSP Editor
You’ll see on the Main tab that the BSP is configured to use UART_0 device as stdout/stdin/stderr. This will route the classic “printf” command to the correct device.
On the linker scripts tab is the memory lay-out of your hardware
There are multiple memory devices on our system and the linker scripts tab configure where the binaries should be loaded. Linker sections and regions:
- .entry and reset: where CPU will execute the first instruction after reset. This is pointing to on_chip_flash region. The MAX10 FPGA device on our development board contains an on-chip flash memory that stores FPGA configuration and a region called UFM (User flash memory). We’re going to store our binaries in this flash. You can see MAX10 is quite an awesome FPGA with built-in non-volatile memory, no need for external flash. All embedded systems need the “reset” region to contain valid data at power-on.
- .text and sdram0: the hello_niosii application is stored in the on-chip-flash but is copied to SDRAM and executed from that. The task of copying and jump to SDRAM is done by a block called “boot-loader” or “boot-copier” which is inserted by Altera’s tool when you generate the flash file. It figures out that a copier is required by looking at the .text section which is mapped to SDRAM device which is different from the .entry section. You can read more about booting processes of MAX10 device in this article.
- .exception and on-chip memory: .exception section stores the interrupt service routine which should be executed relatively quickly so we select on-chip ram to run those.
Click Generate and Finish to generate all the files that we need to compile our humble “Hello Nios” program.
- Compile Hello Nios Program and generate memory initialization file by selecting Make-Targets –> Build
Then you’ll see a few new files added to your project, but the one that we’re interested in is the onchip_flash_0.hex file
That’s DONE for the Software part.
Generate POF Programming File
Now we have to download this hex file to the on-chip flash. We do so using Quartus Prime Software. You’ve got the .SOF file from me and created a HEX file. We’ll bundle those two into a .POF file and download this file to the FPGA flash. The HEX file contains data to be written to user flash memory. The .SOF file contains the configuration for the FPGA itself.
- From Quartus Prime software, open “Convert Programming Files”.
- Then select: Internal Configuration and Open “Boot Options”. In the “Boot Options” dialogue, select “Load memory File” in the UFM source option and point to the onchip_flash_0.hex file.
- Then close the “Boot Options” and select the SOF file and finally click “Generate”.
Download pof file to hardware
- In the same Quartus Prime software, select Tools –> Programmer and setup your JTAG dongle.
- Then click “Auto detect” then you should see the device listed as above. Select change file, point to the output.pof file and click “Start” to start the Programming
To develop more interesting stuff, you need to know what you have on the hardware. Here’s the peripherals that I’ve created. More can be added later, for now I’m keeping it simple. The address range is defined here and exported to system.h file in the BSP folder
System Clock and System Reset: The input system clock is 50MHz. An internal PLL generates 80MHz clock and we use this clock throughout the system. Reset pin is mapped to Button0 on the kit. UART_TX and UART_RX is mapped to pin 1 and pin 2 of J5 header.
PIO ports are connected to 8 LEDs on board.
You can find other information about the hardware configuration in the BSP system.h file.
With the reconfigurability of FPGA, the possibility is endless.