Introducción
Enviar un flujo de bits (bitstream) a la FPGA normalmente implica usar una interfaz gráfica de usuario. Herramientas como el Hardware Manager de Vivado ofrecen esta funcionalidad, pero el procedimiento suele parecer demasiado complicado para una tarea tan sencilla. En particular, cuando solo hay una FPGA conectada al ordenador mediante un único cable JTAG, la interfaz exige un montón de pasos innecesarios. Si solo hay una FPGA, ¿por qué no puede deducir el ordenador que debe escribir el archivo de bitstream en esa FPGA? ¿Por qué hace falta decirle explícitamente a las herramientas lo que queremos hacer? Realmente solo hay una opción.
Una solución posible es usar un script de bash que realice esta tarea en un solo paso. Este script localiza la FPGA que está conectada al ordenador mediante un cable JTAG y envía el archivo de bitstream a esa FPGA.
El script
Este es el script que envía un archivo de bitstream a la FPGA:
#!/bin/bash
set -e
if [ "$#" -ne 1 ]; then
echo "Usage: $0 bitstream-file.bit"
exit 1
fi
if ! which vivado >/dev/null ; then
echo Vivado is not in the execution path. Please run something like
echo source /path/to/..../Vivado/20nn.n/settings64.sh
exit 1
fi
if [ ! -f "$1" ] ; then
echo \"$1\" file doesn''t exist
exit 1
fi
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" <<"EOF"
# Tcl script begins here.
set bitfile [lindex $argv 0]
open_hw
connect_hw_server
open_hw_target [lindex [get_hw_targets -of_objects [get_hw_servers localhost*]] 0]
set thefpga [lindex [get_hw_devices] 0]
set_property PROGRAM.FILE "$bitfile" $thefpga
set_property PROBES.FILE {} $thefpga
current_hw_device $thefpga
refresh_hw_device -update_hw_probes false $thefpga
program_hw_devices $thefpga
# Tcl script ends here
EOF
then
echo -e "\nProgramming successful.\n"
else
echo -e "\nProgramming failed.\n"
fi
Ten en cuenta que este script de bash contiene un script de Tcl. Uno de los argumentos que se le pasa al comando «vivado» es «-source /dev/stdin». Eso hace que Vivado lea el script de Tcl desde la entrada estándar. Para ello se utiliza el conocido método del «here document», gracias a «<<».
Cómo usar el script
Escribe el script que se muestra arriba en un archivo, por ejemplo con el nombre fpga_program. Haz que ese archivo sea ejecutable con un comando como este:
$ chmod a+x fpga_program
Antes de intentar ejecutar el script, configura las variables de entorno con un comando parecido a este:
$ source /opt/xilinx/Vivado/2023.1/settings64.sh
Cambia la parte «/opt/xilinx/Vivado/2023.1» de ese comando para que la ruta (path) refleje el sitio donde está instalado Vivado en tu ordenador.
Después ejecuta el script con un comando como este:
$ ./fpga_program myproj.bit
Por supuesto, cambia «myproj.bit» por el nombre de tu archivo de bitstream.
Vivado genera mucha salida mientras se ejecuta este script, pero la última línea será «Programming successful» o «Programming failed».
Algunos comentarios sobre el script
Este script se ha probado con Vivado 2015.2 y Vivado 2023.1, así que hay muchas posibilidades de que funcione con todas las versiones de Vivado. Sin embargo, con las versiones recientes de Vivado, el software imprime la siguiente advertencia:
WARNING: 'open_hw' is deprecated, please use 'open_hw_manager' instead.
El script funciona a pesar de esta advertencia. No obstante, es posible que las versiones futuras de Vivado no reconozcan el comando «open_hw». Si este comando da un error, cámbialo en el script por «open_hw_manager».
Otro cambio posible en el script tiene que ver con la cantidad de salida que genera. Si no quieres tanto texto de salida, añade una redirección para que la salida vaya a /dev/null.
Si quieres hacerlo, localiza esta línea en el script:
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" <<"EOF"
Y cámbiala por:
if vivado -mode batch -nolog -nojournal -source /dev/stdin -tclargs "$1" > /dev/null <<"EOF"
Cómo detener el servidor de hardware
Si usas varias versiones de Vivado en el mismo ordenador, puede haber dificultades con la conexión al cable JTAG. La razón de este problema es que Vivado utiliza un servidor TCP/IP para comunicarse con el hardware (escucha en el puerto 3121). Vivado arranca este servidor automáticamente cuando hace falta.
Pero si el servidor lo arrancó una versión de Vivado y otra versión de Vivado intenta conectarse con la FPGA, la comunicación puede no funcionar. La razón es que la versión del servidor es la misma que la de Vivado. Esta situación también ocurre cuando se usa el Hardware Manager con la interfaz gráfica.
Cuando ocurra este problema, se puede detener el servidor con este comando:
$ killall hw_server
Ten en cuenta que el servidor se detiene solo si permanece sin uso durante un tiempo.