Cree y programe diseños basados en un FPGA de manera rápida con los cuadernos de Python y Jupyter

Por Stephen Evanczuk

Colaboración de Editores de Digi-Key de América del Norte

Los diseñadores, tradicionalmente, han optado por arreglos programables de puertas en campo (FPGA) para acelerar el rendimiento en los diseños de hardware para aplicaciones con un uso intensivo de los recursos informáticos, como la visión por computadora, las comunicaciones, los sistemas industriales incorporados y, cada vez más, el Internet de las cosas (IoT). Sin embargo, los pasos detallados que conlleva la programación convencional de FPGA han sido prohibitivos, y eso llevó a los diseñadores a buscar soluciones de procesamiento alternativas, hasta ahora.

La aparición del entorno de desarrollo Python Productivity para Zynq (PYNQ), que se basa en los cuadernos de Jupyter, trata el problema de la programación de FPGA. Al utilizar una placa de desarrollo diseñada específicamente para apoyar a PYNQ, los desarrolladores que tienen poca experiencia con FPGA pueden implementar diseños rápidamente que son capaces de aprovechar al máximo el rendimiento de FPGA para acelerar las aplicaciones con un uso intensivo de recursos informáticos.

Este artículo describirá el enfoque de FPGA típico antes de presentar y mostrar cómo comenzar a usar una placa de desarrollo de Digilent que brinda una alternativa de código abierto potente para acelerar el desarrollo de los sistemas basados en FPGA.

¿Por qué FPGA?

Los ingenieros que necesitan emplear algoritmos con un uso intensivo de recursos informáticos, generalmente dependen de los FPGA para acelerar la ejecución sin comprometer presupuestos energéticos ajustados De hecho, los FPGA han surgido como una plataforma dominante para acelerar los algoritmos de inteligencia artificial en sistemas de informática “de borde” (consulte “Utilizar los FPGA para crear aplicaciones de visión integradas de alto rendimiento con el aprendizaje automático”).

Los dispositivos más avanzados de FPGA con sistemas en chip (SoC) integran un tejido lógico programable (PL) con un microcontrolador y están diseñados específicamente para aplicaciones integradas. Por ejemplo, el SoC Zynq-7000 de Xilinx combina un sistema de procesador Arm® Cortex®-A9 de doble núcleo con hasta 444,000 celdas lógicas en su tejido lógico programable (PL) (Figura 1). Junto con los procesadores incorporados y un amplio complemento de periféricos, el SoC Zynq brinda hasta 2,020 bloqueos o fragmentos de procesamiento de señal digital (DSP). Con estos recursos, los desarrolladores pueden configurar el tejido PL y formar cadenas de procesamiento especializadas que se necesitan para acelerar la tasa de producción en algoritmos con un uso intensivo de recursos informáticos.

Diagrama del SoC Zynq-7000 de Xilinx

Figura 1: El SoC Zynq-7000 de Xilinx combina un procesador Arm Cortex-A9 de doble núcleo, el tejido lógico programable y un amplio conjunto de periféricos e interfaces que son necesarios en muchas aplicaciones integradas. (Fuente de la imagen: Xilinx)

Además de reducir el recuento de piezas, la integración de los procesadores y el tejido PL permiten que se lleven a cabo operaciones en los buses en chip en lugar de mediante el acceso fuera del chip. Esta integración simplifica más la tarea crítica de cargar el tejido PL durante las secuencias de reinicio o de encendido.

En un sistema basado en un microcontrolador con un FPGA típico, los desarrolladores necesitan controlar la secuencia y la seguridad para cargar flujos de bits que programan el FPGA. Con el SoC Zynq, un procesador incorporado realiza las tareas de un microcontrolador convencional, lo que incluye controlar el tejido PL y otros periféricos en chip. Como consecuencia, el proceso de carga del FPGA se asemeja más al proceso de arranque de un microcontrolador convencional que a una inicialización del flujo de bits de FPGA tradicional.

