Ich versuche VHDL-Programmierung mit einigen Büchern und einem Altera DE1-Entwicklungskit von Terasic zu lernen.VGA-Controller mit VHDL
Das Problem hier ist, dass ich versuche, einen VGA-Controller für die Arbeit mit einer Auflösung von 640x480 zu programmieren (obwohl mein Bildschirm ein TFT-LCD mit 1280x1024 ist).
Ich habe einige Probleme mit dem Code.
Ich verwende ein FSM, um die vertikalen und horizontalen Signale, ein weiterer Block, um die RGB-Eingänge und auch eine 27 MHz-Takt von der DE1 zu fahren.
Ich denke, dass etwas mit dem Code falsch sein muss, weil das Bild, das ich auf dem Bildschirm drucke, nicht die richtige Größe (640x480) sondern größer (ca. 1174x980) hat.
Jetzt versuche ich eine einzige Farbe in den Bildschirm zu setzen, um es zu vereinfachen, bis ich den Fehler entdecken kann.
Mein Projekt hat 3 Dateien, 1 für den Block RGB, 1 für die FSM und einen anderen, um beide zu instanziieren.
Ich würde eine Art von Hilfe schätzen, um dieses Problem zu lösen, weil ich versucht habe, es herauszufinden, aber ich kann nicht sehen, wo die Fehler sind.
Vielen Dank!
Omar
VGA-Controller-Datei
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-Sync-Datei
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 Anzeigedatei
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;
Sind Sie sicher, dass Ihr Monitor den 640x480-Eingang nicht auf 1280x960 skaliert (d. H. 2x2 Pixel), um das Panel zu füllen? – NPE
Eines der großen Probleme mit der 2-Prozess-Zustandsmaschine ist die Schwierigkeit, die Empfindlichkeitsliste korrekt zu machen. Ich habe Ihren Code nicht im Detail betrachtet (ich mache keine SMs mit zwei Prozessen), aber es sieht falsch aus, 'next_state_ *' in die Sensitivitätsliste zu setzen und dann 'present_state_ *' in der case-Anweisung zu testen. Es kann auch andere Empfindlichkeitslistenprobleme geben. –
Die zwei Prozesse, die Brians Empfindlichkeitsliste betreffen, sind "oberes_Teil_1" und "oberes_Teil_2". Ich glaube nicht, dass sie ein Syntheseproblem sind, Sensitivitätslisten werden eher ignoriert. Sie sollten sie alle gleich beheben. – user1155120