Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> VHDL

Uso del analizador lógico integrado (ILA) y entrada/salida virtual (VIO)

Este tutorial cubre el uso del Integrated Logic Analyzer (ILA) y Entrada/Salida Virtual (VIO) núcleos para depurar y monitorear su diseño VHDL en el IDE de Xilinx Vivado.

En muchos casos, los diseñadores necesitan realizar una verificación en el chip. Es decir, obtener acceso al comportamiento de una señal interna en su diseño de FPGA con fines de verificación.

Una opción es llevar estas señales a los pines de la FPGA y conectarlas a los LED para ver su comportamiento visualmente. Esta opción es fácil, rápida y funciona bien para casos simples, pero no es flexible, escalable ni realista.

Otra opción es tener un analizador lógico externo con funciones avanzadas que puedan mostrar y representar el comportamiento de estas señales, pero requiere un equipo externo y relativamente costoso.

El Integrated Logic Analyzer (ILA) es una alternativa que combina las ventajas de las dos opciones anteriores. Es fácil, rápido, flexible y tiene muchas funciones avanzadas que ayudan a los diseñadores a ver y verificar rápidamente el comportamiento de las señales elegidas.

Resumen

Este artículo contiene múltiples capturas de pantalla de la GUI de Vivado. ¡Haz clic en las imágenes para agrandarlas!

Use la barra lateral para navegar por el esquema para este tutorial, o desplácese hacia abajo y haga clic en el botón de navegación emergente en la esquina superior derecha si está utilizando un dispositivo móvil.

ILA y VIO

ILA y VIO son direcciones IP personalizables gratuitas de Xilinx. El ILA IP lo ayuda a sondear fácilmente las señales internas dentro de su FPGA y llevarlas a un entorno similar a una simulación para monitorearlas y verificar su comportamiento.

A diferencia de ILA, VIO IP le permite controlar virtualmente señales internas dentro de su FPGA para estimular o controlar su diseño, como controlar la señal RESET.

Requisitos

  1. Una placa FPGA de Xilinx
  2. La suite de diseño Vivado
  3. Conocimiento básico de VHDL

Estoy usando el kit de evaluación Kintex-7 FPGA KC705, pero los métodos que se muestran en este tutorial deberían funcionar en cualquier placa Xilinx FPGA moderna.

Descargar el proyecto de ejemplo

Puede descargar el proyecto de ejemplo y el código VHDL mediante el siguiente formulario. Debería funcionar en Vivado versión 2020.2 o posterior.

Extrae el Zip y abre el ila_tutorial.xpr archivo en Vivado para ver el diseño de ejemplo, o lea el resto de este artículo para aprender a crearlo desde cero.

Crea un proyecto con Vivado

Comience abriendo Vivado. En la pantalla de bienvenida de Vivado, haga clic en Crear proyecto botón.

Haga clic en Siguiente para continuar.

Cambia el nombre del proyecto a ila_tutorial y haga clic en Siguiente.

Nota: No utilice espacios en el nombre del proyecto. En su lugar, utilice un guión bajo o un guión.

Elija proyecto RTL y desmarque No especificar fuentes en este momento y haga clic en Siguiente para continuar.

Agregue los archivos de origen; contador.vhdl y counter_top.vhdl de la carpeta de diseño. Elija VHDL para el idioma de destino. Marque Copiar fuentes en el proyecto y haga clic en Siguiente para continuar.

Agregue el archivo de restricciones top.xdc de la carpeta de diseño. Marque Copiar archivos de restricciones en el proyecto y haga clic en Siguiente para continuar.

Nota: este archivo de restricciones es específico de la placa KC705. Tienes que cambiar el pin clk y el palo led según tu tablero. Y también, el -período del reloj de tu tablero.

Busque su tablero y selecciónelo de la lista. Haga clic en Siguiente para continuar.

Esta es la pantalla final del asistente Nuevo proyecto. Haga clic en Finalizar para abrir su proyecto.

La explicación del ejemplo de diseño

Usaremos un ejemplo simple de cadena de dos contadores para este tutorial.

