jueves, 6 de abril de 2017

Tutorial: Cómo Programar y Simular la FPGA de ZYBO en VDHL con Vivado

En este tutorial explicaré como empezar un proyecto en Vivado para crear sencillos programas en la FPGA usando la placa ZYBO de Digilent. (aunque analogamente se puede usar para otros tarjetas de desarrollo como ZedBoard o otras basadas en Zynq).
La tarjeta ZYBO, y todos los Soc (System on Chip) cuentan con una parte FPGA y otra de Procesador. El FPGA se considera programar "Hardware" y el porcesador es un ARM de 2 núcleos que se programa con software, como cualquier otro microprocesador.
Al final veremos como simular nuestro código VHDL con la herramienta Vivado.

Empezamos creando un nuevo proyecto seleccionando la placa Zybo como 'target board'


Selecciona  en "boards" Zybo. Por defecto vivado no cuenta con el archivo de definicion "Definition file" de todas las tarjetas. para añadir la Zybo (o ZedBoard) descarga aquí los archivos de Digilent e introdúcelos en el directorio de instalación de Vivado. Esta carpeta se encuentra normalmente, y en mi caso, en C:\Xilinx\Vivado\2016.2\data\boards\board_files pero puede variar en función de dónde hayas instalado Vivado.



Crea un nuevo diagrama de bloques y ábrelo:


Una vez abierto el diagrama de bloques podrás incluir tus IPs (Intelectual Property). Un IP es una función que puede ser creada por tí mismo o de una librería. Ahora incluye el bloque "ZYNQ7_Processing_system".
Puedes clickear en el "run processor system". Esto crea automáticamente

Doble click en el bloque ZYNQ para entrar en el menú de propiedades del IP. Esto funciona con todos los bloques.
 En este caso no vamos a usar el bus AXI, por lo que podemos desseleccionar la casilla.



Para alimentar nuestro circuito FPGA con una señal de reloj, usaremos la señal procedente del Processor System. Este reloj se puede configurar, entre 0 y 250MHz, en las propiedades del bloque de ZYNQ.

Para el caso que quieras usar una frequencia de reloj mayor, (ZYBO admite en la FPGA hasta 400 MHz) deberás añadir un bloque llamado "clock wizard" para generar la frecuencia necesaria hasta 400 MHz.

[FOTO clock Wizard]

Ahora añadimos una nueva fuente "Add source" para crear nuestro código VHDL:


Ahora te saldrá la opción de configurar el módulo del VHDL, esto se puede hacer por código en el archivo. Puedes añadir las entradas y salidas del modulo, aunque yo prefiero no utilizar el editor y escribir directamente después en VHDL. Ahora configuramos una señal clk como entrada y una pwm como salida:

Hemos creado un archivo VHDL como fuente, 'source code'. Este ahora lo insertamos en nuestro diagrama de bloques, para ello hacemos doble click y seleccionamos "add module"



seleccionamos el módulo previamente creado:
Y nos quedará el diagrama de bloques de la siguiente manera:

Ya podemos rutear la señal del reloj del PS (Processing System) con nuestra entrada "clk". La salida "pwm" debemos conectarla a un pin de salida, esto se hace haciendo click derecho en el pin pwm y seleccionando "make external"
Así queda hasta ahora el diagrama de bloques:

Para modificar el código de nuestro bloque lo seleccionamos y pulsamos F7. Nos encontraremos con el archivo VHDL de la siguiente manera:
Añadir el código necesario para el PWM:



Ahora debemos empezar la simulación, para testear que todo funciona.
Para empezar la simulación creamos un nuevo diagrama de bloques, para hacer un banco de pruebas y probar las funcionalidades de nuestro bloque.
Hacemos click en "create Block Design" y lo renombramos como testbench:

Si nos fijamos en la ventana "sources" de Vivado, está la carpeta "Design Sources" y "Simulation Sources". El contenido de la carpeta Design se usará luego para generar los archivos necesarios para cargarlos en la tarjeta. Los archivos de Simulation se usarán sólo en el entorno de simulación y serán obviados en los pasos posteriores. Ahora seleccionamos qué archivos deben ser únicamente simulados y cuáles deben ser compilados.



Haciendo click derecho sobre el diagrama de bloques podemos ir a "Set used in..."

Nuestro banco de pruebas o testbench ha de tener la siguientes propiedades:

Y para nuestro diseño o programa para sintetizar, implementar y cargar en la tarjeta ZYBO ha de ser:


En el diagrama de bloques para la simulación añadimos el bloque "Simulation Clock Generator". Este bloque nos generará un reloj para las simulaciones.
 A continuación añadimos el módulo previamente creado PWM2, conectamos la señal de reloj y creamos el pin externo para la salida pwm.


El siguiente paso será crear un envoltorio o 'wrap' para los diagramas de bloques:


Como norma general hay que refrescar lo módulos que no están actualizados. En este caso tendremos un error si no actualizamos todos los módulos. Para ello hacemos click en "refresh modules" y posteriormente creamos el wrap de ambos diagramas.
nuestra jerarquía quedaría de la forma:


En la opciones de simulación hemos de comprobar que el 'top module' es nuestro diagrama testbench.


