miércoles, 30 de octubre de 2013

3. VHDL: Conceptos Básicos

Empecemos de una buena vez con lo que es el VHDL. Como les he venido diciendo, este lenguaje está orientado al desarrollo de diseños mediante la descripción del comportamiento del hardware que deseamos. Pero como todo lenguaje, éste implica el manejo de una sintaxis propia, definiciones y estilos, aspectos que van más allá de qué tan bueno eres diseñando soluciones digitales (si manejan algún otro lenguaje, sea java o C, recuerden lo duro que fue aprenderse como funcionaban las instrucciones if, then... o el polimorfismo en java... bueno, creo que me dejo entender). 
A continuación, unas cuantas definiciones básicas que nos serán muy útiles para empezar a enfrentar al VHDL con optimismo.

Conceptos Básicos


Entidad

Todo diseño en VHDL se centra en la creación de entidades. Una entidad es una representación formal de tu diseño, en el que se especificarán sus parámetros como si se tratase de una caja negra, lo cual implica establecer sus puertos de entrada y salida, sus modos y tipos, así como la determinación de parámetros que le den mayor versatilidad al diseño, denominados genéricos. La sintaxis básica para crear una entidad es la siguiente:

entity nombre_entidad is 
generic  (nombre_parámetro : tipo_genérico :=valor);
port (
nombre_terminal1    : modo   tipo;
nombre_terminal2    : modo   tipo;
...
nombre_terminaln    : modo   tipo -- La última declaración no terminará en ";"
);end  nombre_entidad;

Se puede apreciar la palabra clave entity. Esta le indica al compilador que se está creando una entidad. Recordar que el nombre que le pongan a la entidad debe ser el mismo nombre con el que guarden el archivo .vhd.

VHDL impone las siguientes restricciones en cuanto a como hemos de llamar tanto entidades, puertos, etc.:

  • Debe iniciar con una letra. No es válido: 3contador.
  • No debe contener espacios. No es válido: mi contador.
  • Si quieren usar dos o más palabras, se deberán unir con guión abajo. Sí es válido: mi_contador.
  • No puede usarse una palabra clave.
Ejemplos de identificadores válidos son: mux_4_a_2, mi_microprocesador, ejem245, a23_ft, y similares.

La palabra clave generic es opcional, y sirve para indicar parámetros genéricos. Estos básicamente actuarán como valores constantes para el diseño, pero modificables por quien hace el código. Quizá no se entienda con claridad esta idea, pero cuando veamos lo que son registros universales de n bits me parece que cualquier duda será eliminada. Un ejemplo introductorio: imagínense que quieren definir un sistema que trabaje con 4 bits. Entonces, realizan su diseño y lo compilan exitosamente. Pero luego resulta que desean que el mismo sistema trabaje ahora con 8 bits. En este caso, el parámetro genérico sería la longitud de bits, la cual se ajusta de acuerdo a lo que se quiera. De esa forma, para cambiar la longitud de la palabra de bits solo hará falta cambiar el valor del parámetor genérico. Como les dije, más adelante os explicaré esto con mayor claridad, asi que no se preocupen. Además, como lo dije al principio, esta es opcional.

Mediante port definiremos en si los puertos de entrada y salida de nuestro diseño, como si los viésemos en una caja negra. Cabe resaltar que al finalizar cada declaración se usa punto y coma (;), a excepción de la última declaración. Esta no deberá terminar en (;).

Ahora, cada declaración se lleva a cabo mediante el siguiente formato:

nombre_terminal1    : modo   tipo   :=   valor_inicial;

nombre_terminal1: Nombre con el que referenciaremos al puerto. Deberá cumplir con las restricciones descritas líneas arriba.

modo: Identifica el modo de operación del puerto. VHDL nos ofrece los siguientes modos:

IN: Configura al puerto como puerto de entrada.  El flujo de datos va desde el exterior del sistema hacia dentro del mismo. Sólo se pueden leer los datos de este puerto, y no se puede escribir nada sobre ellos (puerto de sólo lectura).

Modo de operación del puerto: IN

OUT: Configura al puerto como puerto de salida. El flujo de datos va desde el interior del sistema hacia el exterior. Sólo se puede escribir sobre este puerto, y no se puede leer el valor que tenga (puerto de sólo escritura).

