viernes, 22 de noviembre de 2013

4. Primer ejemplo y Simulación utilizando archivos .VWF


En esta entrada voy a mostrar como simular un diseño en VHDL utilizando el archivo de formas de onda o waveform file .vwf.

Empecemos con el sistema que hemos de programar:

El primer circuito digital que hemos de implementar en este curso... ¡qué emoción!
Quizá digan que el sistema a diseñar ahora es demasiado simple..., pero para empezar está bien. Más adelante nos toparemos con sistemas más desafiantes, y antes de querer correr, deberíamos primero gatear. Así que empecemos...

Llamemos a la salida de esta sistema Z. Entonces, gracias a nuestros conocimientos en circuitos digitales sabemos que Z= (A and C) or B. Esta descripción booleana de nuestro resultado nos ayudará a obtener la tabla de verdad de nuestro circuito. Como todos sabemos, la talba de verdad contiene toda la información que hay que tener sobre un sistema a fin de conocer su funcionamiento. Tras asignar los valores , obtenemos la siguiente tabla de verdad:

Tabla de verdad del circuito.

Con todo lo hallado, tenemos ya una descripción completa del circuito propuesto. Ahora... ¿y en VHDL?

Primera forma para codificarlo


Abrimos el Quartus II, y seleccionamos New => VHDL File. Ello nos proveerá del lienzo en el que hemos de pintar nuestro primer ejemplo.

library ieee;
use ieee.std_logic_1164.all;

entity primerejemplo1 is
port(
a,b,c :in std_logic;
z :out std_logic);
end primerejemplo1;

architecture arqej1 of primerejemplo1 is
begin
z<=(a and c)or b;
end arqej1;

Como se puede apreciar, z recibe exactamente la función booleana obtenida líneas arriba. Esta forma de programar está muy bien, pero complica las cosas cuando hablamos de circuitos más complejos, con más entradas, o circuitos secuenciales.

Al guardar el archivo (recordar hacerlo con el mismo nombre de la entidad), Quartus II nos preguntará si deseamos crear un proyecto con este archivo. Para simular el diseño, primero debemos compilarlo, y toda compilación sólo puede darse en un proyecto. Entonces la damos . Ello lanzará al Porject Wizard descrito en la entrada anterior... Seguir los pasos descritos en dicha entrada para crear el proyecto satisfactoriamente. En este caso, yo llamé al proyecto como primerejemplo, y elegí al archivo que acabamos de crear como archivo top-file. 

Nota: Como quizá lo habrán notado, esta es otra forma de crear proyectos... Esta forma es la más segura para evitar errores de compilación y evitar marearse con todas las entidades que quisieramos añadir al proyecto: Escribimos nuestro código en VHDL, lo guardamos, pero no desmarcamos la opción que sugerí desmarcar en la entrada anterior. Luego, aceptar la petición para crear el proyecto a partir de ese archivo. En la ventana del Project Wizard que les saldrá, tener cuidado al momento de escribir los nombres. Sugiero que no llamen al proyecto con el nombre del archivo .VHD que acaben de crear, debido a que si quieren añadir más archivos al proyecto, el esquema de jerarquias no quedará muy bien que digamos... Guardar con un nombre genérico al proyecto, por ejemplo, si el código que hemos hecho implementa un contador BCD de 4 bits y lo hemos guardado como contadorBDC4bits.vhd; no llamar al proyecto así, sino, por ejemplo, proyecto_contadores. Eso si, en la casilla inferior elegir como archivo top a la entidad que hallamos creado (en este caso sí sería contadorBCD4bits). Si hacen esto, si mañana más tarde desean agregar otro archivo al proyecto e implementar un diseño jerárquico, podrán hacerlo sin el temor de que se asigne mal la jerarquía.

Bueno... sigamos... Luego de esto queda compilar... para ello hacemos click en un botón similar la PLAY, de colo morado, y listo... a esperar...

Iniciando la compilación...

Si se ha hecho bien todo lo mencionado anteriormente, la compilación solo arrojará advertencias, mas no errores. Estas advertencias saltan debido a que muchas de las herramientas especiales de síntesis están deshabilitadas debido a que la versión del Quartus II es la versión gratis y no la de subscripción... Otras advertencias pueden relacionarse con las asignaciones de los pines del diseño. 

NOTA: En caso de que salga algún error, o la compilación tome mucho tiempo, para los fines de la presente entrada bastará con emplear la herramienta Start Analysis and Síntesis. Para ello, hacer click en el botón que está al lado del botón de Compilación. Si aun así se obtienen errores, entonces deberá revisar el fichero .vhd, en búsqueda de algún error.

Iniciar análisis y síntesis.




Mientras no tengamos errores, por ahora, digamos que todo va bien... Al final de la compilación, Quartus II nos proporcionará un reporte con información sobre la síntesis. 


