lunes, 28 de enero de 2013

Intermitencia de encendido y apagado de LED en Spartan 3E con VHDL

Ejercicio: Un Led disponible en la tarjeta Digilent Spartan-3E debe parpadear cada segundo.

Solución:

La tarjeta Digilent Spartan-3E dispone de un reloj a cristal de 50 Mhz, y el Led hay que hacerlo encender y apagar con una frecuencia de 1 Hz, de tal manera que lo primero requerido es un divisor de frecuencia.

El divisor de frecuencia es un componente para reducir la frecuencia de entrada. Éste se implementa con ayuda de una Escala  y un contador, donde la Escala  es la relación o división entre la frecuencia de entrada y la frecuencia de salida deseada: 

Escala = \frac{f_{entrada}}{f_{deseada}}  


Recordemos que la frecuencia y el periodo de la señal son inversamente proporcionales, tal como se observa en las ondas mostradas, las cuales corresponden a un contador binario ascendente de 3 bits.

Como el contador cuenta del 0 al 7 (modo 8) al dividir la señal de entrada (50 Mhz) por 8 nos dá 6.25 Mhz, en el bit más significativo del contador.

Como el cristal tiene una frecuencia de 50MHz ( frecuencia de entrada) y deseamos una salida de  1 Hz, tenemos que:
Escala = 50 Mhz / 1Hz = 50 000 000 

Si el reloj tiene el mismo tiempo en alto que en bajo:

t_{alto} = t_{bajo} = \frac{50 000 000}{2} = 25 000 000

SI empezamos el conteo desde cero, y  un contador al llegar a  24 999 999 genera un pulso, esto quiere decir que la frecuencia de salida , de los pulsos generados,  debe ser de 1 Hz.

Veamos el programa en VHDL:


--Divisor de frecuencia de 50MHz a 1Hz para parpadeo de LED
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 entity clk1Hz is
    Port (
        clk50Mhz: in  STD_LOGIC;
        reset   : in  STD_LOGIC;
        led     : out STD_LOGIC
    );
end clk1Hz;

architecture Behavioral of clk1Hz is
    signal pulso: STD_LOGIC;
    signal contador: integer range 0 to 24999999 := 0;
begin
    divisor_frecuencia: process (reset, clk50Mhz) begin
        if (reset = '0') then
            pulso <= '0';
            contador <= 0;
        elsif rising_edge(clk50Mhz) then
            if (contador = 24999999) then
                pulso <= NOT(pulso);
                contador <= 0;
            else
                contador <= contador+1;
            end if;
        end if;
    end process;
     led  <= pulso;
end Behavioral;


El contador dispone de una entrada de reset que se activa con nivel bajo, es decir si reset = 0, sin importar el flanco del reloj el contador se resetea. 
La primera vez que el contador llega al 24999999, la señal interna pulso pasa del nivel bajo a nivel alto, el contador pasa a 0, y vuelve a comenzar a contar, mientras la entrada reset sea alta, y al volver a llegar a  

24999999,pulso pasa ahora de 1 a 0, completando un pulso completo, o sea un periodo de reloj; 

de esta forma la salida es de solo 1 Hz.


¡ Cada 50 millones de pulsos a la entrada se produce 1 pulso a la salida !

Con captura esquemática es imposible lograr esto; en cambio con lenguaje VHDL se hace de una
forma muy sencilla. Por eso VHDL se impone cada día mas, como lenguaje para describir hardware y efectuar en forma simple y práctica el diseño digital, pero se requiere, por ejemplo, de una FPGA 
donde el programa se pueda aplicar e implementar.


Con el navegador de proyectos de Xilinx ISE 10.1  creamos como nuevo proyecto: LedParpadeo, y como nueva fuente en Módulo VHDL: clk1Hz. 

Copiamos y pegamos el programa ya visto, salvamos y chequeamos sintaxis

Para este caso no es necesario efectuar la simulación.

Procedemos a elaborar la síntesis y la asignación de pines.



Verificamos en Pinout Report que los pines quedaron bien asignados, 

implementamos el diseño y generamos el archivo de programación, para

configurar el dispositivo.