Este proceso de arranque sucede a través de una secuencia corta de pasos que están controlados por uno de los procesadores de Zynq (Figura 2). En el encendido o el reinicio, el proceso de arranque comienza cuando un procesador de Zynq ejecuta una pequeña parte de un código de su ROM de inicio de solo lectura para buscar el código de arranque real de un dispositivo de arranque. Junto con el código para configurar los componentes del sistema de procesador, el código de arranque incluye el flujo de bits de la PL y la aplicación de usuario. Cuando se completa la carga del código de arranque, el procesador utiliza el flujo de bits incluido para configurar la PL. Después de que se completen la configuración y la configuración de la PL, el dispositivo comienza a ejecutar la aplicación incluida en el código de arranque.

Imagen de la secuencia de arranque del SoC Zynq-7000 de Xilinx

Figura 2: En una secuencia de arranque parecida a los microcontroladores convencionales, un SoC Zynq-7000 de Xilinx ejecuta el código desde la ROM de inicio que carga y ejecuta el cargador de arranque, que maneja las etapas posteriores, incluida la utilización de un flujo de bits dentro del código de arranque para configurar el tejido lógico programable. (Fuente de la imagen: Xilinx)

Incluso con el procesamiento de carga de la PL simplificado, los desarrolladores, anteriormente, han tenido que lidiar con el complejo proceso de desarrollo de FPGA que se necesita para generar los flujos de bits requeridos. Para los desarrolladores que buscan aprovechar el rendimiento de FPGA, el proceso de desarrollo de FGPA convencional sigue siendo un obstáculo significativo a la implementación. Xilinx eliminó de manera eficaz ese obstáculo con su entorno PYNQ.

Entorno PYNQ

En PYNQ, los flujos de bits están encapsulados en librerías prefabricadas denominadas plantillas, que desempeñan un papel parecido al de las librerías de software en cuanto al proceso de desarrollo y el entorno de ejecución. Durante el proceso de carga de arranque, los flujos de bits relacionados con las plantillas requeridas configuran el tejido de PL. Sin embargo, el proceso sigue siendo transparente para los desarrolladores que aprovechan la funcionalidad de la plantilla a través de la interfaz de programación de aplicaciones (API) de Python relacionada con cada plantilla. Durante el desarrollo, los ingenieros pueden combinar librerías y plantillas de software según sea necesario, al trabajar a través de sus API respectivas para implementar la aplicación. Durante la ejecución, el sistema de procesador ejecuta el código de la librería de software como siempre, mientras que el tejido de PL implementa la funcionalidad proporcionada en la plantilla. El resultado es la clase de rendimiento acelerado que sigue impulsando el interés en los diseños basados en FPGA para las aplicaciones que demandan cada vez más.

Como lo indica su nombre, PYNQ aprovecha las ganancias de productividad de desarrollo relacionadas con el lenguaje de programación Python. Python ha emergido como uno de los lenguajes más populares, no solo porque es relativamente simple, sino también debido a su ecosistema grande y creciente. Es probable que los desarrolladores encuentren librerías de software necesarias para los dispositivos de apoyo o los algoritmos especializados en repositorios de módulos de código abierto de Python. A su vez, los desarrolladores pueden implementar funciones críticas en el lenguaje C ya que PYNQ utiliza la implementación del lenguaje C común del intérprete de Python. La implementación brinda acceso fácil a miles de librerías C existentes y simplifica el uso de las librerías de lenguaje C proporcionadas por el desarrollador. Si bien los desarrolladores con experiencia pueden extender PYNQ con plantillas de hardware especializadas y librerías de software de lenguaje C, la fortaleza de PYNQ radica en su capacidad de proporcionar un entorno de desarrollo de alta productividad para cualquier desarrollador capaz de crear un programa Python.

PYNQ, al ser un proyecto de código abierto, se crea sobre otro proyecto de código abierto, el cuaderno de Jupyter. Los cuadernos de Jupyter brindan un entorno especialmente eficaz para explorar algoritmos de manera interactiva y hacer un prototipo de las aplicaciones complejas en Python o cualquiera de los otros lenguajes de programación compatibles, que actualmente son más de 40. Un cuaderno de Jupyter, que se desarrolló con el consenso comunitario bajo el proyecto Jupyter, combina líneas de código ejecutable con texto y gráficos descriptivos. Esta capacidad les permite a los desarrolladores individuales registrar, de manera más eficaz, su progreso sin avanzar hacia otro entorno de desarrollo. Por ejemplo, un desarrollador puede utilizar un cuaderno que combina algunas líneas de código necesarias para ver los datos con el gráfico generado por el código (Figura 3).

