-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVGA_controller.vhd
114 lines (95 loc) · 3.6 KB
/
VGA_controller.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 18:39:44 09/13/2010
-- Design Name:
-- Module Name: OwnVGA - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity VGA_controller is
port ( CLK_50MHz : in std_logic;
VS : out std_logic;
HS : out std_logic;
RED : out unsigned(3 downto 0);
GREEN : out unsigned(3 downto 0);
BLUE : out unsigned(3 downto 0);
RESET : in std_logic;
ColorIN : in unsigned(11 downto 0);
ScanlineX : out unsigned(10 downto 0);
ScanlineY : out unsigned(10 downto 0)
);
end VGA_controller;
architecture Behavioral of VGA_controller is
-- VGA Definitions
constant HDisplayArea: integer:= 640; -- horizontal display area
constant HLimit: integer:= 800; -- maximum horizontal amount (limit)
constant HFrontPorch: integer:= 16; -- h. front porch
constant HBackPorch: integer:= 48; -- h. back porch
constant HSyncWidth: integer:= 96; -- h. pulse width
constant VDisplayArea: integer:= 480; -- vertical display area
constant VLimit: integer:= 525; -- maximum vertical amount (limit)
constant VFrontPorch: integer:= 10; -- v. front porch
constant VBackPorch: integer:= 33; -- v. back porch
constant VSyncWidth: integer:= 2; -- v. pulse width
signal Clk_25MHz: std_logic := '0';
signal HBlank, VBlank, Blank: std_logic := '0';
signal CurrentHPos: unsigned(10 downto 0) := (others => '0'); -- goes to 1100100000 = 800
signal CurrentVPos: unsigned(10 downto 0) := (others => '0'); -- goes to 1000001101 = 525
begin
Generate25MHz: process (CLK_50MHz)
begin
if rising_edge(CLK_50MHz) then
Clk_25MHz <= not Clk_25MHz;
end if;
end process Generate25MHz;
VGAPosition: process (Clk_25MHz, RESET)
begin
if RESET = '1' then
CurrentHPos <= (others => '0');
CurrentVPos <= (others => '0');
elsif rising_edge(CLK_25MHz) then
if CurrentHPos < HLimit-1 then
CurrentHPos <= CurrentHPos + 1;
else
if CurrentVPos < VLimit-1 then
CurrentVPos <= CurrentVPos + 1;
else
CurrentVPos <= (others => '0'); -- reset Vertical Position
end if;
CurrentHPos <= (others => '0'); -- reset Horizontal Position
end if;
end if;
end process VGAPosition;
-- Timing definition for HSync, VSync and Blank (http://tinyvga.com/vga-timing/640x480@60Hz)
HS <= '0' when CurrentHPos < HSyncWidth else
'1';
VS <= '0' when CurrentVPos < VSyncWidth else
'1';
HBlank <= '0' when (CurrentHPos >= HSyncWidth + HFrontPorch) and (CurrentHPos < HSyncWidth + HFrontPorch + HDisplayArea) else
'1';
VBlank <= '0' when (CurrentVPos >= VSyncWidth + VFrontPorch) and (CurrentVPos < VSyncWidth + VFrontPorch + VDisplayArea) else
'1';
Blank <= '1' when HBlank = '1' or VBlank = '1' else
'0';
ScanlineX <= CurrentHPos - HSyncWidth - HFrontPorch when Blank = '0' else
(others => '0');
ScanlineY <= CurrentVPos - VSyncWidth - VFrontPorch when Blank = '0' else
(others => '0');
RED <= ColorIN(11 downto 8) when Blank = '0' else "0000";
GREEN <= ColorIN(7 downto 4) when Blank = '0' else "0000";
BLUE <= ColorIN(3 downto 0) when Blank = '0' else "0000";
end Behavioral;