Reporte de compilación para nuestro primer ejemplo.

¿Qué parámetros deberían tomarse en cuenta? Inicialmente, de acuerdo al FPGA o CPLD elegida para la compilación (esto se elige en el Project Wizard o haciendo click después en Assignments=>Device), el reporte nos dice el área ocupada por nuestro circuito. Esta área representa el total de elementos lógicos empleados para sintetizar el sistema, respecto a la cantidad total de elementos lógicos de la FPGA o CPLD. En este caso, vemos que nuestro circuito solo toma un elemento lógico, lo cual representa menos del 1% del total del área del FPGA, en este caso una Cyclone IV GX. Este caso nuestro ejemplo ni siquiera le hizo cosquillas a la FPGA, pero conforme incrementos la complejidas de los diseños, veremos que este parámetro será determinante al elegir entre uno u otro FPGA o CPLD.

Hecho esto, queda simular nuestro diseño. Para ello haremos uso de los waveform files o VWF. files. Para crear estos archivos, debemos abrir otra IDE: Altera University Program Simulator. Puede descargar este software gratuitamente desde la página de Altera. Este simulador externo es necesario para todas las versiones recientes del Quartus II, debido a que estas IDE's ya no vienen con el simulador incluido (recuerdo que la versión 9.1 venía con el simulador integrado... pero a partir de la versión 11.0 ya no más). 

Hecho esto, al ejecutar el programa les saldrá una ventana tipo CMD, tras la cual la verdadera IDE simuladora arrancará.

No se asusten si ven esta ventana... a través de esta el simulador arrancará...

Luego verán la siguiente plataforma, que es en la que crearán el archivo waveform para simular su diseño.

Qsim, para simular nuestros diseños en VHDL y ver si hacen lo que supuestamente deberían hacer...

El primer paso es cargar nuestro proyecto. Para ello, hacer click en File => Open Project.

Buscar el proyecto que hemos creado y cargarlo. El programa les avisará mediante:

>> Opened project: primerejemplo (Revision: primerejemplo1)

Luego, hacemos click en New (la hoja en blanco). Con esto, nos saldrá una ventana con un waveform en blanco. 

Ventana de creación de un waveform file.

Un waveform file es básicamente un diagrama de tiempos en el que asignaremos a las señales de entrada de nuestro sistema valores que cambien en el tiempo, para observar como varía la salida. (Recordar los diagramas de tiempo de las memorias RAM, algo parecido...).

Bueno, seguimos... Ahora, hacemos doble click sobre el espacio en blanco rotulado por Name. Ello hará saltar la siguiente ventana:

Ventana para seleccionar los puertos que hemos de usar para simular.

Seleccionar el Node Finder. En Filter, elegir Pins: all, luego hacer click en List. Hecho eso aparecerán todos los puertos creados en el proyecto. Hacer click en >>, luego en OK para finalizar.

Veremos todos los puertos que hemos creado en nuestro proyecto...




Hecho esto, la ventana quedará lista para determinar las formas de onda para simular nuestro proyecto.

Ya estamos listos para crear nuestras señales de prueba...

Notar que nuestra salida Z tiene valor desconocido. Ello debido que aun no se simulado nada. Debemos dejarlo así para evitar que el simulador lo interprete como colisión de señal y nos bote un error.

Por defecto, el simulador elige un tiempo de simulación de 1us. Si quieren ampliar este intervalo, hacer click en Edit => Set End Time. 

Elegir cuanto tiempo quieres simular...


Por ahora lo dejaremos en 1 us. 

Dentro del cuadro rojo, los posibles niveles que le podemos asignar a nuestras entradas... interesante ¿no creen?
Para asignar los niveles a las señales, resaltar el intervalo que deseen aignar, y elegir el nivel deseado en la parte indicada por el recuadro rojo. 

Para este caso, elegí los siguiente para las tres entradas:

Señales con sus valores ya definidos... ahora sí, ¡a simular!

A la entrada a le asigné un reloj de 100ns de periodo, a la entrada b, reloj de 200ns, y a la entrada c, un reloj de 400ns. Hecho esto, guardamos el archivo con el mismo nombre de la entidad que queremos simular y cerramos el editor de vwf.

En la ventana principal del simulador, hacer click Assign => Simulator Settings...

Ajustes de simulación.

En esta ventana, elegir el archivo .vwf que hemos creado. En este caso, primerejemplo1.vwf. La opción de abajo es importante. Existen dos tipos de simulación con archivos .vwf: la simulación funcional y la simulación temporal. La primera (Functional), simulará asumiendo que todos los elementos lógicos son ideales, y que por ende, no tienen retardos de propagación. Este tipo de simulación se usa para verificar si la estructura de tu diseño es correcta o no. La simulación temporal (Timing) en cambio sí toma en cuenta estos retardos. Esta simulación es más realista, y se usa para contrastar si tu diseño se ve afecto o no en su desempeño debido a estos retardos.

