Práctica 5

Anuncio
ELECTRÓNICA DIGITAL
PRÁCTICA 5
SIMULACIÓN EN VHDL
CON VERIBEST
En esta práctica vamos a ver una breve introducción a la simulación de circuitos
electrónicos mediante el uso de Lenguajes de Descripción de Hardware, y en concreto
utilizaremos el simulador de VHDL de Veribest. El uso de los comandos e
instrucciones más comunes de esta herramienta se ilustra mediante un ejemplo sencillo,
y abarca desde la creación de un fichero, la compilación, la visualización de las formas
de onda...
0-. Realización de la práctica.
Para el desarrollo de la práctica, vamos a realizar la simulación completa de
cuantos circuitos electrónicos podamos. Sugerencia: comenzar por los más sencillos
(puertas), y luego aumentar la complejidad (mux, sumadores…).
1-. Arranque del programa.
Se puede realizar de varias formas, desde el menú de Inicio, bien mediante el
icono de acceso directo (si existe), o conociendo la ruta del programa, que debería ser:
C:\Programs\Veribest VB99.0\Veribest VHDL simulator \ Veribest VHDL
La ventana del simulador se muestra en la siguiente figura:
Fig. 1. Ventana inicial del simulador Veribest.
2-. Creación de espacio de trabajo.
Antes de empezar a trabajar con esta herramienta, es conveniente crearse lo que
se llama un espacio de trabajo (Workspace), donde guardaremos todos nuestros ficheros
VHDL. En la barra de herramientas seleccionad Workspace, y dentro de ella New. A
continuación se nos pedirá un nombre para nuestro espacio y una ruta. El nombre será
Practicas y la ruta c:\Practicas_VHDL.
Aparecerá inmediatamente una nueva ventana con el nombre Practicas.vpd, con
una serie de botones algunos de los cuales se comentarán más adelante, y una carpeta
llamada Practicas source, donde se guardarán nuestros ficheros.
3-. Edición de un fichero.
Para crear un fichero nuevo se selecciona FileÎNew, y en la ventana que
aparece escogeremos la opción VHDL source file. Como nombre del fichero
escogeremos el que más nos interese, guardándolo desde FileÎSave as. En ocasiones
perderemos la extensión *.vhd, necesaria para que nuestro fichero sea reconocido.
A partir de este momento, podemos introducir nuestro código. Es una buena
costumbre que las palabras reservadas del lenguaje las escribamos en mayúsculas y el
resto en minúsculas, aunque el compilador no distingue entre ambas.
Una vez escrito el código lo guardamos (FileÎSave), y añadimos el fichero
creado al espacio de trabajo, presionando en la ventana del Workspace la tecla +, y
escogiendo el nombre de nuestro fichero creado. Si no apareciese, hemos perdido la
extensión, abriendo todos los archivos (*.*) se soluciona el problema. Aparecerá
nuestro archivo añadido, y podemos cerrar la ventana con el código fuente.
Como simple ejemplo, empezaremos con un circuito muy sencillo; una puerta
OR de dos entradas. El código para esta podría ser:
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
ENTITY or2 IS
PORT (a, b: in bit;
q: out bit);
END or2;
ARCHITECTURE or2_comp OF or2 IS
BEGIN
q <= a OR b;
END or2_comp;
4-. Compilación.
En realidad no es un proceso exactamente de compilación el que vamos a
realizar, porque no crearemos un archivo ejecutable, sino uno listo para ser simulado.
Establecemos las condiciones de compilación:
WorkspaceÎSettings
En la nueva ventana, aseguraos que la opción Debug está seleccionada, después
haced clic en aceptar. A continuación se analiza el fichero:
WorkspaceÎCompile <nombre de nuestro fichero>
Si el código es correcto, aparecerán mensajes de compilación de las entidades y
arquitecturas, componentes y demás que nuestro circuito posea, seguidos del mensaje
Done. Si el código no es correcto, aquí se marcará la línea donde se encuentra(n) el
error(es) y de que tipo es. En este caso los corregiremos y repetiremos el proceso de
compilación.
Cuando el proceso no da errores, lo guardamos (Save). La unidad compilada se
almacena en la librería WORK. Para ver su ubicación, seleccionad Library en la barra
de herramientas, y dentro de ella Library Browser, o pinchad en el icono
correspondiente. Aparecen las diferentes librerías, IEEE, STD, VB, y en rojo WORK,
WORKLIB. Si pinchamos en esta aparecen, con símbolos de chip, los diferentes
circuitos que hayamos compilado; no su código, sino la entidad, arquitectura…etc., que
llevan asociadas. Podemos Ver información de fecha y opciones de compilación en la
parte derecha de la ventana. (Ver figura).
Fig. 2. Aspecto del Veribest con el Library Browser activado.
5-. Preparación del diseño.
Por cuestiones de flexibilidad, se aconseja que la entidad y la(s) arquitectura(s)
asociadas a un diseño ocupen ficheros separados (pero no es en realidad necesario). Si
lo hacemos así, llegados a este punto y dentro de WORK, tendremos el icono de
nuestra entidad en blanco. Si el fichero de código lleva asociada una arquitectura, estará
en rojo. No se puede simular un circuito si no tiene asociada al menos una arquitectura y
un fichero de test. En nuestro caso podríamos haber separado la declaración de entidad
de la puerta OR en un fichero (p. ej. OR2_ENT.vhd), y la arquitectura en otro
(OR2_ARQ.vhd), respetando en ambos casos el código fuente, y de ser así al compilar
la entidad tendríamos el chip en blanco (sin opción a simular), y tras añadir la
arquitectura el chip en rojo (solo faltaría el test).
El momento más delicado de una simulación es la preparación de este fichero de
test. Debe barrer, idealmente, todas las posibles variaciones en las entradas del sistema
para que estemos seguros de que las salidas sean las correctas, pero lógicamente no
siempre va a poder ser así. En nuestro caso, está bastante claro cuales son las formas
de onda que necesitamos para verificar el comportamiento de nuestro sistema.
a
Fig. 3. Formas de onda que representan la tabla de
verdad de una puerta OR de dos entradas.
b
q
0
5 10 15 20
(tiempo en nanosegundos).
El fichero de test necesita una entidad y una arquitectura. Las entidades de
ficheros test no tienen puertos. Las arquitecturas son estructurales, incluyendo en su
declaración el componente que se va a testear, la arquitectura que se le asocia y la
declaración de señales. En nuestro caso:
ENTITY or2_test IS
END or2_test;
ARCHITECTURE test_flujo OF or2_test IS
COMPONENT
or2 PORT ( a, b: IN BIT;
q: OUT BIT);
END COMPONENT;
FOR I: or2 USE ENTITY WORK.or2 (or2_comp);
SIGNAL a, b, q: BIT;
BEGIN
I: or2 PORT MAP (a, b, q);
a <= '0', '1' AFTER 5 ns, '0' AFTER 15 ns;
b <= '0', '1' AFTER 10 ns, '0' AFTER 20 ns;
END test_flujo;
Se compilará el fichero buscando errores, y añadiéndose a la librería WORK
como se vio anteriormente. De momento, es recomendable que veamos como se han
añadido las nuevas entidad y arquitectura a la librería.
6-. Simulación
Lo primero que hay que hacer es establecer las condiciones de simulación, en
WorkspaceÎSettings
Como en el caso de la compilación, pero ahora se selecciona SIMULATE y se
abre la carpeta WORK. Ahí aparece la entidad y la arquitectura de nuestro fichero de
test, y por supuesto el resto de las que tengamos. Hay que simular el test, que es donde
tenemos configurada la entidad de nuestra puerta OR2, de modo que pinchamos en él.
Sobre el espacio que acompaña a la palabra Entity nos colocaremos, activando el botón
de Set. A continuación seleccionamos la arquitectura Test_flujo, seleccionándola como
arquitectura mediante el mismo procedimiento. Por último, activamos la opción Trace
On (que nos permite visualizar las formas de onda resultantes). Esto también se logra
desplegando SimulateÎTrace.
A continuación activaremos el simulador. Es recomendable tener activada, en la
parte inferior de la pantalla, la pestaña GENERAL de la ventana de mensajes. Podemos
poner en marcha la simulación desde WorkspaceÎExecute Simulator, y en la pantalla
de mensajes se nos avisara, probablemente, de la no existencia de la licencia, y por lo
tanto de que el simulador funcionará a baja capacidad. Esto no es importante,
aceptaremos el mensaje y continuaremos. En la pestaña SIMULATE Se puede observar
que no hay errores, y la simulación está lista para ser comenzada.
En la barra de herramientas, presionad el botón de Play, en verde. El tiempo en
nanosegundos resaltado debe ser superior al que en nuestro fichero de test hayamos
empleado. En nuestro caso lo es. Se nos avisará de que se ha efectuado la simulación del
tiempo requerido. Otra opción para activar la simulación es, en la barra de herramientas
SimulateÎRun. Se puede detener la simulación mediante la selección de la función
Quit, o su símbolo en la barra de herramientas (Stop).
Queremos visualizar los resultados de la simulación. Lo lograremos pinchando
en el icono de visualización de las formas de onda (en la barra de herramientas aparece
muy gráficamente reflejado de cual se trata). Aparece una ventana nueva, Waveform
Viewer, en la que debemos seleccionar las señales a visualizar, lo cual haremos una a
una mediante la función Add, o todas ellas a la vez con Add All. En cualquier caso,
obtenemos lo siguiente:
Fig. 4. Waveform Viewer, las formas de onda obtenidas en la simulación.
Donde podemos ver que el resultado obtenido es el que cabía esperar. Ahora
estamos en disposición de comenzar desde el principio, añadiendo nuevos circuitos a
nuestro espacio de trabajo. Salimos del simulador mediante el icono Eject.
7-. VHDL
Es de resaltar que, como en todos los lenguajes de programación, la versatilidad
del VHDL nos permite realizar el mismo circuito de muchas formas distintas. En un
circuito medianamente complicado tendremos probablemente tantas soluciones
diferentes como personas aborden el problema.
Un último circuito nos permite estudiar algunas de las funciones más destacadas
del VHDL. En este ejemplo nos encontramos con uno de los casos en los que el archivo
de testeo no puede cubrir todas las posibilidades, o no resulta rentable así hacerlo:
Comparador de 4 bits.
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
ENTITY comp_4bit IS
PORT (a, b: IN BIT_VECTOR (3 DOWNTO 0);
agtb, altb, aeqtb: OUT BIT);
END comp_4bit;
ARCHITECTURE comportamental OF comp_4bit IS
BEGIN
PROCESS (a, b)
VARIABLE var_agtb: BIT := '0';
VARIABLE var_altb: BIT := '0';
VARIABLE var_aeqtb: BIT := '0';
BEGIN
L1: FOR i IN 3 DOWNTO 0 LOOP
IF ((a(i) = '1') and (b(i) = '0')) THEN
var_agtb := '1';
ELSE
var_agtb := '0';
END IF;
IF ((a(i) = '0') and (b(i) = '1')) THEN
var_altb := '1';
ELSE
var_altb := '0';
END IF;
IF (a(i) = b(i)) THEN
var_aeqtb := '1';
ELSE
var_aeqtb := '0';
END IF;
END LOOP L1;
agtb <= var_agtb;
altb <= var_altb;
aeqtb <= var_aeqtb;
END PROCESS;
END comportamental;
Test del comparador.
ENTITY comp_test IS
END comp_test;
ARCHITECTURE test_flujo OF comp_test IS
COMPONENT
comp_4bit PORT (
a, b: IN BIT_VECTOR (3 DOWNTO 0);
agtb, altb, aeqtb: OUT BIT);
END COMPONENT;
FOR I: comp_4bit USE ENTITY WORK.comp_4bit (comportamental);
SIGNAL a, b: BIT_VECTOR (3 DOWNTO 0);
SIGNAL agtb, altb, aeqtb: BIT;
BEGIN
I: comp_4bit PORT MAP (a, b, agtb, altb, aeqtb);
a <= "0000", "0001" AFTER 5 ns, "0010" AFTER 10 ns, "0011" AFTER
15 ns, "0100" AFTER 20 ns, "0101" AFTER 25 ns, "0110" AFTER 30 ns,
"0111" AFTER 35 ns, "1000" AFTER 40 ns, "1001" AFTER 45 ns, "1010"
AFTER 50 ns, "1011" AFTER 55 ns, "1100" AFTER 60 ns, "1101" AFTER 65
ns, "1110" AFTER 70 ns, "1111" AFTER 75 ns, "0000" AFTER 80 ns;
b <= "0001", "0000" AFTER 5 ns, "0010" AFTER 10 ns, "0011" AFTER
15 ns, "0001" AFTER 20 ns, "0100" AFTER 25 ns, "0110" AFTER 30 ns,
"1111" AFTER 35 ns, "0110" AFTER 40 ns, "1000" AFTER 45 ns, "1011"
AFTER 50 ns, "1011" AFTER 55 ns, "1100" AFTER 60 ns, "1101" AFTER 65
ns, "0110" AFTER 70 ns, "1101" AFTER 75 ns, "0000" AFTER 80 ns;
END test_flujo;
NOTA: En las formas de onda que el simulador nos ofrece podemos observar que, por
ejemplo ante las entradas a = “0100”, b = “0001” la salida del sistema es a < b, no a > b. Este error
se repite en la misma dirección y a la inversa (a > b cuando debería ser a < b) en diferentes
ejemplos de entrada y salida. ¿A que se debe el fallo de comparación? ¿Cómo lo podríamos
corregir?
Descargar