Cyclone V + EDS

Esta es una guía básica basada en mi experiencia sobre los pasos a seguir en el diseño de FPGA + HPS con la Cyclone V.

Biblioman

1/10/202612 min leer

Introducción

Conseguir entender la base de como funciona el ciclo de trabajo de un proyecto que utiliza la FPGA Cyclone V y que se integre dentro del HPS (ARM Cortex de dos núcleos que incorpora el SoC) no fue una tarea fácil para mí, así que he decidido documentar con estos apuntes el proceso que he seguido. Las dificultades que me encontré son las siguientes:

  • Para diseñar o modificar un proyecto basado en FPGA + HPS se necesitan varias herramientas las cuales se integran principalmente en dos paquetes de software: Quartus Prime y SoC EDS (Embedded Design Suite), de Quartus tenemos las opciones con licencias (muy caras) y la lite (gratuita) si estas leyendo estos apuntes seguro que tú única opción viable es la lite. Te las puedes descargar desde este enlace previamente te tienes que crear una cuenta. Hay varias versiones disponibles, aunque tú primer impulso sea descargarte la última versión porque pienses que es la más funcional no ha sido esa mi experiencia, Altera ahora propiedad de Intel ha ido quitando herramientas que antes venían integradas en la versión Lite y ahora solo están disponibles en las versiones con licencia, por poner unos ejemplos la herramienta ModelSim-Altera, simulador gratuito ya no está disponible ni tampoco el BSP-Editor en la parte del EDS. Después de probar varias versiones me decanté por la versión 18.1 tanto para Quartus como para EDS.

  • Para realizar el primer ejemplo es mejor partir de una plantilla que te sirva de referencia para luego modificarla para ello Altera cuenta con el ejemplo GHRD (General Hardware Reference Design). Problema que vas a tener con esto, el ejemplo es específico para una versión determinada de Quartus y EDS al cambiar las herramientas cambia el flujo de trabajo y la forma de generar los archivos necesarios para grabar luego en la micro-SD. Estos apuntes se basan en la versión 18.1.

  • A parte de los archivos de configuración de la FPGA necesitamos una imagen de Linux con el kernel compatible para este procesador, hay varias opciones disponibles yo he utilizado la imagen Linux LXDE Desktop (kernel 4.5) que te puedes descargar gratuitamente de la página de Terasic una vez registrado desde aquí.

  • El ejemplo que te servirá de plantilla GHRD también te lo puedes descargar desde la misma página, concretamente yo me descargue DE10-Nano CD-ROM (rev. C Hardware) donde además de los ejemplos vienen manuales de la placa DE10-Nano. Hay que tener en cuenta que a pesar de que la placa se sigue vendiendo actualmente los ejemplos no están actualizados concretamente están hechos con la versión 16.0 de Quartus. En cada versión Altera (Intel) actualiza los IP Cores que son esos bloques de componentes hardware que puedes utilizar pero que su código fuente no está disponible ni en las versiones de pago. Actualizar los IPs no me dio problema de la versión 16 a la 18.1 pero probé actualizar a la versión 25.1 (actual) y si que los tuve, también probé la versión de 16 de Quartus pero no me gusto mucho porque todavía llama al Platform Designer con el nombre Qsys.

    Por todo esto y algunas cosas mas me decante por la versión 18.1. Una vez aprendido los conceptos te será mas fácil migrar a otra versión mas moderna y con IP cores mas actualizados aunque con limitaciones, Intel prioriza en todo incluida la documentación sus versiones con licencia (Standard y Pro) y se enfoca a clientes de grandes empresas y corporaciones el aficionado o desarrollador individual no están dentro de sus prioridades de negocio.

    Para terminar esta introducción decir que el Software está disponible tanto para Windows como para Linux, he probado el software en las dos plataformas y cada una tiene sus ventajas e inconvenientes, estos apuntes están basados en la versión para Windows.

Placa utilizada en el ejemplo

Se puede utilizar cualquier placa que incorpore la FPGA Cyclone V, yo concretamente he utilizado la QMTECH, tenéis la review en el siguiente vídeo.

Diagrama de bloques

Una buena forma de empezar es establecer un diagrama de bloque con el flujo de trabajo a realizar:

La parte en verde representa el punto de partida de nuestro proyecto (la plantilla) junto al contenido de la SD-Cart. Después de modificar el proyecto con Quartus y compilarlo nos generará una serie de archivos, a partir de ellos y usando una serie de herramientas debemos de obtener los archivos binarios que se encuentran en azul y que deberemos de cargar en la SD-Cart sobrescribiendo los que vienen por defecto.

Contenido de la SD-Cart

