Con
este software hay diferentes formas de simular, aquí vamos a usar la más fácil
para este caso.
Lo
que obtendremos de esta simulación es un cronograma, si eso de cronograma te
suena a crucigrama y no tienes ni idea que es, no te preocupes que lo verás. De
hecho si echas un ojo a la última entrada, ahí encontrarás que uso cronogramas
como este:
También
subrayo lo dicho, que hay distintas formas de simular con XILINX, (e incluso
con XILINX en colaboración con SIMULINK o Labview), esta forma de simular es
sólo una más.
En
VHDL, como en prácticamente todos los lenguajes de programación, hay muchas
formas de hacer código para obtener un mismo resultado, pero es que además en
el caso concreto de VHDL depende mucho de cómo describas el sistema.
En
VHDL la descripción de un sistema digital puede ser de res tipos: flujo de
datos, funcional (también llamada algorítmica) o estructural.
En
este caso tenemos una descripción funcional (o algorítmica), y eso hace que la
forma de simular que veremos sea probablemente la más fácil.
Sobre
estos conceptos (formas de describir un sistema digital en VHDL) hay abundante
documentación en Internet, y de todas formas si no los conoces me conformo de
momento con que sepas que un sistema digital se puede abordar de diferente
maneras. Con eso por ahora basta.
Ahora
“vayamos al grano”.
En
el código que tenemos, justo dónde señalo en la siguiente imagen:
Aquí dejo el código modificado para copiar y pegar:
--???21EDA?? --?????:A-C8V4 --www.21eda.com --??LED???LED??????0??????1??? --????????21EDA???????? LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.std_logic_unsigned.ALL; ENTITY LEDA_blog is PORT( clk:in STD_LOGIC; --System Clk --???? led1:out STD_LOGIC_VECTOR(3 DOWNTO 0); LCD_N : out std_logic; --?????? LCD_P : out std_logic ); --LED output???8? END LEDA_blog ; ARCHITECTURE light_blog OF LEDA_blog IS SIGNAL clk1:std_logic := ‘0’; SIGNAL CLK2:std_logic := ‘0’; BEGIN LCD_N<='0'; LCD_P<='0'; P1:PROCESS (clk) VARIABLE count:INTEGER RANGE 0 TO 9999999; BEGIN IF clk'EVENT AND clk='1' THEN --????????????????? IF count<=4999999 THEN clk1<='0'; --?count<=499999?divls=0??count?1 count:=count+1; ELSIF count>=4999999 AND count<=9999999 THEN --?ount>=499999 ?count<=999998 clk1<='1'; -- count:=count+1; --clk1=1??count?1 ELSE count:=0; --?count>=499999???count1 END IF; END IF; END PROCESS ; P3:PROCESS(CLK1) Begin IF clk1'event AND clk1='1'THEN clk2<=not clk2; END IF; END PROCESS P3; --------------------------------------------------------- P2:PROCESS(clk2) variable count1:INTEGER RANGE 0 TO 16; --???????????? BEGIN -- IF clk2'event AND clk2='1'THEN --????????????????? if count1<=4 then --?COUNT1<=9??????? if count1=4 then --?COUNT1=8??COUNT1?? count1:=0; -- end if; -- CASE count1 IS --CASE?????LED1?? WHEN 0=>led1<="1110"; --????????? WHEN 1=>led1<="1101"; -- WHEN 2=>led1<="1011"; -- WHEN 3=>led1<="0111"; -- WHEN OTHERS=>led1<="1111"; END CASE; count1:=count1+1; end if; end if; end process; END light_blog;
Estas
modificaciones no afectan de forma sustancial el comportamiento del sistema. De
hecho, si volvemos a implementar este código modificado en el hardware que
expliqué en las doce primeras entradas (el kit Open3S250E) veremos que
funciona exactamente igual.
funciona exactamente igual.
No
es raro que no se haya cambiado esencialmente el algoritmo a implementar,
porque lo único que hemos hecho es inicializar las señales clk1 y clk2 a ‘0’.
También las podíamos haber inicializado a ‘1’ sin ningún problema. La cuestión
es inicializar esas señales a un valor cero o uno (son de tipo std_logic que ya
vimos es un tipo de dato para bits 0 o 1).
Ahora
activamos el casillero de Simulation (configurado para simular con “isim”),
justo dónde señala la flecha roja en la siguiente imagen:
A continuación nos queda:
En la anterior interfaz surgido de activar el casillero
Simulation (con Isin), se hace doble clic en dónde señalo en la figura
siguiente:
Nos
surge una nueva ventana llamada Isim, que forma parte del paquete software de
XILINX, con la siguiente apariencia.
A continuación ponemos el cursor dónde señalo a
continuación:
Con
el cursor en clk, hacemos clic derecho en el ratón:
Ya
vemos que surge un desplegable, en dicho desplegable hacemos clic en “Force
Clock...”.
Aparece una ventana emergente con el nombre “Define Clock”.
Esta ventana emergente rellenamos tres campos como explicaré
a continuación (los demás se dejan igual o en blanco):
Para explicar el porque de estos valores que damos a estos
parámetros usare la siguiente figura (una imagen vale más que mil palabras).
Leading
Edge Value: 0
Trailing
Edge Value: 1
Period: 20ns
Es decir, es así como se inicia el periodo de reloj.
Una
vez iniciado el reloj, sigue el tren de pulsos que suelen ser las señales de
reloj:
El periodo lo hemos puesto a 20ns porque (como ya vimos) la
señal de reloj de clk tiene una frecuencia de 50 MHz, o sea fclk = 50 MHz. Por tanto:
Periodo = Tclk
= 1/ fclk = 20 ns
Sin embargo si lo hubiéramos iniciado como sigue:
Leading
Edge Value: 1
Trailing
Edge Value: 0
Period: 20ns
Tendríamos:
y por tanto la señal de reloj:
Ahora clic en OK.
Y tenemos:
---------------------------------------------------------------------------------
Inciso:
Antes de seguir con el proceso de simulación tengamos en
cuenta como realiza el proceso de simulación (pre-síntesis) el software.
Si no lo viste en su momento, ahora sería bueno que vieses
los conceptos de sentencias concurrentes y las diferencias entre señal y
variable (que más adelante nos vendrá bien conocer) que describí en esta entrada:
Si por cuestiones de tiempo o lo que sea, estás más
interesado en el “como simular” que en el “ como el software simula”, puedes
saltarte estas explicaciones.
Tenemos que tener en cuenta que un PC – en principio-
trabaja con las instrucciones o sentencias de forma secuencial y no
concurrente, y en cualquier caso el procesador de un PC no trabaja como un
sistema digital.
Sin embargo la simulación se hace en el PC, es por ello que
básicamente lo que hace el software de XILINX es convertir cada sentencia
concurrente a su proceso secuencial equivalente. Luego se simula todos esos
procesos concurrentes entre sí.
Como el algoritmo se diseñó con procesos, en este caso la
simulación se facilita.
--------------------------------------------------------------------------------------------------------------------------
Una vez hecho este inciso, seguimos con el tutorial.
Para que podamos ver el resultado de la simulación en forma
de cronograma mejor hacer lo que voy a explicar:
Clic derecho del ratón en la pestaña que señalo a
continuación:
Clic en float:
Ahora tenemos el visor de cronogramas a pantalla completa:
Si quisiéramos colocar el cronograma en su situación
original, bastaría con hacer clic derecho en la pestaña ya mencionada y hacer
clic en “Dock”.
Como vimos que no vamos a considerar ni LCD_N ni LCD_P,
podemos eliminarlos del cronograma como sigue:
Clic en LCD_N clic en botón derecho del ratón:
Clic en “Delete”.
Lo mismo con LCD_P y
ya tenemos:

