When using a SoC-FPGA (SoC coupled with an FPGA for programmable logic) such as the DE1-SoC from Terasic, programming the FPGA can be performed in many different ways:

  • Directly from an FPGA software (Quartus for example)
  • From U-boot before launching the OS
  • From the OS

Using this last option allows the FPGA to be reconfigured without having to reboot the OS and with the adequate support, even allows the OS to reconfigure itself to use the newly programmed features of the FPGA.

In this example, we wanted to program the FPGA from linux to access the DE1-SoC board’s IOs (10 LEDS, 10 switches, 4 buttons and 6 7-segments HEX displays)

Generate RBF file

FPGAs are programmed using “bitstreams”: files that configure the interconnections between the FPGA’s logic units to obtain the desired design. Those bitstreams are generated by Quartus after synthesizing HDL projects. We created our own design to offer access to the desired IOs, you may use your own. Many formats are available but Linux supports bitstreams in binary formats. By default, Quartus generates the bitstream as a SOF file. To convert this file into a binary RBF file, open “File”>”Convert Programming File”.

  1. Under “Input files to convert”, click “Add File…” and select the generated SOF file.
  2. In “Output programming file”>”Programming file type” select “Raw binary file” in the dropdown menu. You can give the output file any name.
  3. In the “Mode” dropdown, select “Passive Parallel x16”. In theory, the DE1-SoC expects to be programmed in “Passive Parallel x32” when programmed from Linux but Quartus (version 18.1) prevents the use of this mode for the chip for unknown reasons and the board can be programmed in “x16” as well.
  4. Finally, open “Advanced…” and configure the new window as shown below

Once done, Click on “Generate” and you should have your bitstream file

Linux-socfpga

The DE1-SoC board’s SoCFPGA chip possesses 2 ARM cores that are available to run an OS like linux. These may access the FPGA’s design using AXI bridges. Programming the FPGA from Linux requires driver support that is currently only available in Altera’s custom linux kernel. We cloned it and built it with

$ make ARCH=arm CROSS_COMPILE=<path/to/toolchain-> socfpga_defconfig
$ make ARCH=arm CROSS_COMPILE=<path/to/toolchain-> -j$(nproc)

This generated a zImage file that could be substituted for the one already present of the previously formatted SD-Card

Device Tree

As the DE1-SoC is an ARM board, linux expects to be provided with a device tree to know the hardware architecture it runs on. The linux(-socfpga) source tree provides some DTS source files but none specifically for the DE1-SoC board. The one provided for DE0_nano however is very close and can be used as a basis for our board with minimal changes which will allow us not to start from scratch. The example overlay we want to create uses the “fpga_bridge0” node which is declared by default in socfpga DTSs. The default address configured however does not correspond to the one used in the DE1 board. It must thus be reconfigured like this

&fpga_bridge0 {
	reg = <0xff200000 0x100000>;
	status = "ok";
};

The Device Tree overlay

We are now at the heart of the subject. Although linux provides access to the FPGA-Manager’s state, it is not meant to be used by the user to program the FPGA. Instead, the user provides a device tree overlay: an add-on that can be added to the OS’s current device tree to inform it of other available hardware devices. If the overlay refers to a FPGA design, Linux will use the FPGA Manager itself to apply it. Using this documentation, it is possible to create an overlay file for the base DTS.

For this example, the overlay will look like this

/dts-v1/;
/plugin/;
&base_fpga_region {
    firmware-name = "DE1_SoC_IO.rbf";
    fpga-bridges = <&fpga_bridge0>;
    de1_io {
        compatible = "de1_io";
        status = "ok";
    };
};

The “base_fpga_region” property is defined in the “socfpga.dtsi” base file used by the other files for this family. By using the “firmware-name” property with the name of the RBF file generated beforehand, we signal the kernel that we want to reprogram this region with the bitstream with this name. Both the RBF file and the compiled overlay will have to be placed in a configured firmware folder in the filesystem (/lib/firmware in this example). The “fpga-bridges” property in necessary to signal which bridge will be used to access this region. As explained before, here we will use the lwh2f bus, defined in the DTS as “fpga_bridge0”. Note that this property is only necessary because the “base_fpga_region” isn’t declared as a child of this bridge

Configuration

Once the base device tree, overlay and all other drivers and test applications are ready and in the board’s filesystem, all that is left is to power the board and insert the overlay.

Before powering on the board, make sure that the MSEL dipswitch (under the card) is as follows

MSEL = “00000” (all ON) (see user manual page 13)

This configuration informs the FPGA manager that it should expect to be configured using a “Passive Parallel x16” bitstream. You can see the state of the FPGA manager using the following command

$ cat /sys/class/fpga_manager/fpga0/state

At the moment, it should indicate “Power off” but once the FPGA is programmed, it will display “operating”.

Now we can Inject the overlay using the following commands to

  • Mount the necessary filesystem
  • Create a new folder in the filesystem
  • Write the name of the overlay file in one of the automatically created file of the newly created folder to ask the system to inject the overlay into the current device tree
$ mount -t configfs none /sys/kernel/config
$ mkdir -p /sys/kernel/config/device-tree/overlays/socfpga_cyclone5_de1_soc_io
$ echo socfpga_cyclone5_de1_soc_io.dtb > /sys/kernel/config/device-tree/overlays/socfpga_cyclone5_de1_soc_io/path

Note: Only the name of the file is necessary, as it is expected to be found in one of the configured firmware folders as well as the bitstream

Once installed, the system may display the following errors

OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/base-fpga-region/firmware-name
OF: overlay: WARNING: memory leak will occur if overlay removed, property: /soc/base-fpga-region/fpga-bridges

They are (apparently) OK and if they are the only error messages that you obtain, you can expect the Device tree to have been updated and the FPGA to be programmed. You can check it by using the cat command on the FPGA manager again and making sure that it now displays “operating”. If you inserted a module beforehand, and the compatible string now matches that of one of the DT node, the probe function should have been called.

Our test design contains a constant test register at offset 0 that contains a “0xBADB100D” value. Once the FPGA is programmed, we can use the devmem2 utility program to check that this value is returned

To remove the overlay, simply delete the corresponding folder

$ rmdir /sys/kernel/config/device-tree/overlays/socfpga_cyclone5_de1_soc_io

Conclusion

Using this method, we were able to program the FPGA with a new design. The inserted driver for this device was configured correctly thanks to the informations found in the overlay and now allows us to use the board’s IOs from the Linux userspace