Al flashear la imagen Linux LXDE Desktop (kernel 4.5) en la micro-SD nos genera tres particiones:

  1. Partición RAW A2 Altera de solo 1MB de tamaño es donde va el Preloader generado por EDS 18.1

  2. Partición FAT32 de 500 MB que contiene los siguientes archivos binarios:

    • u-boot.img generado también por las herramientas EDS

    • soc_system.rbf archivo con la configuración de la FPGA convertido a la extensión .rbf necesario para que se pueda cargar la configuración desde la micro-SD

    • soc_system.dtb (Device Tree Blob) arbol de dispositos describe los componentes hardware para el kernel.

    • u-boot.scr es un script para u-Boot (compilado a partir de un archivo .scr o .txt mediante mkimage). Contiene comandos para que U-Boot se ejecute automáticamente durante el arranque y en las configuraciones de SoC FPGA, generalmente incluye pasos para cargar y aplicar el .rbf (En el ejemplo no se modifica).

    • ZImage es la imagen comprimida del kernel de Linux (formato vmlinuz). En el ejemplo no se modifica porque no es necesario añadir ningún controlador adicional, en el caso de que fuera necesario configurar y compilar el kernel de nuevo lo haríamos a través de proyectos como Yocto o BuildRoot hay un ejemplo paso a paso del último aquí

  3. Partición con el sistema de ficheros ext3 es donde se guarda el sistema de archivos raíz (rootfs) para el sistema operativo Linux completo. Viene con un tamaño predeterminado de unos 2GB pero se puede re-dimensionar la partición con el resto de espacio libre con GParted u otra herramienta similar.

Proceso de arranque del HPS

Nota: los micro-switches deben de estar todos a ON

Proceso de diseño con Plaform Designer (.qsys)
  1. Creamos un nuevo proyecto o partimos de un proyecto a modificar (GHRD) y lo copiamos en la ruta: C:\intelFPGA\18.1\embedded\examples

Nota: Con esta ruta no he tenido problemas en el PATH al utilizar las aplicaciones de EDS.

  1. Lo abrimos con Quartus Lite 18.1

  2. Hacemos clic (botón derecho) en Cycone V: 5CSEBA6U23I7 -->Device (para seleccionar nuestra FPGA) en Name Filter--> 5CSEMA6U23A7

  3. Hacemos clic en Tools-> Platform Designer y seleccionamos soc_system.qsys

  4. Modificar el proyecto, aquí tenemos varias opciones: añadir IP cores y conectarlos a qsys, Habilitar o des-habilitar Interfaces del HPS, para ello en el IP hps_0 botón derecho--> Edit desde la pestaña Peripheral Pins añadimos las interfaces disponibles comprobando en Mux. Table que no haya conflicto de pines, con esta opción podemos utilizar los pines asignados al HPS o mapear los pines a los disponibles en la FPGA.

  5. En System-> Assing Base Address y Assing Interrupt Numbers

  6. Le dados a guardar File-> save

  7. Le damos al botón Generate HDL..

  8. Después de eso nos sale una advertencia de añadir el nuevo archivo soc_system.qip (le damos ok y lo añadimos en Project -> Add/Remove Files in Project..)

  9. Vamos a tools-> Tcl Scripts..y en la subcarpeta submodules ejecutamos hps_sdram_p0_parameters.tcl y hps_sdram_p0_pin_assignements.tcl

  10. Instanciamos los componentes añadidos en qsys en nuestro archivo TOP y el código adicional necesario.

    Nota: Dentro de los archivos que genera Platform Designer en la carpeta soc_system nos crea el archivo soc_system_inst.v que nos sirve para saber el nombre con el que tenemos que instanciar en nuestro TOP los IP cores personalizados que hayamos añadido a nuestro diseño qsys.

  11. Asignamos los pines externos con Pin Planner

  12. Compilamos el proyecto y corregimos errores si los hubiera.

  13. Si todo ha ido bien Quartus nos creará varios archivos, en base a estos archivos tenemos que crear otros nuevos con las herramientas de EDS para obtener los archivos binarios que cargaremos en la micro-SD.

Ejemplo práctico (UART1)

La QMTECH (CycloneV) dispone de la Uart0 que está conectada a la consola de Linux para comunicarnos con el sistema operativo, el ejemplo consiste en añadir una UART adicional a nuestro diseño. Para ello disponemos de varias opciones.

  1. Añadir el IP Core a nuestro diseño qsys y conectarlo tal y como se muestra en la figura:

En la figura se ha añadido el componente "uart1" (16550 Compatible UART Intel FPGA IP) y se conecta de la siguiente manera:

  • uart1.avalon_slave (slave) → mm_bridge_0.m0 (master)

  • clock →clk

  • reset_sink →clk_reset

  • irq_sender→ILC.irq

  • RS_232_Serial →Doble clic para exportar las señales