Dónde aparece como valor (Value) la letra ‘U’ (y los
cronogramas aún no simulados en naranja)
significa “Undefined” o indefinido en inglés. Lo que está en verde, si está definido, pues lo inicializamos a
cero.
Aun nos aparece como “U” (indefinido) la señal clk,
calm-down, en cuanto simulemos eso se arregla.
Ahora podemos dar un rango de tiempo a la simulación (de
tiempo del proceso a implementar, no el tiempo de la simulación ojo).
Para ello vamos a el campo que señalo y escribimos 2
segundos por ejemplo (por defecto está puesto a 1.00us, muy poco en este caso).
A continuación se pulsa el icono “Run for the specified on
toolbar”:
--------------------------------------------------------------------------------------------------------------------------
Nota:
Existe otra opción para simular.
También se podría haber hecho pulsando el icono “Run All”,
para simular sin rango de tiempo establecido.
--------------------------------------------------------------------------------------------------------------------------
Pero lo haremos con
“Run for the specified on toolbar” para
que podamos sacar más partido a las potencialidades del ISim.
Una vez que hemos empezado la simulación puedes observar que
el cronograma aparece intermitente. Esto es porque la pantalla avanza en
el tiempo más rápido que la simulación. De manera que en muchos momentos no
vemos los cronogramas (esto no sucede con la opción “Run All”).
Para resolver esto, sin ni siquiera parando la simulación,
hacemos como sigue:
Con lo que tenemos ahora:
Si queremos parar la simulación basta con dar al icono:
Y si queremos reanudar:
Además, podemos mejorar la visualización alejando (Zoom Out) o
acercando (Zoom In) la imagen de los cronogramas, tanto en simulación como en pausa.
Para
ello tenemos dos iconos justo a la izquierda de la ventana de cronogramas y
encima del icono “Zoom to full view”:
Así pues, si partimos de:
Pulsando varias veces el icono de “Zoom out” se tiene:
Resultado que por cierto encaja bastante bien con lo que
habíamos descifrado del código VHDL en la entrada anterior.
Hay, sin embargo un par de detalles que destacan de la
última figura y que aún no hemos abordado.
El primero es que hasta los 100 ms (una décima de segundo),
la señal de los LEDs aparece como indefinida. Esto no es tan extraño si
consideramos que led1 es una señal, y tal y como abordamos en la segunda parte
de la entrada:
(que trataba de la diferencia entre variables y señales y
abordaba especialmente la cuestión de las señales), cuando hacemos una
asignación a señal realmente estamos dándole un valor futuro (para el siguiente
instante de tiempo en que vuelva a ejecutarse), tomando la señal el valor
actual (anteriormente asignado).
Como el vector de bits led1 no se inicializa, por defecto
empieza con el “valor” indefinido (o Undefined, de ahí la U y el
correspondiente color anaranjado), hasta que pasados los 100 ms se hace vigente
el valor anteriormente asignado.
La segundo cuestión es el cursor en forma de línea vertical
amarilla.
Si mantenemos pulsado dicho cursor no sólo podemos ir
desplazándonos por la señal simulada, además nos marcará el valor de las señales
dónde este situado en cada momento, así como el instante de tiempo dónde está
situado en los cronogramas.
Vamos a hacer una prueba de su utilidad, en el anterior post
a este (el que explicaba el algoritmo VHDL del código LEDA_blog), calculamos
que el periodo de la señal clk2 era 0,4 segundos o 400 milisegundos. Veamos si
el calculo era correcto.
Al principio de periodo (en el primer flanco de subida),
tenemos el tiempo de 100 ms.
Al final del periodo (en el segundo flanco de subida),
tenemos el tiempo de 500 ms.
Luego:
Tclk2 = 500 ms – 100 ms = 400 ms =
0,4 ms.
Luego el resultado del periodo que predijimos para Tclk2,
Tclk2 = 0,4 ms, era correcto.
Además en el la siguiente figura del cronograma resultante
de la simulación se oserva que se cumple la secuencia esperada de 0s y 1s del
vector de bits led1.
Como ya comentamos al principio de esta entrada del blog, hay otras formas de simular, incluso en colaboración con otras aplicaciones como el SIMULINK de MATLAB por ejemplo.