Turn your SoCFPGA into an Emulation Platform (DE10-NANO Version)

You can map your RTL IP on the Programmable Logic (PL) of the Cyclone V processor. That is what PL is meant for. Here, you will learn how to map an Embedded UVM testbench on the Hard Processor System (HPS) of the Cyclone V, thus converting your de10-nano board into a small but efficient Emulation platform.

For the purpose of illustration, we have taken SHA3 IP from the Cryptech Project. An Avalon MM lite interface has been added around the IP, so that it can be integrated into the Cyclone V FPGA and accessed from the HPS. You can clone the RTL from the https://github.com/uvm/avmm_sha3 repository. Note that the git repository also contains an Embedded UVM testbench that runs with Icarus Verilog for the purpose of testing the RTL design. For the purpose of emulation, we will be modifying this same testbench and running it on the de10-nano board. But before that, we need to go through the process of synthesizing and mapping the RTL to the PL.


Before we start, two tools are required to be installed.

  1. Quartus Prime:
    It used to create customized hardware designs.Use free Lite version.

  2. Intel SoC FPGA Embedded Development Suite (EDS):
    This is the tool used to design the required device tree(explained later).

We use 18.3 version of both the software suites.

Step 1- Setting up Environment

1.a) Installation of Quartus Prime:

Install Quartus Prime lite on the system. It will be installed in intelFPGA_lite folder (for the lite version).

1.b) Installation of SoC EDS:

Install SoC EDS in the same folder where Quartus Prime is installed.

1.c) Setting Up MSEL Switches on Board:

All MSEL switches are kept On as FPGA is configured with HPS software: U-Boot, using SD card which contains image file.

MSEL is incorporated as 6 pin DIP switch SW10 on DE10-Nano board. Out of the box, The switches are configured as On, Off, On, Off, On, On for switches starting from 1 to 6 respectively


Failing to match the mode, the boot-loader throws an error and continue Linux boot process without notifying the user that the FPGA is not programmed.

Step 2- Create and modify the hardware design

2.a) Obtaining the GHRD:

Terasic provides GHRD for their boards.Download system CD from Terasic website for the appropriate board version and extract it. The GHRD will be used for the project is placed in Demonstrations/SoC_

To find out version (A/B/B2/C), flip the board. It contains a seal mark on the backside. If A/B/B2/C is written, it indicates the respective version.

2.b) IP up-gradation in Quartus:

Load the provided design in Quartus prime. Open project file named as DE10_NANO_SoC_GHRD
. It is recommended to upgrade IP as this design was drafted in version 16 whereas we are using version 17.1.


Click the Launch IP Upgrade Tool button. And another window will appear. Ignore the warnings.

click on the Perform Automatic Upgrade button.Close it once the process is done.

2.c) Modification of GHRD in Qsys:

To modify the existing design, go to tools -> Qsys within Quartus prime to start Qsys tool.

in case if you don’t find Qsys under tools dropdown, go to file-> open file inside Quartus environment.

Go to File -> Open file . Open soc_system.qsys . It contains the hardware reference design .We would like to place a custom component in place of led_pio.On Bottom left, under hierarchy tab, you will find led_pio . Right click on that & click on Remove .

2.d) Creating a custom IP:

Here we will be creating Avalon Memory-Mapped wrapped SHA3 hardware component and add it to existing design. Download avalon_sha3.tgz provided with the tutorial. Extract it.

2.e) Custom Component Creation

To incorporate Avalon Memory-Mapped wrapped SHA3 IP in Qsys,click File, choose new component from the drop-down menu. It opens the Component Editor’. Add component information under component Type tab. Go to Files Click on Add File button under Synthesis Files. select all the extracted files from avalon_sha3.tgz file.

Look for the Top-level file under the Attributes tab. Select that file. For our project, Top level file is avalon_sha3.v. Click on Analyze Synthesis Files.

Analyze Synthesis Files button provides the editor the signals of the IP and joins them in component automatically.

Under the signals and interference Tab, set Read Latency to 1.