Nota: La Cyclon V dispone de tres puentes AXI: HPS-to-FPGA, Lightweight HPS-to-FPGA y FPGA-to-HPS para conectar el hardware personalizado de la FPGA con el HPS. El Lightweight HPS-to-FPGA bridge es ideal para periféricos de bajo ancho de banda como UARTs, ya que ofrece acceso memory-mapped desde el HPS con latencia baja (32-bit AXI, hasta 150 MHz), sin DMA. Es más simple que el HPS-to-FPGA o FPGA-to-HPS.

Después de hacer las conexiones del componente uart1 seguimos los pasos a partir del punto 6.

  1. El HPS de la Cyclone V como cualquier SBC que se precie tiene varias interfaces de comunicación: 2xEMAC, 2xUSB, 2xSPI, 2xUART, 4xI2C, 2xCAN, etc. Pero a diferencia de una Raspberry o Orange PI no se habilitan desde el SO sino que se hace en la etapa de diseño con Platform Designer. ¿Que problema hay? que como se ve en la figura siguiente hay pocos pines libres de conexión en el lado del HPS, casi todos los pines de expansión solo están disponibles para su conexión con el mundo exterior a través de la FPGA.

Pero hay una solución fácil a esto, desde la pestaña Peripheral Pins donde habilitamos/des-habilitamos las diferentes interfaces si hacemos clic en el combo de cada interfaz nos permite utilizar los pines directos asignados al HPS o mapearlos a través de la FPGA tal y como se muestra en la figura de abajo.

Generar los archivos binarios que faltan y grabarlos en la micro-SD

Si hemos compilado nuestro proyecto sin errores Quartus nos habrá generado las siguientes carpetas y archivos:

  • hps_isw_handoff\soc_system_hps_0 →Dentro de esta carpeta Quartus nos crea varios archivos de configuración que utilizará el BSP-EDITOR para generar el código fuente del preloader y uboot.

  • output_files\DE10_NANO_SoC_GHRD.sof →El archivo .sof es el bitstream con la configuración de la FPGA es el que debemos utilizar si queremos cargar la configuración de la FPGA con el USB-Blaster.

  • soc_system.sopcinfo →Este archivo contiene información de nuestro diseño hardware y lo utilizaremos con la aplicación sopc2dts para generar el archivo binario .dtb (Device Tree Generator) árbol de dispositivos que describe los componentes hardware de nuestro diseño necesario para el kernel de linux.

  • soc_system\synthesis\soc_system_hps_0_hps.svd →El archivo .svd es utilizado por el debugger DS-5 incluido en las herramientas SoC EDS 18.1 para depurar el código HPS.

Generar archivo .dtb (árbol de dispositivos para Linux)

Lo primero que hay que hacer es abrir la consola Intel FPGA Embedded Command Shell como administrador, para ello vamos al directorio: C:\intelFPGA\18.1\embedded y seleccionamos Embedded_Command_Shell.bat botón derecho del ratón ejecutar como administrador. Esta es una terminal Cygwin que nos permite "emular" una consola de Linux en Windows.

Desde la consola vamos al directorio:

cd /cygdrive/c/intelFPGA/18.1/embedded/host_tools/altera/device_tree

Donde se encuentra la aplicación sopc2dts.exe y ejecutamos los siguientes comandos:

./sopc2dts.exe --input soc_system.sopcinfo --output soc_system.dtb --type dtb --board soc_system_board_info.xml --board hps_common_board_info.xml --bridge-removal all --clocks -v

./sopc2dts.exe --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 -v

Nota (1): El único archivo que necesitamos para grabar en la partición FAT32 es el soc_system.dtb que es un archivo binario. El soc_system.dts que obtenemos con el segundo comando es una versión en texto plano que podemos abrir con el bloc de notas.

Nota (2): Si ejecutamos el comando tal cual (sin añadir rutas) debemos copiar a ese directorio los archivos siguientes soc_system.sopcinfo (generado por Quartus en base a nuestro diseño qsys), soc_system_board_info.xml y board hps_common_board_info.xml incluyen información del hardware del resto de la placa donde va montado el SoC CycloneV y que no cambia, información necesaria para Linux.

Generar archivo .rbf

El archivo que nos genera Quartus tras compilar tiene la extensión .sof si queremos que la configuración de la FPGA se cargue desde la micro-SD hay que convertirlo al formato .rbf. Para ello hay varias opciones yo he utilizado la herramienta de conversión que se incluye en el EDE de Quartus:

  1. Desde Quartus 18.1 y con el proyecto abierto (C:\intelFPGA\18.1\embedded\examples\DE10_NANO_SoC_GHRD_UART1_TX)

  2. File -> Convert Programming Files

  3. En Programming file type--> Raw Binary File (.rbf)

  4. En Mode: Seleccionamos Passive Parallel x16

  5. En File name: soc_system.rbf y seleccionamos por ejemplo la carpeta output_files del proyecto para guardarlo

  6. Luego hacemos clic sobre SOF data y pulsamos en Add Files y seleccionamos el archivo .sof en mi caso DE10_NANO_SoC_GHRD.sof

  7. Por último hacemos clic en Generate

