Home Analysis and system design Running Linux on MIPSfpga and Altera FPGAs

Running Linux on MIPSfpga and Altera FPGAs

by admin

Running Linux on MIPSfpga and Altera FPGAs

The MIPSfpga documentation provided by Imagination Technologies describes the Linux deployment very well and in detail. But the on-chip system used is built with Xilinx-specific peripheral modules. That is why it cannot be replicated on an Altera FPGA debug board in its original form. The solution is the MIPSfpga-plus chip system with its platform-independent peripherals. Read this article on how to run Linux on it.


We must note at once that the resulting configuration of the following steps is still far from ideal. At the moment there is no boot from an external drive, and among the supported devices we can mention only UART and GPIO. Therefore the front of further development of the MIPSfpga-plus system seems to be very wide.
It is further assumed that the reader :

  • familiar with the subject area to the extent of the Harris Harris textbook [ L1 ];
  • has access to the MIPSfpga source codes [ L2 ] and mipsfpga-plus [ L3 ];
  • configured and tested MIPSfpga-plus with SDRAM [ L5 ] and UART [ L6 ], as well as in remote debugging mode [ L4 ];
  • Has some skills in using Linux development tools, experience with git;

The following configuration is used in the described case :

  • Terasic DE10-Lite debug board with Altera MAX10 FPGA and 64Mb SDRAM on board;
  • Pinboard II board as a debugger and UART converter. You can use any board with an FTDI USB chip which supports MPSSE, an example configuration is described in [ L4 ];
  • Windows 7 (x64) computer and Quartus Prime 16.1 for FPGA synthesis and programming;
  • virtual machine with Ubuntu 17.04 (x64) for building a kernel and RAM file system image;
  • Internet access;

In case you plan to seriously and deeply dive into the magic of the Linux kernel, we strongly recommend that you read the materials of [ L7 ], in particular the presentations of [ L8 ] and [ L9 ].
If all of the above requirements are met, let’s begin!

Synthesis of configuration and programming of FPGA

  • the MIPSfpga-plus settings (file mfp_ahb_lite_matrix_config.vh) must have SDRAM and UART peripherals enabled, as well as debugging via MPSSE – if using the debugging mechanism described in [ L4 ]:


  • Using Quartus, perform MIPSfpga-plus assembly and FPGA programming;

Kernel and RAM disk assembly

It is assumed that further actions are performed on a machine running Linux.

  • update the list of available packages for the system :

    sudo apt-get update

  • install the utilities and libraries needed to configure and build :

    sudo apt-get install -y build-essential git libncurses5-dev bc unzip

  • create a directory in which all further work will go and go to it :

    mkdir ~/mipsfpgacd ~/mipsfpga

  • Perform a toolchain download from the Imagination Technologies website:

    wget http://codescape-mips-sdk.imgtec.com/components/toolchain/2016.05-06/Codescape.GNU.Tools.Package.2016.05-06.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz

  • create a directory and deploy the downloaded package in it :

    mkdir ~/mipsfpga/toolchaintar -xvf Codescape.GNU.Tools.Package.2016.05-06.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz -C ~/mipsfpga/toolchain

  • It is advisable (but not obligatory) to put the path to the expanded executables in the $PATH variable, this will makeworking with them easier. For example, in ~/.profile

    pathadd() {if [ -d "$1" ] [[ ":$PATH:" != *":$1:"* ]];thenPATH="$1${PATH:+":$PATH"}"fi}pathadd "$HOME/bin"pathadd "$HOME/.local/bin"pathadd "$HOME/mipsfpga/toolchain/mips-mti-linux-gnu/2016.05-06/bin"

  • Get the Linux kernel:

    git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git kernel

  • get the buildroot, which will be used to form the RAM image of the file system :

    git clone git://git.buildroot.net/buildroot

  • create a directory for the buildroot and Linux patches needed for a MIPSfpga-plus deployment:

    mkdir patches

  • download patches [ L10 ], save them in the directory we just created;

  • Go to the buildroot directory and roll back to version 2017.05.1 (commit f3d8beeb3694):

    cd buildrootgit checkout 2017.05.1

  • Apply the patch to the buildroot:

    git apply ../patches/MIPSfpga_buildroot.patch

  • Perform configuration of the buildroot:

    make xilfpga_static_defconfig

  • make changes to the configuration if necessary :

    make menuconfig

  • start building the RAM image of the file system and go have a nice coffee (tea, beer or whatever you like), as this process is quite time consuming:


  • go to the directory with the Linux kernel and check that the file system RAM image is in the expected path (we will have to specify it later in the kernel configuration):

    cd ../kernel/ls -l ../buildroot/output/images/rootfs.cpio

  • rollback to v4.12.1 (commit cb6621858813), because the patch was generated from it :

    git checkout v4.12.1

  • apply the patch :

    git apply ../patches/MIPSfpga_linux.patch

  • Apply the basic configuration of the MIPSfpga kernel:

    make ARCH=mips xilfpga_de10lite_defconfig

  • Start the configuration editor :

    make ARCH=mips menuconfig

  • enable RAMdisk support and write the path to it (we checked the existence of this file earlier):

Running Linux on MIPSfpga and Altera FPGAs

  • save changes, exit the graphical configurator and start the kernel build :
    make ARCH=mips CROSS_COMPILE=~/mipsfpga/toolchain/mips-mti-linux-gnu/2016.05-06/bin/mips-mti-linux-gnu-