If any error comes, check if any port is left unconnected. connect the port using the drop-down menu if there is an error present.

Click on the finish button and save the changes.The newly created componenent avalon_sha3 is visible on the IP catalog.


2.f) Adding hardware information in ‘*_hw.tcl’ file:

Upon creation of avalon_sha3’ Qsys generates avalon_sha3_hw.tcl file in /Demonstrations

To add this custom component to the Device Tree, append the following lines to avalon_sha3_hw.tcl file.

# Device tree generation

set_module_assignment embeddedsw.dts.vendor "sha3" 

set_module_assignment embeddedsw.dts.compatible "dev,avalon_sha3"

set_module_assignment embeddedsw.dts.group "avalon_sha3"

2.g) Adding the custom component to the hardware design file:

To adjoin avalon_sha3 component to existing hardware design, double-click on avalon_sha3 under project section inside IP Catalog.Click finish to add component and close the window. Make the connection as per the image given below. and save it .

2.h) Generate HDL:

To generate the HDL that is used to systhesize and to generate bitstream of the design we drafted in Qsys, click on Generate -> Generate HDL in Qsys. Click on the Generate button in the newly appeared windows.

Click close and close Qsys.

2.i) Synthesis the System:

Open Quartus. On the left-hand side, under Entity: Instance tab, double-click on DE10_NANO_SoC_GHRD to open the top level file of this hardware design file DE10_NANO_

Search for led_pio_external_connection_export.Add ‘//’ before it to disable the statement .On the panel, under Task section, locate Assembler (Generate programming files).


double-click on it. The entire process will take 10-15 mins time depending on system performance.
Upon completion of this, to generate a Raw Binary File(rbf). go to file -> Convert Programming files.

Select Raw Binary file(.rbf) as Programming file type , Mode as Passive Parallel x16 and Output file name as soc_system.rbf .

Click on SOF data in input files to convert section, Click on the Add file button , browse and go to output_file folder and select DE10_NANO_SoC_GHRD.sof file.

click on Generate.It will generate soc_system.rbf file . Click close when its done.

Step 3- Preloader Generation:

The generating process of preloader is not very complicated as BSP, a handy GUI tool takes care of it. It is required to re-generate preloader if there is any change in hardware design in Qsys

BSP editor is part of intelFPGA_EDS package. Load the intelFPGA_EDS package.

3.a) Generating the preloader & configuration:

Go to /opt/intel/intelFPGA_EDS/17.1/embedded and run a script named embedded_command_shell.sh to get access to several tools of SoC EDS. To check the successful execution of script , run

echo $PATH

open terminal, go to DE10_NANO_SoC_GHRD folder and execute the following command:

bsp-editor &  	

A new window will appear,go to FILE-> New HSP BSP .


To set Preloader settings directory , click on ‘…’ button next to it and select DE10_NANO_SoC
folder.The rest of the empty fields in that window ,will get filled up automatically. Click ‘OK’ .

On the left-hand panel, Click on common. Make sure BOOT_FROM_SDMMC and FAT_SUPPORT are enabled .

we will be placing U-Boot on FAT partition of our SD card.

Click on the Generate button. Click Exit when it’s done.

3.b) Preloader Compilation:

BSP editor stores output at DE10_NANO_SoC_GHRD/software/spl_bsp/ folder.And it also generates a Makefile that will be used to compile preloader.

To compile,go to software/ spl_bsp/ folder

run make command


if you face any difficulty to run make, check $PATH and if you find any issue load intelFPGA_EDS package again <step 3>

Step 4- U-BOOT setup:

As the preloader is ready, Our SoC has been informed about the next boot stage, Boot-loader. U-Boot is most popular boot-loader in embedded Linux designs.

It’s is expected that the present working directory is DE10_NANO_SoC_GHRD/software/spl_bsp/
folder. Let’s go back to the software folder.

cd ..

4.a) GCC toolchain installation and setup:

To compile U-Boot as well as Linux Kernel, we will acquire Linaro GCC toolchain for the ARMV7 instruction set.

we will be using the 6.x version.
you can download it from https://releases.linaro.org/components/toolchain/binaries/latest-6/arm-linux-gnueabihf/ .
gcc-arm-linux-gnueabihf is the cross-toolchain package for the armhf (hardware floating point) architecture .

To download that enter the following command given below,

wget https://releases.linaro.org/components/toolchain/binaries/latest-6/arm-linux-gnueabihf/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz

tar -xvf gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz

To set the CROSS_COMPILE environment variable to extracted GCC tool chain.

export CROSS_COMPILE=$PWD/ gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-

Please note this path setup is temporary which implies that if the terminal is closed, we need to set it again. In that case, repeat the steps mentioned above.

4.b) U-Boot Compilation :

Altera / Intel provides modified version of U-boot on Altera Github repository .

To get it in your system, execute

git clone https://github.com/altera-opensource/u-boot-socfpga.git

cd u-boot-socfpga

To ensure bug-free experience we . we are going to use latest stable version rel_soc_fpga_v2013.01.01_17.08.01_pr.

git checkout rel_socfpga_v2013.01.01_17.08.01_pr

//to find the other options
git tag -l rel_socfpga*

To clean the U-boot folder to start the process with a clean state run the command given below.

make mrproper

make mrproper deletes the present configuration and all generated files.

To compile U-boot, execute the following commands

make socfpga_cyclone5_config
cd ..

This generates u-boot.img file in the current working directory.

4.c) Configuring boot script:

Boot script is U-Boot commands list which will be running when the device boots up. This script programs the FPGA, loads up the device tree, kernel and executes the kernel with boot arguments.

Create a file called ‘boot.script’.Paste the content given below.

echo -- Programming FPGA --
fatload mmc 0:1 $fpgadata soc_system.rbf;
fpga load 0 $fpgadata $filesize;
run bridge_enable_handoff;

echo -- Setting Env Variables --
setenv fdtimage soc_system.dtb;
setenv mmcroot /dev/mmcblk0p2;
setenv mmcload 'mmc rescan;${mmcloadcmd} mmc 0:${mmcloadpart} ${loadaddr} ${bootimage};${mmcloadcmd} mmc 0:${mmcloadpart} ${fdtaddr} ${fdtimage};';
setenv mmcboot 'setenv bootargs console=ttyS0,115200 root=${mmcroot} rw rootwait; bootz ${loadaddr} - ${fdtaddr}';

run mmcload;
run mmcboot;

Once the boot-script is ready, we need to compile it into a binary file. Execute the command given below.

mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "Boot Script Name" -d boot.script u-boot.scr

The outcome would be u-boot.scr.This concludes U-BOOT part.

Step 5- Device Tree Generation and Compilation:

Device tree is a data structure that contains information regarding hardware present in the system. It’s distinct file which allows modification from U-Boot and kernel. The device tree written in text format is called device tree source(dts) and compiled version comes with dtb extension which stands for device tree binary.

Intel SoC EDS tool provides an application called sopc2dts

sopc2dts takes .sopinfo ( SOPC information file ) file and .xml board files as input and produces device tree source(.dts) file.

DE10_NANO_SoC_GHRD folder contains two .xml board files which contain information about external peripherals.

  • hps_common_board_info.xml
  • soc_system_board.info.xml

open hps_common_board_info.xml in any text editor and search for ‘led_pio’.

Comment the section that contains led_pio. Check the image given below.

<DTAppend name="label" type="string" parentlabel="led_hps0" val="hps_led0"/>
<DTAppend name="gpios" parentlabel="led_hps0" >
<val type="phandle">hps_0_gpio1_porta</val>
<val type="number">24</val>
<val type="number">0</val>

<DTAppend name="label" type="string" parentlabel="led_fpga0" val="fpga_led0"/>
<DTAppend name="gpios" parentlabel="led_fpga0" >
<!-- <val type="phandle">led_pio</val> -->
<!-- <val type="number">0</val> -->
<!-- <val type="number">0</val> -->

