sábado, 2 de febrero de 2013

Contador binario ascendente descendente de 5 bits con VHDL en FPGA de Spartan 3E

Ejercicio: Diseñar con VHDL e implementar en la tarjeta Digilent con FPGA Spartan 3E un contador binario de 5 bits tanto ascendente como en forma descendente, que trabaje a 1 Hz de frecuencia. El contador dispone además de entrada de habilitación con la cual se puede bloquear.


Solución:  Creamos el proyecto contador0al31 tal como se ha indicado en entradas anteriores de este blog, definiendo como VHDL el modo jerárquico de trabajo.


Como no vamos a trabajar nada en Esquemático lo aconsejable es elaborar un gráfico que resuma el diseño, para elaborar los diferentes módulos VHDL requeridos.


Observamos que hay un bloque principal CONTADOR5BITS de entradas: CLK50Mhz, Habilitador y Dirección y salidas: Q4,Q3,Q2,Q1,Q0.  Hay dos bloques sen su interior: el Divisor_Frecuencia de entradas: CLKentrada y Reset, y salida: CLK1Hz.  El otro bloque es el contador0al31 cuyas entradas son: Reloj y ModoConteo y salidas: Salida4,...,Salida0.

Vamos a elaborar un programa VHDL  para cada bloque en el siguiente órden:

  • contador0al31
  • Divisor_Frecuencia
  • CONTADOR5bits (que enlace los dos anteriores de acuerdo al gráfico)


Al crear Módulo VHDL  como nueva fuente para contador0al31 defina las entradas y salidas tal como se indica a continuación:


Observe que la Salida se configura como vector (Bus de 5 bits) .

El ISE 10.1  nos lleva a la ventana para escribir el programa en VHDL del contador el cual lo editamos así:


Para escribir lo concerniente a la arquitectura ...después de begin nos ayudamos de las plantillas de VHDL.

Para ello vaya a Edit --> Language Templates ... --> VHDL --> Synthesis Constructs --> Coding Examples --> Counters --> Binary --> Up/Down Counters --> Simple Counter

La plantilla nos muestra:

 process (<clock>) 
begin
   if <clock>='1' and <clock>'event then
      if <ModoConteo = '1' then   
         <count> <= <count> + 1;
      else
         <count> <= <count> - 1;
      end if;
   end if;
end process;

Editamos de acuerdo al nombre dado nuestras entradas, así:


process (Reloj) 
begin
   if   Reloj = '1' and Reloj'event then
      if ModoConteo = '1' then   
        cuenta <= cuenta + 1;
      else
         cuenta <=  cuenta - 1;
      end if;
   end if;
end process;


Copiamos y pegamos al comienzo (begin) de la arquitectura ... en el archivo en VHDL, y cerramos la plantilla. Salvamos el archivo VHDL, y chequeamos la sintaxis para saber si está bien en este aspecto.

Vemos que se presenta error de sintaxis...



Se indica en el reporte que  se presenta un error porque no se ha definido la variable "cuenta"

Procedemos entonces a declarar esa variable "cuenta" como una señal auxiliar interna SIGNAL antes de comenzar el proceso del reloj  y así mismo después de finalizar el mismo proceso hay que señalar que lo que está en "cuenta" hay que enviarlo a la "Salida" del contador.

Después de haber efectuado las correcciones el programa queda así:


Al chequear sintaxis vemos que ahora no se presenta error.Luego continuamos con la simulación del circuito.

Creamos el archivo de chequeo de formas de onda, que llamamos contador0al31_tb.



Configure la ventana de tiempos de inicialización como se indica:


Cuando la entrada ModoConteo = 1, el contador lo hace ascendentemente, y si vale 0 cuenta en forma descendente. Dibujamos dicha entrada arbitrariamente, para observar en la simulación el comportamiento del contador:


Salvamos el archivo del banco de pruebas y cerramos la ventana de las formas de onda, y procedemos a efectuar su simulación:


