Mostrando entradas con la etiqueta Sistemas reconfigurables. Mostrar todas las entradas
Mostrando entradas con la etiqueta Sistemas reconfigurables. Mostrar todas las entradas

sábado, 26 de octubre de 2013

Bloques lógicos útiles en VHDL #3 Control de sincronización para VGA

Ok, ahora les voy a enseñar como hacer un controlador VGA usando un FPGA para que con base en eso puedan mandarle cualquier imagen a un monitor. Lo primero es entender las señales. Los monitores VGA trabajan con 5 señales básicas: la señal de sincronía vertical, la señal de sincronía horizontal, la señal del color rojo, la señal del color verde y la señal del color azul (RGB). 

Las señales de los colores son analógicas y varían entre 0 y 0.7V. Entre más voltaje, más brillante es el color. Haciendo combinaciones con los tres colores, se puede representar cualquier imagen.

Por otro lado, las señales de sincronía funcionan de la siguiente manera. El monitor va "imprimiendo" cada pixel de izquierda a derecha y de arriba hacia abajo, como se ve en la siguiente imagen



Por lo tanto, tiene que haber alguien que le diga cuándo empieza y cuándo termina. Este alguien son las señales de sincronización vertical y horizontal, y funcionan así.


Tanto la señal horizontal como la señal vertical tienen este formato. La señal comienza con un pulso de sincronización (Sync Pulse). Luego pasa a un "tiempo de espera" llamado Back Porch. Durante el Sync Pulse y el Front Porch, no se despliega ninguna imagen, y es recomendable no mandar a desplegar nada en ese momento. Después de que el pasó el Sync Pulse y el Back Porch, comienza el área visible. Aquí es el momento de comenzar a mandar la imagen. Una vez que termina de mandarse la imagen, se llega a un segundo tiempo de espera llamado Front Porch. Terminando este tiempo, la señal vuelve a comenzar.

Si tenemos un monitor de X pixeles de ancho por Y pixeles de alto, la señal de sincronización horizontal se debe mandar Y veces por cada vez que se refresca la pantalla (una por cada línea). Es decir, si tenemos un monitor de 640x480 pixeles, la señal de sincronización vertical se debe mandar 480 veces por cada señal de sincronización horizontal.

Ahora se estarán preguntando ¿cuánto deben durar estas señales?
Pues la respuesta varía según dos factores: la resolución que deseamos lograr y la frecuencia de actualización de nuestro monitor. La mayoría de los monitores utilizan una frecuencia de 50 o 60Hz, pero las resoluciones pueden variar mucho.

El motivo de estas señales que pueden llegar a ser hasta cierto punto ambiguas, es debido a la tecnología que usaban los monitores CRT. Ahora ya casi nadie usa estos monitores, pero el protocolo VGA sigue siendo bastante popular y prácticamente no ha cambiado.