<DTAppend name="label" type="string" parentlabel="led_fpga1" val="fpga_led1"/>
<DTAppend name="gpios" parentlabel="led_fpga1" >
<!-- <val type="phandle">led_pio</val> -->
<!-- <val type="number">1</val> -->
<!-- <val type="number">0</val> -->

<DTAppend name="label" type="string" parentlabel="led_fpga2" val="fpga_led2"/>
<DTAppend name="gpios" parentlabel="led_fpga2" >
<!-- <val type="phandle">led_pio</val> -->
<!-- <val type="number">2</val> -->
<!-- <val type="number">0</val> -->

<DTAppend name="label" type="string" parentlabel="led_fpga3" val="fpga_led3"/>
<DTAppend name="gpios" parentlabel="led_fpga3" >
<!-- <val type="phandle">led_pio</val> -->
<!-- <val type="number">3</val> -->
<!-- <val type="number">0</val -->>

<DTAppend name="label" type="string" parentlabel="led_fpga4" val="fpga_led4"/>
<DTAppend name="gpios" parentlabel="led_fpga4" >
<!-- <val type="phandle">led_pio</val> -->
<!-- <val type="number">4</val> -->
<!-- <val type="number">0</val> -->

<DTAppend name="label" type="string" parentlabel="led_fpga5" val="fpga_led5"/>
<DTAppend name="gpios" parentlabel="led_fpga5" >
<!-- <val type="phandle">led_pio</val> -->
<!-- <val type="number">5</val> -->
<!-- <val type="number">0</val> -->

<DTAppend name="label" type="string" parentlabel="led_fpga6" val="fpga_led6"/>
<DTAppend name="gpios" parentlabel="led_fpga6" >
<!-- <val type="phandle">led_pio</val> -->
<!-- <val type="number">6</val> -->
<!-- <val type="number">0</val> -->

Repeat the steps for all section containing led_pio .

To compile the device tree,Go to DE10_NANO_SoC_GHRD folder and run the command given below.

sopc2dts --input soc_system.sopcinfo --output soc_system.dts --type dts --board soc_system_board_info.xml --board hps_common_board_info.xml --bridge-removal all --clocks

The above step will generate .dts file and to compile the generated .dts file , execute the command given below

dtc -I dts -O dtb -o soc_system.dtb soc_system.dts

Step 6- Dump Image in SD card:

  • Download the linux-console image from terasic website .
  • put SD card of at least 8GB in an adaptor and plug it in system.
  • Run lsblk to find out the name of the memory card.


In the above picture, the name of the memory card is mmcblk0.

  • Go to the folder where linux_image is downloaded. Unzip it to get the .img format available to be dumped.

  • Execute the following command to dump the image into SD card.

sudo dd if=<<name of image>> of=/dev/mmcblk0 BS=+4M status=progress
  • It will create two partitions, One with 1.1GB and another with 859MB. The file system of the first one is EXT4 and second one is FAT.

  • Copy soc_system.dtb , soc_system.dts , soc_system.rbf from the folder DE10_NANO_SoC_GHRD and u-boot.scr from DE10_NANO_SoC_GHRD/ software folder and replace them in FAT partiation of the SD Card.

Step 7- Run linux on Device:

Plug the memory card in the device. run putty in serial mode .To run putty enter following command on terminal

sudo putty -D /dev/ttyUSB0

In putty set the serial line as /dev/ttyUSB0 and speed as 115200.

  • Linux will Boot Up. Enter username as root.

We ran the Linux for the first time without configuring the FPGA to make sure the Linux is working fine.

Step 8- Programming FPGA:

  • To program the FPGA, we need to get root access on the terminal as we would need to write on Ext partition. To get the root access, Enter the following command.
sudo bash
  • place the … folder in /home/root folder of MMC card
  • plugin and run the Linux. once Linux loads up, go to … folder
  • enter make and execute it, it will run the embedded UVM.