VHDL VGA控制器

VHDL VGA控制器,vhdl,fpga,vga,Vhdl,Fpga,Vga,我试图通过一些书籍和Terasic的Altera DE1开发工具包来学习VHDL编程 这里的问题是,我正在尝试为分辨率为640x480的工作编程VGA控制器(尽管我的屏幕是1280x1024的TFT LCD) 我对代码有一些问题 我用一个FSM产生垂直和水平信号,另一个模块驱动RGB输入,还有一个来自DE1的27 MHz时钟 我认为代码一定有问题,因为我在屏幕上打印的图像大小不正确(640x480),但更大(约1174x980) 到目前为止,我正试图在屏幕上只使用一种颜色来简化它,直到我发现错误

我试图通过一些书籍和Terasic的Altera DE1开发工具包来学习VHDL编程

这里的问题是,我正在尝试为分辨率为640x480的工作编程VGA控制器(尽管我的屏幕是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;
ieee库;
使用ieee.std_logic_1164.all;
实体FSM_同步是
端口(时钟,复位:在标准逻辑中;
Hsync、Vsync、VIDON:输出标准逻辑;
Vcount,Hcount:out整数范围0到799);
终端实体;
FSM_sync的体系结构是
--康斯坦茨·帕拉迪尼·洛斯·德雷洛伊·卡达·塞纳尔·德尔赫辛克(cada señal del HSYNC)酒店
常量计数器最大值:整数:=640;
常数计数器P:整数:=96;
常数计数器bp:整数:=48;
常数计数器HV:整数:=640;
常数p:整数:=16;
--康斯坦茨·帕拉迪尼·洛斯·德雷洛伊·德卡德·斯尼亚尔·德尔瓦辛克(cada señal del VSYNC)的定义
常量计数器max_V:整数:=384000;--计算水平方向上的像素数(800)
常量计数器P_V:整数:=1600;--在垂直方向上,我们需要对尸体进行重新测量
常数计数器bp_V:整数:=26400;
常数计数器Vv:整数:=384000;
常数p_V:整数:=8000;
--水平方向和垂直方向的像素最大值和控制值
常量像素最大值:整数:=800;
常量像素最大值:整数:=525;
类型状态为(SP_1、BP、HV、FP、reseteo)--4.新克罗尼齐翁地区(垂直和水平)
信号当前状态、下一状态、当前状态、下一状态:状态;
信号计时器:从0到计数器最大值的整数范围;--这是一个价值观的抗衡,也是一个比较利益观和资产观的程序
--卡达埃斯塔多杜拉西翁酒店
信号定时器2:从0到计数器最大值V的整数范围--这是一个垂直方向的前方
信号video_1、video_2:std_逻辑;
信号hcount_reg,vcount_reg:整数范围0至799;
开始
--==============================================
--FSM帕拉西克罗尼齐奥德尔巴里多水平酒店
--===============================================
下部零件1:过程(时钟、复位)
变量计数器:从0到计数器最大值-1的整数范围--可调节的空调系统
变量计数器2:整数范围0到数字\u像素最大值\u H-1--contador para los pixeles horizontales
变量计数器3:整数范围0到数字\u像素最大值\u V-1--contador para los垂直像素
开始——在水平方向上,卡根控制800个像素
如果(reset='1'),则--esto隐式地包含10位数字。
--你可以在我的房间里找到我的号码
计数器:=0--垂直独奏德贝莫斯康塔酒店521
计数器2:=0;
计数器3:=0;

当前状态我认为您的显示器正在与输出同步,并且只显示视频全屏,就像您的电视可能带有辅助输入一样

我计算了你的H和V速率,根据你报告的27兆赫(~37纳秒),看看能不能找到一个1280 x 1024的液晶显示器来接受它们

您的水平计数器是计数器2,从0计数到
number\u pixelsMAX\u H-1
(799),垂直计数器是计数器3,从0计数到
number\u pixelsMAX\u V-1
(524)

这样,水平速率为800 x 37 ns=29.600 us,垂直速率为15.54 ms.33.8 KHz H,V 64 Hz

在不知道您正在使用的特定监视器的情况下,我四处寻找了一个监视器的任何规范,发现了一个定义同步速率范围的AMOLED显示规范

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

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

所有版本的主板似乎都使用相同的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接口传送的预设,在这种情况下限制为10
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;