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:
@@ -28,9 +28,16 @@ CONSTRAINTS = src/VGATimingGenerator_test.ucf
|
|||||||
# @example `VSOURCE += src/main.v` (add a single Verilog file per line)
|
# @example `VSOURCE += src/main.v` (add a single Verilog file per line)
|
||||||
# @example `VHDSOURCE += src/main.vhd` (add a single VHDL file per line)
|
# @example `VHDSOURCE += src/main.vhd` (add a single VHDL file per line)
|
||||||
|
|
||||||
VHDSOURCE += src/VGATimingGenerator_pb.vhd
|
# VHDSOURCE += src/VGATimingGenerator_pb.vhd
|
||||||
VHDSOURCE += src/VGATimingGenerator_test.vhd
|
VHDSOURCE += src/VGATimingGenerator_test.vhd
|
||||||
VHDSOURCE += src/VGATimingGenerator.vhd
|
VHDSOURCE += src/VGATimingGenerator.vhd
|
||||||
|
VHDSOURCE += src/XY_Generator.vhd
|
||||||
|
VHDSOURCE += src/VGA.vhd
|
||||||
|
VHDSOURCE += ../Asynchronous-FIFO-AXI-Handshake/libs/GrayCounter.vhd
|
||||||
|
VHDSOURCE += ../Asynchronous-FIFO-AXI-Handshake/src/AsyncFIFO.vhd
|
||||||
|
VHDSOURCE += ../Asynchronous-FIFO-AXI-Handshake/libs/Pipeline-AXI-Handshake/src/PipelineRegister.vhd
|
||||||
|
VHDSOURCE += ../Asynchronous-FIFO-AXI-Handshake/libs/Pipeline-AXI-Handshake/src/PipelineStage.vhd
|
||||||
|
VHDSOURCE += ../Asynchronous-FIFO-AXI-Handshake/libs/Pipeline-AXI-Handshake/src/PipelineController.vhd
|
||||||
|
|
||||||
## Test files settings.. ##
|
## Test files settings.. ##
|
||||||
# The testbench files to be compiled
|
# The testbench files to be compiled
|
||||||
|
173
src/VGA.vhd
Normal file
173
src/VGA.vhd
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
use ieee.math_real.all;
|
||||||
|
|
||||||
|
entity VGA is
|
||||||
|
port (
|
||||||
|
--@ Pixel Clock; (**Rising edge** triggered)
|
||||||
|
I_VGA_PixelCLK : in std_logic;
|
||||||
|
--@ Pixel Clock Enable; (**Synchronous**, **Active high**)
|
||||||
|
I_VGA_PixelCE : in std_logic;
|
||||||
|
--@ Pixel Reset; (**Synchronous**, **Active high**)
|
||||||
|
I_VGA_PixelRST : in std_logic;
|
||||||
|
|
||||||
|
--@ Clock; (**Rising edge** triggered)
|
||||||
|
I_VGA_CLK : in std_logic;
|
||||||
|
--@ Clock Enable; (**Synchronous**, **Active high**)
|
||||||
|
I_VGA_CE : in std_logic;
|
||||||
|
--@ Reset; (**Synchronous**, **Active high**)
|
||||||
|
I_VGA_RST : in std_logic;
|
||||||
|
|
||||||
|
--@ @virtualbus VGA-Signals @dir out VGA signals
|
||||||
|
--@ Horizontal Sync signal; **Active low**
|
||||||
|
O_VGA_HSync : out std_logic;
|
||||||
|
--@ Vertical Sync signal; **Active low**
|
||||||
|
O_VGA_VSync : out std_logic;
|
||||||
|
--@ VGA Red Channel
|
||||||
|
O_VGA_Red : out std_logic_vector(2 downto 0);
|
||||||
|
--@ VGA Green Channel
|
||||||
|
O_VGA_Green : out std_logic_vector(2 downto 0);
|
||||||
|
--@ VGA Blue Channel
|
||||||
|
O_VGA_Blue : out std_logic_vector(1 downto 0);
|
||||||
|
--@ @end
|
||||||
|
|
||||||
|
--@ @virtualbus XY-Request @dir Out Request for the X and Y positions
|
||||||
|
O_VGA_Req_Y_Valid : out std_logic;
|
||||||
|
I_VGA_Req_Y_Ready : in std_logic;
|
||||||
|
O_VGA_Req_Y : out std_logic_vector(9 downto 0);
|
||||||
|
O_VGA_Req_X_Valid : out std_logic;
|
||||||
|
I_VGA_Req_X_Ready : in std_logic;
|
||||||
|
O_VGA_Req_X : out std_logic_vector(9 downto 0);
|
||||||
|
--@ @end
|
||||||
|
|
||||||
|
--@ @virtualbus Pixel-Data @dir In Calculated pixel data
|
||||||
|
I_VGA_PixelData_Valid : in std_logic;
|
||||||
|
O_VGA_PixelData_Ready : out std_logic;
|
||||||
|
I_VGA_PixelData : in std_logic_vector(7 downto 0);
|
||||||
|
--@ @end
|
||||||
|
|
||||||
|
--@ @virtualbus Error-Register @dir Out Error register; (Synchronous to I_VGA_CLK)
|
||||||
|
I_VGA_Error_RST : in std_logic := '0';
|
||||||
|
O_VGA_Error : out std_logic_vector(7 downto 0) := (others => '0')
|
||||||
|
--@ @end
|
||||||
|
|
||||||
|
);
|
||||||
|
end entity VGA;
|
||||||
|
|
||||||
|
architecture RTL of VGA is
|
||||||
|
signal O_TimingGenerator_PixelReady : std_logic;
|
||||||
|
signal O_TimingGenerator_HSync : std_logic;
|
||||||
|
signal O_TimingGenerator_VSync : std_logic;
|
||||||
|
signal O_AsyncPixelDataFIFO_Valid : std_logic;
|
||||||
|
signal O_AsyncPixelDataFIFO_Data : std_logic_vector(7 downto 0);
|
||||||
|
signal C_DisablePixelOutput : std_logic := '0';
|
||||||
|
|
||||||
|
-- Error signals --
|
||||||
|
signal R_Error : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
--@ Is set if the pixel data is requested but not available in the FIFO
|
||||||
|
signal C_Error_PixelUnderrun : std_logic := '0';
|
||||||
|
begin
|
||||||
|
INST_TimingGenerator : entity work.VGATimingGenerator
|
||||||
|
port map(
|
||||||
|
I_CLK => I_VGA_PixelCLK,
|
||||||
|
I_CE => I_VGA_PixelCE,
|
||||||
|
I_RST => I_VGA_PixelRST,
|
||||||
|
O_PixelReady => O_TimingGenerator_PixelReady,
|
||||||
|
O_HSync => O_TimingGenerator_HSync,
|
||||||
|
O_VSync => O_TimingGenerator_VSync
|
||||||
|
);
|
||||||
|
|
||||||
|
O_VGA_HSync <= O_TimingGenerator_HSync;
|
||||||
|
O_VGA_VSync <= O_TimingGenerator_VSync;
|
||||||
|
|
||||||
|
C_DisablePixelOutput <= not O_TimingGenerator_HSync and
|
||||||
|
not O_TimingGenerator_VSync;
|
||||||
|
|
||||||
|
INST_XY_Generator : entity work.XY_Generator
|
||||||
|
generic map(
|
||||||
|
G_X => 640,
|
||||||
|
G_Y => 480,
|
||||||
|
G_X_Width => 10,
|
||||||
|
G_Y_Width => 10
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
I_CLK => I_VGA_CLK,
|
||||||
|
I_CE => I_VGA_CE,
|
||||||
|
I_RST => I_VGA_RST,
|
||||||
|
O_Y_Valid => O_VGA_Req_Y_Valid,
|
||||||
|
I_Y_Ready => I_VGA_Req_Y_Ready,
|
||||||
|
O_Y => O_VGA_Req_Y,
|
||||||
|
|
||||||
|
O_X_Valid => O_VGA_Req_X_Valid,
|
||||||
|
I_X_Ready => I_VGA_Req_X_Ready,
|
||||||
|
O_X => O_VGA_Req_X
|
||||||
|
);
|
||||||
|
|
||||||
|
INST_AsyncPixelDataFIFO : entity work.AsyncFIFO
|
||||||
|
generic map(
|
||||||
|
G_Width => 8,
|
||||||
|
G_Depth => 16,
|
||||||
|
G_RamTypeFifo => "Distributed"
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
I_Write_CLK => I_VGA_CLK,
|
||||||
|
I_Write_CE => I_VGA_CE,
|
||||||
|
I_Write_Data => I_VGA_PixelData,
|
||||||
|
I_Write_Valid => I_VGA_PixelData_Valid,
|
||||||
|
O_Write_Ready => O_VGA_PixelData_Ready,
|
||||||
|
I_Read_CLK => I_VGA_PixelCLK,
|
||||||
|
I_Read_CE => I_VGA_PixelCE,
|
||||||
|
O_Read_Data => O_AsyncPixelDataFIFO_Data,
|
||||||
|
I_Read_Ready => O_TimingGenerator_PixelReady,
|
||||||
|
O_Read_Valid => O_AsyncPixelDataFIFO_Valid
|
||||||
|
);
|
||||||
|
|
||||||
|
P_O_Pixel_Register : process (I_VGA_PixelCLK)
|
||||||
|
begin
|
||||||
|
if rising_edge(I_VGA_PixelCLK) then
|
||||||
|
if I_VGA_PixelRST = '1' then
|
||||||
|
O_VGA_Red <= (others => '0');
|
||||||
|
O_VGA_Green <= (others => '0');
|
||||||
|
O_VGA_Blue <= (others => '0');
|
||||||
|
C_Error_PixelUnderrun <= '0';
|
||||||
|
elsif I_VGA_PixelCE = '1' then
|
||||||
|
-- Reset Error flags --
|
||||||
|
C_Error_PixelUnderrun <= '0';
|
||||||
|
-- -- -- -- -- -- -- --
|
||||||
|
|
||||||
|
if (O_TimingGenerator_PixelReady and O_AsyncPixelDataFIFO_Valid) = '1' then
|
||||||
|
O_VGA_Red <= O_AsyncPixelDataFIFO_Data(7 downto 5);
|
||||||
|
O_VGA_Green <= O_AsyncPixelDataFIFO_Data(4 downto 2);
|
||||||
|
O_VGA_Blue <= O_AsyncPixelDataFIFO_Data(1 downto 0);
|
||||||
|
elsif O_TimingGenerator_PixelReady = '1' then
|
||||||
|
--@ Pixel data is requested but not available in the FIFO
|
||||||
|
--@ Set error flag
|
||||||
|
C_Error_PixelUnderrun <= '1';
|
||||||
|
elsif C_DisablePixelOutput = '1' then
|
||||||
|
--@ Disable pixel output
|
||||||
|
O_VGA_Red <= (others => '0');
|
||||||
|
O_VGA_Green <= (others => '0');
|
||||||
|
O_VGA_Blue <= (others => '0');
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
|
||||||
|
P_Error_Register : process (I_VGA_CLK)
|
||||||
|
begin
|
||||||
|
if rising_edge(I_VGA_CLK) then
|
||||||
|
if I_VGA_RST = '1' then
|
||||||
|
R_Error <= (others => '0');
|
||||||
|
elsif I_VGA_Error_RST = '1' then
|
||||||
|
R_Error <= (others => '0');
|
||||||
|
else
|
||||||
|
R_Error(0) <= R_Error(0) or C_Error_PixelUnderrun;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
O_VGA_Error <= R_Error;
|
||||||
|
|
||||||
|
end architecture;
|
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------
|
||||||
--@ - Name: **VGA Timing Generator**
|
--@ - Name: **VGA Timing Generator**
|
||||||
--@ - Version: 0.0.1
|
--@ - Version: 0.0.1
|
||||||
--@ - Author: _Maximilian Passarello ([Blog](mpassarello.de))_
|
--@ - Author: _0xMax42 ([Blog](0xMax42.io))_
|
||||||
--@ - License: [MIT](LICENSE)
|
--@ - License: [MIT](LICENSE)
|
||||||
--@
|
--@
|
||||||
--@ The VGA Timing Generator is a simple module that generates the horizontal and vertical sync signals for a VGA display.
|
--@ The VGA Timing Generator is a simple module that generates the horizontal and vertical sync signals for a VGA display.
|
||||||
@@ -35,14 +35,15 @@ entity VGATimingGenerator is
|
|||||||
G_VBack : integer := 33;
|
G_VBack : integer := 33;
|
||||||
--@ Vertical Total resolution
|
--@ Vertical Total resolution
|
||||||
G_VTotal : integer := 525
|
G_VTotal : integer := 525
|
||||||
);
|
);
|
||||||
port (
|
port (
|
||||||
--@ Clock signal; **Rising edge** triggered
|
--@ Clock; (**Rising edge** triggered)
|
||||||
I_CLK : in std_logic;
|
I_CLK : in std_logic;
|
||||||
--@ Clock Enable signal
|
--@ Clock Enable; (**Synchronous**, **Active high**)
|
||||||
I_CE : in std_logic;
|
I_CE : in std_logic;
|
||||||
--@ Synchronous reset signal
|
--@ Reset; (**Synchronous**, **Active high**)
|
||||||
I_RST : in std_logic;
|
I_RST : in std_logic;
|
||||||
|
|
||||||
--@ Ready signal (AXI like) to indicate that the pixel data is ready to be displayed
|
--@ Ready signal (AXI like) to indicate that the pixel data is ready to be displayed
|
||||||
O_PixelReady : out std_logic;
|
O_PixelReady : out std_logic;
|
||||||
--@ @virtualbus VGA-Timing-Signals @dir out VGA timing signals
|
--@ @virtualbus VGA-Timing-Signals @dir out VGA timing signals
|
||||||
@@ -50,8 +51,8 @@ entity VGATimingGenerator is
|
|||||||
O_HSync : out std_logic;
|
O_HSync : out std_logic;
|
||||||
--@ Vertical Sync signal; **Active low**
|
--@ Vertical Sync signal; **Active low**
|
||||||
O_VSync : out std_logic
|
O_VSync : out std_logic
|
||||||
--@ @end
|
--@ @end
|
||||||
);
|
);
|
||||||
end entity VGATimingGenerator;
|
end entity VGATimingGenerator;
|
||||||
|
|
||||||
architecture RTL of VGATimingGenerator is
|
architecture RTL of VGATimingGenerator is
|
||||||
@@ -61,19 +62,19 @@ architecture RTL of VGATimingGenerator is
|
|||||||
signal R_VerticalCounter : unsigned(integer(ceil(log2(real(G_VTotal)))) - 1 downto 0) := (others => '0');
|
signal R_VerticalCounter : unsigned(integer(ceil(log2(real(G_VTotal)))) - 1 downto 0) := (others => '0');
|
||||||
|
|
||||||
--@ Counter Enable signal for Vertical Counter
|
--@ Counter Enable signal for Vertical Counter
|
||||||
signal C_VerticalCE : std_logic := '0';
|
signal C_VerticalCE : std_logic := '0';
|
||||||
|
|
||||||
--@ Flag to indicate if the horizontal counter is in the visible area
|
--@ Flag to indicate if the horizontal counter is in the visible area
|
||||||
signal C_HorizontalVisible : std_logic := '0';
|
signal C_HorizontalVisible : std_logic := '0';
|
||||||
--@ Flag to indicate if the vertical counter is in the visible area
|
--@ Flag to indicate if the vertical counter is in the visible area
|
||||||
signal C_VerticalVisible : std_logic := '0';
|
signal C_VerticalVisible : std_logic := '0';
|
||||||
|
|
||||||
--@ Horizontal Sync signal shift register
|
--@ Horizontal Sync signal shift register
|
||||||
signal R_HSync : std_logic_vector(1 downto 0) := (others => '0');
|
signal R_HSync : std_logic_vector(1 downto 0) := (others => '0');
|
||||||
--@ Vertical Sync signal register
|
--@ Vertical Sync signal register
|
||||||
signal R_VSync : std_logic := '1';
|
signal R_VSync : std_logic := '1';
|
||||||
--@ Pixel Ready signal
|
--@ Pixel Ready signal
|
||||||
signal C_PixelReady : std_logic := '0';
|
signal C_PixelReady : std_logic := '0';
|
||||||
begin
|
begin
|
||||||
--@ Horizontal Pixel Counter.
|
--@ Horizontal Pixel Counter.
|
||||||
--@ Overflows at G_HTotal.
|
--@ Overflows at G_HTotal.
|
||||||
@@ -138,7 +139,7 @@ begin
|
|||||||
if rising_edge(I_CLK) then
|
if rising_edge(I_CLK) then
|
||||||
if I_RST = '1' then
|
if I_RST = '1' then
|
||||||
R_VerticalCounter <= (others => '0');
|
R_VerticalCounter <= (others => '0');
|
||||||
elsif C_VerticalCE = '1' then
|
elsif (I_CE and C_VerticalCE) = '1' then
|
||||||
if R_VerticalCounter = G_VTotal - 1 then
|
if R_VerticalCounter = G_VTotal - 1 then
|
||||||
R_VerticalCounter <= (others => '0');
|
R_VerticalCounter <= (others => '0');
|
||||||
else
|
else
|
||||||
@@ -154,8 +155,8 @@ begin
|
|||||||
if rising_edge(I_CLK) then
|
if rising_edge(I_CLK) then
|
||||||
if I_RST = '1' then
|
if I_RST = '1' then
|
||||||
R_VSync <= '1';
|
R_VSync <= '1';
|
||||||
elsif C_VerticalCE = '1' then
|
elsif (I_CE and C_VerticalCE) = '1' then
|
||||||
if R_VerticalCounter < G_VSync then
|
if R_VerticalCounter >= G_VTotal - G_VSync then
|
||||||
R_VSync <= '0';
|
R_VSync <= '0';
|
||||||
else
|
else
|
||||||
R_VSync <= '1';
|
R_VSync <= '1';
|
||||||
@@ -167,8 +168,8 @@ begin
|
|||||||
--@ Flag generator for vertical visible area.
|
--@ Flag generator for vertical visible area.
|
||||||
P_VerticalVisible : process (R_VerticalCounter)
|
P_VerticalVisible : process (R_VerticalCounter)
|
||||||
begin
|
begin
|
||||||
if R_VerticalCounter >= G_VSync + G_VBack and
|
if R_VerticalCounter >= G_VBack and
|
||||||
R_VerticalCounter <= G_VTotal - G_VFront - 1 then
|
R_VerticalCounter <= G_VTotal - G_VFront - G_VSync - 1 then
|
||||||
C_VerticalVisible <= '1';
|
C_VerticalVisible <= '1';
|
||||||
else
|
else
|
||||||
C_VerticalVisible <= '0';
|
C_VerticalVisible <= '0';
|
||||||
|
@@ -2,14 +2,14 @@ NET I_CLK LOC = B8;
|
|||||||
NET I_CLK TNM_NET = CLOCK;
|
NET I_CLK TNM_NET = CLOCK;
|
||||||
TIMESPEC TS_CLOCK = PERIOD CLOCK 50 MHz HIGH 50 %;
|
TIMESPEC TS_CLOCK = PERIOD CLOCK 50 MHz HIGH 50 %;
|
||||||
|
|
||||||
NET O_HSync LOC = T4 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_HSync LOC = T4 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
NET O_VSync LOC = U3 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_VSync LOC = U3 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
|
|
||||||
NET O_Red<0> LOC = R9 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_Red<0> LOC = R9 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
NET O_Red<1> LOC = T8 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_Red<1> LOC = T8 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
NET O_Red<2> LOC = R8 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_Red<2> LOC = R8 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
NET O_Green<0> LOC = N8 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_Green<0> LOC = N8 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
NET O_Green<1> LOC = P8 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_Green<1> LOC = P8 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
NET O_Green<2> LOC = P6 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_Green<2> LOC = P6 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
NET O_Blue<0> LOC = U5 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_Blue<0> LOC = U5 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
||||||
NET O_Blue<1> LOC = U4 | IOSTANDARD = LVCMOS25 | SLEW = FAST | DRIVE = 12;
|
NET O_Blue<1> LOC = U4 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2;
|
@@ -23,11 +23,17 @@ entity VGATimingGenerator_test is
|
|||||||
end entity VGATimingGenerator_test;
|
end entity VGATimingGenerator_test;
|
||||||
|
|
||||||
architecture RTL of VGATimingGenerator_test is
|
architecture RTL of VGATimingGenerator_test is
|
||||||
|
|
||||||
|
function rgb_to_vector(red : unsigned(2 downto 0); green : unsigned(2 downto 0); blue : unsigned(1 downto 0)) return std_logic_vector is
|
||||||
|
begin
|
||||||
|
return std_logic_vector(std_logic_vector(red) & std_logic_vector(green) & std_logic_vector(blue));
|
||||||
|
end function;
|
||||||
|
|
||||||
signal I_VGA_PixelCE : std_logic := '0';
|
signal I_VGA_PixelCE : std_logic := '0';
|
||||||
signal I_VGA_PixelRST : std_logic := '1';
|
signal I_VGA_PixelRST : std_logic := '1';
|
||||||
|
|
||||||
signal O_VGA_Req_Y_Valid : std_logic;
|
signal O_VGA_Req_Y_Valid : std_logic;
|
||||||
signal I_VGA_Req_Y_Ready : std_logic;
|
signal I_VGA_Req_Y_Ready : std_logic := '0';
|
||||||
signal O_VGA_Req_Y : std_logic_vector(9 downto 0);
|
signal O_VGA_Req_Y : std_logic_vector(9 downto 0);
|
||||||
|
|
||||||
signal O_VGA_Req_X_Valid : std_logic;
|
signal O_VGA_Req_X_Valid : std_logic;
|
||||||
@@ -43,24 +49,60 @@ architecture RTL of VGATimingGenerator_test is
|
|||||||
signal I_VGA_PixelData : std_logic_vector(7 downto 0);
|
signal I_VGA_PixelData : std_logic_vector(7 downto 0);
|
||||||
|
|
||||||
----
|
----
|
||||||
constant COLOR_RED : std_logic_vector(7 downto 0) := "11100000"; -- R=7, G=0, B=0
|
constant K_COLOR_BLACK : std_logic_vector(7 downto 0) := rgb_to_vector("000", "000", "00");
|
||||||
constant COLOR_GREEN : std_logic_vector(7 downto 0) := "00011100"; -- R=0, G=7, B=0
|
constant K_COLOR_WHITE : std_logic_vector(7 downto 0) := rgb_to_vector("111", "111", "11");
|
||||||
constant COLOR_BLUE : std_logic_vector(7 downto 0) := "00000011"; -- R=0, G=0, B=3
|
|
||||||
|
|
||||||
signal R_CurrentColor : std_logic_vector(7 downto 0) := COLOR_BLUE; -- Pre-Startfarbe: Blau
|
constant K_COLOR_RED : std_logic_vector(7 downto 0) := rgb_to_vector("111", "000", "00");
|
||||||
constant COLOR_CHANGE_INTERVAL : integer := 16;
|
constant K_COLOR_GREEN : std_logic_vector(7 downto 0) := rgb_to_vector("000", "111", "00");
|
||||||
|
constant K_COLOR_BLUE : std_logic_vector(7 downto 0) := rgb_to_vector("000", "000", "11");
|
||||||
|
|
||||||
-- Farbwechsel-Logik (einfache zyklische Farben)
|
constant K_COLOR_CYAN : std_logic_vector(7 downto 0) := rgb_to_vector("000", "111", "11"); -- G + B
|
||||||
function next_color(current : std_logic_vector(7 downto 0)) return std_logic_vector is
|
constant K_COLOR_MAGENTA : std_logic_vector(7 downto 0) := rgb_to_vector("111", "000", "11"); -- R + B
|
||||||
|
constant K_COLOR_YELLOW : std_logic_vector(7 downto 0) := rgb_to_vector("111", "111", "00"); -- R + G
|
||||||
|
|
||||||
|
constant K_COLOR_GRAY : std_logic_vector(7 downto 0) := rgb_to_vector("100", "100", "10"); -- mittelgrau
|
||||||
|
constant K_COLOR_DARK_GRAY : std_logic_vector(7 downto 0) := rgb_to_vector("010", "010", "01");
|
||||||
|
constant K_COLOR_LIGHT_GRAY : std_logic_vector(7 downto 0) := rgb_to_vector("110", "110", "10");
|
||||||
|
|
||||||
|
constant K_COLOR_ORANGE : std_logic_vector(7 downto 0) := rgb_to_vector("111", "011", "00");
|
||||||
|
constant K_COLOR_PINK : std_logic_vector(7 downto 0) := rgb_to_vector("111", "100", "10");
|
||||||
|
constant K_COLOR_BROWN : std_logic_vector(7 downto 0) := rgb_to_vector("100", "010", "00");
|
||||||
|
constant K_COLOR_LIME : std_logic_vector(7 downto 0) := rgb_to_vector("010", "111", "00");
|
||||||
|
constant K_COLOR_NAVY : std_logic_vector(7 downto 0) := rgb_to_vector("000", "000", "01");
|
||||||
|
|
||||||
|
|
||||||
|
constant K_DEFAULT_COLOR : std_logic_vector(7 downto 0) := K_COLOR_CYAN;
|
||||||
|
|
||||||
|
signal R_CurrentColor : std_logic_vector(7 downto 0);
|
||||||
|
signal R_CurrentColorAlt : std_logic_vector(7 downto 0);
|
||||||
|
signal R_MUX_Color : std_logic := '0';
|
||||||
|
constant K_COLOR_CHANGE_INTERVAL : integer := 16;
|
||||||
|
|
||||||
|
-- Farbwechsel-Logik (einfache zyklische Farben)
|
||||||
|
function next_color(currentColor : std_logic_vector(7 downto 0)) return std_logic_vector is
|
||||||
begin
|
begin
|
||||||
if current = COLOR_RED then -- Rot
|
case currentColor is
|
||||||
return COLOR_GREEN; -- Grün
|
when K_COLOR_BLACK => return K_COLOR_WHITE;
|
||||||
elsif current = COLOR_GREEN then -- Grün
|
when K_COLOR_WHITE => return K_COLOR_RED;
|
||||||
return COLOR_BLUE; -- Blau
|
when K_COLOR_RED => return K_COLOR_GREEN;
|
||||||
else
|
when K_COLOR_GREEN => return K_COLOR_BLUE;
|
||||||
return COLOR_RED; -- Rot
|
when K_COLOR_BLUE => return K_COLOR_CYAN;
|
||||||
end if;
|
when K_COLOR_CYAN => return K_COLOR_MAGENTA;
|
||||||
|
when K_COLOR_MAGENTA => return K_COLOR_YELLOW;
|
||||||
|
when K_COLOR_YELLOW => return K_COLOR_GRAY;
|
||||||
|
when K_COLOR_GRAY => return K_COLOR_DARK_GRAY;
|
||||||
|
when K_COLOR_DARK_GRAY => return K_COLOR_LIGHT_GRAY;
|
||||||
|
when K_COLOR_LIGHT_GRAY => return K_COLOR_ORANGE;
|
||||||
|
when K_COLOR_ORANGE => return K_COLOR_PINK;
|
||||||
|
when K_COLOR_PINK => return K_COLOR_BROWN;
|
||||||
|
when K_COLOR_BROWN => return K_COLOR_LIME;
|
||||||
|
when K_COLOR_LIME => return K_COLOR_NAVY;
|
||||||
|
when K_COLOR_NAVY => return K_COLOR_BLACK; -- wieder von vorn
|
||||||
|
when others => return K_DEFAULT_COLOR;
|
||||||
|
end case;
|
||||||
end function;
|
end function;
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
process (I_CLK)
|
process (I_CLK)
|
||||||
@@ -72,23 +114,33 @@ begin
|
|||||||
|
|
||||||
I_VGA_PixelData_Valid <= O_VGA_Req_X_Valid;
|
I_VGA_PixelData_Valid <= O_VGA_Req_X_Valid;
|
||||||
I_VGA_Req_X_Ready <= O_VGA_PixelData_Ready;
|
I_VGA_Req_X_Ready <= O_VGA_PixelData_Ready;
|
||||||
|
|
||||||
|
I_VGA_PixelData <= R_CurrentColor when R_MUX_Color = '0' else
|
||||||
|
R_CurrentColorAlt;
|
||||||
process(I_CLK)
|
process(I_CLK)
|
||||||
begin
|
begin
|
||||||
if rising_edge(I_CLK) then
|
if rising_edge(I_CLK) then
|
||||||
I_VGA_PixelRST <= '0';
|
I_VGA_PixelRST <= '0';
|
||||||
|
|
||||||
I_VGA_PixelData <= R_CurrentColor;
|
if O_VGA_Req_X_Valid = '1' and O_VGA_PixelData_Ready = '1' then
|
||||||
|
if unsigned(O_VGA_Req_X) = to_unsigned(640-1, O_VGA_Req_X'length) then
|
||||||
|
R_MUX_Color <= '0';
|
||||||
|
elsif unsigned(O_VGA_Req_X) = to_unsigned(320-1, O_VGA_Req_X'length) then
|
||||||
|
R_MUX_Color <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
-- Default
|
|
||||||
I_VGA_Req_Y_Ready <= '0';
|
|
||||||
|
|
||||||
-- Zeilenwechsel erkennen (Req_X zurück auf 0)
|
|
||||||
if O_VGA_Req_Y_Valid = '1' and I_VGA_Req_Y_Ready = '0' then
|
if O_VGA_Req_Y_Valid = '1' and I_VGA_Req_Y_Ready = '0' then
|
||||||
I_VGA_Req_Y_Ready <= '1';
|
I_VGA_Req_Y_Ready <= '1';
|
||||||
|
if O_VGA_Req_Y = (O_VGA_Req_Y'range => '0') then
|
||||||
if (unsigned(O_VGA_Req_Y) mod COLOR_CHANGE_INTERVAL) = 0 then
|
R_CurrentColor <= K_DEFAULT_COLOR;
|
||||||
R_CurrentColor <= next_color(R_CurrentColor);
|
R_CurrentColorAlt <= next_color(K_DEFAULT_COLOR);
|
||||||
|
elsif (unsigned(O_VGA_Req_Y) mod K_COLOR_CHANGE_INTERVAL) = 0 then
|
||||||
|
R_CurrentColor <= next_color(R_CurrentColor);
|
||||||
|
R_CurrentColorAlt <= next_color(R_CurrentColorAlt);
|
||||||
end if;
|
end if;
|
||||||
|
elsif I_VGA_Req_Y_Ready = '1' then
|
||||||
|
I_VGA_Req_Y_Ready <= '0';
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
end if;
|
end if;
|
||||||
|
92
src/XY_Generator.vhd
Normal file
92
src/XY_Generator.vhd
Normal 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;
|
Reference in New Issue
Block a user