Adds VGA controller and testbench enhancements

Introduces a new VGA module for pixel rendering and sync signal generation. Implements an XY position generator for coordinate management. Updates testbench with color cycling logic and additional color constants. Adjusts timing generator logic for improved sync signal handling and accuracy. Modifies UCF constraints for compatibility with LVTTL standard.

Improves modularity and flexibility of the VGA system.
This commit is contained in:
2025-04-25 15:59:37 +00:00
parent 167901eaa6
commit 50f36afcf4
6 changed files with 380 additions and 55 deletions

92
src/XY_Generator.vhd Normal file
View File

@@ -0,0 +1,92 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity XY_Generator is
generic (
G_X : integer := 640;
G_Y : integer := 480;
--@ Width of the X position (Row) register
G_X_Width : integer := 10;
--@ Width of the Y position (Line) register
G_Y_Width : integer := 10
);
port (
--@ Clock; (**Rising edge** triggered)
I_CLK : in std_logic;
--@ Clock Enable; (**Synchronous**, **Active high**)
I_CE : in std_logic;
--@ Reset; (**Synchronous**, **Active high**)
I_RST : in std_logic;
--@ @virtualbus Y @dir Out Output of the Y positions, with priority over X
O_Y_Valid : out std_logic;
I_Y_Ready : in std_logic;
O_Y : out std_logic_vector(G_Y_Width - 1 downto 0);
--@ @end
--@ @virtualbus Y @dir Out Output of the X positions
O_X_Valid : out std_logic;
I_X_Ready : in std_logic;
O_X : out std_logic_vector(G_X_Width - 1 downto 0)
--@ @end
);
end entity XY_Generator;
architecture RTL of XY_Generator is
signal R_X_Counter : unsigned(G_X_Width - 1 downto 0) := (others => '0');
signal R_Y_Counter : unsigned(G_Y_Width - 1 downto 0) := (others => '0');
signal R_Y_Valid : std_logic := '1';
signal R_X_Valid : std_logic := '1';
signal C_X_Valid : std_logic := '0';
begin
C_X_Valid <= R_X_Valid and not R_Y_Valid;
process (I_CLK)
begin
if rising_edge(I_CLK) then
if I_RST = '1' then
R_X_Counter <= (others => '0');
R_Y_Counter <= (others => '0');
R_Y_Valid <= '1';
R_X_Valid <= '1';
elsif I_CE = '1' then
if R_Y_Valid = '1' then
if I_Y_Ready = '1' then
R_Y_Valid <= '0';
end if;
elsif R_X_Valid = '1' then
if I_X_Ready = '1' then
R_X_Valid <= '0';
end if;
else
if R_X_Counter = (G_X - 1) then
R_X_Counter <= (others => '0');
R_X_Valid <= '1';
if R_Y_Counter = (G_Y - 1) then
R_Y_Counter <= (others => '0');
R_Y_Valid <= '1';
else
R_Y_Counter <= R_Y_Counter + 1;
R_Y_Valid <= '1';
end if;
else
R_X_Counter <= R_X_Counter + 1;
R_X_Valid <= '1';
end if;
end if;
end if;
end if;
end process;
O_X <= std_logic_vector(R_X_Counter);
O_Y <= std_logic_vector(R_Y_Counter);
O_Y_Valid <= R_Y_Valid;
O_X_Valid <= C_X_Valid;
end architecture;