En este caso elegiré la simulación temporal. 

Hecho esto queda hacer click en la gran flecha azul para inicar la simulación. Lamentablemente os saldrá un error. Ello debido a que la familia Cyclone no es soportada por el simulador. Para corregir el error, simplemente compilar el diseño sobre otro FPGA o CPLD. En este caso, elegiremos un CPLD de la familia MAX3000A. Para hacer el cambio, hacer click en Assignments => Device.

 
Elegiremos a la buena familia de CPLD MAX3000A.

Compilamos nuevamente, y leemos el reporte. Vemos que esta vez se consumió el 3% de área del CPLD. Ello debido a que solo tiene 32 macroceldas (para los CPLD's, ya no son elementos lógicos, sino macroceldas). 

32 macroceldas ofrecidas por la MAX3000A, 1 macrocelda destinada a nuestro proyecto.
Hecho esto, en el simulador recargamos el proyecto, recargamos el archivo .vwf y le damos click a la gran flecha azul. Esta vez la simulación será exitosa. 

Aun se puede ver en rojo el error producido por querer simular en una FPGA de la familia Cyclone.

Es importante lograr el 100% de covertura en la simulación, a fin de que todas las posibilidades sean simuladas. En este caso, para las formas de onda creadas, se obtuvo un 100.00% de coverage. Si no se hubiese logrado, deberíamos cambiar las formas de onda de las entradas, buscando cubrir todas las posibilidades. Bueno, al acabar de simular, no saltará el reporte de simulación con la forma de onda de la salida.

Reporte de simulación... ¡yeah! Resultados esperados... diseño funcionando bien...

Se aprecia en el diagrama obtenido que la salida se comporta según lo esperado, lo cual verifica que el diseño está bien. Acercándonos más en la respuesta, podemos medir los retrasos de propagación de nuestro diseño. Para ello, agregamos punteros. Para ello, hacemos doble click  en el espacio en blanco entre la barra en donde están los tiempos, y el espacio en donde dibujamos nuestras formas de onda. Aparece un puntero en dicha posición. Luego, hacemos click en Edit => Snap to grid para hacer que los punteros puedan posicionarse en cualquier punto  (si Snap to grid está seleccionada, los punteros se posicionarán solo en los ejes marcados por las líneas verticales punteadas (grid)). El segundo puntero marcará la diferencia en tiempo respecto al puntero master (para diferenciarlo, el puntero master tiene un indicar de posición en la parte superior y además, tendrá una línea azul bien definida, mientras que los punteros secundarios serán líneas delgadas azules). 

Añadiendo punteros.

En este caso, el ratardo, medido usando punteros, es de 3.584ns. 

Con esto, la simulación queda finalizada.


Segunda y tercera de codificación para el primer ejemplo


Ahora, utilizaremos una señal para codificar el circuito.
library ieee;

use ieee.std_logic_1164.all;

entity primerejemplo2 is
port(
a,b,c :in std_logic;
z :out std_logic);
end primerejemplo2;

architecture arqej of primerejemplo2 is
signal ac:std_logic;
begin
ac<= a and c;
z<=ac or b;
end arqej;
Creamos la señal ac, y le asignamos el producto lógico de las entrada a y c. Luego, obtenemos nuestra salida z a partir de ella.

Al guardar el diseño, lo hacemos dentro del proyecto primerejemplo, y luego le asignamos la prioridad este archivo (lo seteamos como archivo top-level). Para ello, ver la siguiente imagen:

Set a Top-level Entity...

Compilar y seguir los pasos anteriores para simular. El resultado es el siguiente:

Mismo resultado al anterior... eso implica que los diseños son equivalentes...

La última forma para diseñar el sistema del primer ejemplo es usando la tabla de verdad:
library ieee;
use ieee.std_logic_1164.all;

entity primerejemplo3 is
port(
abc :in std_logic_vector(2 downto 0);
z :out std_logic);
end primerejemplo3;

architecture arqej of primerejemplo3 is
begin

with abc select z<=
'1' when "010",
'1' when "011",
'1' when "101",
'1' when "111",
'0' when others;

end arqej;
Esta vez se definió la entrada como un vector de 3 bits. Vemos que la salida z se asgina según los valores que tome el vector abc de acuerdo a la tabla de verdad hallada. No se preocupen por entender como funciona esa manera de asignación. En las entradas que vienen me enfocaré en sí al diseño en VHDL, explicándoles todas las maneras de asignación posibles, así como estilos de programación y otros asuntos de interés.

Tras compilar y simular, se verifica que este diseño también es equivalente a los dos planteados previamente. 

Bueno, así termina esta entrada. Hasta la próxima oportunidad.

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.