Podemos verificar con las formas de onda que el contador responde a lo solicitado.


Procedemos ahora con el divisor de frecuencia el cual no simulamos.


De este blog en la entrada (Intermitencia en encendido y apagado de un Led) copiamos el respectivo programa VHDL , lo copiamos, editamos para que se acople a las entradas y salidas que le asignamos en nuestro gráfico donde presentamos los bloques,  salvamos y chequeamos sintaxis:


Vamos ahora a enlazar los dos bloques o programas, de acuerdo al gráfico inicial, al cual le adicionamos una señal interna  X   necesaria  para el diseño:



Creamos el programa final VHDL  CONTADOR5bits para enlazar los dos anteriores:


Fijamos entradas y salidas, como se indica en color amarillo en el gráfico.

El programa final es el siguiente:

--Programa final que enlaza Contador0al31 con Divisor_Frecuencia

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity CONTADOR5bits is
    Port ( CLK50Mhz :    in  STD_LOGIC;
           Habilitador : in  STD_LOGIC;
           Direccion :   in  STD_LOGIC;
           Q :          out  STD_LOGIC_VECTOR (4 downto 0));
end CONTADOR5bits;

architecture Comportamiento of CONTADOR5bits is

    component Divisor_Frecuencia is
        Port (
        CLKentrada: in  STD_LOGIC;
        Reset     : in  STD_LOGIC;
        CLK1Hz    : out STD_LOGIC
           );
        end component;

component contador0al31 is
                Port ( Reloj : in  STD_LOGIC;
                ModoConteo : in  STD_LOGIC;
           Salida : out  STD_LOGIC_VECTOR (4 downto 0));
      end component;

signal X : STD_LOGIC;

begin

 C1:  Divisor_Frecuencia port map
( CLKentrada => CLK50Mhz, Reset => Habilitador, CLk1Hz => X); 

C2: contador0al31 port map
 ( Reloj => X, ModoConteo => Direccion , Salida => Q); 

end Comportamiento;


Chequeamos sintaxis para estar seguros que no se presenta error alguno, y puede ser compilado.


Sigue ahora la asignación de pines a la FPGA para el archivo CONTADOR5bits.vhd final:



Damos doble click en Floor Area /IO/ Logic-Post-Synthesis para entrar al editor PACE donde se asignan los pines a las entradas y salidas:


 Observe que se ha fijado el iterruptor  L13 para la dirección y  el pulsador K17 para habilitar el contador.

Salvamos el archivo de asiganación de pines y cerramos el editor PACE.

Damos doble click en Implement Design ( que presenta un interrogante color naranja a su derecha):



Corroboramos observando en el  resumen del diseño (View Design Summary), el reporte de pines (Pinout Report), dando click en la columna (Signal Name) que los pines están localizados correctamente:


Alimentamos la tarjeta Digilent Spartan 3E y conectamos el cable USB para efectuar la programación de la FPGA dando doble click en Configure Target Device. 

Al programar la FPGA vimos que el comportamiento del contador presentaba problemas al manejar el pulsador K17.  Se decidió cambiarlo por el interruptor N17; para ello editamos el archivo de asignación de pines CONTADOR5bits.ucf   y efectuamos el cambio en la entrada Habilitador de K17 por N17 (interruptor al extremo izquierdo de la tarjeta)


Como variamos la asignación de pines, después de salvar el archivo .ucf,  se requiere volver a implementar el diseño.  Damos doble click en Implement Design (que aparece nuevamente con interrogante color naranja).

Verificamos en el Pinout Report del resúmen del diseño, dando click en la columna de nombre de señal, que se haya verificado el cambio respectivo:


Configuramos el dispositivo en la tarjeta para que se genere el archivo de programación nuevamente, ya con el cambio efectuado.Luego volver a efectuar la programación de la FPGA, alimentando la tarjeta y conectando el cable USB.

En el video podemos observar su correcto funcionamiento: