7

我正在尝试通过一些书籍和 Terasic 的 Altera DE1 开发套件来学习 VHDL 编程。

这里的问题是我正在尝试对 VGA 控制器进行编程,使其能够以 640x480 的分辨率工作(尽管我的屏幕是 1280x1024 的 TFT LCD)。

我的代码有一些问题。

我正在使用 FSM 来制作垂直和水平信号,另一个块来驱动 RGB 输入以及来自 DE1 的 27 MHz 时钟。

我认为代码一定有问题,因为我在屏幕上打印的图像尺寸不正确(640x480)而是更大(大约1174x980)。

到现在为止,我正试图在屏幕上只放一种颜色来简化它,直到我发现错误为止。

我的项目有 3 个文件,1 个用于块 RGB,1 个用于 FSM,另一个用于实例化它们。

我将不胜感激解决此问题的某种帮助,因为我已经努力解决了这个问题,但我看不出错误在哪里。

非常感谢!

奥马尔

VGA 控制器文件

library ieee;
use ieee.std_logic_1164.all;

entity VGA_controller is
     port(clk, reset : in std_logic;
        Hsync,Vsync : out std_logic;
        R,G,B : out std_logic_vector(3 downto 0));
end entity;

architecture arch of VGA_controller is

component FSM_sync is
    port(clk,reset : in std_logic;
        Hsync,Vsync,VIDON : out std_logic;
        Vcount,Hcount : out integer range 0 to 799);
end component;

component VGA_display is
    port(hcount,vcount : in integer range 0 to 799;
        r,g,b : out std_logic_vector(3 downto 0);
        video_on : in std_logic);
end component;

signal video : std_logic;
signal signal1 : integer range 0 to 799;
signal signal2 : integer range 0 to 799;

begin

maquinaestado_sync : FSM_sync port map (clk=>clk, reset=>reset, Hsync=>Hsync, Vsync=>Vsync, Vcount=>signal1, Hcount=>signal2, VIDON=>video);

salida_pantalla : VGA_display port map (r=>R, g=>G, b=>B, video_on=>video, vcount=>signal1, hcount=>signal2 );

end arch;

FSM 同步文件

library ieee;
use ieee.std_logic_1164.all;


entity FSM_sync is
    port(clk,reset : in std_logic;
        Hsync,Vsync,VIDON : out std_logic;
        Vcount,Hcount : out integer range 0 to 799);
end entity;


architecture arch of FSM_sync is
--constantes para definir los ciclos de reloj de cada señal del HSYNC
constant counterMAX : integer := 640;
constant counterSP : integer := 96;
constant counterBP : integer := 48;
constant counterHV : integer := 640;
constant counterFP : integer := 16;
--constantes para definir los ciclos de reloj de cada señal del VSYNC
constant counterMAX_V : integer := 384000;  -- calculamos estos valores multiplicando el numero de filas por los pixeles en cada fila horizontal (800)
constant counterSP_V : integer := 1600;     -- de manera que cada estado de la sincronizacion vertical dure todo el recorrido de los pixeles de cada fila
constant counterBP_V : integer := 26400;
constant counterVV : integer := 384000;
constant counterFP_V : integer := 8000;
--constantes para el numero de pixeles maximo que debemos controlar en horizontal y en vertical
constant number_pixelsMAX_H : integer := 800;
constant number_pixelsMAX_V : integer := 525;

type state is (SP_1,BP,HV,FP,reseteo);  --4 estados para cada maquina de estado de sincronizacion (vertical y horizontal)
signal present_state_H,next_state_H,present_state_V,next_state_V : state;

signal timer : integer range 0 to counterMAX ; -- señal para pasar el valor counterXX al proceso secuencial para compararlo con un contador y establecer el
                                                -- tiempo de duracion de cada estado
signal timer2 : integer range 0  to counterMAX_V ;  --lo mismo que la señal anterior pero para el sincronizacion vertical

signal video_1,video_2 : std_logic; 

signal hcount_reg,vcount_reg : integer range 0 to 799;

begin

--==============================================
--FSM para la sincronizacion del barrido HORIZONTAL
--===============================================