Load kernel into memory and startup

  • On the machine to which the hardware debugger is connected, run OpenOCD, for example as described in [ L4 ];
  • on the same machine, start a terminal (e.g. PuTTY) and connect to the COM port (speed 115200);
  • on the Linux computer where we did the build, run gdb from the MIPS toolchain. We assume that we are in the directory with the built kernel :

    mips-mti-linux-gnu-gdb ./vmlinux

    Further steps are performed in the gdb console.

  • connect to OpenOCD, which is running on a machine with a hardware debugger :

    (gdb) target remote 192.168.X.x :3333

  • perform a reset of the MIPSfpga system:

    (gdb) mo reset stop

  • tell the debugger that our system is Little Endian:

    (gdb) set endian little

  • Load a kernel image into memory :

    (gdb) load

  • run the kernel for execution :

    (gdb) continues

  • if everything is done correctly, then after some time in the previously started terminal we should see a loading log similar to the one below. Due to the peculiarities of the current kernel configuration, it won’t appear immediately, but after a short delay.

Download log

Linux version 4.12.1+ (stas@ubuntu) (gcc version 4.9.2 (Codescape GNU Tools 2016.05-06 for MIPS MTI Linux) ) #1 Sat Jul 22 14:35:05 MSK 2017CPU0 revision is: 00019e60 (MIPS M14KEc)MIPS: machine is terasic, de10liteDetermined physical RAM map:memory: 04000000 @ 00000000 (usable)Initrd not found or empty - disabling initrdPrimary instruction cache 4kB, VIPT, 2-way, linesize 16 bytes.Primary data cache 4kB, 2-way, VIPT, no aliases, linesize 16 bytesZone ranges:Normal [mem 0x0000000000000000-0x0000000003ffffff]Movable zone start for each nodeEarly memory node rangesnode 0: [mem 0x0000000000000000-0x0000000003ffffff]Initmem setup node 0 [mem 0x0000000000000000-0x0000000003ffffff]Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256Kernel command line: console=ttyS0, 115200PID hash table entries: 256 (order: -2, 1024 bytes)Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)Memory: 60512K/65536K available (1830K kernel code, 99K rwdata, 320K rodata, 944K init, 185K bss, 5024K reserved, 0K cma-reserved)NR_IRQS:8clocksource: MIPS: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 38225208935 nssched_clock: 32 bits at 50MHz, resolution 20ns, wraps every 42949672950nsConsole: colour dummy device 80x25Calibrating delay loop... 10.81 BogoMIPS (lpj=21632)pid_max: default: 32768 minimum: 301Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)devtmpfs: initializedclocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 nsfutex hash table entries: 256 (order: -1, 3072 bytes)clocksource: Switched to clocksource MIPSrandom: fast init doneworkingset: timestamp_bits=30 max_order=14 bucket_order=0Serial: 8250/16550 driver, 4 ports, IRQ sharing disabledconsole [ttyS0] disabledb0400000.serial: ttyS0 at MMIO 0xb0401000 (irq = 0, base_baud = 3125000) is a 16550Aconsole [ttyS0] enabledFreeing unused kernel memory: 944KThis architecture does not have kernel memory protection.mount: mounting devpts on /dev/pts failed: No such devicemount: mounting tmpfs on /dev/shm failed: Invalid argumentmount: mounting tmpfs on /tmp failed: Invalid argumentmount: mounting tmpfs on /run failed: Invalid argumentStarting logging: OKInitializing random number generator... done.Starting network: ip: socket: Function not implementedip: socket: Function not implementedFAILWelcome to MIPSfpgamipsfpga login:

GPIO operation

Let’s use Linux to manage the peripherals that are available to us (at the moment of writing this article it is a GPIO, not a complete one though):

  • check that the GPIO driver is loaded and the device is available :

    ls /sys/class/gpio/export gpiochip480 unexport

  • in order to determine the available range of the pins (in the current configuration the LEDs on the board are connected), mount debugfs and use it to get the necessary information :

    mount -t debugfs none /sys/kernel/debugcat /sys/kernel/debug/gpiogpiochip0: GPIOs 480-511, parent: platform/bf800000.gpio, bf800000.gpio:

  • activate LED0 (in the current case it is gpio480):

    echo 480 >/sys/class/gpio/export

  • put it in output mode :

    echo out >/sys/class/gpio/gpio480/direction

  • put it into a high level :

    echo 1 >/sys/class/gpio/gpio480/value

  • if everything is done correctly, the LED0 should light up.

What next

This configuration is essentially just the beginning of the porting of Linux to a MIPSfpga-plus system. Some of the work that needs to be done before the system can be used normally for practical tasks include :

  • support for existing peripherals: interrupt controller, fuller GPIO support, Altera ADC;
  • support for MIPSfpga-plus peripherals, including currently missing PWM, SPI (limited presence), I2C, DDR and Ethernet interfaces;
  • support for external drives (mmc/sdram) and the ability to boot from them;
    For this reason, if you come across any bugs in the current configuration, don’t be surprised, there is still a lot of work to be done.


The author would like to thank the team of translators of David Harris and Sarah Harris’ textbook, Digital Circuitry and Computer Architecture [ L1 ], Imagination Technologies for the academic license of the state-of-the-art processor core and educational materials, and personally to Yuri Panchul YuriPanchul For his work in popularizing MIPSfpga.


[L1] – Digital circuitry and computer architecture
[L2] – How to get started with MIPSfpga ;
[L3] – MIPSfpga-plus project on github ;
[L4] – MIPSfpga and in-circuit debugging ;
[L5] – MIPSfpga and SDRAM. Part 1 ;
[L6] – MIPSfpga and UART ;
[L7] — Free Electrons. Free training materials and conference presentations ;
[L8] — Free Electrons. Embedded Linux system development course ;
[L9] — Free Electrons. Linux kernel and driver development course ;
[L10] – Buildroot and Linux patches needed for deployment on MIPSfpga-plus

You may also like