Una vez configurado, empezamos la simulación:


Tras pulsar "Run behavioral Simulation" se debe abrir la siguiente ventana:

Para añadir señales a nuestro diagrama de ondas, simplemente buscamos los bloques previamente instanciados en la parte izquierda y arrastramos hasta el diagrama. Después ejecutamos la simulación para actualizar los valores añadidos.


Reajustando el zoom configurando la señal counter como analógica para una mejor visualización... obtenemos algo parecido a esto:
Sin entrar en detalles, la simulación comprobamos que todo funciona como habíamos diseñado, en caso contrario habría que volver al código VHDL, reescribir y volver a simular.

Ahora suponemos que la simulación es correcta. El siguiente paso es comprobar que nuestro design_1 está actualizado. Los siguientes pasos serán:
  1. Validar el diseño
  2. Síntesis
  3. Configuración de los pines de entrada/salida.
  4. Implementación
  5. Generar Bitstream
Para validar el diseño (F6) oclick en el símbolo de la siguiente imagen:

Iniciar Síntesis:

Cuando la síntesis termina, debemos indicarle a Vivado que pines queremos utilizar para la salida del PWM en este caso. Este paso deberemos realizarlo únicamente la primera vez. En el caso en que cambiemos algo en nuestro diseño y debamos sintetizar otra vez, podemos realizar la implementación directamente, ya que los pines quedarán guardados. Por tanto la segunda vez nos da la opción (si ha terminado sin errores) de ejecutar la implementación.


Para configurar los pines cliqueamos en "open synthesized Design"
Para elegir el pin, abrimos el esquemático de la tarjeta Zybo. En la primera página encontramos los diferentes conectores, debemos elegir un pin. Algunos pines tienen una resistencia en serie de 200 Ohm como medida de seguridad para limitar la corriente. Para un PWM con una respuesta rápida, necesitamos un puerto que no tenga las resistencias de seguridad, por ejemplo el puerto JC, JB o el JD. El conector MIO PMOD es un puerto especial que va directamente al procesador, y no pasa por la FPGA.

En mi caso eslegí el JC1
 Que buscando en la página 10 encontramos a que pin está conectado. En este caso V15.

Volvemos a Vivado y buscamos el pin V15 en la lista:

En el campo "Port" seleccionamos nuestra señal de salida pwm. En el "I/O Standart" LCVMOS33

Ahora ya podemos iniciar la implementación. Pero antes Vivado nos preguntará para guardar la configuración de los pines. Esto se guarda en un archivo llamado 'constraints' . A este archivo le nombraremos "my_pins" por ejemplo.
Este archivo "constraints"  puede ser modificado posteriormente abriéndolo desde los archivos del proyecto en la carpeta Constraints. De hecho, se podría modificar la configuración de los pines únicamente modificando este archivo. 


A continuación iniciamos la implementación, y si todo finaliza sin errores generaremos el Bitstream después. File>> Export>> Export Hardware


Importante incluir el bitstream al exportar el hardware.
A continuación ejecutaremos SDK. SDK es un compilador para programar el procesor ARM. En nuestro caso cargaremos una aplicación vacía, para encender el reloj en el sistema. Para ello click en File>> Lauch SDK

Vivado nos dará la opción para elegir carpetas. Elegimos la opción por defecto, <Local project>.

SDK


Una vez abierto elprograma, seleccionamos File>> New >> Board Support Package
Dejamos la configuración como está y simplemente click en Finish para crear el board_support_package.

En el siguiente panel de configuración tampoco cambiaremos nada, click en OK.
Ahora crea un nuevo projecto vacío:
File >> New >> Application Project
Nombra el proyecto como quieras, en mi caso "Empty_project" y presiona "Next".



Abre el proyecto creado e incluye un loop infinito:
He modificado el código para que escriba por pantalla periódicamente un mensaje. Aunque realmente este paso no es necesario

int main()
{
    init_platform();
while(1){
 int i;
 for(i = 0;i<0XFFFFFF;i++); //Delay
    print("empty project \n\r");
}
    cleanup_platform();
    return 0;
}


Ahora programa la FPGA haciendo click en el icono o en Xilix Tools>> Program FPGA
Confirma que el Bitstream sea el correcto, es decir, el creado y exportado anteriormente.

Una vez programada la FPGA cargamos el software en el procesador ARM. Para ello seleccionamos nuestro proyecto con click derecho >> Debug as.. >> 4.Launch on Hardware (GDB)

Si quieres ver el texto en la pantalla basta con seleccionar

En la etiqueta de STDIO, seleccionar "Connect STDIO to Console" y elige el puerto al que tengas conectado la ZYBO, en mi caso el COM4. Un pequeño truco para ver en que puerto está tu tarjeta conectada es: En el administrador de dispositivos de windows (Device Manager), en la pestaña de COM puedes ver fácilmente conectando y desconectando el USB cuál de los COMs aparece y desaparece. La velocidad de transmisión (Baud rate es 115200).

Con debuggear una vez el código, o ejecutarlo, el reloj de procesador empezará a correr y por tanto nuestro programa en la FPGA.






No hay comentarios:

Publicar un comentario