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

Archivo de estímulo leído en el banco de pruebas usando TEXTIO

La lectura de valores de señal del archivo es una forma alternativa de generar estímulos para el dispositivo en prueba (DUT). La secuencia y el tiempo del banco de pruebas están codificados en un archivo de estímulo que lee el banco de pruebas VHDL, línea por línea. Esto le permite cambiar fácilmente el patrón de la forma de onda que desea enviar al objeto de prueba.

A veces, tiene un patrón de prueba muy específico o una secuencia de eventos por los que desea someter su DUT. Puede lograr esto especificando en un archivo ASCII los valores de señal que debe tener cada señal, así como el tiempo de simulación relativo en el que deben cambiar. El papel del banco de pruebas VHDL en dicha estrategia es leer los datos del archivo de estímulo y aplicar los valores a las entradas del DUT en el momento correcto.

Este artículo es el segundo de una serie sobre el acceso a archivos en VHDL. Vimos cómo leer valores hexadecimales, octales y binarios desde un archivo en la publicación de blog anterior, regrese y léalo si quiere saber más sobre cómo leer desde un archivo usando el TEXTIO biblioteca en VHDL.

Esta publicación de blog es parte de una serie sobre el uso de la biblioteca TEXTIO en VHDL. Lea los otros artículos aquí:

Cómo inicializar RAM desde un archivo usando TEXTIO

Imagen de mapa de bits de archivo BMP leída con TEXTIO

El caso de prueba

El DUT de ejemplo será un multiplexor de 4 entradas (MUX) tomado de una de mis publicaciones de blog anteriores. Es un MUX 4 a 1 asíncrono estándar con un ancho de datos de un byte. Cómo funciona no es importante para este artículo porque no vamos a hacer ninguna verificación de los resultados, es solo para fines de demostración.

La entidad del MUX se muestra a continuación.

entity mux_4 is
  port(
    -- Data in
    din_0 : in unsigned(7 downto 0);
    din_1 : in unsigned(7 downto 0);
    din_2 : in unsigned(7 downto 0);
    din_3 : in unsigned(7 downto 0);

    -- Selector
    sel  : in unsigned(1 downto 0);

    -- Data out
    dout : out unsigned(7 downto 0));
end entity;

Después de importar los paquetes necesarios en la parte superior del archivo VHDL, declaramos las señales de entrada que vamos a conectar al DUT. Como puede ver en la lista a continuación, son planos de la declaración de entidad MUX.

signal din_0 : unsigned(7 downto 0);
signal din_1 : unsigned(7 downto 0);
signal din_2 : unsigned(7 downto 0);
signal din_3 : unsigned(7 downto 0);
signal sel  : unsigned(1 downto 0);
signal dout : unsigned(7 downto 0);

Usamos el método de creación de instancias de entidades para crear una instancia de MUX con la etiqueta "DUT" en la parte superior de la región de arquitectura de nuestro banco de pruebas. Las señales de la entidad están conectadas a las señales del banco de pruebas local con los mismos nombres, como se muestra en el código a continuación.

DUT: entity work.mux_4(rtl)
port map (
    din_0 => din_0,
    din_1 => din_1,
    din_2 => din_2,
    din_3 => din_3,
    sel  => sel,
    dout => dout
);

El archivo de estímulo

Un archivo de estímulo puede tener muchos formatos diferentes, el que se presenta aquí es solo un ejemplo que se me ocurrió mientras escribía este artículo. Sin embargo, cuando entiendas cómo lo creé, deberías poder modificarlo para adaptarlo a tus necesidades.

La siguiente lista muestra el archivo de estímulo completo utilizado en este ejemplo.

# Column description:
# wait_time | sel | din_0 | din_1 | din_2 | din3 # Optional console printout

0 ns 0 AA BB CC DD # Setting initial values
10 ns 1 AA BB CC DD # Testing by changing the selector signal
10 ns 2 AA BB CC DD
10 ns 3 AA BB CC DD
10 ns 3 A1 B1 C1 D1 # Testing by changing all data inputs
10 ns 3 A2 B2 C2 D2
10 ns 3 A3 B3 C3 D3
10 ns 3 00 00 00 D2 # Changing all unselected inputs
10 ns 3 01 02 03 D2
10 ns 3 11 22 33 D2
1 ns 0 CC DD EE FF # Changing all inputs fast
1 ns 1 DD EE FF CC
1 ns 2 EE FF CC DD
1 ns 3 FF CC DD EE
10 ns 0 00 00 00 00 # Simulation stop

Ignoremos los comentarios por ahora, esos son los marcados en verde, siempre comenzando con un carácter '#'. Cada línea representa un paso de tiempo en la simulación. Hay seis columnas de comandos en cada línea, en realidad siete columnas de texto, pero las dos primeras columnas pertenecen al mismo elemento de datos.

Las columnas de texto uno y dos describen un valor de tiempo, por cuánto tiempo el simulador debe hacer una pausa en esa línea antes de aplicar los valores que se enumeran en las otras columnas. Así, el tiempo absoluto de simulación cuando se ejecuta el comando es relativo al evento descrito en la línea anterior. Estamos usando solo 0, 1 o 10 nanosegundos, pero podría ser cualquier cosa, 1000 nanosegundos o 1000 horas (1000 hr ) para el caso.

Las cinco columnas de texto restantes describen los valores de señal que se aplicarán a las entradas del dispositivo bajo prueba. Se dan como literales hexadecimales y el orden de las señales es sel , din_0 , din_1 , din_2 y finalmente din_3 .

Ahora, pasemos a los comentarios. Hay dos tipos de comentarios; comentarios de una sola línea y comentarios finales. Nuestro banco de pruebas los tratará de manera diferente. Los comentarios de una sola línea, como los que se encuentran en la parte superior del archivo, se ignorarán. Los comentarios posteriores, por otro lado, se imprimirán en la consola del simulador. Podemos usarlos para darnos pistas sobre lo que sucede mientras se ejecuta la simulación.

Leyendo el archivo de estímulo en VHDL

VHDL no es el mejor lenguaje para el procesamiento de texto, pero hace el trabajo. El soporte para cadenas dinámicas es limitado y carece de rutinas convenientes, por ejemplo, para eliminar u omitir espacios en blanco. Para que sea más fácil para nosotros, vamos a suponer que el archivo de estímulo está bien escrito. Tengamos mucho cuidado para asegurarnos de que siempre haya un espacio entre los elementos de texto y un solo espacio entre el carácter '#' y el texto del comentario. Además, no hay espacios iniciales o finales adicionales en ninguna parte del archivo de estímulo.

PROC_SEQUENCER : process
  file text_file : text open read_mode is "stimulus.txt";
  variable text_line : line;
  variable ok : boolean;
  variable char : character;
  variable wait_time : time;
  variable selector : sel'subtype;
  variable data : dout'subtype;
begin

La región declarativa del PROC_SEQUENCER el procedimiento se muestra arriba. Primero, declaramos el file especial objeto, un tipo de controlador de archivos VHDL. Luego, declaramos una variable de tipo line . Esto es simplemente un tipo de acceso a una cadena, un puntero a un objeto de cadena asignado dinámicamente. El ok La variable de tipo booleano sirve para comprobar que las operaciones de lectura se han realizado correctamente. Finalmente, declaramos las cuatro variables char , wait_time , selector y data . Estas variables son para extraer los datos de cada columna de cada línea de texto.

  while not endfile(text_file) loop

    readline(text_file, text_line);

    -- Skip empty lines and single-line comments
    if text_line.all'length = 0 or text_line.all(1) = '#' then
      next;
    end if;

En el cuerpo del proceso, vamos directamente a un ciclo while que iterará a través de cada línea de texto en el archivo de estímulo. El readline procedimiento asigna una nueva línea de texto al text_line variable en cada iteración de este bucle. Después de leer la línea, verificamos si la línea está vacía o si el primer carácter es '#', en cuyo caso pasamos a la siguiente línea inmediatamente usando el next palabra clave para omitir una iteración del bucle. Tenga en cuenta que estamos usando text_line.all para obtener acceso a la cadena dentro del line objeto.

    read(text_line, wait_time, ok);
    assert ok
      report "Read 'wait_time' failed for line: " & text_line.all
      severity failure;

    hread(text_line, selector, ok);
    assert ok
      report "Read 'sel' failed for line: " & text_line.all
      severity failure;
    sel <= selector;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_0' failed for line: " & text_line.all
      severity failure;
    din_0 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_1' failed for line: " & text_line.all
      severity failure;
    din_1 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_2' failed for line: " & text_line.all
      severity failure;
    din_2 <= data;

    hread(text_line, data, ok);
    assert ok
      report "Read 'din_3' failed for line: " & text_line.all
      severity failure;
    din_3 <= data;