Imagen de un cuaderno de Jupyter de un repositorio de muestra de Xilinx

Figura 3: Un cuaderno de Jupyter de un repositorio de muestra de Xilinx combina un texto descriptivo, un código ejecutable y una salida relacionada con una aplicación. (Fuente de la imagen: Xilinx)

Es posible que tenga un código, una salida y texto descriptivo, ya que un cuaderno es un documento activo que se mantiene en un entorno de desarrollo interactivo proporcionado por un servidor portátil de Jupyter (Figura 4). En una sesión de Jupyter, el servidor reproduce el archivo de cuaderno en un navegador web convencional utilizando HTTP y una combinación de HTTP y protocolos Websockets para el contenido estático y dinámico del documento reproducido. En el back end, el servidor se comunica con un núcleo de ejecución de código utilizando un protocolo de mensajería ZeroMQ (ØMQ) de código abierto.

Diagrama del flujo de trabajo de una sesión de Jupyter

Figura 4: En una sesión de Jupyter, un servidor del cuaderno transfiere el contenido de un archivo portátil a un navegador web y, a su vez, interactúa con un núcleo de back end que ejecuta el código. (Fuente de la imagen: Project Jupyter)

En el modo de edición, el usuario puede modificar el texto y el código. Por otra parte, el servidor actualiza el archivo del cuaderno correspondiente, que es un archivo de texto que está formado por una serie de pares de claves/valores de JSON. Estos pares se denominan celdas en el entorno Jupyter. Por ejemplo, la pantalla del navegador web del cuaderno de Jupyter que se mostró anteriormente está formada por algunas celdas para código y texto plano (Listado 1).