El contador.vhdl El archivo contiene el código RTL para un contador trivial de 4 bits que cuenta de 0 a 15 cuando está habilitado. Afirma la salida de 1 bit cuando el conteo está entre 12 y 15. Para todos los demás valores, la salida permanece bajo '0' .

Aquí está la interfaz de entidad para el módulo contador.

----------------------------------------------------------------------------
-- ENTITY DECLARATION.
----------------------------------------------------------------------------
  ENTITY counter IS
    PORT(clk     : IN  STD_LOGIC;  -- Main clock 
         reset   : IN  STD_LOGIC;  -- reset, active_high
         enable  : IN  STD_LOGIC;  -- enable the next counter
         trigger : OUT STD_LOGIC   -- trigger the next counter
        );
  END ENTITY;

El diseño del contador tiene dos señales internas:contar y trigger_o .

contar se utiliza para implementar la funcionalidad de conteo.

– y trigger_o es una señal intermedia para conectar el puerto de salida trigger .

No te preocupes por ATTRIBUTE , se explicará más adelante.

----------------------------------------------------------------------------
-- ARCHITECTURE DECLARATION.  
----------------------------------------------------------------------------
  ARCHITECTURE rtl OF counter IS

    -- INTERNAL SIGNALS DECLARATION --
    SIGNAL count     : UNSIGNED(3 DOWNTO 0) := (OTHERS => '0');
    SIGNAL trigger_o : STD_LOGIC := '0';
  
    -- ATTRIBUTE DECLARATION --  
    ATTRIBUTE MARK_DEBUG : STRING;
    ATTRIBUTE MARK_DEBUG OF count : SIGNAL IS "true";

En el listado a continuación, vemos la implementación para el contador. El seq_proc el proceso se activa en el flanco ascendente del puerto de entrada clk y está en modo de reinicio cuando el puerto de entrada reinicia es alto '1'.

El recuento la señal se incrementa cuando el puerto de entrada habilita es alto '1', y el trigger_o la señal se afirma alta cuando el valor de la señal cuenta es entre 12 y 15.

seq_proc: PROCESS (reset, clk)
BEGIN -- for seq_proc
  IF (reset = '1') THEN
    count     <= (OTHERS => '0');
    trigger_o <= '0';
  ELSIF rising_edge(clk) THEN
    IF (enable = '1') THEN
      count <= count + 1;
      IF (count > x"B" AND count <= x"F") THEN
        trigger_o <= '1';
      ELSE
        trigger_o <= '0';
      END IF;
    END IF;
  END IF;
END PROCESS;

El archivo counter_top.vhdl contiene dos instantes del contador conectados secuencialmente.

– El contra_1_inst siempre está habilitado y cronometra el counter_2_inst . Es decir, el puerto de salida disparador de contador_1_inst está conectado al puerto de entrada clk de contra_2_inst .

– El comportamiento resultante es que counter_1_inst activa counter_2_inst sólo 4 de 16 ciclos de reloj. Por lo tanto, count_2_inst incrementará su contador cuatro veces cada 16 cuentas.

Creación del núcleo VIO para RESET

Ahora que comprende el ejemplo de diseño, crearemos un VIO para controlar el puerto de entrada restablecer . Eso nos dará la capacidad de manipular (alternar) el reinicio de Vivado IDE para que podamos controlar manualmente cuándo iniciar/detener los contadores.

Haga clic en Catálogo IP y luego busca VIO , luego haga doble clic en VIO (entrada/salida virtual) .

Primero, cambiamos el nombre a vio_reset .

En segundo lugar, solo necesitamos un puerto de salida para el restablecimiento, por lo que ponemos 0 en el cuadro de recuento de sondas de entrada. y ponemos 1 en el cuadro de recuento de sondas de salida .

Haga clic en PROBE_OUT pestaña de puerto. Como restablecer es una señal de 1 bit, colocamos 1 en el cuadro probe_width, y también ponemos 0x1 en el cuadro de valor inicial por lo que comienza con alto '1'. Luego haga clic en Aceptar y Generar . Vivado ahora comenzará a sintetizar el VIO.

