From a73f125357864a65b67ddabf1349feaff09f8519 Mon Sep 17 00:00:00 2001 From: Max P Date: Sat, 26 Apr 2025 10:26:52 +0000 Subject: [PATCH] Refactors VGA timing and mode handling Renames and restructures VGA timing generator for clarity and modularity. Introduces VGA modes package for centralized resolution and timing configuration. Updates related testbenches and constraints to align with new structure. Improves maintainability and flexibility for future VGA mode additions. --- build | 2 +- project.cfg | 11 +- ...mingGenerator.vhd => Timing_Generator.vhd} | 63 +++--- src/VGA.vhd | 24 +- src/VGATimingGenerator_pb.ucf | 3 - src/VGATimingGenerator_pb.vhd | 56 ----- src/VGA_Modes_Pkg.vhd | 43 ++++ ...ATimingGenerator_test.ucf => VGA_test.ucf} | 22 +- ...ATimingGenerator_test.vhd => VGA_test.vhd} | 107 ++++++--- src/XY_Generator.vhd | 25 +- tests/VGATimingGenerator_tb.vhd | 45 ---- tests/VGATimingGenerator_test_tb.vhd | 12 +- tests/default.wcfg | 214 ++++++++++++++++-- 13 files changed, 404 insertions(+), 223 deletions(-) rename src/{VGATimingGenerator.vhd => Timing_Generator.vhd} (77%) delete mode 100644 src/VGATimingGenerator_pb.ucf delete mode 100644 src/VGATimingGenerator_pb.vhd create mode 100644 src/VGA_Modes_Pkg.vhd rename src/{VGATimingGenerator_test.ucf => VGA_test.ucf} (75%) rename src/{VGATimingGenerator_test.vhd => VGA_test.vhd} (64%) delete mode 100644 tests/VGATimingGenerator_tb.vhd diff --git a/build b/build index 54949f4..d1a3b7c 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit 54949f43c0a900256c15d5d964c6b1da95d27473 +Subproject commit d1a3b7cec979d04999fd6e4e0560281ac65ec94e diff --git a/project.cfg b/project.cfg index 1afe342..5c7a2a1 100644 --- a/project.cfg +++ b/project.cfg @@ -2,7 +2,7 @@ # Project name # @remark The name of the project is used as default name for the top module and the ucf file -PROJECT = VGATimingGenerator +PROJECT = VGA # Target device # @example xc3s1200e-4-fg320 | xc5vlx50t-1-ff1136 @@ -12,10 +12,10 @@ TARGET_PART = xc3s1200e-4-fg320 XILINX = /opt/Xilinx/14.7/ISE_DS/ISE # Optional the name of the top module (default is the project name) -TOPLEVEL = VGATimingGenerator_test +TOPLEVEL = VGA_test # Optional the path/name of the ucf file (default is the project name) -CONSTRAINTS = src/VGATimingGenerator_test.ucf +CONSTRAINTS = src/VGA_test.ucf # Optional a target to copy the bit file to (make copy) # COPY_TARGET_DIR = @@ -29,10 +29,11 @@ CONSTRAINTS = src/VGATimingGenerator_test.ucf # @example `VHDSOURCE += src/main.vhd` (add a single VHDL file per line) # VHDSOURCE += src/VGATimingGenerator_pb.vhd -VHDSOURCE += src/VGATimingGenerator_test.vhd -VHDSOURCE += src/VGATimingGenerator.vhd +VHDSOURCE += src/VGA_test.vhd +VHDSOURCE += src/Timing_Generator.vhd VHDSOURCE += src/XY_Generator.vhd VHDSOURCE += src/VGA.vhd +VHDSOURCE += src/VGA_Modes_Pkg.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 diff --git a/src/VGATimingGenerator.vhd b/src/Timing_Generator.vhd similarity index 77% rename from src/VGATimingGenerator.vhd rename to src/Timing_Generator.vhd index 1be7a26..a85d968 100644 --- a/src/VGATimingGenerator.vhd +++ b/src/Timing_Generator.vhd @@ -16,25 +16,12 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; +use work.VGA_Modes_Pkg.all; -entity VGATimingGenerator is +entity Timing_Generator is generic ( - --@ Horizontal Front Porch - G_HFront : integer := 16; - --@ Horizontal Sync Pulse - G_HSync : integer := 96; - --@ Horizontal Back Porch - G_HBack : integer := 48; - --@ Horizontal Total resolution - G_HTotal : integer := 800; - --@ Vertical Front Porch - G_VFront : integer := 10; - --@ Vertical Sync Pulse - G_VSync : integer := 2; - --@ Vertical Back Porch - G_VBack : integer := 33; - --@ Vertical Total resolution - G_VTotal : integer := 525 + --@ VGA Mode (0-9) from VGA_Modes_Pkg + G_VGA_Mode : integer := 1 ); port ( --@ Clock; (**Rising edge** triggered) @@ -53,13 +40,31 @@ entity VGATimingGenerator is O_VSync : out std_logic --@ @end ); -end entity VGATimingGenerator; +end entity Timing_Generator; + +architecture RTL of Timing_Generator is + --@ Horizontal Front Porch + constant K_HFront : integer := K_VGA_Modes(G_VGA_Mode).H_Front; + --@ Horizontal Sync Pulse + constant K_HSync : integer := K_VGA_Modes(G_VGA_Mode).H_Sync; + --@ Horizontal Back Porch + constant K_HBack : integer := K_VGA_Modes(G_VGA_Mode).H_Back; + --@ Horizontal Total resolution + constant K_HTotal : integer := K_VGA_Modes(G_VGA_Mode).H_Total; + --@ Vertical Front Porch + constant K_VFront : integer := K_VGA_Modes(G_VGA_Mode).V_Front; + --@ Vertical Sync Pulse + constant K_VSync : integer := K_VGA_Modes(G_VGA_Mode).V_Sync; + --@ Vertical Back Porch + constant K_VBack : integer := K_VGA_Modes(G_VGA_Mode).V_Back; + --@ Vertical Total resolution + constant K_VTotal : integer := K_VGA_Modes(G_VGA_Mode).V_Total; + -architecture RTL of VGATimingGenerator is --@ Horizontal Counter; max value = G_HTotal - signal R_HorizontalCounter : unsigned(integer(ceil(log2(real(G_HTotal)))) - 1 downto 0) := (others => '0'); + signal R_HorizontalCounter : unsigned(K_VGA_Modes(G_VGA_Mode).X_Width - 1 downto 0) := (others => '0'); --@ Vertical Counter; max value = G_VTotal - signal R_VerticalCounter : unsigned(integer(ceil(log2(real(G_VTotal)))) - 1 downto 0) := (others => '0'); + signal R_VerticalCounter : unsigned(K_VGA_Modes(G_VGA_Mode).Y_Width - 1 downto 0) := (others => '0'); --@ Counter Enable signal for Vertical Counter signal C_VerticalCE : std_logic := '0'; @@ -84,7 +89,7 @@ begin if I_RST = '1' then R_HorizontalCounter <= (others => '0'); elsif I_CE = '1' then - if R_HorizontalCounter = G_HTotal - 1 then + if R_HorizontalCounter = K_HTotal - 1 then R_HorizontalCounter <= (others => '0'); else R_HorizontalCounter <= R_HorizontalCounter + 1; @@ -101,7 +106,7 @@ begin if I_RST = '1' then R_HSync <= (others => '1'); elsif I_CE = '1' then - if R_HorizontalCounter < G_HSync then + if R_HorizontalCounter < K_HSync then R_HSync <= R_HSync(R_HSync'high - 1 downto R_HSync'low) & '0'; else R_HSync <= R_HSync(R_HSync'high - 1 downto R_HSync'low) & '1'; @@ -113,8 +118,8 @@ begin --@ Flag generator for horizontal visible area. P_HorizontalVisible : process (R_HorizontalCounter) begin - if R_HorizontalCounter >= G_HSync + G_HBack and - R_HorizontalCounter <= G_HTotal - G_HFront - 1 then + if R_HorizontalCounter >= K_HSync + K_HBack and + R_HorizontalCounter <= K_HTotal - K_HFront - 1 then C_HorizontalVisible <= '1'; else C_HorizontalVisible <= '0'; @@ -140,7 +145,7 @@ begin if I_RST = '1' then R_VerticalCounter <= (others => '0'); elsif (I_CE and C_VerticalCE) = '1' then - if R_VerticalCounter = G_VTotal - 1 then + if R_VerticalCounter = K_VTotal - 1 then R_VerticalCounter <= (others => '0'); else R_VerticalCounter <= R_VerticalCounter + 1; @@ -156,7 +161,7 @@ begin if I_RST = '1' then R_VSync <= '1'; elsif (I_CE and C_VerticalCE) = '1' then - if R_VerticalCounter >= G_VTotal - G_VSync then + if R_VerticalCounter >= K_VTotal - K_VSync then R_VSync <= '0'; else R_VSync <= '1'; @@ -168,8 +173,8 @@ begin --@ Flag generator for vertical visible area. P_VerticalVisible : process (R_VerticalCounter) begin - if R_VerticalCounter >= G_VBack and - R_VerticalCounter <= G_VTotal - G_VFront - G_VSync - 1 then + if R_VerticalCounter >= K_VBack and + R_VerticalCounter <= K_VTotal - K_VFront - K_VSync - 1 then C_VerticalVisible <= '1'; else C_VerticalVisible <= '0'; diff --git a/src/VGA.vhd b/src/VGA.vhd index 9f1c9a8..2c25a2b 100644 --- a/src/VGA.vhd +++ b/src/VGA.vhd @@ -2,8 +2,14 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; +use work.VGA_Modes_Pkg.all; entity VGA is + generic ( + --@ VGA Mode (0-9) from VGA_Modes_Pkg + G_VGA_Mode : integer := 2; + G_PixelBuffer_Depth : integer := 16 + ); port ( --@ Pixel Clock; (**Rising edge** triggered) I_VGA_PixelCLK : in std_logic; @@ -31,10 +37,10 @@ entity VGA is --@ @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_Y : out std_logic_vector(K_VGA_Modes(G_VGA_Mode).Y_Width - 1 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); + O_VGA_Req_X : out std_logic_vector(K_VGA_Modes(G_VGA_Mode).X_Width - 1 downto 0); --@ @end --@ @virtualbus Pixel-Data @dir In Calculated pixel data @@ -68,7 +74,10 @@ architecture RTL of VGA is --@ 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 + INST_TimingGenerator : entity work.Timing_Generator + generic map( + G_VGA_Mode => G_VGA_Mode + ) port map( I_CLK => I_VGA_PixelCLK, I_CE => I_VGA_PixelCE, @@ -90,10 +99,7 @@ begin INST_XY_Generator : entity work.XY_Generator generic map( - G_X => 640, - G_Y => 480, - G_X_Width => 10, - G_Y_Width => 10 + G_VGA_Mode => G_VGA_Mode ) port map( I_CLK => I_VGA_CLK, @@ -111,7 +117,7 @@ begin INST_AsyncPixelDataFIFO : entity work.AsyncFIFO generic map( G_Width => 8, - G_Depth => 16, + G_Depth => G_PixelBuffer_Depth, G_RamTypeFifo => "Distributed" ) port map( @@ -144,10 +150,12 @@ begin 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'); diff --git a/src/VGATimingGenerator_pb.ucf b/src/VGATimingGenerator_pb.ucf deleted file mode 100644 index 606c607..0000000 --- a/src/VGATimingGenerator_pb.ucf +++ /dev/null @@ -1,3 +0,0 @@ -NET I_CLK LOC = B8; -NET I_CLK TNM_NET = CLOCK; -TIMESPEC TS_CLOCK = PERIOD CLOCK 30 MHz HIGH 50 %; \ No newline at end of file diff --git a/src/VGATimingGenerator_pb.vhd b/src/VGATimingGenerator_pb.vhd deleted file mode 100644 index e9db739..0000000 --- a/src/VGATimingGenerator_pb.vhd +++ /dev/null @@ -1,56 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; -use ieee.math_real.all; - -entity VGATimingGenerator_pb is - port ( - --@ Clock signal; **Rising edge** triggered - I_CLK : in std_logic; - --@ Clock Enable signal - I_CE : in std_logic; - --@ Synchronous reset signal - I_RST : in std_logic; - --@ Ready signal to indicate that the pixel data is ready to be displayed - O_PixelReady : out std_logic; - --@ @virtualbus VGA-Timing-Signals @dir out VGA timing signals - --@ Horizontal Sync signal; **Active low** - O_HSync : out std_logic; - --@ Vertical Sync signal; **Active low** - O_VSync : out std_logic - --@ @end - ); -end entity VGATimingGenerator_pb; - -architecture RTL of VGATimingGenerator_pb is - signal R_RST : std_logic; - signal R_CE : std_logic; - signal C_PixelReady : std_logic; - signal R_HSync : std_logic; - signal R_VSync : std_logic; -begin - - BenchmarkEnvironmentFFs : process (I_CLK) - begin - if rising_edge(I_CLK) then - -- General Interace - R_CE <= I_CE; - R_RST <= I_RST; - - -- Output Interface - O_PixelReady <= C_PixelReady; - O_HSync <= R_HSync; - O_VSync <= R_VSync; - end if; - end process; - - VGATimingGenerator : entity work.VGATimingGenerator - port map( - I_CLK => I_CLK, - I_CE => R_CE, - I_RST => R_RST, - O_PixelReady => C_PixelReady, - O_HSync => R_HSync, - O_VSync => R_VSync - ); -end architecture RTL; diff --git a/src/VGA_Modes_Pkg.vhd b/src/VGA_Modes_Pkg.vhd new file mode 100644 index 0000000..9d3b2ca --- /dev/null +++ b/src/VGA_Modes_Pkg.vhd @@ -0,0 +1,43 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package VGA_Modes_Pkg is + + -- Struktur für einen Timing-Eintrag + type T_VGA_Mode is record + X_Resolution : integer; + Y_Resolution : integer; + + X_Width : integer; + Y_Width : integer; + + H_Front : integer; + H_Sync : integer; + H_Back : integer; + H_Total : integer; + + V_Front : integer; + V_Sync : integer; + V_Back : integer; + V_Total : integer; + end record; + + -- Array mit allen Modi + type T_VGA_Mode_Array is array(0 to 9) of T_VGA_Mode; + + constant K_VGA_Modes : T_VGA_Mode_Array := ( + -- X, Y, XW, YW, H_Front, H_Sync, H_Back, H_Total, V_Front, V_Sync, V_Back, V_Total + 0 => (320, 240, 9, 9, 8, 48, 24, 400, 5, 1, 16, 262), -- ~12.6 MHz + 1 => (400, 300, 10, 9, 20, 64, 44, 528, 0, 2, 12, 314), -- ~20 MHz + 2 => (640, 480, 10, 10, 16, 96, 48, 800, 10, 2, 33, 525), -- 25.175 MHz + 3 => (800, 600, 11, 10, 40, 128, 88, 1056, 1, 4, 23, 628), -- 40 MHz + 4 => (1024, 768, 11, 10, 24, 136, 160, 1344, 3, 6, 29, 806), -- 65 MHz + 5 => (1280, 720, 11, 10, 110, 40, 220, 1650, 5, 5, 20, 750), -- 74.25 MHz + 6 => (1280, 1024, 11, 11, 48, 112, 248, 1688, 1, 3, 38, 1066), -- 108 MHz + 7 => (1600, 1200, 12, 11, 64, 192, 304, 2160, 1, 3, 46, 1250), -- 162 MHz + 8 => (1920, 1080, 12, 11, 88, 44, 148, 2200, 4, 5, 36, 1125), -- 148.5 MHz + 9 => (0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0) -- Reserve + ); + +end package; diff --git a/src/VGATimingGenerator_test.ucf b/src/VGA_test.ucf similarity index 75% rename from src/VGATimingGenerator_test.ucf rename to src/VGA_test.ucf index 70a8966..0830fe7 100644 --- a/src/VGATimingGenerator_test.ucf +++ b/src/VGA_test.ucf @@ -2,14 +2,16 @@ NET I_CLK LOC = B8; NET I_CLK TNM_NET = CLOCK; TIMESPEC TS_CLOCK = PERIOD CLOCK 50 MHz HIGH 50 %; -NET O_VGA_HSync LOC = T4 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; -NET O_VGA_VSync LOC = U3 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; +NET O_VGA_HSync LOC = T4 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; +NET O_VGA_VSync LOC = U3 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; -NET O_VGA_Pixel<0> LOC = R9 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; -NET O_VGA_Pixel<1> LOC = T8 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; -NET O_VGA_Pixel<2> LOC = R8 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; -NET O_VGA_Pixel<3> LOC = N8 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; -NET O_VGA_Pixel<4> LOC = P8 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; -NET O_VGA_Pixel<5> LOC = P6 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; -NET O_VGA_Pixel<6> LOC = U5 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; -NET O_VGA_Pixel<7> LOC = U4 | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 2; +NET O_VGA_Pixel<0> LOC = R9 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; +NET O_VGA_Pixel<1> LOC = T8 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; +NET O_VGA_Pixel<2> LOC = R8 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; +NET O_VGA_Pixel<3> LOC = N8 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; +NET O_VGA_Pixel<4> LOC = P8 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; +NET O_VGA_Pixel<5> LOC = P6 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; +NET O_VGA_Pixel<6> LOC = U5 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; +NET O_VGA_Pixel<7> LOC = U4 | IOSTANDARD = LVTTL | SLEW = FAST | DRIVE = 12; + +NET "O_LED" LOC = "P4"; \ No newline at end of file diff --git a/src/VGATimingGenerator_test.vhd b/src/VGA_test.vhd similarity index 64% rename from src/VGATimingGenerator_test.vhd rename to src/VGA_test.vhd index b1f9dc2..01e8def 100644 --- a/src/VGATimingGenerator_test.vhd +++ b/src/VGA_test.vhd @@ -2,8 +2,16 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; +use work.VGA_Modes_Pkg.all; +library UNISIM; +use UNISIM.vcomponents.all; -entity VGATimingGenerator_test is + +entity VGA_test is + generic ( + --@ VGA Mode (0-9) from VGA_Modes_Pkg + G_VGA_Mode : integer := 2 + ); port ( --@ Clock signal; **Rising edge** triggered I_CLK : in std_logic; @@ -13,29 +21,32 @@ entity VGATimingGenerator_test is --@ Vertical Sync signal; **Active low** O_VGA_VSync : out std_logic; --@ VGA Pixel Data: 3 bits Red, 3 bits Green, 2 bits Blue - O_VGA_Pixel : out std_logic_vector(7 downto 0) + O_VGA_Pixel : out std_logic_vector(7 downto 0); --@ @end - + O_LED : out std_logic := '0' ); -end entity VGATimingGenerator_test; +end entity VGA_test; -architecture RTL of VGATimingGenerator_test is +architecture RTL of VGA_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 S_CLK_FB : std_logic; + signal S_CLK : std_logic; + signal I_VGA_PixelCE : std_logic := '0'; signal I_VGA_PixelRST : std_logic := '1'; signal O_VGA_Req_Y_Valid : 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(K_VGA_Modes(G_VGA_Mode).Y_Width-1 downto 0); signal O_VGA_Req_X_Valid : std_logic; signal I_VGA_Req_X_Ready : std_logic; - signal O_VGA_Req_X : std_logic_vector(9 downto 0); + signal O_VGA_Req_X : std_logic_vector(K_VGA_Modes(G_VGA_Mode).X_Width-1 downto 0); signal I_VGA_CE : std_logic := '1'; @@ -99,9 +110,36 @@ architecture RTL of VGATimingGenerator_test is end case; end function; + signal R_Error : std_logic_vector(7 downto 0) := (others => '0'); + signal R_ResetCounter : integer := 0; + constant K_ResetCounterMax : integer := 255; begin + INST_ClockManager : DCM_SP + generic map( + CLKDV_DIVIDE => 2.0, + CLKFX_MULTIPLY => 5, + CLKFX_DIVIDE => 5, + CLKIN_DIVIDE_BY_2 => false, + CLKIN_PERIOD => 20.0, + CLKOUT_PHASE_SHIFT => "NONE", + CLK_FEEDBACK => "1X", + DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", + DFS_FREQUENCY_MODE => "LOW", + DLL_FREQUENCY_MODE => "LOW", + DUTY_CYCLE_CORRECTION => true, + FACTORY_JF => X"C080", + PHASE_SHIFT => 0, + STARTUP_WAIT => false) + port map + ( + CLK0 => S_CLK_FB, + CLKFX => S_CLK, + CLKFB => S_CLK_FB, + CLKIN => I_CLK + ); + process (I_CLK) begin if rising_edge(I_CLK) then @@ -114,44 +152,50 @@ begin I_VGA_PixelData <= R_CurrentColor when R_MUX_Color = '0' else R_CurrentColorAlt; - process(I_CLK) + process(S_CLK) begin - if rising_edge(I_CLK) then - I_VGA_PixelRST <= '0'; + if rising_edge(S_CLK) then + if R_ResetCounter = K_ResetCounterMax then + I_VGA_PixelRST <= '0'; - 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'; + if O_VGA_Req_X_Valid = '1' and O_VGA_PixelData_Ready = '1' then + if unsigned(O_VGA_Req_X) = to_unsigned(K_VGA_Modes(G_VGA_Mode).X_Resolution-1, O_VGA_Req_X'length) then + R_MUX_Color <= '0'; + elsif unsigned(O_VGA_Req_X) = to_unsigned((K_VGA_Modes(G_VGA_Mode).X_Resolution/2)-1, O_VGA_Req_X'length) then + R_MUX_Color <= '1'; + end if; end if; - end if; - if O_VGA_Req_Y_Valid = '1' and I_VGA_Req_Y_Ready = '0' then - I_VGA_Req_Y_Ready <= '1'; - if O_VGA_Req_Y = (O_VGA_Req_Y'range => '0') then - R_CurrentColor <= K_DEFAULT_COLOR; - 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); + if O_VGA_Req_Y_Valid = '1' and I_VGA_Req_Y_Ready = '0' then + I_VGA_Req_Y_Ready <= '1'; + if O_VGA_Req_Y = (O_VGA_Req_Y'range => '0') then + R_CurrentColor <= K_DEFAULT_COLOR; + 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; + elsif I_VGA_Req_Y_Ready = '1' then + I_VGA_Req_Y_Ready <= '0'; end if; - elsif I_VGA_Req_Y_Ready = '1' then - I_VGA_Req_Y_Ready <= '0'; + else + R_ResetCounter <= R_ResetCounter + 1; end if; - end if; end process; INST_VGA : entity work.VGA + generic map( + G_VGA_Mode => G_VGA_Mode + ) port map( - I_VGA_PixelCLK => I_CLK, + I_VGA_PixelCLK => S_CLK, I_VGA_PixelCE => I_VGA_PixelCE, I_VGA_PixelRST => I_VGA_PixelRST, O_VGA_HSync => O_VGA_HSync, O_VGA_VSync => O_VGA_VSync, O_VGA_Pixel => O_VGA_Pixel, - I_VGA_CLK => I_CLK, + I_VGA_CLK => S_CLK, I_VGA_CE => I_VGA_CE, I_VGA_RST => I_VGA_RST, O_VGA_Req_Y_Valid => O_VGA_Req_Y_Valid, @@ -162,9 +206,10 @@ begin O_VGA_Req_X => O_VGA_Req_X, I_VGA_PixelData_Valid => I_VGA_PixelData_Valid, O_VGA_PixelData_Ready => O_VGA_PixelData_Ready, - I_VGA_PixelData => I_VGA_PixelData + I_VGA_PixelData => I_VGA_PixelData, + O_VGA_Error => R_Error ); - + O_LED <= R_Error(0); end architecture RTL; diff --git a/src/XY_Generator.vhd b/src/XY_Generator.vhd index 46b8e2a..491ec08 100644 --- a/src/XY_Generator.vhd +++ b/src/XY_Generator.vhd @@ -2,15 +2,12 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; +use work.VGA_Modes_Pkg.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 + --@ VGA Mode (0-9) from VGA_Modes_Pkg + G_VGA_Mode : integer := 2 ); port ( --@ Clock; (**Rising edge** triggered) @@ -23,12 +20,12 @@ entity XY_Generator is --@ @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); + O_Y : out std_logic_vector(K_VGA_Modes(G_VGA_Mode).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) + O_X : out std_logic_vector(K_VGA_Modes(G_VGA_Mode).X_Width - 1 downto 0) --@ @end ); @@ -36,8 +33,12 @@ entity XY_Generator is 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'); + + constant K_X : integer := K_VGA_Modes(G_VGA_Mode).X_Resolution; + constant K_Y : integer := K_VGA_Modes(G_VGA_Mode).Y_Resolution; + + signal R_X_Counter : unsigned(K_VGA_Modes(G_VGA_Mode).X_Width - 1 downto 0) := (others => '0'); + signal R_Y_Counter : unsigned(K_VGA_Modes(G_VGA_Mode).Y_Width - 1 downto 0) := (others => '0'); signal R_Y_Valid : std_logic := '1'; signal R_X_Valid : std_logic := '1'; @@ -64,11 +65,11 @@ begin R_X_Valid <= '0'; end if; else - if R_X_Counter = (G_X - 1) then + if R_X_Counter = (K_X - 1) then R_X_Counter <= (others => '0'); R_X_Valid <= '1'; - if R_Y_Counter = (G_Y - 1) then + if R_Y_Counter = (K_Y - 1) then R_Y_Counter <= (others => '0'); R_Y_Valid <= '1'; else diff --git a/tests/VGATimingGenerator_tb.vhd b/tests/VGATimingGenerator_tb.vhd deleted file mode 100644 index edc7927..0000000 --- a/tests/VGATimingGenerator_tb.vhd +++ /dev/null @@ -1,45 +0,0 @@ - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity VGATimingGenerator_tb is -end; - -architecture bench of VGATimingGenerator_tb is - -- Clock period - constant clk_period : time := 40 ns; - -- Ports - signal I_CLK : std_logic := '0'; - signal I_CE : std_logic := '1'; - signal I_RST : std_logic := '1'; - signal O_PixelReady : std_logic; - signal O_HSync : std_logic; - signal O_VSync : std_logic; -begin - - VGATimingGenerator_inst : entity work.VGATimingGenerator - port map - ( - I_CLK => I_CLK, - I_CE => I_CE, - I_RST => I_RST, - O_PixelReady => O_PixelReady, - O_HSync => O_HSync, - O_VSync => O_VSync - ); - - I_CLK <= not I_CLK after clk_period/2; - - process - begin - wait for 100 ms; - I_RST <= '0'; - wait for 500 ms; - I_RST <= '1'; - wait for 100 ms; - I_RST <= '0'; - wait; - end process; - -end; \ No newline at end of file diff --git a/tests/VGATimingGenerator_test_tb.vhd b/tests/VGATimingGenerator_test_tb.vhd index e49e49b..5843f53 100644 --- a/tests/VGATimingGenerator_test_tb.vhd +++ b/tests/VGATimingGenerator_test_tb.vhd @@ -17,17 +17,21 @@ architecture bench of VGATimingGenerator_test_tb is signal O_Red : std_logic_vector(2 downto 0); signal O_Green : std_logic_vector(2 downto 0); signal O_Blue : std_logic_vector(1 downto 0); + signal O_Pixel : std_logic_vector(7 downto 0); begin - VGATimingGenerator_test_inst : entity work.VGATimingGenerator_test + VGATimingGenerator_test_inst : entity work.VGA_test port map ( I_CLK => I_CLK, O_VGA_HSync => O_HSync, O_VGA_VSync => O_VSync, - O_Red => O_Red, - O_Green => O_Green, - O_Blue => O_Blue + O_VGA_Pixel => O_Pixel ); + + O_Red <= O_Pixel(2 downto 0); + O_Green <= O_Pixel(5 downto 3); + O_Blue <= O_Pixel(7 downto 6); + I_CLK <= not I_CLK after clk_period/2; end; diff --git a/tests/default.wcfg b/tests/default.wcfg index 9ea8e2c..34d5ae1 100644 --- a/tests/default.wcfg +++ b/tests/default.wcfg @@ -9,33 +9,209 @@ - + + + + + + + - - + + + label + i_clk + i_clk + Clock + + + s_clk_fb + s_clk_fb + + + s_clk_pixel + s_clk_pixel + + + s_clk_logic + s_clk_logic + + + label + i_vga_pixelce + i_vga_pixelce + Pixel_CE + + + Testbench + label + + o_hsync + o_hsync + + + o_vsync + o_vsync + + + o_red[2:0] + o_red[2:0] + + + o_green[2:0] + o_green[2:0] + + + o_blue[1:0] + o_blue[1:0] + + + + UUT + label + + i_vga_pixelrst + i_vga_pixelrst + + + i_vga_ce + i_vga_ce + + + i_vga_rst + i_vga_rst + + + i_vga_pixeldata_valid + i_vga_pixeldata_valid + + + o_vga_pixeldata_ready + o_vga_pixeldata_ready + + + i_vga_pixeldata[7:0] + i_vga_pixeldata[7:0] + + + r_currentcolor[7:0] + r_currentcolor[7:0] + + + + Y + label + + o_vga_req_y_valid + o_vga_req_y_valid + + + i_vga_req_y_ready + i_vga_req_y_ready + + + o_vga_req_y[9:0] + o_vga_req_y[9:0] + UNSIGNEDDECRADIX + + + + X + label + + o_vga_req_x_valid + o_vga_req_x_valid + + + i_vga_req_x_ready + i_vga_req_x_ready + + + o_vga_req_x[9:0] + o_vga_req_x[9:0] + UNSIGNEDDECRADIX + + + + Errors + label + + label + [0] + r_error[0] + Pixel Underrun + + + Raw + label + + r_error[7:0] + r_error[7:0] + + [7] + r_error[7] + + + [6] + r_error[6] + + + [5] + r_error[5] + + + [4] + r_error[4] + + + [3] + r_error[3] + + + [2] + r_error[2] + + + [1] + r_error[1] + + + label + [0] + r_error[0] + Pixel Underrun + + + + + + Slow + label + 128 128 255 + 230 230 230 + + i_clk i_clk - - i_ce - i_ce + + i_read_clk + i_read_clk - - i_rst - i_rst + + Fast + label + 128 128 255 + 230 230 230 - - o_pixelready - o_pixelready + + i_clk + i_clk - - o_hsync - o_hsync - - - o_vsync - o_vsync + + i_write_clk + i_write_clk