1 |
16 |
rudi |
--
|
2 |
|
|
-- file: vga.vhd
|
3 |
|
|
-- project: VGA/LCD controller
|
4 |
|
|
-- author: Richard Herveille
|
5 |
|
|
--
|
6 |
|
|
-- rev 1.0 May 10th, 2001
|
7 |
|
|
-- rev 1.1 June 3th, 2001. Changed WISHBONE addresses. Addresses are byte oriented, instead of databus-independent
|
8 |
|
|
-- rev 1.2 June 29th, 2001. Many hanges in design to reflect changes in fifo's. Design now correctly maps to Xilinx-BlockRAMs.
|
9 |
|
|
-- rev 1.3 July 15th, 2001. Added CLUT bank switching
|
10 |
|
|
|
11 |
|
|
library ieee;
|
12 |
|
|
use ieee.std_logic_1164.all;
|
13 |
|
|
use ieee.std_logic_arith.all;
|
14 |
|
|
|
15 |
|
|
entity VGA is
|
16 |
|
|
port (
|
17 |
|
|
CLK_I : in std_logic;
|
18 |
|
|
RST_I : in std_logic;
|
19 |
|
|
NRESET : in std_logic;
|
20 |
|
|
INTA_O : out std_logic;
|
21 |
|
|
|
22 |
|
|
-- slave signals
|
23 |
|
|
ADR_I : in unsigned(4 downto 2); -- only 32bit databus accesses supported
|
24 |
|
|
SDAT_I : in std_logic_vector(31 downto 0);
|
25 |
|
|
SDAT_O : out std_logic_vector(31 downto 0);
|
26 |
|
|
SEL_I : in std_logic_vector(3 downto 0);
|
27 |
|
|
WE_I : in std_logic;
|
28 |
|
|
STB_I : in std_logic;
|
29 |
|
|
CYC_I : in std_logic;
|
30 |
|
|
ACK_O : out std_logic;
|
31 |
|
|
ERR_O : out std_logic;
|
32 |
|
|
|
33 |
|
|
-- master signals
|
34 |
|
|
ADR_O : out unsigned(31 downto 2);
|
35 |
|
|
MDAT_I : in std_logic_vector(31 downto 0);
|
36 |
|
|
SEL_O : out std_logic_vector(3 downto 0);
|
37 |
|
|
WE_O : out std_logic;
|
38 |
|
|
STB_O : out std_logic;
|
39 |
|
|
CYC_O : out std_logic;
|
40 |
|
|
CAB_O : out std_logic;
|
41 |
|
|
ACK_I : in std_logic;
|
42 |
|
|
ERR_I : in std_logic;
|
43 |
|
|
|
44 |
|
|
-- VGA signals
|
45 |
|
|
PCLK : in std_logic; -- pixel clock
|
46 |
|
|
HSYNC : out std_logic; -- horizontal sync
|
47 |
|
|
VSYNC : out std_logic; -- vertical sync
|
48 |
|
|
CSYNC : out std_logic; -- composite sync
|
49 |
|
|
BLANK : out std_logic; -- blanking signal
|
50 |
|
|
R,G,B : out std_logic_vector(7 downto 0) -- RGB color signals
|
51 |
|
|
);
|
52 |
|
|
end entity vga;
|
53 |
|
|
|
54 |
|
|
architecture dataflow of vga is
|
55 |
|
|
--
|
56 |
|
|
-- components
|
57 |
|
|
--
|
58 |
|
|
|
59 |
|
|
-- dual clock-fifo. Change the dual-port memory section, depending on the target technology
|
60 |
|
|
component FIFO_DC is
|
61 |
|
|
generic(
|
62 |
|
|
DEPTH : natural := 128;
|
63 |
|
|
DWIDTH : natural := 32
|
64 |
|
|
);
|
65 |
|
|
port(
|
66 |
|
|
rclk : in std_logic; -- read clock input
|
67 |
|
|
wclk : in std_logic; -- write clock input
|
68 |
|
|
aclr : in std_logic := '1'; -- active low asynchronous clear
|
69 |
|
|
|
70 |
|
|
D : in std_logic_vector(DWIDTH -1 downto 0); -- Data input
|
71 |
|
|
wreq : in std_logic; -- write request
|
72 |
|
|
|
73 |
|
|
Q : out std_logic_vector(DWIDTH -1 downto 0); -- Data output
|
74 |
|
|
rreq : in std_logic; -- read request
|
75 |
|
|
|
76 |
|
|
rd_empty, -- FIFO is empty, synchronous to read clock
|
77 |
|
|
rd_full, -- FIFO is full, synchronous to read clock
|
78 |
|
|
wr_empty, -- FIFO is empty, synchronous to write clock
|
79 |
|
|
wr_full : out std_logic -- FIFO is full, synchronous to write clock
|
80 |
|
|
);
|
81 |
|
|
end component FIFO_DC;
|
82 |
|
|
|
83 |
|
|
-- WISHBONE slave block
|
84 |
|
|
component wb_slave is
|
85 |
|
|
port (
|
86 |
|
|
CLK_I : in std_logic;
|
87 |
|
|
RST_I : in std_logic;
|
88 |
|
|
NRESET : in std_logic;
|
89 |
|
|
ADR_I : in unsigned(4 downto 2);
|
90 |
|
|
DAT_I : in std_logic_vector(31 downto 0);
|
91 |
|
|
DAT_O : out std_logic_vector(31 downto 0);
|
92 |
|
|
SEL_I : in std_logic_vector(3 downto 0);
|
93 |
|
|
WE_I : in std_logic;
|
94 |
|
|
STB_I : in std_logic;
|
95 |
|
|
CYC_I : in std_logic;
|
96 |
|
|
ACK_O : out std_logic;
|
97 |
|
|
ERR_O : out std_logic;
|
98 |
|
|
INTA_O : out std_logic;
|
99 |
|
|
|
100 |
|
|
-- control register settings
|
101 |
|
|
BL : out std_logic; -- blanking level
|
102 |
|
|
CSL : out std_logic; -- composite sync level
|
103 |
|
|
VSL : out std_logic; -- vsync level
|
104 |
|
|
HSL : out std_logic; -- hsync level
|
105 |
|
|
PC : out std_logic; -- pseudo color
|
106 |
|
|
CD : out std_logic_vector(1 downto 0); -- color depth
|
107 |
|
|
VBL : out std_logic_vector(1 downto 0); -- burst length
|
108 |
|
|
CBSW : out std_logic; -- clut bank switching enable
|
109 |
|
|
VBSW : out std_logic; -- video page bank switching enable
|
110 |
|
|
Ven : out std_logic; -- video system enable
|
111 |
|
|
|
112 |
|
|
-- status register inputs
|
113 |
|
|
AVMP, -- active video memory page
|
114 |
|
|
ACMP : in std_logic; -- active clut page
|
115 |
|
|
bsint_in,
|
116 |
|
|
hint_in,
|
117 |
|
|
vint_in,
|
118 |
|
|
luint_in,
|
119 |
|
|
sint_in : in std_logic; -- interrupt request signals
|
120 |
|
|
|
121 |
|
|
-- Horizontal Timing Register
|
122 |
|
|
Thsync : out unsigned(7 downto 0);
|
123 |
|
|
Thgdel : out unsigned(7 downto 0);
|
124 |
|
|
Thgate : out unsigned(15 downto 0);
|
125 |
|
|
Thlen : out unsigned(15 downto 0);
|
126 |
|
|
|
127 |
|
|
-- Vertical Timing Register
|
128 |
|
|
Tvsync : out unsigned(7 downto 0);
|
129 |
|
|
Tvgdel : out unsigned(7 downto 0);
|
130 |
|
|
Tvgate : out unsigned(15 downto 0);
|
131 |
|
|
Tvlen : out unsigned(15 downto 0);
|
132 |
|
|
|
133 |
|
|
VBARa,
|
134 |
|
|
VBARb : buffer unsigned(31 downto 2);
|
135 |
|
|
CBAR : buffer unsigned(31 downto 11)
|
136 |
|
|
);
|
137 |
|
|
end component wb_slave;
|
138 |
|
|
|
139 |
|
|
-- WISHBONE master block
|
140 |
|
|
component wb_master is
|
141 |
|
|
port(
|
142 |
|
|
-- WISHBONE signals
|
143 |
|
|
CLK_I : in std_logic; -- master clock input
|
144 |
|
|
RST_I : in std_logic; -- synchronous active high reset
|
145 |
|
|
nRESET : in std_logic; -- asynchronous active low reset
|
146 |
|
|
CYC_O : out std_logic; -- cycle output
|
147 |
|
|
STB_O : out std_logic; -- strobe output
|
148 |
|
|
CAB_O : out std_logic; -- Consecutive Address Burst output
|
149 |
|
|
WE_O : out std_logic; -- write enable output
|
150 |
|
|
ADR_O : out unsigned(31 downto 2); -- address output
|
151 |
|
|
SEL_O : out std_logic_vector(3 downto 0); -- Byte Select outputs (only 32bit accesses are supported)
|
152 |
|
|
ACK_I : in std_logic; -- WISHBONE cycle acknowledge signal
|
153 |
|
|
ERR_I : in std_logic; -- oops, bus-error
|
154 |
|
|
DAT_I : in std_logic_vector(31 downto 0); -- WISHBONE data in
|
155 |
|
|
|
156 |
|
|
SINT : out std_logic; -- Non recoverable error, interrupt host
|
157 |
|
|
|
158 |
|
|
-- control register settings
|
159 |
|
|
ctrl_Ven : in std_logic; -- video enable bit
|
160 |
|
|
ctrl_cd : in std_logic_vector(1 downto 0); -- color depth
|
161 |
|
|
ctrl_pc : in std_logic; -- 8bpp pseudo color/bw
|
162 |
|
|
ctrl_vbl : in std_logic_vector(1 downto 0); -- burst length
|
163 |
|
|
ctrl_vbsw : in std_logic; -- enable video bank switching
|
164 |
|
|
ctrl_cbsw : in std_logic; -- enable clut bank switching
|
165 |
|
|
|
166 |
|
|
-- video memory addresses
|
167 |
|
|
VBAa, -- Video Memory Base Address-A
|
168 |
|
|
VBAb : in unsigned(31 downto 2); -- Video Memory Base Address-B
|
169 |
|
|
CBA : in unsigned(31 downto 11); -- CLUT Base Address Register
|
170 |
|
|
|
171 |
|
|
Thgate : unsigned(15 downto 0); -- horizontal visible area (in pixels)
|
172 |
|
|
Tvgate : unsigned(15 downto 0); -- vertical visible area (in horizontal lines)
|
173 |
|
|
|
174 |
|
|
stat_AVMP : out std_logic; -- active video memory page
|
175 |
|
|
stat_ACMP : out std_logic; -- active color lookup table
|
176 |
|
|
bs_req : out std_logic; -- bank-switch request: memory page switched (when enabled). bs_req is always generated
|
177 |
|
|
|
178 |
|
|
-- to/from line fifo
|
179 |
|
|
line_fifo_wreq : out std_logic;
|
180 |
|
|
line_fifo_d : out std_logic_vector(23 downto 0);
|
181 |
|
|
line_fifo_full : in std_logic
|
182 |
|
|
);
|
183 |
|
|
end component wb_master;
|
184 |
|
|
|
185 |
|
|
-- pixel generator. Generates video and pixel timing.
|
186 |
|
|
component Pgen is
|
187 |
|
|
port(
|
188 |
|
|
mclk : in std_logic; -- master clock
|
189 |
|
|
pclk : in std_logic; -- pixel clock
|
190 |
|
|
|
191 |
|
|
ctrl_Ven : in std_logic; -- VideoEnable signal
|
192 |
|
|
|
193 |
|
|
-- horizontal timing settings
|
194 |
|
|
ctrl_HSyncL : in std_logic; -- horizontal sync pulse polarization level (pos/neg)
|
195 |
|
|
Thsync : in unsigned(7 downto 0); -- horizontal sync pulse width (in pixels)
|
196 |
|
|
Thgdel : in unsigned(7 downto 0); -- horizontal gate delay (in pixels)
|
197 |
|
|
Thgate : in unsigned(15 downto 0); -- horizontal gate (number of visible pixels per line)
|
198 |
|
|
Thlen : in unsigned(15 downto 0); -- horizontal length (number of pixels per line)
|
199 |
|
|
|
200 |
|
|
-- vertical timing settings
|
201 |
|
|
ctrl_VSyncL : in std_logic; -- vertical sync pulse polarization level (pos/neg)
|
202 |
|
|
Tvsync : in unsigned(7 downto 0); -- vertical sync width (in lines)
|
203 |
|
|
Tvgdel : in unsigned(7 downto 0); -- vertical gate delay (in lines)
|
204 |
|
|
Tvgate : in unsigned(15 downto 0); -- vertical gate (visible number of lines in frame)
|
205 |
|
|
Tvlen : in unsigned(15 downto 0); -- vertical length (number of lines in frame)
|
206 |
|
|
|
207 |
|
|
ctrl_CSyncL : in std_logic; -- composite sync pulse polarization level
|
208 |
|
|
ctrl_BlankL : in std_logic; -- blank signal polarization level
|
209 |
|
|
|
210 |
|
|
-- status outputs
|
211 |
|
|
eoh, -- end of horizontal
|
212 |
|
|
eov, -- end of vertical
|
213 |
|
|
Gate : out std_logic; -- vertical AND horizontal gate (logical AND function)
|
214 |
|
|
|
215 |
|
|
-- pixel control outputs
|
216 |
|
|
Hsync, -- horizontal sync pulse
|
217 |
|
|
Vsync, -- vertical sync pulse
|
218 |
|
|
Csync, -- composite sync: Hsync OR Vsync (logical OR function)
|
219 |
|
|
Blank : out std_logic -- blank signals
|
220 |
|
|
);
|
221 |
|
|
end component Pgen;
|
222 |
|
|
|
223 |
|
|
--
|
224 |
|
|
-- signals
|
225 |
|
|
--
|
226 |
|
|
|
227 |
|
|
-- from wb_slave
|
228 |
|
|
signal ctrl_bl, ctrl_csl, ctrl_vsl, ctrl_hsl, ctrl_pc, ctrl_cbsw, ctrl_vbsw, ctrl_ven : std_logic;
|
229 |
|
|
signal ctrl_cd, ctrl_vbl : std_logic_vector(1 downto 0);
|
230 |
|
|
signal Thsync, Thgdel, Tvsync, Tvgdel : unsigned(7 downto 0);
|
231 |
|
|
signal Thgate, Thlen, Tvgate, Tvlen : unsigned(15 downto 0);
|
232 |
|
|
signal VBARa, VBARb : unsigned(31 downto 2);
|
233 |
|
|
signal CBAR : unsigned(31 downto 11);
|
234 |
|
|
|
235 |
|
|
-- to wb_slave
|
236 |
|
|
signal stat_avmp, stat_acmp, bsint, hint, vint, luint, sint : std_logic;
|
237 |
|
|
|
238 |
|
|
-- from wb_master
|
239 |
|
|
signal line_fifo_wreq : std_logic;
|
240 |
|
|
signal line_fifo_d : std_logic_vector(23 downto 0);
|
241 |
|
|
|
242 |
|
|
-- from pixel generator
|
243 |
|
|
signal cgate : std_logic; -- composite gate signal
|
244 |
|
|
signal ihsync, ivsync, icsync, iblank : std_logic; -- intermediate horizontal/vertical/composite sync, intermediate blank
|
245 |
|
|
-- signal dhsync, dvsync, dcsync, dblank : std_logic; -- delayed intermedates (needed for fifo synchronization)
|
246 |
|
|
|
247 |
|
|
-- from line fifo
|
248 |
|
|
signal line_fifo_full_wr, line_fifo_empty_rd : std_logic;
|
249 |
|
|
signal RGB : std_logic_vector(23 downto 0);
|
250 |
|
|
begin
|
251 |
|
|
|
252 |
|
|
-- hookup wishbone slave
|
253 |
|
|
u1: wb_slave port map (CLK_I => CLK_I, RST_I => RST_I, nRESET => nRESET, ADR_I => ADR_I, DAT_I => SDAT_I, DAT_O => SDAT_O,
|
254 |
|
|
SEL_I => SEL_I, WE_I => WE_I, STB_I => STB_I, CYC_I => CYC_I, ACK_O => ACK_O, ERR_O => ERR_O, INTA_O => INTA_O,
|
255 |
|
|
BL => ctrl_bl, csl => ctrl_csl, vsl => ctrl_vsl, hsl => ctrl_hsl, pc => ctrl_pc, cd => ctrl_cd, vbl => ctrl_vbl,
|
256 |
|
|
cbsw => ctrl_cbsw, vbsw => ctrl_vbsw, ven => ctrl_ven, acmp => stat_acmp, avmp => stat_avmp, bsint_in => bsint,
|
257 |
|
|
hint_in => hint, vint_in => vint, luint_in => luint, sint_in => sint, Thsync => Thsync, Thgdel => Thgdel,
|
258 |
|
|
Thgate => Thgate, Thlen => Thlen, Tvsync => Tvsync, Tvgdel => Tvgdel, Tvgate => Tvgate, Tvlen => Tvlen,
|
259 |
|
|
VBARa => VBARa, VBARb => VBARb, CBAR => CBAR);
|
260 |
|
|
|
261 |
|
|
-- hookup wishbone master
|
262 |
|
|
u2: wb_master port map (CLK_I => CLK_I, RST_I => RST_I, nReset => nReset, CYC_O => CYC_O, STB_O => STB_O, CAB_O => CAB_O, WE_O => WE_O,
|
263 |
|
|
ADR_O => ADR_O, SEL_O => SEL_O, ACK_I => ACK_I, ERR_I => ERR_I, DAT_I => MDAT_I, SINT => sint,
|
264 |
|
|
ctrl_Ven => ctrl_ven, ctrl_cd => ctrl_cd, ctrl_pc => ctrl_pc, ctrl_vbl => ctrl_vbl, ctrl_cbsw => ctrl_cbsw, ctrl_vbsw => ctrl_vbsw,
|
265 |
|
|
VBAa => VBARa, VBAb => VBARb, CBA => CBAR, Thgate => Thgate, Tvgate => Tvgate, stat_acmp => stat_acmp, stat_AVMP => stat_avmp,
|
266 |
|
|
bs_req => bsint, line_fifo_wreq => line_fifo_wreq, line_fifo_d => line_fifo_d, line_fifo_full => line_fifo_full_wr);
|
267 |
|
|
|
268 |
|
|
-- hookup pixel and video timing generator
|
269 |
|
|
u3: pgen port map (mclk => CLK_I, pclk => pclk, ctrl_Ven => ctrl_ven,
|
270 |
|
|
ctrl_HSyncL => ctrl_hsl, Thsync => Thsync, Thgdel => Thgdel, Thgate => Thgate, Thlen => Thlen, ctrl_VSyncL => ctrl_vsl,
|
271 |
|
|
Tvsync => Tvsync, Tvgdel => Tvgdel, Tvgate => Tvgate, Tvlen => Tvlen, ctrl_CSyncL => ctrl_csl, ctrl_BlankL => ctrl_bl,
|
272 |
|
|
eoh => hint, eov => vint, gate => cgate, Hsync => ihsync, Vsync => ivsync, Csync => icsync, Blank => iblank);
|
273 |
|
|
|
274 |
|
|
-- delay video control signals 1 clock cycle (dual clock fifo synchronizes output)
|
275 |
|
|
del_video_sigs: process(pclk)
|
276 |
|
|
begin
|
277 |
|
|
if (pclk'event and pclk = '1') then
|
278 |
|
|
HSYNC <= ihsync;
|
279 |
|
|
VSYNC <= ivsync;
|
280 |
|
|
CSYNC <= icsync;
|
281 |
|
|
BLANK <= iblank;
|
282 |
|
|
end if;
|
283 |
|
|
end process del_video_sigs;
|
284 |
|
|
|
285 |
|
|
-- hookup line-fifo
|
286 |
|
|
u4: FIFO_DC generic map (DEPTH => 256, DWIDTH => 24)
|
287 |
|
|
port map (rclk => pclk, wclk => CLK_I, aclr => ctrl_Ven, D => line_fifo_d, wreq => line_fifo_wreq,
|
288 |
|
|
q => RGB, rreq => cgate, rd_empty => line_fifo_empty_rd, wr_full => line_fifo_full_wr);
|
289 |
|
|
R <= RGB(23 downto 16);
|
290 |
|
|
G <= RGB(15 downto 8);
|
291 |
|
|
B <= RGB(7 downto 0);
|
292 |
|
|
|
293 |
|
|
-- generate interrupt signal when reading line-fifo while it is empty (line-fifo under-run interrupt)
|
294 |
|
|
luint_blk: block
|
295 |
|
|
signal luint_pclk, sluint : std_logic;
|
296 |
|
|
begin
|
297 |
|
|
gen_luint_pclk: process(pclk)
|
298 |
|
|
begin
|
299 |
|
|
if (pclk'event and pclk = '1') then
|
300 |
|
|
luint_pclk <= cgate and line_fifo_empty_rd;
|
301 |
|
|
end if;
|
302 |
|
|
end process gen_luint_pclk;
|
303 |
|
|
|
304 |
|
|
process(CLK_I)
|
305 |
|
|
begin
|
306 |
|
|
if(CLK_I'event and CLK_I = '1') then
|
307 |
|
|
sluint <= luint_pclk; -- resample at CLK_I clock
|
308 |
|
|
luint <= sluint; -- sample again, reduce metastability risk
|
309 |
|
|
end if;
|
310 |
|
|
end process;
|
311 |
|
|
end block luint_blk;
|
312 |
|
|
|
313 |
|
|
end architecture dataflow;
|
314 |
|
|
|
315 |
|
|
|
316 |
|
|
|
317 |
|
|
|
318 |
|
|
|
319 |
|
|
|