Copy   {    "cell_type": "markdown",    "metadata": {},    "source": [     "## Error plot with Matplotlib\n",     "This example shows plots in notebook (rather than in separate window)."
]   },  {    "cell_type": "code",    "execution_count": null,    "metadata": {     "scrolled": true    },    "outputs": [     {      "data": {       "image/png": "iVBORw0KGgoAAAA[truncated]",       "text/plain": [        "<matplotlib.figure.Figure at 0x2f85ef50>"       ]      },      "metadata": {},      "output_type": “display_data"     }    ],    "source": [     "%matplotlib inline\n",     "    \n",     "X = np.arange(len(values))\n",     "plt.bar(X + 0.0, values, facecolor='blue', \n",     "        edgecolor='white', width=0.5, label=\"Written_to_DAC\")\n",     "plt.bar(X + 0.25, samples, facecolor='red', \n",     "        edgecolor='white', width=0.5, label=\"Read_from_ADC\")\n",     "\n",     "plt.title('DAC-ADC Linearity')\n",     "plt.xlabel('Sample_number')\n",     "plt.ylabel('Volts')\n",     "plt.legend(loc='upper left', frameon=False)\n",     "\n",     "plt.show()"    ]   }, 

Listado 1: Un cuaderno de Jupyter es un archivo de texto que está formado por una serie de pares de claves/valores de JSON que tienen secciones de código, lenguaje de marcado y salida como estos, que corresponden a la página representada que se muestra en la Figura 3. Tenga en cuenta que la cadena que corresponde a la imagen .png en esa figura ha sido truncada aquí a los fines de la presentación. (Fuente del código: Xilinx)

Además de las características de registro, el poder del entorno Jupyter se encuentra en su capacidad de ejecutar celdas de código de manera interactiva. Los desarrolladores simplemente seleccionan la celda de interés en su navegador (el borde azul en la Figura 3) y hacen clic en el botón ejecutar en el menú de Jupyter en la parte superior de la ventana de su navegador. A su vez, el servidor del cuaderno de Jupyter le entrega la celda de código correspondiente a un núcleo de ejecución, que es el núcleo interactivo Python (IPython) en el entorno PYNQ. Después de la ejecución del código, el servidor actualiza, de manera asincrónica, tanto el sitio web representado como el archivo de cuaderno con cualquier salida generada por el núcleo.

PYNQ extiende este mismo enfoque al desarrollo basado en FPGA al integrar el marco de Jupyter, incluido el núcleo IPython y el servidor web del cuaderno en los procesadores Arm del SoC de Zynq. El módulo de Python pynq que se incluye en el entorno les proporciona a los programadores la API de Python necesaria para acceder a los servicios de PYNQ en los programas de Python.

Entorno de desarrollo de FPGA

El kit de desarrollo PYNQ-Z1 de Digilent, que está diseñado específicamente para apoyar a PYNQ, les permite a los desarrolladores explorar rápidamente las aplicaciones aceleradas de FPGA simplemente cargando la imagen de Linux reiniciable de PYNQ disponible. La placa PYNQ-Z1 combina el SoC de Zynq XC7Z020 de Xilinx con 512 megabytes (Mbytes) de memoria RAM, 16 Mbytes de memoria flash y una ranura microSD para memoria flash externa adicional. Junto con los interruptores, los botones, los LED y los múltiples puertos de entrada/salida, la placa también proporciona conectores que permiten la expansión a hardware externo a través de la interfaz del Pmod (módulo periférico) de Digilent y a través de los escudos Arduino y los escudos chipKIT de Digilent. La placa también destaca el convertidor analógico-digital (ADC) del SoC de Zynq, denominado XADC, como seis puertos de entrada analógica de un solo extremo o cuatro puertos de entrada analógica diferenciales. Digilent también provee el kit de productividad PYNQ-Z1, que incluye un suministro de energía, un cable micro USB, una tarjeta microSD precargada con una imagen PYNQ y un cable de Ethernet para actualizar o agregar módulos de Python.

Para el desarrollador, las capacidades completas del SoC y de la placa están disponibles prontamente a través de un cuaderno de Jupyter. Por ejemplo, acceder a la interfaz de Pmod de la placa para leer el ADC y escribir valores del convertidor de digital a analógico (DAC) en una prueba de bucle de retorno requiere solo algunas líneas de código (Figura 5). Después de importar los módulos de Python requeridos, la PL del SoC se ejecuta con una plantilla de “base” (celda dos en la Figura 5). Al igual que un paquete de soporte de una placa convencional, esta plantilla de base brinda acceso a los periféricos de la placa.

Imagen del cuaderno de Jupyter incluido en el repositorio de muestra de Xilinx

Figura 5: Un cuaderno de Jupyter incluido en el repositorio de muestra de Xilinx muestra el patrón de diseño simple asociado con el acceso a los servicios de hardware para las transacciones de entrada/salida. (Fuente de la imagen: Xilinx)

Los desarrolladores solo tienen que recurrir a los módulos importados para leer y escribir los valores (celda tres en la Figura). En el cuaderno de muestra que se muestra, el servidor del cuaderno emite cada celda en secuencia y actualiza el cuaderno con los resultados generados. En este caso, el único valor de salida es 0.3418, pero cualquier error de ejecución aparecerá como pilas de rastreo Python normales alineadas con sus celdas de código correspondientes.

Crear aplicaciones complejas

Este enfoque aparentemente simple orientado al desarrollo de las aplicaciones integradas, junto con la amplia gama de módulos de Python disponibles, esconde una plataforma potente para implementar, de manera rápida, aplicaciones complejas con un uso intensivo de recursos informáticos. Por ejemplo, los desarrolladores pueden implementar rápidamente una cámara web de detección facial utilizando la entrada HDMI de la PYNQ-Z1 y la famosa librería de visión por computadora de código abierto OpenCV. Después de cargar la plantilla de base y la interfaz de la cámara web, los desarrolladores inicializan una entrada de video de objeto de cámara OpenCV (Figura 6). Entonces, leer la imagen de video es tan simple como un llamado a videoIn.read(), frame_vga recurrente en este ejemplo.

Imagen del cuaderno de Jupyter incluido en el repositorio de muestra de Xilinx

Figura 6: Un cuaderno de Jupyter, que se incluye en el repositorio de muestra de Xilinx, muestra cómo los desarrolladores pueden crear rápidamente un sistema de reconocimiento facial con una cámara web al combinar los recursos de hardware de la placa de desarrollo PYNQ-Z1 con funciones de procesamiento de imágenes potentes disponibles en la librería de OpenCV (cv2). (Fuente de la imagen: Xilinx)

En un paso posterior, administrado como una celda separada en el cuaderno, los desarrolladores crean objetos clasificadores de OpenCV (cv2) utilizando criterios preestablecidos y agregando cuadros delimitadores para identificar características (verde para los ojos y azul para las caras, en este ejemplo). En otro par de celdas, la aplicación se completa después de mostrar la salida utilizando la salida de HDMI de la placa (Figura 7).

Imagen de las celdas finales en el cuaderno de detección facial con cámara web de Xilinx

Figura 7: Las celdas finales en el cuaderno de detección facial con cámara web de Xilinx usan los clasificadores de OpenCV, cuyos resultados se utilizan para agregar cuadros de delimitación a las imágenes originales y se muestran utilizando el puerto de salida HDMI de la placa de desarrollo PYNQ-Z1. (Fuente de la imagen: Xilinx)

La capacidad de crear, probar y compartir de manera interactiva el análisis sobre un software complejo ha hecho que los cuadernos de Jupyter sean elegidos por los científicos y los ingenieros que buscan optimizar los algoritmos para aplicaciones de inteligencia artificial. A medida que evoluciona el trabajo, el cuaderno no solo muestra el código y la salida, sino también el análisis del desarrollador sobre los resultados, y esto brinda un tipo de descripción informática que se puede compartir con los miembros del equipo y colegas.

Sin embargo, los desarrolladores deben entender que es poco probable que los cuadernos sean repositorios para más esfuerzos orientados a la producción. Por ejemplo, su inclusión de grandes cadenas hexadecimales codificadas para los datos de imágenes (consulte la sección truncada en el Listado 1), no solo aumenta el tamaño del documento, sino que puede complicar métodos de diferencias utilizados por los sistemas de control de versión de fuente típicos. El entrelazamiento del código y el texto no funcional puede complicar aún más la transferencia del código creado en las etapas analíticas tempranas en los procesos de desarrollo en el nivel de producción. Sin embargo, para la exploración del código y para hacer prototipos rápidamente, los cuadernos de Jupyter brindan un entorno de desarrollo potente.

Conclusión

Los FPGA brindan una mejora de rendimiento necesaria para alcanzar las crecientes demandas de los sistemas integrados diseñados para el IoT, la visión por computadora, la automatización industrial, la industria automotriz y muchas más. Si bien las metodologías de desarrollo de FPGA convencionales siguen siendo un obstáculo para muchos desarrolladores, el surgimiento del entorno de desarrollo de PYNQ basado en Python que se basa en los cuadernos de Jupyter brinda una alternativa eficaz. Al utilizar una placa de desarrollo diseñada específicamente para apoyar a PYNQ, los desarrolladores que tienen poca experiencia con FPGA pueden implementar rápidamente diseños que son capaces de aprovechar al máximo el rendimiento de FPGA para acelerar las aplicaciones con un uso intensivo de recursos informáticos.

Descargo de responsabilidad: Las opiniones, creencias y puntos de vista expresados por los autores o participantes del foro de este sitio web no reflejan necesariamente las opiniones, las creencias y los puntos de vista de Digi-Key Electronics o de las políticas oficiales de Digi-Key Electronics.

Acerca de este autor

Stephen Evanczuk

Stephen Evanczuk tiene más de 20 años de experiencia escribiendo para y sobre la industria de electrónica en un amplio rango de temas, entre ellos hardware, software, sistemas y aplicaciones, que incluyen IoT. Se doctoróen neurociencias (redes neuronales) y trabajó en la industria aeroespacial en sistemas seguros con distribución masiva y métodos de aceleración de algoritmos. Actualmente, cuando no escribe artículos sobre tecnología e ingeniería, trabaja en aplicaciones de aprendizaje profundo sobre sistemas de reconocimiento y recomendaciones.

Acerca de este editor

Editores de Digi-Key de América del Norte