Después de que Vivado termine de sintetizar el VIO, debemos agregarlo a nuestro diseño declarando un componente para él e instanciarlo en counter_top.vhdl archivo como se muestra a continuación.

Primero, agregue una declaración de componente para el vio_reset en la sección de declaración de componentes en counter_top.vhdl archivo.

  -- Declare vio_reset
  COMPONENT vio_reset
    PORT(
      clk        : IN STD_LOGIC;
      probe_out0 : OUT STD_LOGIC_VECTOR(0 DOWNTO 0)
    );
  END COMPONENT;

Ahora, el VIO está completo y estamos listos para sintetizar el diseño. Pero antes de eso, debemos cambiar la configuración de síntesis flatten_hierarchy a Ninguno .

Haga clic en Ejecutar síntesis. y luego en OK .

Cuando Vivado termine la síntesis, haga clic en Abrir diseño sintetizado .

Cambie el diseño a depurar haciendo clic en Diseño y luego Depurar .

Inserción del flujo de la sonda de depuración

Nuestro diseño sintetizado ahora contiene el vio_reset instancia, y es hora de especificar las señales que queremos sondear. Hay tres formas de hacerlo:

  1. Inserción desde archivo VHDL
  2. Inserción desde Netlist
  3. Inserción desde archivo xdc/tcl

Usaremos los dos primeros métodos y dejaremos el tercero para un tutorial posterior.

Inserción desde archivo VHDL

Este método es la forma más fácil y rápida de insertar una sonda, especialmente cuando es de tipo compuesto (matriz o registro). Pero requiere agregar código a los archivos de diseño, código VHDL que es redundante en el producto real.

Podemos insertar una sonda en el archivo de diseño VHDL mediante:

  1. Declarar un atributo especial llamado MARK_DEBUG
  2. Adjunte la señal que queremos sondear con este atributo
  3. Y actívelo dándole el valor "verdadero" como se muestra a continuación:
    -- ATTRIBUTE DECLARATION --  
    ATTRIBUTE MARK_DEBUG : STRING;
    ATTRIBUTE MARK_DEBUG OF count : SIGNAL IS "true";

Nota: solo necesitamos declarar el atributo una vez en cada archivo de diseño VHDL, lo que nos permite adjuntarlo a varias señales.

Podemos ver en el diseño sintetizado que la señal cuenta en ambos counter_1_inst y contra_2_inst se enumeran en Redes de depuración no asignadas y marcado con un icono de error tanto en Netlist y el Esquema .

Inserción desde Netlist

Este método de inserción también es fácil, pero requiere que primero sintetice el diseño y luego haga clic manualmente en cada señal para marcarla para su depuración. Podría ser agotador si el diseño es grande y desea monitorear muchas señales.

Probaremos el puerto de salida trigger en ambos contadores usando la Netlist . Podemos hacerlo desde la ventana Netlist o el Esquema localizando la red de señal y luego haga clic con el botón derecho en él y elija Marcar depuración .

Desde la ventana Netlist, busque trigger en counter_1_inst → Redes → disparador . Luego, haz clic con el botón derecho en él y elige Marcar depuración .

En la ventana Esquema, busque gatillo salida de counter_2_inst . Luego, haz clic con el botón derecho en él y elige Marcar depuración .

Podemos ver que ahora se enumeran en Redes de depuración no asignadas .

Creación del núcleo de depuración de ILA

Ahora es el momento de crear el núcleo de depuración de ILA. Necesitamos crear una sonda para cada señal que queremos analizar. La forma más sencilla es aprovechar el asistente de Vivado Configurar depuración .

Haga clic en Configurar depuración y luego haga clic en Siguiente .

Vivado enumerará todas las señales de depuración y capturará el dominio del reloj automáticamente. Aquí vemos que nuestras cuatro señales están listadas. Puede eliminar las señales que no le interesen o agregar señales adicionales, pero las usaremos todas.

Nota: no tenemos que usar todas las señales que hemos marcado como Depuración.

Haga clic en Siguiente .

