controlador VGA no funciona

2

En este momento estoy tratando de hacer un controlador vga para mi FPGA, pero algo no va bien, y parece que no puedo descubrir qué está saliendo mal ...

El código se basa en este ejemplo de código: Controlador VGA de ejemplo

Aquí está mi código: (Solo he cambiado la resolución y algunos nombres de variables, aparte de que debería ser exactamente el mismo).

    ----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date: 03/07/2016 08:53:44 AM
-- Design Name: 
-- Module Name: vga - Behavioral
-- Project Name: 
-- Target Devices: 
-- Tool Versions: 
-- Description: 
-- 
-- Dependencies: 
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
----------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity vga is
    GENERIC(
            constant HR:integer:=640;--Horizontal Resolution
            constant HFP:integer:=16;--Horizontal Front Porch
            constant HBP:integer:=48;--Horizontal Back Porch
            constant HRet:integer:=96;--Horizontal retrace
            h_pol    :  STD_LOGIC := '0';   --horizontal sync pulse polarity (1 = positive, 0 = negative)

            constant VR:integer:=480;--Vertical Resolution
            constant VFP:integer:=10;--Vertical Front Porch
            constant VBP:integer:=33;--Vertical Back Porch
            constant VRet:integer:=2;--Vertical Retrace); 
            v_pol    :  STD_LOGIC := '0'  --vertical sync pulse polarity (1 = positive, 0 = negative)

            );
    Port ( clk : in STD_LOGIC;
           LED0: out std_logic;
           vga_r: out std_logic_vector(4 downto 0);
           vga_g: out std_logic_vector(5 downto 0);
           vga_b: out std_logic_vector(4 downto 0);
           vga_vs: out std_logic;
           vga_hs: out std_logic);
end vga;

architecture Behavioral of vga is
signal COUNT : integer range 0 to 100000000;
constant x_counter:  integer := HR + HFP + HBP + HRet;   
constant y_counter:  integer := VR + VFP + VBP + VRet;
signal newCounter: integer range 0 to 4 := 0;
signal newClk: std_logic; 
begin

alive: process(CLK)
    begin
        if rising_edge(CLK) then 
           COUNT  <= COUNT + 1;

           if COUNT = 100000000 then 
               COUNT <= 0; 
           end if;

           if COUNT < 100000000/2 then 
           --     LED0 <=  '1';
           else 
           --     LED0 <= '0';
           end if;           
        end if;
end process;

prescaler: process(clk)
begin
    if rising_edge(clk) then 
        newCounter <= newCounter +1; 
            if newCounter = 4  then 
                newClk <= ‘1’;
                newCounter <= 0;
            else    
                newClk <= ‘0’;  
            end if;
    end if; 
end process;




screen:process(newClk)
VARIABLE h_count  :  INTEGER RANGE 0 TO x_counter - 1 := 0;  --horizontal counter (counts the columns)
VARIABLE v_count  :  INTEGER RANGE 0 TO y_counter - 1 := 0;  --vertical counter (counts the rows)
begin
 -- Horizontal 640 
 -- Vertical 480
 if rising_edge(newClk) then
 -- Increase Horizontal counter
    if (h_count < x_counter - 1 ) then 
        h_count := h_count + 1;
    else 
        h_count := 0 ;    
        -- Increase Vertical counter   
        if (v_count < y_counter - 1 ) then 
            v_count := v_count + 1;
        else 
            v_count := 0 ;
        end if; 
    end if; 

     --horizontal sync signal
     IF(h_count < HR + HFP OR h_count > HR + HFP + HRet) THEN
        vga_hs <= NOT h_pol;    --deassert horiztonal sync pulse
        LED0 <= NOT h_pol; 
     ELSE
        vga_hs <= h_pol;        --assert horiztonal sync pulse
        LED0 <= h_pol;
     END IF;

     --vertical sync signal
     IF(v_count < VR + VFP OR v_count > VR + VFP + VRet) THEN
        vga_vs <= NOT v_pol;    --deassert vertical sync pulse
     ELSE
        vga_vs <= v_pol;        --assert vertical sync pulse
     END IF;       
 end if;
 end process;

 vga_r <= "11111";
 vga_g <= "000000";
 vga_b <= "00000";



end Behavioral;
    
pregunta Carlton Banks

2 respuestas

3

Usted asigna valores constantes a sus líneas de color VGA, que no funcionarán.

Un monitor VGA analógico espera ver un nivel de "negro" de referencia durante parte de la duración de la traza fuera de la pantalla. Si maneja un valor substancialmente distinto de cero allí, se adaptará a la idea de que este voltaje significa negro, y no obtendrá el rectángulo de color esperado (en algunos monitores, puede obtener un breve destello de color en la conexión, antes de yendo a todo negro).

Deberá alternar las líneas de color entre el color deseado y el negro durante los periodos de tiempo en que deberían estar señalando el color en el área activa o la referencia de negro fuera de él.

Dos herramientas muy útiles serán un diagrama de tiempo de cómo debería ser VGA y, si es posible, un osciloscopio que compara su señal con la de una configuración de tarjeta VGA para generar algo similar (¿protector de pantalla a todo color?)

    
respondido por el Chris Stratton
1

Como ya mencionó Chris Stratton et.al., debe establecer el color en negro durante los intervalos de supresión. Esto se logró mediante la señal disp_ena en el diseño de ejemplo vinculado en su pregunta.

Para agregar dicho comportamiento a su diseño, debe:

1) Agregue una nueva señal disp_ena en la parte de declaración de arquitectura:

signal disp_ena : std_logic;

2) Establezca esta señal sincronizada con el reloj en '1' cuando se muestra la imagen, y en '0' en caso contrario (durante el borrado).

screen:process(newClk)
-- ... existing code
begin
  if rising_edge(newClk) then
     -- ... existing code

     --set display-enable control signal
     IF(h_count < HR and v_count < VR) THEN
        disp_ena <= '1';
     ELSE
        disp_ena <= '0';
     end IF;
  end if;
end process;

3) Establezca el color en rojo solo cuando la pantalla esté habilitada ( disp_ena = '1' ); de lo contrario, será negro. Por lo tanto, cambie las líneas existentes a:

vga_r <= "11111" when disp_ena = '1' else (others => '0');
vga_g <= "000000" when disp_ena = '1' else (others => '0');
vga_b <= "00000" when disp_ena = '1' else (others => '0');

Está generando una nueva señal de reloj usando un contador. Esto no es una buena práctica de diseño. Debe utilizar uno de los PLL en el FPGA en su lugar. Puede crear una instanciación adecuada a través del Xilinx IP Core Generator.

Si desea mantener el contador, tiene dos opciones:

1) Use un componente BUFG para minimizar el sesgo en la red de reloj newclk . Para usar este componente, debe incluir:

library unisim;
use unisim.vcomponents.all;

Luego crea una instancia del BUFG a través de:

newclk_bufg: BUFG (I => newclk, O => newclk2);

Luego use newclk2 para controlar los registros.

2) Utilice newclk como una señal de habilitación de reloj en lugar de una señal de reloj. El proceso screen luego se activará en CLK , pero la carga de los nuevos valores de registro solo ocurrirá si newclk es alto:

screen:process(CLK)
-- ... existing code
begin
  if rising_edge(CLK) then
     if newclk = '1' then   -- newclk used as clock-enable here
        -- ... existing code
     end if;
  end if;
end process;

También verifique si ha especificado las restricciones de tiempo correctas para el reloj CLK en el archivo UCF (ISE) o el archivo XDC (Vivado).

    
respondido por el Martin Zabel

Lea otras preguntas en las etiquetas