A continuación sigue una serie de lecturas del text_line objeto. El read y hread las llamadas al procedimiento saltan los espacios iniciales para que no tengamos que hacer lecturas ficticias para mover la posición de inicio de lectura interna dentro del text_line objeto. Podríamos haber omitido las declaraciones de afirmación, pero quiero que la simulación se detenga si falla una lectura. Al menos en ModelSim, la simulación no se detiene automáticamente cuando esto sucede. Asignamos cada variable leída con éxito a la señal DUT relevante, excepto el wait_time variable que no tiene una entrada DUT correspondiente.

    wait for wait_time;

Después de asignar los valores de la señal, esperamos el tiempo especificado. Pulsar la declaración de espera hace que los valores de la señal programada se hagan efectivos con el mismo ciclo delta.

    -- Print trailing comment to console, if any
    read(text_line, char, ok); -- Skip expected newline
    read(text_line, char, ok);
    if char = '#' then
      read(text_line, char, ok); -- Skip expected newline
      report text_line.all;
    end if;

  end loop;

  finish;

end process;

Finalmente, cuando el programa se despierta de la declaración de espera, buscamos un comentario final adicional en el text_line objeto. Cualquier comentario se imprime en la consola usando la declaración del informe después de haber eliminado el carácter '#' y el siguiente espacio en blanco usando lecturas ficticias.

Después de que se haya procesado la última línea de texto del archivo de estímulo, el bucle while termina. Hay un VHDL-2008 finish palabra clave al final del proceso que es responsable de detener el banco de pruebas.

La salida

El banco de pruebas de ejemplo imprime el texto que se muestra a continuación en la consola del simulador cuando se ejecuta en ModelSim. Podemos ver que los comentarios son los del archivo de estímulo. Los valores de tiempo impresos son los tiempos de simulación acumulados basados ​​en los retrasos de nanosegundos que se especificaron en el archivo de estímulo.


# ** Note: Setting initial values
#    Time: 0 ns  Iteration: 1  Instance: /file_stim_tb
# ** Note: Testing by changing the selector signal
#    Time: 10 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Testing by changing all data inputs
#    Time: 40 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Changing all unselected inputs
#    Time: 70 ns  Iteration: 0  Instance: /file_stim_tb
# ** Note: Changing all inputs fast
#    Time: 91 ns  Iteration: 0  Instance: /file_stim_tbf
# ** Note: Simulation stop
#    Time: 104 ns  Iteration: 0  Instance: /file_stim_tb
# Break in Process PROC_SEQUENCER at file_stim_tb.vhd line 98

La forma de onda para la simulación se muestra a continuación. Muestra una representación visual de cómo se aplican los valores de nuestro archivo de estímulo a las señales en los tiempos de simulación especificados.

Reflexiones finales

Leer los estímulos del banco de pruebas desde un archivo puede ser ventajoso si tiene un patrón de prueba muy específico que necesita aplicar. Todo el banco de pruebas no tiene que ser controlado por el archivo de texto, este ejemplo solo pretende mostrar las posibilidades de acceso a archivos en VHDL.

Sin embargo, una cosa que no hemos discutido es la verificación de las salidas del dispositivo bajo prueba. Nuestro banco de pruebas de ejemplo no verifica las salidas en absoluto. Puede verificar el comportamiento del DUT tal como lo haría en un banco de pruebas VHDL completo, por ejemplo, utilizando un modelo de comportamiento para comparar. O puede modificar el código y el archivo de estímulo para incluir los valores de salida esperados. Independientemente de la estrategia que elija, asegúrese de crear un banco de pruebas de autocomprobación y no confíe en la comprobación manual de la forma de onda.


VHDL

  1. C # usando
  2. Manejo de archivos C
  3. Clase de archivo Java
  4. Uso de firmas digitales para comprobar la integridad de los datos en Linux
  5. Cómo inicializar RAM desde un archivo usando TEXTIO
  6. Cómo crear un banco de pruebas de autocomprobación
  7. Java BufferedReader:cómo leer un archivo en Java con un ejemplo
  8. Python JSON:codificar (volcados), decodificar (cargas) y leer archivos JSON
  9. Operaciones de E/S de archivos de Verilog
  10. C - Archivos de encabezado
  11. ¿Qué es un archivo triangular?