Ahora configuramos el ILA eligiendo la profundidad FIFO y revisando Control de captura . Podemos dejar el FIFO en 1024 ya que es suficiente profundidad para nuestro ejemplo.

Haga clic en Siguiente .

Ahora vemos que Vivado encontró un reloj y creará un núcleo de depuración.

Haga clic en Finalizar .

Ahora podemos ver un núcleo de depuración de ILA con cuatro sondas agregadas a la pestaña de depuración y la ventana Netlist .

IMPORTANTE: Es muy importante guardar la restricción en esta etapa para que pueda agregarse al diseño. De lo contrario, corremos el riesgo de perder nuestro núcleo ILA.

Haz clic en Guardar o presiona Ctrl+S.

Nombre el archivo ila_core y haz clic en Aceptar .

El ila_core.xdc El archivo se agregará a la restricción e incluye el código y la configuración para el ILA.

Echemos un vistazo al contenido del archivo. Puede abrir el archivo yendo a la ventana de origen → expanda la carpeta de restricciones → expanda constr_1 .

Primero, vemos que el archivo agrega un atributo de depuración a las señales que marcamos como depuración mediante la inserción de Netlist.

A continuación, vemos la creación y configuración de un núcleo ILA.

A continuación, vemos la creación, configuración y conexión de cada sonda.

A continuación, vemos la creación de un centro de depuración (dbg_hub ).

El concentrador de depuración es responsable de la comunicación entre Vivado IDE y los núcleos de depuración (ILA y VIO). Vemos que define una frecuencia de reloj (la predeterminada es 300 MHz). Debe cambiar ese reloj para que coincida con su frecuencia de reloj y guardar el archivo.

Nota: el reloj conectado a ILA y Debug_hub debe ser un reloj de ejecución libre.

Ahora, el ILA está completo y guardado. Necesitamos volver a ejecutar la síntesis para que el ILA se pueda agregar al diseño sintetizado.

Haga clic en Ejecutar síntesis. y luego en OK .

Cuando Vivado termine de ejecutar la síntesis, haga clic en Abrir diseño sintetizado y luego en Esquema .

Podemos ver ahora que Vivado agregó ILA y Debug_Hub a nuestro diseño y conectó las señales de depuración a las sondas ILA.

Ahora estamos listos para implementar nuestro diseño y generar el flujo de bits para que podamos probar nuestro diseño.

Haga clic en Ejecutar implementación y luego en OK .

Después de que Vivado termine de ejecutar la implementación, haga clic en Generar flujo de bits y luego en OK .

Después de que Vivado termine de generar el flujo de bits, haga clic en Abrir administrador de hardware y luego en Open Target, y finalmente en Conexión automática .

A continuación, necesitamos programar el FPGA con el archivo de bits (*.bit) y el archivo de sonda de depuración (*.ltx). Vivado los encuentra automáticamente por usted.

Haga clic en Dispositivo de programa y luego en Programa .

Configurar los activadores de ILA

Después de programar el dispositivo, podemos ver que el diseño de la GUI de Vivado ha cambiado y un nuevo hw_ila_1 se ha abierto el panel de control, que contiene varias ventanas.

Minimizaremos algunas ventanas que no necesitamos para poder trabajar cómodamente.

En las opciones del panel, marca hw_vio_1 y desmarque Configuración de captura .

Además, cierre el hw_vios pestaña porque cuando comprobamos hw_vio_1 , se ha agregado a la Configuración de activadores ventana.

Ahora, necesitamos agregar el restablecer botón al VIO para que podamos controlar el restablecer .

Haz clic en hw_vio_1 y luego agregue restablecer como se muestra en la imagen de abajo.

Podemos ver que hw_vio_1 ahora contiene el restablecer sonda.

Cambiar el valor del restablecimiento en vio_reset a 1 si no es 1.

Ahora, agregaremos los disparadores que usaremos. Un cambio de valor en una señal de disparo hará que el ILA comience a registrar las señales probadas.

Digamos que queremos disparar (comenzar a grabar) en el flanco ascendente del puerto de salida disparar de contra_1_inst . Para ello, sigue estos pasos:

  1. Ir a la Configuración del activador:hw_ila_1 ventana
  2. Haga clic en + icono para agregar un nuevo activador y elegir counter_1_inst/trigger y haga clic en Aceptar.

  1. Podemos ver que se agregó el activador y ahora debemos configurar la condición. Haga clic en el cuadro Valor y elija R (transición de 0 a 1) . Haga clic en el cuadro Operador y elige ==(igual)

También cambiaremos la posición de activación a 32, lo que significa que grabará 32 muestras antes del evento de activación además de lo que viene después.

Ahora, el gatillo está configurado y listo para ser armado.

Ahora, pasamos a la ventana de forma de onda para añadir las señales que queremos visualizar. Primero, maximicemos la ventana interior para obtener una mejor vista.

En segundo lugar, necesitamos agregar algunas señales faltantes a la sonda. Vivado generalmente agrega todas las señales asignadas automáticamente, pero en este caso no lo hizo.

Ahora, cambiamos la raíz del conteo señal a Unsigned ya que es más fácil de seguir.

Haga clic derecho en el recuento nombre de la señal y luego elija radix y luego Sin firmar .

Ejecución de ILA y VIO

Ahora, hemos terminado de configurar y personalizar el ILA y estamos listos para ejecutarlo.

ILA tiene dos modos de ejecución:Inmediato y gatillo .

Modo inmediato

El modo inmediato activa el ILA inmediatamente y comienza a registrar las muestras directamente hasta que el FIFO está lleno.

Haga clic en Ejecutar activación inmediata botón.

Ahora podemos ver las muestras grabadas en la ventana de forma de onda. Vemos que ambos cuentan las señales son 0, y ambos gatillo las señales son bajo '0' porque el restablecer está activo.

Modo de disparo

El modo de activación requiere que configuremos una condición para al menos un activador y lo armemos. El ILA seguirá esperando que la condición del disparador armado se haga realidad y luego comenzará a registrar las muestras directamente hasta que el FIFO esté lleno.

Ya agregamos el activador y lo configuramos en R (transición de 0 a 1) .

Ejecutar ILA con un disparador

Cambiar restablecer volver a 1 de vio_reset .

Haga clic en la ventana Estado hw_ila_1 . Vemos que el estado principal es Inactivo ya que no hay gatillos armados. Haz clic en el Activador de ejecución y eso armará el gatillo.

Vemos ahora que el estado principal cambió a esperando activación . Como restablecer es alta, no hay actividad en nuestra señal de disparo (puerto trigger de contra_1_inst ), e ILA está esperando.

Ahora, cambiemos el restablecer a 0 para que los contadores empiecen a funcionar.

Ahora vemos que el ILA se activó y registró las muestras, y el estado del núcleo volvió a cambiar a Inactivo .

Vemos la línea vertical roja (marcador) en el borde ascendente de nuestra señal de disparo (puerto disparador de contra_1_inst ), y está en la posición 32 . También podemos verificar que la señal cuenta se comporta correctamente y la señal counter_1_inst/trigger es alta durante cuatro ciclos de reloj entre 12 y 15 (la salida se retrasa un ciclo de reloj).

Si nos alejamos un poco, también podemos verificar el comportamiento de count y activar señales para counter_2_inst .

Ejecutar ILA con múltiples disparadores

Podemos usar una combinación de disparadores para condiciones complejas o avanzadas. Para capturar varios marcos de tiempo inconexos en la misma forma de onda, podemos usar múltiples disparadores que se disparan repetidamente.

Por ejemplo, digamos que queremos activar cuando el recuento señal de counter_1_inst es igual a 9 (cuenta ==9) y cuando el cuenta señal de counter_2_inst es mayor que 2 (recuento> 2). Para hacer eso y dividir el FIFO en cuatro ventanas de tiempo, siga estos pasos:

  1. Cambiar restablecer volver a 1 de vio_reset
  2. Eliminar la sonda desencadenante anterior:

  1. Agregue ambos recuentos señales como disparadores:

  1. Configurar el recuento de señales para contra_1_inst a (contar ==9):

  1. Configurar el recuento de señales para contra_2_inst a (contar> 2):

  1. Configure el número de ventanas en 4 y profundidad FIFO a 256, y posición a 32 .

  1. Haga clic en el Activador de ejecución botón, y eso armará el gatillo. Observe que en la ventana Status hw_ila_1 , el estado de captura ahora es ventana 1 de 4 porque tenemos cuatro ventanas.

Cambiar restablecer volver a 0 de vio_reset .

Maximice la ventana de forma de onda. Vemos ahora que tenemos cuatro ventanas y un activador asociado a cada ventana. Tenga en cuenta que estas ventanas son independientes y no continuas.

El ILA espera a que suceda el evento desencadenante y, cuando lo hace, utiliza la primera ventana para registrar 256 muestras. It then immediately waits for the next trigger until all the windows are full.

Running ILA with Auto re-trigger mode

ILA has a nice feature called Auto re-trigger that will automatically arm the trigger after it gets triggered. It is useful when monitoring events that occur seldom and you want to run a test overnight. Or you can use it when the trigger happens so often and fast that you cannot arm the trigger manually to capture the samples repeatedly.

Let us assume that the output port trigger of counter_2_inst gets asserted every 3 hours, and you want to record the data each time it happens. To use the Auto trigger, follow these steps:

  1. Change reset back to 1 from vio_reset
  2. Remove the previous trigger probe
  3. Add trigger_2_OBUF signal as trigger:

  1. Configure the trigger to the condition to equal (==) and falling edge F(1-to-0 transition)
  2. Configure the number of windows to 1 and FIFO depth to 1024, and position to 32:

  1. Click on Auto re-trigger button:

  1. Finally, change reset back to 0 from vio_reset:

We can see now that the waveform window is getting refreshed and updated as the trigger happen. It is fast, but the behavior is noticeable.

Click on Stop trigger and toggle Auto re-trigger .

Running ILA with Capture mode

Another feature of ILA is the Capture mode . In some cases, you are not interested in recording all the data but rather capture a specific sample. Capture mode helps you filter out data and record only the samples you are interested in.

Let’s say we are only interested in sampling when the output port trigger of counter_1_inst is ‘1’ AND the output port trigger of counter_2_inst is ‘0’.

To use Capture mode to achieve this, follow these steps:

  1. Change reset back to 1 from vio_reset
  2. Remove the previous trigger probe
  3. From the dashboard, Uncheck Trigger Setup and check Capture Setup . Notice that a Capture Setup window will appear. From the Settings – hw_ila_1 window, Change Capture mode to BASIC , the window to 1, the FIFO depth to 1024, and position to 1:

  1. Add trigger_2_OBUF , and counter_1_inst/trigger from the Capture Setup window:

  1. Configure counter_1_inst/trigger to the condition equal (==) and 1 (logical one) :

  1. Configure trigger_2_OBUF to the condition equal (==) and 0 (logical zero) :

  1. Change the Capture Condition to Global AND :

  1. Click on the Run trigger button and then change reset to 0 from vio_reset :

As we can see from the image below, the waveform has only recorded data when counter_1_inst’s count signal is 13, 14, 15, or 0. Any other counts are filtered out because counter_1_inst/trigger is high on these counts only.

Conclusión

In this tutorial, we learned about ILA and VIO and different use-cases for them. ILA and VIO are excellent options for on-chip debugging. They are free, easy to use, flexible, scalable, and simple yet offer advanced features. The use of multiple triggers and Capture mode helps you achieve a complex debugging scheme.


VHDL

  1. Tutorial - Escritura de código combinacional y secuencial
  2. A Cloud Infinity y más allá
  3. Entrada y salida básica de C#
  4. Entrada/salida básica de C++
  5. C Entrada Salida (E/S)
  6. Entrada, salida e importación de Python
  7. Entrada y salida básica de Java
  8. Sensor de temperatura Python y Raspberry Pi
  9. Pestillo D
  10. C - Entrada y Salida
  11. RightHand Robotics y Element Logic lanzan una solución robótica integrada de selección de piezas