我正在尝试使用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;
答案 0 :(得分:2)
我认为您的显示器正在与您的输出同步,只是全屏显示视频,就像您的电视可能带有辅助输入一样。
我根据您报告的27 MHz(~37 ns)计算了您的H和V速率,看看我是否能找到一台能接受它们的1280 x 1024 LCD显示器。
你的水平计数器是counter2,从0到number_pixelsMAX_H - 1
(799),你的垂直计数器是counter3,从0到number_pixelsMAX_V - 1
(524)计数。
这使您的水平速率为800 x 37 ns = 29.600 us,垂直速率为15.54 ms。 33.8 KHz H,V 64 Hz。
在不知道您正在使用的特定显示器的情况下,我四处寻找任何规格,并找到定义同步速率范围的SXGA AMOLED显示规格。
在第14页上,有一个显示H和V范围的表格:
它表明此特定的LCD面板可以显示您的帧速率。如何从同步信号恢复像素时钟取决于使用此特定显示器的监视器构建。
所有版本的DE1电路板似乎都使用相同的ADV7123将SVGA信号转换为通过15针VGA连接器传输的模拟信号。
我认为您的SXGA速率监视器很可能能够显示SVGA。
看起来Acer 17英寸V173L将同步到它,例如有3种VGA模式(60 Hz,72 Hz和75 Hz)和Mac模式640 x 480(66 Hz)。
如今,监视器中同步到多种扫描速率的能力非常普遍。
我六岁的戴尔2208WP告诉我,我在60赫兹时输入了1680x1050的DVI-D信号。我可以告诉我的Mac切换分辨率并忠实地跟随,遵守DVI接口传达的预设,在这种情况下限制为1024x640(调整所有打开的窗口大小,展平它们)。
根据您的显示器,您应该通过模拟输入(DE1提供)在更广泛的范围内进行多同步。
使其适用于模拟视频输入的机制是LCD面板的像素时钟与水平线的非消隐部分相关,在该间隔期间提供与面板分辨率匹配的多个像素时钟,将模拟视频重新转换为数字,其速率可以填满所有(或几乎所有)屏幕像素。
答案 1 :(得分:0)
有关VGA控制器的VGA理论和VHDL代码的详细信息,请参阅VH Pedroni在2010年第3版“VHDL&#34;电路设计与仿真”(第2版)(第2版)中的第15章。< / p>