Я пытаюсь изучить VHDL-программирование с помощью некоторых книг и комплекта разработчика Altera DE1 от Terasic.VGA-контроллер с VHDL
Проблема в том, что я пытаюсь запрограммировать VGA-контроллер для работы с разрешением 640x480 (хотя мой экран - TFT-дисплей с разрешением 1280x1024).
У меня возникли проблемы с кодом.
Я использую FSM для создания вертикальных и горизонтальных сигналов, еще один блок для управления входами RGB, а также часы 27 МГц от DE1.
Я думаю, что с кодом должно быть что-то неправильно, потому что изображение, которое я печатаю на экране, не соответствует размеру (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;
ВГД дисплей файл
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;
Вы уверены, что это не ваш монитор, масштабирующий вход 640x480 до 1280x960 (т. Е. 2x2 пикселя), чтобы заполнить панель? – NPE
Одной из больших проблем с 2-процессорным автоматом является сложность получения списка чувствительности. Я не смотрел ваш код подробно (я не делаю 2-процессорных SM), но выглядит неправильно в 'list_state_ *' в списке чувствительности, а затем проверять 'present_state_ *' в выражении case. Могут быть и другие проблемы с списком чувствительности. –
В двух процессах, представляющих список чувствительности Брайана, относятся 'upper_part_1' и' upper_part_2'. Я не верю, что это проблема синтеза, списки чувствительности, как правило, игнорируются. Вы должны исправить их все равно. – user1155120