Libro de trabajo de laboratorio Funciones, procedimientos y bancos de pruebas Funciones, procedimientos y bancos de pruebas Introducción VHDL le permite definir subprogramas usando procedimientos y funciones. Se utilizan para mejorar la legibilidad y explotar la reutilización del código VHDL. Las funciones son equivalentes a la lógica combinatoria y no se pueden usar para reemplazar el código que contiene operadores de eventos o control de retardo (como se usa en una lógica secuencial). Los procedimientos son más generales que las funciones y pueden contener controles de tiempo. Un banco de pruebas es un programa o modelo escrito en HDL con el propósito de ejercitar y verificar la correcta funcionalidad de un modelo de hardware a través de simulación. VHDL es principalmente un medio para el modelado de hardware (simulación), el lenguaje contiene varios recursos para formatear, leer, almacenar, asignar dinámicamente, comparar y escribir datos de simulación, incluidos estímulos de entrada y resultados de salida. En esta práctica de laboratorio, aprenderá cómo escribir funciones, procedimientos y bancos de pruebas. Aprenderá sobre los componentes de un banco de pruebas y las construcciones de lenguaje disponibles para verificar la corrección del modelo de hardware subyacente. Consulte el tutorial de PlanAhead sobre cómo usar la herramienta PlanAhead para crear proyectos y verificar circuitos digitales. Objetivos Después de completar esta práctica de laboratorio, usted será capaz de: Desarrollar procedimientos para modelar un circuito combinatorio Desarrollar funciones para modelar un circuito combinatorio Desarrollar un banco de pruebas para probar y validar un diseño bajo prueba Procedimientos Parte 1 Un procedimiento proporciona la capacidad de ejecutar piezas comunes de código de diferentes lugares en un modelo. Un procedimiento puede contener controles de tiempo y puede llamar a otros procedimientos y funciones (que se describen en la siguiente parte). Un procedimiento se define, dentro de una definición de módulo, como: procedure identifier [input/output port declarations] is [variable declarations] begin procedure statements end identifier Un procedimiento proporciona la capacidad de ejecutar piezas comunes de código de diferentes lugares en un modelo. Un procedimiento puede contener controles de tiempo y puede llamar a otros 1 Libro de trabajo de laboratorio Funciones, procedimientos y bancos de pruebas procedimientos y funciones (que se describen en la siguiente parte). Un procedimiento se define, dentro de una definición de módulo, como: 1-1. Escriba un procedimiento llamado add_two_values que tome dos parámetros de 4 bits, agréguelos y genere una suma de 4 bits y un acarreo. Escriba un módulo, llamado add_two_values_procedure, que invoca el procedimiento con los operandos recibidos a través de los puertos de entrada y emite el resultado. Simule el diseño con el banco de pruebas proporcionado, add_two_values_procedure_tb.vhd y verifique la funcionalidad. 1-1-1. Abra PlanAhead y cree un proyecto en blanco llamado lab4_1_1. 1-1-2. Cree y agregue el módulo VHDL, llamado add_two_values_procedure, que define un procedimiento llamado add_two_values. El procedimiento tomará dos parámetros de 4 bits, los agregará y generará una suma de 4 bits y un acarreo. El módulo llamará al procedimiento con los operandos recibidos a través de los puertos de entrada y enviará el resultado. 1-1-3. Simule el diseño con el banco de pruebas proporcionado: add_two_values_procedure_tb.vhd y verifique que el diseño funcione. Busque los mensajes que se muestran en la ventana de la consola del simulador. 1-2. Escriba un procedimiento llamado calc_even_parity que tomará un número de 8 bits y calculará y devolverá la paridad. Escriba un módulo, llamado calc_even_parity_procedure, que invoca el procedimiento con el operando recibido a través del puerto de entrada y emite el resultado. Utilice el banco de pruebas proporcionado, calc_even_parity_procedure_tb.vhd, que muestra el resultado en la ventana de la consola del simulador. Simule el diseño y verifique la funcionalidad. 2 Libro de trabajo de laboratorio Funciones, procedimientos y bancos de pruebas Funciones Parte 2 Las funciones difieren principalmente de los procedimientos en que se devuelve un único valor ejecutar el código. al Las funciones se utilizan si todas las siguientes condiciones son verdaderas: No hay construcciones de retardo, temporización o control de eventos que estén presentes Devuelve un valor único Hay al menos un argumento de entrada No hay argumentos de salida o inout No hay asignaciones sin bloqueo En resumen, las funciones pueden implementar solo el comportamiento combinatorio, es decir, calculan un valor sobre la base del valor presente de los argumentos de entrada y devuelven un solo valor. Cada línea de código en la función se ejecuta secuencialmente (no son de no bloqueo). Se usan en el lado derecho de una declaración de asignación. Aquí hay un ejemplo de una definición de función y llamada. Un ejemplo de definición de función en VHDL es el siguiente: function identifier [input/output port declarations] return type is [variable declarations] begin function statements end identifier Para llamar a una función, se necesita usar el identificador de función (con entrada(s) definida(s)) como un operando de asignación en un bloque de proceso: Func_Out <= identifier (input, output); Aquí hay un fragmento de código que muestra cómo se usan las funciones: 3 Libro de trabajo de laboratorio Funciones, procedimientos y bancos de pruebas 2-1. Escriba una función llamada add_two_values que tomará dos parámetros de 4 bits, los agregará y devolverá una suma de 5 bits. Escriba un módulo, llamado add_two_values_function, con dos puertos de entrada de 4 bits y un puerto de salida de 5 bits y llama a la función. Simule el diseño con el banco de pruebas proporcionado, add_two_values_function_tb.vhd, y verifique la funcionalidad. 2-1-1. Abra PlanAhead y cree un proyecto en blanco llamado lab4_2_1. 2-1-2. Cree y agregue un módulo VHDL, llamado add_two_values_function, que define una función llamada add_two_values que toma dos parámetros de 4 bits, los agrega y devuelve una suma de 5 bits. El módulo tendrá dos puertos de entrada de 4 bits y un puerto de salida de 5 bits. Llamará a la función. 2-1-3. Simule el diseño con el add_two_values_function_tb.vhd provisto durante 50 ns y verifique que el diseño funcione. 2-2. Escribe una función llamada calc_ones que tomará un número de 8 bits, y calculará y devolverá el número de unidades. Escriba un módulo, llamado calc_ones_function, con un puerto de entrada de 8 bits y un puerto de salida de 3 bits y llama a la función. Simule el diseño con el banco de pruebas proporcionado, calc_ones_function_tb.vhd, y verifique la funcionalidad. Banco de pruebas Parte 3 Los principales componentes de un banco de pruebas son: o Módulo, que define la estructura de nivel superior del banco de pruebas Un banco de pruebas generalmente no tiene puertos de entrada o salida o Señales internas, que conducirán los estímulos al UUT y monitorearán la respuesta del UUT Señal para conducir y monitorear o instanciación de UUT o Generación de estímulos Escribir declaraciones para crear estímulo y bloque de procedimiento o Monitoreo de respuestas y comparación Declaraciones de autoverificación que informarán valores, errores y advertencias Aquí hay un ejemplo del banco de pruebas que utilizamos en el laboratorio de Aprendizaje PlanAhead. 4 Libro de trabajo de laboratorio Funciones, procedimientos y bancos de pruebas Saltando las primeras líneas del código, la línea 14 muestra el paquete TEXTIO que se está utilizando. Las líneas 16 y 17 definen el nombre del módulo testbench. La línea 19 comienza la descripción arquitectónica del código. Las líneas 19 a 25 definen la asignación de puertos del módulo UUT VHDL. Las líneas 27 a 30 especifican las señales y vectores utilizados en el banco de pruebas. Las líneas 32 a 47 definen el procedimiento utilizado para calcular la salida UUT esperada. Las líneas 50 a 53 5 Libro de trabajo de laboratorio Funciones, procedimientos y bancos de pruebas ejemplifican el UUT, mapeando la entrada y la salida a las señales definidas anteriormente en el módulo. La línea 55 comienza el proceso donde reside el código de comportamiento. Las líneas 56 a 59 definen las variables locales utilizadas solo en el proceso. Las líneas 62 a 81 son for-loop que se ejecutarán 128 veces. Las líneas 65 y 67 muestran cómo se pueden insertar esperas para simular retrasos. Líneas 72 y 73 salidas a la ventana de la consola de simulación. Lo mismo se aplica a las líneas 75 y 76. VHDL admite dos tipos de modelado de retardo: (i) inercial y (ii) transporte. El retraso inercial es la demora que una compuerta o circuito puede experimentar debido a la naturaleza física de la compuerta o circuito. El retardo inercial también se usa para determinar si la entrada tiene un efecto en la compuerta o circuito. Si la entrada no permanece cambiada al menos para el retardo inicial, entonces se ignora el cambio de entrada. Por ejemplo, un retraso de inercia de 5 ns significa que cada vez que cambia la entrada debe permanecer cambiado al menos durante 5 ns para que se considere como cambiado, de lo contrario se ignora el cambio (se considera un pico transitorio). El retraso de transporte es el tiempo de vuelo de una señal que viaja por un cable de un circuito. En VHDL, los retrasos inerciales y de transporte se especifican como parte de las declaraciones de asignación. Estos son algunos ejemplos de transporte y retrasos inerciales: bit_result <= input_bit xor bit_mask after 10ns; Esto es un retraso inercial. La palabra clave after en la instrucción de asignación indica que la salida solo cambiará después de que hayan pasado 10 ns a partir de los cambios en ambos argumentos de entrada. Si una de las entradas revierte a su valor original durante el retardo de 10 ns, entonces el cambio inicial no se registrará. bit_result <= transport input_bit xor bit_mask after 10ns; El ejemplo anterior muestra cómo se especifica el retraso de transporte. Observe que la única diferencia con el ejemplo anterior es la palabra clave transport. Esto retrasa la salida por el tiempo especificado. En este caso, el retraso de transport solo retrasa la salida en las 10 ns especificadas. A veces es importante generar resultados en la ventana de la consola del simulador. Esto puede ser necesario cuando se comparan las salidas de simulación para determinar si el código ha pasado o no la simulación. VHDL admite escribir en un archivo de texto o en la ventana de la consola del simulador. Esto se hace a través del paquete TEXTIO que se puede agregar a un módulo VHDL a través de std.textio.all. Los paquetes permiten hacer referencia a funciones y componentes en un diseño. En el caso de bancos de pruebas de simulación, a menudo es esencial enviar valores y mensajes a la pantalla además de la forma de onda, dependiendo de ciertas condiciones para marcar eventos específicos. El siguiente ejemplo muestra cómo enviar una línea a la consola del simulador: process variable s : line; variable n : integer := 5; 6 Libro de trabajo de laboratorio Funciones, procedimientos y bancos de pruebas begin write (s, string’(“The quick brown fox jumps over the lazy dog. ”)); -Writing a text string. write (s, n); --Writing a variable value. writeline (output, s); --Outputs the above to one line. end process; Donde s es la variable de línea para escribir tanto la cadena como la variable "n". El resultado esperado del ejemplo anterior será: The quick brown fox jumps over the lazy dog. 5 El comando de escritura no se puede sintetizar y se debe usar solo en bancos de pruebas. 3-1. Desarrolle un banco de pruebas para verificar la funcionalidad del sumador de transporte de rizo de 4 bits. Diseñe un sumador de acarreo de rizado de 4 bits utilizando modelado de flujo de datos. Modifique el diseño para incluir 2 unidades de retardo inercial para cada declaración de asignación en el diseño. Desarrollar un banco de pruebas de manera que calcule el resultado esperado, compare el resultado y muestre el resultado como "Prueba aprobada" o "Prueba fallida" 3-1-1. Abra PlanAhead y cree un proyecto en blanco llamado lab4_3_1. 3-1-2. Agregue el módulo VHDL del sumador de rizo. Modifique el diseño para incluir 2 unidades de retardo inercial para cada declaración de asignación en el diseño. Desarrolle un banco de pruebas de forma tal que calcule el resultado esperado, compare el resultado y muestre el resultado como "Prueba aprobada" o "Prueba fallida". 3-1-3. Simule el diseño para el tiempo deseado y verifique que el diseño funcione. Debería poder verificar simplemente mirando en la ventana de la consola del simulador. 3-2. Desarrolle un banco de pruebas que genere la forma de onda que se muestra a continuación. 7 Libro de trabajo de laboratorio Funciones, procedimientos y bancos de pruebas 3-2-1. Abra PlanAhead y cree un proyecto en blanco llamado lab4_3_2. 3-2-2. Cree y agregue el módulo VHDL que genera la forma de onda que se muestra arriba. 3-2-3. Simule el diseño durante 150 ns y verifique que se genere la salida correcta. Conclusión En esta práctica de laboratorio, aprendió cómo escribir funciones, procedimientos y bancos de pruebas. También aprendió las diferencias entre funciones y procedimientos, tanto en sus definiciones como en su uso. Viste cómo se puede usar la función en un banco de pruebas para calcular el resultado esperado 8