Aquí es va el ejemplo. Vamos a utilizar una resolución de 640x480 pixeles a una frecuencia de 60Hz. Si se meten a este link (http://tinyvga.com/vga-timing/640x480@60Hz) encontrarán una tabla muy útil que es esta


Se darán cuenta que el Sync Pulse, el Front Porch y todas las partes de la señal se miden en pixeles. Esto facilitará impresionantemente nuestro código. Cabe destacar que aunque dice que necesitamos una frecuencia de pixeles de 25.175MHz, no es necesario generar esa frecuencia exacta, ya que los monitores modernos se pueden acoplar a tan sólo 25MHz. Sin embargo, si se va a usar un monitor viejo, pues sí hay que generar esa frecuencia exacta.

Pues bien, comencemos con el código. Este código está planeado para una tarjeta de desarrollo Basys2 con un FPGA de Xilinx modelo Spartan 3E y un reloj de 50MHz. Esta tarjeta cuenta con un puerto VGA, que internamente tiene un convertidor digital a analógico de 3 bits para el color rojo y el color verde y de 2 bits para el color azul, teniendo un total de 256 posibles colores.

Primero los puertos y las librerías

La única entrada es la señal de reloj de 50MHz.
Las salidas son las señales de sincronización horizontal y vertical, una señal que nos indique en qué momento comienza el área visible, una cuenta de pixeles en X y en Y, y el reloj de 25MHz para que esté todo bien sincronizado.

Ahora siguen las constantes que vamos a usar

Estas constantes son los datos de la tabla de hace un momento

Ahora siguen las señales internas


Ahora comenzamos con el divisor de frecuencia (de 50 a 25 MHz)

Luego, con esta nueva frecuencia, pasamos a hacer un contador horizontal y un contador vertical. Cada vez que el contador horizontal llegue a su límite, el contador vertical aumenta 1

Ahora viene la parte que manda el pulso de sincronización y la parte donde detecta cuándo comienza la parte visible de la señal

Finalmente viene la parte donde la cuenta horizontal y vertical del área visible comienza (aquí es donde se cuenta en qué pixel del área visible nos encontramos), y las asignaciones de las señales.

Como podrán ver, si lo implementamos en el FPGA, obtenemos estas señales (arriba es la horizontal y abajo es la vertical)


Señal horizontal completa


Pulso de sincronización vertical


Pulso de sincronización horizontal

Y pues si hacemos un código de prueba que despliegue 3 colores verticales, obtenemos el siguiente resultado



Y pues bueno, aquí les dejo los códigos de la simulación en Active HDL y del proyecto completo del Xilinx ISE Design Suite. Incluyen la imagen de prueba.

Simulación


Proyecto


Puro código de sincronización


My Github
https://github.com/DiegoRosales

domingo, 6 de octubre de 2013

Bloques lógicos útiles en VHDL #1 - Flip Flop tipo D con Clear y Chip Enable (FDCE)

Como ahora ando metido en esto de los FPGAs, he decidido comprartirles unos cuantos códigos útiles que pueden utilizar en sus diseños a bloques. Este primer código es un Flip Flop tipo D con habilitador (Chip Enable), Reset (Clear) asíncrono y entrada de reloj.
Si se dan cuenta (y con mucha imaginación), el nombre de este Flip Flop se puede simplificar como FDCE. Recuerden esto, pues les será muy útil después. El circuito es este:



Como podrán ver, tiene una entrada "D", una salida "Q", un habilitador "CE", un reset asíncrono "CLR" y una entrada de reloj (el triangulito). Es bastante básico, pero muy útil.

Este es el código.



library IEEE;
use IEEE.STD_LOGIC_1164.all;  

entity FDCE is
generic (INIT :std_logic:='0'); -- El Flip Flop inicia en 0
port(CE, CLR, C, D: in std_logic;
Q: out std_logic);
end FDCE;

architecture FDCE of FDCE is
signal temp: std_logic :=INIT;
begin
process (CLR, C)
begin
if(CLR='1') then -- Clear asíncrono
temp <='0';
elsif(CE='1' and C' event and C='1') then -- Si hay una señal de reloj con flanco positivo, Q obtiene el valor de D
temp <=D;
end if;
end process;
Q<= temp;
end FDCE;


Aquí les dejo una captura de la simulación en Active-HDL para que vean que sí funciona


Ahora lo padre de este Flip Flop es que en prácticamente todos los FPGAs viene ya construido y es muy fácil hacerlo funcionar sin necesidad de escribir este código. Lo único que tienen que hacer es instanciarlo y ya. Ni siquiera lo tienen que declarar como componente. Aquí les va un ejemplo usando las librerías de Xilinx para un Spartan 3E.

library IEEE;
use IEEE.STD_LOGIC_1164.all; 

library UNISIM;
use UNISIM.vcomponents.all;

entity FDCE_Xilinx is
port(
CK, D, CE, CLR: in std_logic;
Q: out std_logic
);
end FDCE_Xilinx;


architecture FDCE_Xilinx of FDCE_Xilinx is
begin

FlipFlop: FDCE generic map('0') -- Comienza en 0
port map (C=>CK, D=>D, CE=>CE, CLR=>CLR, Q=>Q);

end FDCE_Xilinx;

Como podrán ver, estoy utilizando una librería adicional que es la UNISIM. Esta librería es de Xilinx y está hecha para instanciar un montón de cosas en sus FPGAs, entre ellas este FlipFlop llamado FDCE (como el nombre que convenientemente le puse al otro código!!). Existe una muy buena documentación sobre todo lo que trae esta librería. Les dejo el link de la info para el Spartan 3.

Los archivos del Active-HDL también los pueden bajar de mi cuenta de MediaFire. Les dejo el link.

My Github
https://github.com/DiegoRosales

Saludos!!