lower_part_1 : process (clk,reset)
                variable counter : integer range 0 to counterMAX - 1;   --variable para crear un contador de pulsos del clk
                variable counter2 : integer range 0 to number_pixelsMAX_H - 1;          --contador para los pixeles horizontales    
                variable counter3 : integer range 0 to number_pixelsMAX_V - 1;          --contador para los pixeles verticales
             begin                                                  --se cargan con 800 por que 800 son los pixeles que hay que leer en horizontal 
                if (reset = '1') then                               --esto implica contadores de al menos 10 bits para llegar a ese numero.
                                                                    --y para que los dos contadores sean del mismo numero de bits se cargan los dos igual   
                    counter := 0;                                   --realmente en vertical solo debemos contar hasta 521
                    counter2 := 0;          
                    counter3 := 0;
                    present_state_H <= reseteo;


                elsif (clk'event and clk = '1') then
                    counter := counter + 1;

                    if (counter2 < number_pixelsMAX_H-1) then
                        counter2 := counter2 + 1;
                    else
                        counter2 := 0;
                        if (counter3 < number_pixelsMAX_V-1) then
                            counter3 := counter3 + 1;
                        else
                            counter3 := 0;
                        end if;
                    end if;

                    hcount_reg <= counter2;
                    vcount_reg <= counter3;

                    if (counter = timer) then
                        present_state_H <= next_state_H;
                        counter := 0;
                    end if;
                end if;
                end process lower_part_1;


upper_part_1 : process (next_state_H)
             begin

                Hsync <= '1';
                next_state_H <= HV;

                case present_state_H is
                    when SP_1 =>
                        Hsync <= '0';
                        next_state_H <= BP;
                        timer <= counterSP;

                        video_1 <= '0';

                    when BP =>
                        Hsync <= '1';
                        next_state_H <= HV;
                        timer <= counterBP;

                        video_1 <= '0';

                    when HV =>
                        Hsync <= '1';
                        next_state_H <= FP;
                        timer <= counterHV;

                        video_1 <= '1';


                    when FP =>
                        Hsync <= '1';
                        next_state_H <= SP_1;
                        timer <= counterFP;

                        video_1 <= '0';

                    when reseteo =>
                        Hsync <= '1';
                        next_state_H <=HV;



                    end case;
                end process upper_part_1;

--==============================================
--FSM para la sincronizacion del barrido VERTICAL
--===============================================               


lower_part_2 : process (clk,reset)
                variable counter2 : integer range 0 to counterMAX_V;    --variable para crear un contador de pulsos del clk
             begin
                if (reset = '1') then
                    counter2 := 0;
                    present_state_V <= reseteo;



                elsif (clk'event and clk = '1') then
                    counter2 := counter2 + 1;



                    if (counter2 = timer2) then
                        present_state_V <= next_state_V;
                        counter2 := 0;
                    end if;
                end if;
                end process lower_part_2;


upper_part_2 : process (next_state_V)
             begin

                Vsync <= '1';
                next_state_V <= HV;

                case present_state_V is
                    when SP_1 =>
                        Vsync <= '0';
                        next_state_V <= BP;
                        timer2 <= counterSP_V;
                        video_2 <= '0';
                    when BP =>
                        Vsync <= '1';
                        next_state_V <= HV;
                        timer2 <= counterBP_V;

                        video_2 <= '0';

                    when HV =>
                        Vsync <= '1';
                        next_state_V <= FP;
                        timer2 <= counterVV;

                        video_2 <= '1';

                    when FP =>
                        Vsync <= '1';
                        next_state_V <= SP_1;
                        timer2 <= counterFP_V;

                        video_2 <= '0';

                    when reseteo =>
                        Vsync <= '1';
                        next_state_V <=HV;


                    end case;
                end process upper_part_2;


VIDON <= video_1 AND video_2;
Vcount <= vcount_reg;
Hcount <= hcount_reg;

        end arch;

VGD 显示文件

library ieee;
use ieee.std_logic_1164.all;


entity VGA_display is
    port(hcount,vcount : in integer range 0 to 799;
        r,g,b : out std_logic_vector(3 downto 0);
        video_on : in std_logic);
end entity;



architecture arch of VGA_display is

begin

process (video_on)
begin
    if video_on = '1' then  --solo activamos los pixeles cuando vidon esté a uno, es decir, esten en la fase HV y VV las sincronizaciones
            r <= "1111";
            g <= "0000"; 
            b <= "0000";

    else
        r <= (others => '0');
        g <= (others => '0');
        b <= (others => '0');
    end if;

end process;
end arch;
4

2 回答 2

2

我认为您的显示器正在与您的输出同步,并且只是全屏显示视频,就像您的电视使用辅助输入一样。

我根据您报告的 27 MHz(~ 37 ns)计算出您的 H 和 V 速率,看看我是否能找到可以接受它们的 1280 x 1024 LCD 显示器。

您的水平计数器是从 0 计数到 (799) 的 counter2 ,而您的垂直计数器是从 0 计数到(524)number_pixelsMAX_H - 1的 counter3 。number_pixelsMAX_V - 1

这为您提供了 800 x 37 ns = 29.600 us 的水平速率和 15.54 ms 的垂直速率。33.8 KHz 水平,垂直 64 赫兹。

在不知道您使用的特定显示器的情况下,我四处寻找任何规格,并找到了定义同步速率范围的SXGA AMOLED 显示器规格。

在第 14 页有一个表格显示 H 和 V 范围:

表 6-4 交流特性

它表明这个特定的 LCD 面板可以显示您的帧速率。如何从同步信号中恢复它的像素时钟取决于使用此特定显示器的监视器构建。

所有版本的DE1板似乎都使用相同的 ADV7123 将您的 SVGA 信号转换为通过 15 针 VGA 连接器传输的模拟信号。

我认为您的 SXGA 速率监视器很可能能够显示 SVGA。

看起来 Acer 17 英寸 V173L 将与之同步,例如具有 3 种 VGA 模式(60 Hz、72 Hz 和 75 Hz)和 640 x 480(66 Hz)的 Mac 模式。

如今,同步到多个扫描速率的能力在监视器中非常普遍。

我六岁的戴尔 2208WP 告诉我我正在输入 60 Hz 的 1680x1050 的 DVI-D 信号。我可以告诉我的 Mac 切换分辨率并忠实地遵循 DVI 接口传达的预设,在这种情况下限制为 1024x640(它调整了我所有打开的窗口的大小,使它们变平)。

根据您的显示器,您应该使用模拟输入(DE1 提供)在更广泛的范围内进行多同步。

使其适用于模拟视频输入的机制是 LCD 面板的像素时钟与水平线的未消隐部分相关,在该间隔内提供与面板分辨率匹配的多个像素时钟,重新转换模拟视频以填充所有(或几乎所有)屏幕像素的速率转换为数字视频。

于 2014-10-15T22:32:12.210 回答
1

有关 VGA 控制器的 VGA 理论和 VHDL 代码的完整详细信息,请参阅 VA Pedroni 撰写的“Circuit Design and Simulation with VHDL”,第 2 版(仅在第 2 版中)第 15 章。

于 2014-10-16T17:22:17.030 回答