Generar pre-loader y uboot

  • Desde la consola de Intel FPGA ejecutamos el comando:

    bsp-editor

  • Seleccione Archivo->Nuevo HPS BSP.

  • Ir al directorio hps_isw_handoff/soc_system_hps_0 para acceder al directorio de configuración del preloader (el directorio y los archivos son generados por Quartus) Mantenemos todo lo demás igual y hacemos clic en OK.

  • Esto configura el preloader y Uboot. Puedes elegir cómo quieres arrancar después del preloader aquí. mantenemos los valores por defecto salvo que hay que marcar en FAT_SUPPORT spl.boot.FAT_SPPORT para nuestro u-boot.img.

  • Haga clic en Generar para crear la carpeta software/spl_bsp y los archivos necesarios.

    Nota: Si desea abrir un HPS BSP existente, haga Archivo->Abrir y seleccione el archivo settings.bsp en la carpeta software/spl_bsp.

  • Navegue hasta la carpeta software/spl_bsp.(cd /cygdrive/c/intelFPGA/18.1/embedded/examples/DE10_NANO_SoC_GHRD_UART1_TX/software/spl_bsp)

  • Ejecutar: /usr/bin/make y /usr/bin/make uboot

    Nota (1): Si no se pone la ruta completa a make en Windows 11 da error

El primer comando generará generará el archivo preloader-mkpimage.bin que tendremos que cargar en la primera partición de la micro-SD. Mas abajo veremos como.

El segundo comando creará la imagen de uboot dentro de la carpeta uboot-socfpga: u-boot.img que tendremos que copiar en la segunda partición (FAT32) junto a los archivos soc_system.rbf y soc_system.dtb generados anteriormente.

Carga del preloader en la primera partición (RAW A2)

El cargar el archivo preloader-mkpimage.bin en la primera partición presenta un problema adicional y es que es una partición RAW sin un sistema de ficheros por tanto no es reconocida por Windows ni tampoco por un Sistema operativo con Linux. En la carpeta C:\intelFPGA\18.1\embedded\host_tools\altera\diskutils altera tiene la aplicación alt-boot-disk-util.exe en teoría bastaría ejecutar el siguiente comando en la terminal:

alt-boot-disk-util.exe -p preloader-mkpimage.bin -a write -d e

Donde la letra e del final se refiere al nombre de la unidad de la tarjeta micro-SD.

Problema: No me ha funcionado en Windows 11

Solución: Probé Quartus y el EDS en Debian 12 y funcionaba con los comandos utilizados para Linux, así que decidí utilizar esos comandos en Windows a través de la consola cygwin. los pasos a seguir son los siguientes:

  1. Abrimos la terminal de Windows con permisos de administrador

  2. Desmontamos la unidad asignada a la tarjeta micro-SD con el comando mountvol X: /p donde X es la letra de la unidad asignada a la tarjeta micro-SD (solo si da error al ejecutar el comando) en mi caso:

mountvol D: /p

3. Ejecutamos Embedded_Command_Shell.bat como administrador para tener acceso a la consola de altera

  1. Desde la consola vamos a la carpeta donde se encuentra en pre-Loader: cd /cygdrive/c/intelFPGA/18.1/embedded/examples/DE10_NANO_SoC_GHRD_UART1_TX/software/spl_bsp

5. Importante antes desde la consola de altera ejecutamos:

cat /proc/partitions

Para estar seguro del nombre que tiene la partición en Linux en mi caso es sdb3. No te equivoques de partición por tu bien.

6. Ejecutamos el siguiente comando:

dd if=preloader-mkpimage.bin of=/dev/sdb3 bs=64k seek=0

Si todo ha ido bien debemos de obtener algo como esto:

4+0 registros leídos

4+0 registros escritos

262144 bytes (262 kB) copiados, 0,0215126 s, 12,2 MB/s

7. Después de esto puede que Windows no reconozca la unidad eso ocurre por que hay que volver a asignarle una letra.

Solución: abrimos el administrador de discos y seleccionamos la partición FAT32 de 500 MB que es la única que reconoce Windows botón derecho sobre ella y seleccionamos Cambiar la letra y rutas de acceso a de la unidad y le volvemos a asignar la letra a la unidad y con eso ya se abrirá la carpeta.