Lección 3: Introducción a VHDL: primer código.
Introducción a VHDL
En esta lección, se decriben las principales estructuras del lenguaje de descripción de hardware VHDL que son, la entidad y la arquitectura.
Debe siempre tenerse en cuenta que la utilización de un lenguaje de descripción de hardware para la implementación de diseño digitales, es similar a la descripción utilizando esquemáticos. La diferencia es que cuando realizamos un esquemático realizamos “dibujos”, mientras que con lenguajes de descripción de hardware utilizamos códigos.
La utilización incorrecta de las estructuras del lenguaje, es similar a la realización de esquemáticos en la que dibujáramos símbolos arbitrarios inventados por nosotros mismos.
VHDL es un lenguaje que se escribe en un archivo de texto. No distingue entre minúsculas y mayúsculas, por lo que las palabras reservadas del lenguaje y todos los nombres definidos en el código, pueden ser escritos indistintamente en mayúsculas o minúsculas (case insensitive, en inglés).
El archivo consta de tres secciones fundamentales:
- La declaración de librerías: La declaración de librerías se realiza al comienzo del archivo. Una librería que generalmente se incluirá en todos los códigos, es la de lógica multi-valuada. Como se explicó anteriormente, la declaración de lógica multi-valuada se realzó posterior a la estandarización de VHDL. Es por eso que, para declarar señales multi-valuadas del tipo std_logic, debe incorporarse el paquete std_logic_1164 de la librería IEEE, insertando el siguiente código al comienzo del archivo:
library IEEE;
use IEEE.std_logic_1164.all;
- La entidad: describe los puertos de entrada y de salida que tiene el hardware descripto. También define el nombre del componente descripto. El nombre del archivo debe ser el nombre de la entidad, con extensión “.vhd”. Por ejemplo, denominaremos al circuito de la figura 1 como funcion_y_z, su descripción tendrá que realizarse en un archivo con el nombre función_y_z.vhd, e incluirá la siguiente entidad:
entity funcion_y_z is
port (
A : in std_logic;
B : in std_logic;
C : in std_logic;
Z : out std_logic;
Y : out std_logic
);
end entity función_y_z;Puede observarse que las señales de entrada y salidas son declaras dentro de la cláusula port. Las señales A, B y C son declaradas como entradas al especificarlas como in, y las señales Z e Y son declaradas como salidas al especificarlas como out. Todas las señales son declaras del tipo std_logic. Por ende, la entidad define: (1) el nombre del componente, (2) las señales de entrada, de salida y bidireccionales, y (3) el tipo de cada una de ellas.
- La arquitectura: define la funcionalidad del componente especificando; en definitiva, qué valores se le asignarán a las salidas del componente de acuerdo al valor de las entradas. La descripción de la funcionalidad en la arquitectura puede ser de manera funcional o jerárquica o estructural. La arquitectura para el circuito de la figura 1 se resuelve fácilmente mediante una descripción funcional mediante las funciones lógicas que determinan los valores de las salidas de acuerdo al valor de las entradas. La arquitectura para el circuito de la función_y_z tendrá la forma:
architecture A1 of funcion_y_z is
begin
Z <= (A and B) or (A or C);
Y <= not((A or C) xor B);
end architecture A1;La arquitectura tiene un nombre (en este ejemplo se eligió arbitrariamente A1) y está asociada a una determinada entidad (en este caso a la entidad función_y_z) que debe estar en el mismo archivo. La estructura de la arquitectura consta de una primera sección declarativa, que abarca desde la palabra reservada is hasta la palabra reservada begin. En esta sección se declararán señales internas y componentes, pero serán detallados en próximas lecciones. La segunda sección es el cuerpo de la arquitectura, y es en donde se describirá la funcionalidad o la estructura del hardware. Puede observarse que, en el ejemplo utilizado, se especificaron las funciones lógicas que deseamos implementar, utilizando el operador “<=” para la asignar las señales Z e Y. Recordemos que las funciones lógicas tienen entradas y salida: con el operador asignación (“<=”), la salida se define por la señal que está a la izquierda del operador, mientras que la función asignada se define a la derecha del operador de asignación.
Todas las sentencias en el cuerpo de la arquitectura son concurrentes, por lo que no importa el orden en que se especifiquen. En el ejemplo de la función_y_z es equivalente colocar primero la especificación de la función Z y luego la de la función Y (como figura en el código) o, por el contrario, primero la función Y y luego la función Z.
Todas las sentencias en el cuerpo de la arquitectura son consideradas concurrentes y, por lo tanto, no importa el orden en que se especifiquen.
Para finalizar, el código VHDL completo de nuestro ejemplo de la figura 1 quedaría especificado en el archivo función_y_z.vhd:
De esta manera, hemos realizado nuestra primera especificación en el lenguaje de descripción de hardware VHDL. El lenguaje VHDL presenta una estructura para especificar el código. Sin embargo, siempre debe tenerse presente que, cuando realizamos una descripción para ser implementada en hardware, el hardware que queremos describir. Más adelante veremos diferentes estructuras del lenguaje VHDL, pero siempre debemos recordar que VHDL (o cualquier lenguaje de descripción de hardware) no permitirá implementar en hardware algo que no se puede implementar en hardware: el lenguaje no es un fin, sino un medio.
NOTA: siempre hay un esquemático que puede representar gráficamente, la descripción de un código en VHDL. Es decir, no podemos hacer en VHDL nada que no se pueda representar con un esquemático.
Flujo de diseño
El archivo en VHDL especificado en la sección anterior, requiere ser procesado para que un dispositivo FPGA implemente, finalmente, el hardware deseado. Todas las etapas necesarias en este proceso conforman el flujo de diseño. El flujo de diseño puede involucrar varias herramientas de desarrollo, las cuales procesan los datos de la herramienta anterior y producen los datos para la herramienta siguiente.
El flujo de diseño digital con dispositivos FPGA, involucra 4 etapas principales:
- Entrada de diseño (Design entry, en inglés): en esta etapa, el diseño es descripto mediante el código en un lenguaje de descripción de hardware, o mediante un esquemático en un editor de circuitos digitales. Existen diferentes procesadores de texto con las que podemos editar nuestros archivos de código VHDL. Quartus Prime ofrece un editor con características destinadas a facilitar la edición de código de descripción de hardware (soporta diferentes lenguajes HDL), pero no es necesario utilizarlo si al usuario le es más conveniente otro editor de archivos.
- Compilación (Compilation, en inglés): en esta etapa, la descripción realizada en la etapa de “Design entry” es procesada para determinar las funciones lógicas descriptas en el código. En la compilación se obtienen los recursos de hardware, y sus interconexiones, necesarios para implementar el hardware descripto. Existen herramientas de varios fabricantes destinadas a la compilación de diseño digital. Quartus Prime compila el Design entry, pero también es compatible con herramientas de varios fabricantes en el caso de preferirse compiladores de otros fabricantes (Intel denomina “third party” a herramientas o fabricantes con lo que Quartus Prime es compatible). La etapa de compilación produce un archivo denominado netlist.
- Implementación (Design implementation, en inglés): en esta etapa, se determinan los recursos físicos del dispositivo FPGA que se utilizarán para implementar el hardware descripto. Este proceso requiere un profundo conocimiento de los recursos disponibles en el dispositivo FPGA, por lo que generalmente es solamente realizado por la herramienta provista por el fabricante de los dispositivos FPGA (Quartus Prime para los dispositivos FPGA de Intel). El proceso por el cual se determinan los recursos físicos y de interconexión se denomina place and route y su complejidad es generalmente abordada mediante heurísticas. En Quartus Prime, el proceso de place and route es implementada mediante la aplicación Fitter, la cual puede requerir un tiempo considerables para diseño medianamente complejos y produce archivos con extensión .sof o .pof.
- Configuración (FPGA configuration): en esta etapa, se transfiere la información obtenida en la etapa anterior al dispositivo FPGA para su configuración. La configuración de un dispositivo FPGA permite que los recursos de hardware disponible en él, sean interconectados para que, finalmente, el hardware descripto se implemente. Por supuesto, el dispositivo FPGA debe contar con todos los recursos de hardware requeridos para implementar el hardware descripto.
Cada etapa del flujo de diseño permite configurar diferentes parámetros para lograr la implementación deseada. Por ejemplo, el código VHDL describe el hardware que deseamos implementar, pero no determina los pines físicos del dispositivo FPGA que serán configurados como entradas y como salidas. Esto es porque la configuración de los pines físicos cobra importancia en la etapa de implementación en la que determinan los recursos físicos que se utilizarán del dispositivo FPGA. Existen diferentes especificaciones que se pueden realizar para cada una de las etapas del flujo del proceso, pero nos centraremos en la especificación de los pines de entrada y de salida para poder finalizar el flujo de diseño que comenzamos con el hardware de la figura 1. Para ello, debemos primero crear un proyecto en Quartus Prime.