-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathVGA_Controller_256Pallette.vhd
205 lines (161 loc) · 6.9 KB
/
VGA_Controller_256Pallette.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY VGA_Controller_256Pallette IS
PORT (
Clock, Reset : IN STD_LOGIC;
Red,Green,Blue : IN STD_LOGIC_VECTOR(7 downto 0);
-- scroll offsets
VScrollOffset : IN STD_LOGIC_VECTOR(9 downto 0);
HScrollOffset : IN STD_LOGIC_VECTOR(9 downto 0);
H_Sync_out,
V_Sync_out,
VideoBlanking_L : OUT STD_LOGIC;
Red_out,
Green_out,
Blue_out : OUT STD_LOGIC_VECTOR(7 downto 0);
Column_out,
Row_out : OUT STD_LOGIC_VECTOR(9 DOWNTO 0)
);
END;
ARCHITECTURE FSM OF VGA_Controller_256Pallette IS
-- Timings - USE THESE (BCDE/PQRS) for 640x480 @60HZ
-- CONSTANT H_RES: integer:= 640;
-- CONSTANT V_RES: integer:= 480;
-- Horizontal timings
--CONSTANT B: INTEGER := 95; -- sync pulse has to be 3.77us approx or 95*0.04us = 3.8us
--CONSTANT C: INTEGER := 45; -- sync has to return high for 1.79us before video = 45*0.04us = 1.8us
--CONSTANT D: INTEGER := H_RES; -- 800 pixel columns per row; count starts from 0
--CONSTANT E: INTEGER := 20; -- front porch = 0.79uS or
-- Vertical timings
--CONSTANT P: INTEGER := 2; -- vertical sync pulse = at least 64uS so at least 2 horizontal periods = 76.8us
--CONSTANT Q: INTEGER := 27; -- back porch = 102uS (min) so 27 lines of 38.4 uS = at least 26.56 so round up to 27
--CONSTANT R: INTEGER := V_RES ; -- 480 pixel rows per screen; count starts from 0
--CONSTANT S: INTEGER := 12; -- front porch = 450uS (min) so this is at lest 11.8 line periods of 38.4 uS rounded up to 12
-- Timings - USE THESE (BCDE/PQRS)for 800x480 @50HZ
CONSTANT H_RES: integer:= 800;
CONSTANT V_RES: integer:= 480;
-- Horizontal timings
CONSTANT B: INTEGER := 72; -- sync pulse has to be 3.77us approx or 95*0.04us = 3.8us
CONSTANT C: INTEGER := 90; -- back porch has to return high for 1.79us before video = 45*0.04us = 1.8us
CONSTANT D: INTEGER := H_RES; -- 800 pixel columns per row; count starts from 0
CONSTANT E: INTEGER := 24; -- front porch = 0.79uS or
-- total horizontal period = 992 clock periods at 25Mhz = 38.4uS
CONSTANT P: INTEGER := 7; -- vertical sync pulse
CONSTANT Q: INTEGER := 12; -- back porch = 102uS (min) so 27 lines of 38.4 uS = at least 26.56 so round up to 27
CONSTANT R: INTEGER := V_RES ; -- 480 pixel rows per screen; count starts from 0
CONSTANT S: INTEGER := 5; -- front porch = 450uS (min) so this is at lest 11.8 line periods of 38.4 uS rounded up to 12
-- Universal Timings - Use these regardless of resolution / refresh rate
CONSTANT H_TOTAL: INTEGER := (B+C+D+E-2) ;
CONSTANT H_RESPLUS: INTEGER := (H_RES+2) ;
CONSTANT V_TOTAL: INTEGER := (P+Q+R+S-2) ;
CONSTANT V_RESPLUS: INTEGER := (V_RES+2) ;
SIGNAL HCount, VCount : STD_LOGIC_VECTOR(9 DOWNTO 0) ; -- horizontal and vertical counters
SIGNAL Column_out_sig : STD_LOGIC_VECTOR(9 DOWNTO 0) ; -- horizontal counter to include offset
SIGNAL Row_out_sig : STD_LOGIC_VECTOR(9 DOWNTO 0) ; -- horizontal counter to include offset
SIGNAL V_Clock : STD_LOGIC ; -- clock for vertical counter
SIGNAL Blank_L : STD_LOGIC ; -- video DAC Blanking (NOT USED YET)
SIGNAL H_Data_on, V_Data_on : STD_LOGIC ;
BEGIN
PROCESS(Clock, Reset, HScrollOffset) -- Horizontal_Counter: columns
BEGIN
IF (Reset = '0') THEN
HCount <= (OTHERS => '0');
Column_out_sig <= HScrollOffset;
H_Data_on <= '0';
H_Sync_out <= '1';
ELSIF (rising_edge(Clock)) THEN
Column_out_sig <= Column_out_sig + 1 ;
HCount <= HCount + 1;
V_Clock <= '0';
-- Horizontal counter
IF (HCount = B+C+D+E) THEN
HCount <= (OTHERS => '0');
Column_out_sig <= HScrollOffset ;
V_Clock <= '1'; -- generate clock for vertical counter
END IF;
-- generate H_Sync_out
IF (HCount = D+E+B) THEN
H_Sync_out <= '1';
ELSIF (HCount = D+E) THEN
H_Sync_out <= '0';
END IF;
-- generate H_Data_on
IF (HCount = D+E+B+C) THEN
H_Data_on <= '1';
ELSIF (HCount = D) THEN
H_Data_on <= '0';
END IF;
END IF;
END PROCESS;
PROCESS(V_Clock, reset, VScrollOffset) --Vertical_Counter: rows
BEGIN
IF (Reset = '0') THEN
VCount <= (OTHERS => '0');
Row_out_sig <= VScrollOffset;
V_Data_on <= '0';
V_Sync_out <= '1';
ELSIF (V_Clock'EVENT AND V_Clock = '1') THEN
-- Vertical counter
Row_out_sig <= Row_out_sig + 1 ;
VCount <= VCount + 1;
IF (VCount = R+S+P+Q) THEN
VCount <= (OTHERS => '0');
Row_out_sig <= VScrollOffset ;
END IF;
-- generate V_Sync_out
IF (VCount = R+S+P) THEN
V_Sync_out <= '1';
ELSIF (VCount = R+S) THEN
V_Sync_out <= '0';
END IF;
-- generate V_Data_on
IF (VCount = R+S+P+Q) THEN
V_Data_on <= '1';
ELSIF (VCount = R) THEN
V_Data_on <= '0';
END IF;
END IF;
END PROCESS;
-- Asserting blank low, is a signal to graphics chip saying no video is being display so it safe
-- to draw to the screen. We could use it to control the video DAC on the DE2, but setting colour outputs to zero
-- has same effect.
PROCESS(clock)
BEGIN
if(rising_edge(clock)) then
IF(((HCount > H_RESPLUS) AND (HCount < (H_TOTAL))) OR ((VCount > V_RESPLUS) AND (VCount < V_TOTAL))) THEN
Blank_L <= '0';
ELSE
Blank_L <= '1';
END IF;
end if;
END PROCESS;
Red_out(7) <= H_data_on AND V_data_on AND Red(7);
Red_out(6) <= H_data_on AND V_data_on AND Red(6);
Red_out(5) <= H_data_on AND V_data_on AND Red(5);
Red_out(4) <= H_data_on AND V_data_on AND Red(4);
Red_out(3) <= H_data_on AND V_data_on AND Red(3);
Red_out(2) <= H_data_on AND V_data_on AND Red(2);
Red_out(1) <= H_data_on AND V_data_on AND Red(1);
Red_out(0) <= H_data_on AND V_data_on AND Red(0);
Green_out(7) <= H_data_on AND V_data_on AND Green(7);
Green_out(6) <= H_data_on AND V_data_on AND Green(6);
Green_out(5) <= H_data_on AND V_data_on AND Green(5);
Green_out(4) <= H_data_on AND V_data_on AND Green(4);
Green_out(3) <= H_data_on AND V_data_on AND Green(3);
Green_out(2) <= H_data_on AND V_data_on AND Green(2);
Green_out(1) <= H_data_on AND V_data_on AND Green(1);
Green_out(0) <= H_data_on AND V_data_on AND Green(0);
Blue_out(7) <= H_data_on AND V_data_on AND Blue(7);
Blue_out(6) <= H_data_on AND V_data_on AND Blue(6);
Blue_out(5) <= H_data_on AND V_data_on AND Blue(5);
Blue_out(4) <= H_data_on AND V_data_on AND Blue(4);
Blue_out(3) <= H_data_on AND V_data_on AND Blue(3);
Blue_out(2) <= H_data_on AND V_data_on AND Blue(2);
Blue_out(1) <= H_data_on AND V_data_on AND Blue(1);
Blue_out(0) <= H_data_on AND V_data_on AND Blue(0);
-- generate column,row signals
Column_out <= Column_out_sig ; -- WHEN (H_Data_on = '1' AND V_Data_on = '1');
Row_out <= Row_out_sig ; -- WHEN (H_Data_on = '1' AND V_Data_on = '1');
VideoBlanking_L <= Blank_L ; -- low when video is turned off, can be used to allow the graphics chip to draw without iterferring with display
END FSM;