Modo de operación del puerto: OUT
BUFFER: Configura al puerto como puerto de salida. El flujo de datos va desde el interior del sistema hacia el exterior, pero además se puede leer el valor de dicho puerto, por lo que es un puerto de lectura - escritura.


Modo de operación del puerto: BUFFER
 INOUT: Comfigura al puerto como puerto bidireccional. El flujo de datos va en ambas direcciones, lo cual indica que el puerto puede actuar tanto como entrada (IN) o como salida (OUT)... (De ahí el nombre de INOUT).

Modo de operación del puerto: INOUT
tipo: Indica el tipo de puerto. Los tipos básicos de VHDL son:

bit: Define al puerto como un solo bit.
Ejemplo, la entrada de un inversor.

bit_vector(Mbit downto Lbit): Define al puerto como un vector de bits de longitud Mbit-Lbit+1, con prioridad descendente.
Ejemplo, un contador cuya salida se define como: Q3 Q2 Q1 Q0 ==> Q (3 downto 0).

bit_vector(Lbit to Mbit): Define al puerto como un vector de bits de longitud Mbit-Lbit+1, con prioridad ascendente.
Ejemplo, un registro cuya entrada se define como: R2 R3 R4 R5 ==> Q (2 to 5).

Debido a que estos tipos solo admiten los dos estados básicos de la lógica digital: '1' y '0'; para darle mayor versatilidad se crearon otros tipos, los cuales se contienen dentro del paquete std_logic_1164 de la librería IEEE. Una librería, al igual que en cualquier otro lenguaje, es un conjunto de códigos hechos y verificados que nos ayudarán a no reescribir lo que amablemente otros ya han hecho. Un paquete a su vez es una subclasificacion de las librerias, que permiten ordenar los códigos según criterios. Tener en cuenta que Ud. también pueden crear sus propias librerias con sus propios paquetes, de manera que sus diseños puedan servirles como base para encarar diseños más desafiantes y complejos. Más adelante les mostraré cómo hacerlo. Para usar un paquete, primero deberán invocar a la librería, y luego al paquete, de la siguiente manera:

library nombre_libreria;
use nombre_libreria.nombre_paquete.all;

Los tipos que nos ofrece el paquete std_logic_1164 de la librería IEEE son:

std_logic: Puerto de un bit.

std_logic_vector(Mbit downto Lbit): Puerto como vector de (Mbit-Lbit+1) bits con prioridad descendente.

std_logic_vector(Lbit to Mbit): Puerto como vector de (Mbit-Lbit+1) bits con prioridad ascendente.

Pero, ¿no son las mismas definiciones? quizá se preguntará. Pues aparentemente sí. En lo que difieren estos tipos es en los posibles valores que pueden tomar. Si para los tipos bit y bit_vector teniamos solo dos posibles estados, para los tipos std_logic y std_logic_vector tendremos los siguientes:

U: Valor sin inicializar.
X: Valor desconocido forzado.
0:  Estado bajo.
1:  Estado alto.
Z: Alta impedancia.
W:Valor desconocido débil.
L: Nivel bajo forzado.
H:Nivel alto forzado.
-  :No importa (el famoso don't care).

¿Y qué eso de forzado? Bueno, esto sólo es interpretado al simular el circuito. Los valores que usaremos en nuestros diseños serán "0", "1", "Z", "-".

valor_inicial: Valor que queremos asignarle al puerto cada vez que el sistema empiece a respirar. No se utiliza mucho para los puertos, pero si para señales dentro de una arquitectura (no se preocupen, la arquitectura es lo que sigue más abajo). Ver que el símbolo de asignación es ":=".

Para finalizar, no olvidar el end al final de la declaración de la entidad.


Arquitectura

La arquitectura es la parte del código en el que se describe el funcionamiento del sistema en función de los parámetros descritos en la entidad. La forma de hacerlo es:

architecture nombre_arq of nombre_entidad is
--Declaración de señales
signal nombre_senial :tipo := valor_inicial;
begin
--codigo
--codigo
...
--codigo
end nombre_arq;

Esta vez la palabra clave es architecture. Notar que también debemos ponerle un nombre a la arquitectura. Este nombre deberá cumplir con las restricciones descritas previamente. Cada arquitectura debe vincularse a una entidad. Es por ello que se usa of nombre_entidad.

Una señal es una variable intermedia, que se usa para facilitar la codificación. Los tipos para las señales son los mismos que los tipos para los puertos, contando además con los tipos genéricos, pero estos los explicaré más adelante. Además, no olvidar que las señales deben declararse antes de que se inicie la descripción del funcionamiento, pero después de la declaración inicial de la arquitectura. En otras palabras, antes de un begin, pero después de un architecture.

Circuito digital simple en el que se simboliza la acción de una señal.

Si no quedó claro. La imagen muestra un circuito digital simple. Las ecuaciones para este sistema serían:

S=A and C

Salida=B or S

Se puede ver que también pudo usarse usa sola ecuación:

Salida= B or (A and C).

Como se ve, la señal S actuó como una variable intermedia, y con ello se pudo dividir el funcionamiento en dos partes. Esa es la misión de las señales: dividir la complejidad de un sistema.

Aclarado esto, vemos que las líneas de código que describirán el funcionamiento están entre el begin y el end nombre_arq.

Bueno, me parece que esto es suficiente para arrancar con el primer ejemplo. ¿Qué les parece si implementamos el sistema de la figura ejemplo? A mí me parece bien... pero ello se verá en la siguiente entrada, en la que además os mostraré como simular un diseño hecho en VHDL utilizando el waveform file (.vwf). Hasta entonces...

lunes, 28 de octubre de 2013

2. El Entorno de Desarrollo de Altera: el QUARTUS II

El Quartus II de Altera

Si queremos hacer un programa en C++, la IDE que se nos viene a la mente es el famoso Dev C++. Si queremos hacer algo con java, tenemos al NetBeans o el Eclipse. Así mismo, si queremos programar un microcontrolador, como los famosos PIC de Microchip, tenemos al CCS Compiler.
Bueno, para el diseño digital también hay muchas IDE's: tenemos al MAX PLUS II de Altera, al ISE de Xilinx, el WARP de Cypress, al Quartus II de Altera. Particularmente yo prefiero trabajar con Quartus II, y los futuros diseños a explicarse se harán utilizando esta IDE, pero esto no implica que estos diseños solo podrán compilarse en esta IDE. Como lo mencioné en la intruducción, el lenguaje a utilizar será el VHDL, y este lenguaje es estándar, y por ende, independiente de la IDE que se utilice. Eso sí, esta entrada está dedicada a explicar como usar la IDE Quartus II de Altera, así que si alguién utiliza otra IDE, puede saltarse esta entrada y ver los demás artículos. Lo último que quiero es imponer mi estilo, así que cada quien debe usar la IDE que mejor le parezca.

Quartus II de Altera
Continuando, Quartus II es un entorno de diseño orientado a la programación de los dispositivos de Altera. Si están interesados en obtenerlo, pueden descargar una versión gratis, denominada la Web Edition, desde la misma página de Altera. (Acá les dejo el link de su centro de descargas:http://dl.altera.com/?edition=web). Desde este centro de descargas pueden obtener la versión de Quartus que deseen. Tienen desde la versión 9 hasta la 13 (la cual es, hasta el momento en que escribo este artículo, la más avanzada). Eso sí, el programa es pesado (más de 1GB), así que tomen las medidas del caso. Además de la Web Edition, se ofrece la Subscription Edition, y como su nombre lo indica, no es gratis. Pero con la edición gratis me parece que
se dispone de las herramientas suficientes para encarar cualquier problema de diseño.

El entorno de Quartus II


 Como toda IDE, el software Quartus II ofrece herramientas que nos ayudarán a diseñar sistemas digitales. Primeramente os presentaré la ventana principal, y qué podremos encontrar en ella. 

Ventana que observarás cada vez que abras Quartus II. ¿Qué les parece? ¿Bonita, no?
Encontraremos acá la barra de herramientas con las típicas opciones ofrecidas por todas las IDE: File, Edit, View... En este caso, lo nuevo son las opciones Assignments y Processing. La primera contiene herramientas concernientes a la asignación de pines al momento de compilar, la elección del dispositivo, entre otras opciones. Processing contiene herramientas para configurar la compilación, la simulación, entre otras similares. 

 Quartus II ofrece también la posibilidad de simular los diseños. Pero la forma en que lo hace es distinta a como lo hace, por ejemplo, el buen Proteus. Para simular proyectos de diseño digital utilizando VHDL se debe crear un nuevo tipo archivo, denominado waveform file, o archivo forma de onda. Básicamente, se crean las formas de onda en el tiempo de las señales de entrada, y se observa cómo responde el diseño (con ello nos olvidamos de implementar los diseños físicamente para verificar si están bien o no). Más adelante les mostraré como hacer esto.

 

Creación del archivo .vhd


El primer paso es crear el archivo .vhd. Para ello, hacemos click en el ícono New (el de la hojita en blanco). Cuando lo hagan, les saldrá la siguiente ventana:

Lista de todos los tipos de archivo que se pueden generar con Quartus II.
 Como pueden apreciar, en esta ventana se nos ofrece una gran variedad de opciones de diseño. Se ve que está la opción para crear un proyecto, pero me parece que una manera más sencilla de hacerlo, por ahora, es a través del Project Wizard. 

Se pude ver además una clasificación de estos archivos. Por ahora, elegiremos la opción VHDL File. Hecho esto, os aparecerá la siguiente ventana.


En esta ventana podrás dar rienda suelta a tu imaginación, al escribir tus códigos de diseño.

 En la ventana en blanco que aparecerá escribirás tu código. Es importante guardar el archivo .vhd con el nombre de la entidad de diseño que elijas. Más adelante explicaré este concepto de entidad. Por ahora, observando la siguiente imagen ejemplo, en la que se definió la entidad como proyecto1, al momento de guardar, el nombre con el que deberá hacerse será proyecto1 también, y el archivo deberá quedarte como proyecto1.vhd.

 
entity proyecto1 : Con estas palabritas defines una entidad llamada proyecto1 en VHDL.

 
Guardando el código escrito. Recordar hacerlo usando el mismo nombre que la entidad de tu código.


Respecto a la recomendación de desmarcar la opción Create new project based on this file, aconsejo esto debido a que el Project Wizard creará un proyecto estableciendo a tu archivo .vhd como top file. Aunque inicialmente esto no sea problema, cuando se planteen problemas que requieran diseño jerárquico, las cuestiones respecto a los nombres de los proyectos puedrían marearlo. Esta opción es útil si el archivo que se está guardando será en si el archivo top de tu proyecto.

Creación de proyectos


Para empezar de una buena vez, les mostraré como crear un proyecto utilizando el Project Wizard de Quartus II. Tengan en cuenta que para que simulen un diseño, este debe estar contenido dentro de un proyecto. Ello no implica que cada que querramos escribir algún código en VHDL tengamos que crear proyectos independientes. El VHDL permite un estilo de programación denominado diseño jerárquico, en el que códigos independientes de VHDL pueden unirse para formar un solo proyecto final. Más adelante os enseñaré qué esto del diseño jerárquico. Por ahora, continuaré explicando como crear un proyecto.
El primer paso es ir a File, y en la ventana que aparezca, elegir la opción New Project Wizard. 

Elegir New Project Wizard y que el mago haga su magia...

Una vez hagan click en ella, les aparecerá la siguiente ventana, la cual es la primera del Project Wizard. 

 
Ventana introductoria del Project Wizard. Acá se muestran los pasos a seguir a fin de configurar tu proyecto.

Pulsar Next para entrar a la primera ventana de configuración. 




 Se ven tres espacios en los que escribir. El primero determinará el directorio en el que se guardará el proyecto. Este no es tan importante. Los que sí son importantes son los dos espacios siguientes. El nombre del projecto y el nombre del archivo top-level. El archivo top-level es el de mayor prioridad (cuándo explique lo de diseño jerárquico se entenderá mejor esto). Por defecto, el Project Wizard nombrará al archivo top con el nombre del projecto. En vez de dejarlo así, debemos hacer click en el browser de dicho espacio, y una vez en él, buscar el archivo .vhd que hemos creado previamente. Con esto, se elegirá al archivo .vhd que hayamos creado como archivo top y no se presentarán problemas durante la compilación.

 Hecho esto, pulsando Next pasaremos a la siguiente ventana:

Selección de los archivos componenetes del proyecto. Por ahora, con Add All y luego Next quedaríamos satisfechos.

 Parafreaseando a la ventana, siempre es posible añadir nuevos archivos al proyecto. Ello nos da gran flexibilidad al momento de diseñar, pudiendo agregar mejoras en todo momento.

La siguiente ventana será la siguiente:

Ventana de selección de dispositivos.
En esta ventana, como lo insinúa su nombre, elegiremos el dispositivo sobre el que se espera compilar el proyecto. Tener en cuenta que este factor no es clave al momento tanto de simular o verificar si el diseño cumple su función. El tipo de dispositivo determinará los retrasos reales que se tendrán en el diseño. Además, en cualquier momento puede cambiarse el dispositivo, así que no deberían preocuparse mucho en esta ventana. Por ahora, implemente Next.

Configuración de la compilación y la simulación.

No hay mucho que hacer en esta ventana. Se puede seleccionar el tipo de simulación, configuración del análisis de tiempos, etc. Después de esta ventana, Quartus II mostrará un resumen de todas las opcionas configuradas. Tener en cuenta que estos parámetros podrán cambiarse después. 

Resumen de todas las especificaciones para el proyecto.

Un Finish y abremos acabado. 
Con esto, me parece que ya  tenemos la base para afrontar los primeros ejemplos de diseño utilizando el Quartus II de Altera. 

Nota: La versión que utilizo es la 11.1 sp1. Pero no se preocupen, que las opciones son casi las mismas para otras versiones. 

lunes, 21 de octubre de 2013

1. Introducción al Diseño Digital utilizando un FPGA

¿Qué son los dispositivos lógicos programables?


Si hubiera un error aquí, ¿te animarías a buscarlo?
Para todos aquellos que hemos estudiado electrónica, ya sea como parte de un curso universitario o, como dicen, por amor al arte; una de las rutinas más tediosas al momento de diseñar sistemas digitales, aparte del proceso de diseño en si, era el testeo del mismo, implementándolo en un protoboard, empleando IC's con compuertas lógicas, cablecillos conectores, algunos diodos LED y tiempo, mucho... pero mucho tiempo, además de una considerable dosis de paciencia. Y el martirio no terminaba allí, pues muchas veces cuando el circuito armado no funcionaba acorde a las tablas de verdad pedidas, quedaba la heroica tarea de buscar el error entre la maraña de cables e IC's en el protoboard, verificar continuidad en cada punto... en fin, creo que hasta este punto todos entienden lo complicado que sería el diseñar sistemas digitales más complejos (si fuese un microprocesador, esta tarea sería incluso imposible) siguiendo el sacrificado procedimiento descrito líneas arriba.
Es acá donde los PLD's ("Programmable Logic Devices", Dispositivos de lógica programable) aparecen para sacarnos del problema. Básicamente, estos IC's contienen todo ese cableado internamente, y los configuras para que implementen la función lógica deseada. Por ahora no deseo profundizar más en esto, sino más bien darles una introducción al excitante mundo del diseño digital utilizando herramientas CAD, y en este caso, utilizando la IDE ofrecida por Altera, el quizá poco conocido Quartus II.

Cómo mencioné antes, un PLD es un IC que contiene muchas compuertas lógicas cuyas conexiones son configurables. Esto implica que sin haber configurado dichas conexiones previamente, un PLD no implementa ninguna función útil. Nuestra misión es, en este caso, determinar como realizar esas conexiones a fin de que el PLD haga lo que queramos (digitalmente hablando). Hasta este punto cabe decir que un PLD no es lo mismo que un microcontrolador. Un microcontrolador es un dispositivo programable en el que grabamos un programa. En un PLD la definición de programa no existe, pues lo que configuramos es hardware. En resumen, se podría decir que un microcontrolador es básicamente Software, mientras que el PLD es Hardware.

GAL, la primera respuesta para las pesadillas de implementación en el laboratorio.
Pero el término PLD abarca una gran cantidad de dispositivos. La primera PLD fue la PLA, cuyas siglas en inglés eran Programmable Logic Array, o arreglo de lógica programable (esto fue en 1970). Luego le sigue la PAL (Programmable Array Logic) o lógica de arreglo programable. Ambas básicamente eran arreglos de compuertas AND y OR cuyas conexiones se establecían mediante fundido de fusibles. Pero las que marcaron un hito fueron las GAL (Generic Array Logic). Estas eran similares a las PAL, pero añadían un sabroso ingrediente extra: podían ser borradas y reprogramadas. Esta característica ha hecho que hasta estos días se sigan usando. Se programan utilizando un lenguaje llamado ABEL, cuyas siglas significan en inglés Advanced Boolean Expression Languaje, o lo que en nuestro querido idioma sería algo como Lenguaje Avanzado de Expresión Booleana. Mediante este lenguaje lo que se hace es implementar las ecuaciones lógicas y las tablas de verdad que queremos configurar en el PLD. Imagínese haber dispuesto de una GAL en su laboratorio de circuitos digitales, la frustración, las horas que se habría ahorrado armando el circuito sobre el protoboard con el nudo en la garganta por esperar que funcione apropiadamente... Como sea, si quieren ahondar más en cómo consisten las arquitecturas de los dispositivos descritos anteriormente, en la web hay muchísimo material al respecto.


FPGA Stratix IV de ALTERA
El ABEL está bien, pero no se puede llegar a un nivel de abstracción muy elevado, debido a que básicamente es una implementación textual del álgebra de Boole. Pero quizá usted pueda preguntarse, ¿para qué querer más abstracción si solo es hardware? La respuesta la da la aparición de los CPLD, y posteriormente, de los FPGA. Los primeros son los llamados Complex PLD, o PLD complejos, y como su nombre lo indica, la complejidad radica en la cantidad de compuertas disponibles para configurar. Los segundos, sobre los que trataré de basar todos los diseños futuros, son los llamados Field Programmable Gates Array o Arreglos de Compuertas Programables en Campo (en campo, porque puede ser programado y reprogramado fuera de la fábrica, a diferencia de las llamadas ASIC, que se fabrican a medida en las fábricas, pero esa es otra historia).

Para contestar la pregunta anterior, imagínese implementar una tabla de verdad para un sistema digital con 8 entradas y 4 salidas. Ahora, imagínese desarrollar los mapas de Karnaugh para obtener las ecuaciones booleanas para cada salida. Ahora imagínese plantear lo mismo pero para dos vectores de entrada de 8 bits y un vector de salida de 4 bits. Vemos entonces que elevar el nivel de abstracción al programar se hace necesario a fin de no colapsar entre una marea de ceros y unos. Es entonces en donde aparece otra HDL (Hardware Description Languaje, lenguaje de descripción de hardware), y esa pasó a llamarse VHDL, cuyas siglas en inglés significan VHSIC HDL.

El VHDL es una mezcla de dos definiciones, por así decirlo: el VHSIC o Very High Speed Integrated Circuit, que en español significaría Circuito integrado de muy alta velocidad, y el ya conocido HDL. En resumen, VHDL es un HDL mejorado, creado por la IEEE para programar cualquier PLD y también ASIC (Con esta van dos veces que menciono ASIC, estas son las Application-Specific Integrated Circuit, o como lo sugiere su nombre, un IC de aplicación específica). 

Para finalizar esta introducción, resaltaremos las herramientas que usaremos: el VHDL como nuestro idioma para comunicarnos con el FPGA, el Quartus II que será nuestro traductor, y nuestro ingenio. A lo largo de los artículos que iré subiendo indicaré como desarrollar habilidad en las dos primeras herramientas. La última queda en sus manos pulir con esmero...     

Nota: Antes de avanzar más, sugiero al lector manejar definiciones básicas de circuitos digitales, a fin de que no encuentre trabas conceptuales cuando se vean casos de diseño. Si se presentara el caso, en la web hay muchísimas fuentes a las que acudir para eliminar cualquier duda. Además, como textos introductorios para cualquier interesado en seguir los artículos del blog, sugiero echarle un vistazo a los libros:  Sistemas Digitales: principios y aplicaciones de Ronald Tocci; y Fundamentos de Sistemas Digitales de Thomas Floyd.