1 |
9 |
zuofu |
library IEEE, unisim;
|
2 |
|
|
use IEEE.std_logic_1164.all;
|
3 |
|
|
use IEEE.numeric_std.all;
|
4 |
|
|
use unisim.vcomponents.all;
|
5 |
|
|
use work.common.all;
|
6 |
|
|
|
7 |
|
|
package vga_pckg is
|
8 |
|
|
component vga
|
9 |
|
|
generic (
|
10 |
|
|
FREQ : natural := 50_000; -- master clock frequency (in KHz)
|
11 |
|
|
CLK_DIV : natural := 1; -- FREQ / CLK_DIV = pixel clock
|
12 |
|
|
PIXEL_WIDTH : natural := 8; -- pixel width: 1, 2, 4, 8, or 16 bits
|
13 |
|
|
PIXELS_PER_LINE : natural := 800; -- pixels per video scan line
|
14 |
|
|
LINES_PER_FRAME : natural := 600; -- scan lines per video frame
|
15 |
|
|
NUM_RGB_BITS : natural := 2; -- width of R, G and B color output buses (2 or 3 are only valid values)
|
16 |
|
|
FIT_TO_SCREEN : boolean := true -- fit width x length to monitor screen
|
17 |
|
|
);
|
18 |
|
|
port (
|
19 |
|
|
rst : in std_logic; -- reset
|
20 |
|
|
clk : in std_logic; -- master clock
|
21 |
|
|
wr : in std_logic; -- write-enable for pixel buffer
|
22 |
|
|
pixel_data_in : in std_logic_vector(15 downto 0); -- input databus to pixel buffer
|
23 |
|
|
full : out std_logic; -- pixel buffer full
|
24 |
|
|
eof : out std_logic; -- end of vga frame
|
25 |
|
|
r, g, b : out std_logic_vector(NUM_RGB_BITS-1 downto 0); -- R,G,B color output buses
|
26 |
|
|
hsync_n : out std_logic; -- horizontal sync pulse
|
27 |
|
|
vsync_n : out std_logic; -- vertical sync pulse
|
28 |
|
|
blank : out std_logic -- blanking signal
|
29 |
|
|
);
|
30 |
|
|
end component vga;
|
31 |
|
|
end package vga_pckg;
|
32 |
|
|
|
33 |
|
|
|
34 |
20 |
esands |
library ieee, unisim;
|
35 |
|
|
use ieee.std_logic_1164.all;
|
36 |
|
|
use ieee.std_logic_unsigned.all;
|
37 |
|
|
use unisim.vcomponents.all;
|
38 |
9 |
zuofu |
|
39 |
20 |
esands |
|
40 |
|
|
package fifo_cc_pckg is
|
41 |
|
|
component fifo_cc is
|
42 |
|
|
port (
|
43 |
|
|
clk : in std_logic;
|
44 |
|
|
rst : in std_logic;
|
45 |
|
|
rd : in std_logic;
|
46 |
|
|
wr : in std_logic;
|
47 |
|
|
data_in : in std_logic_vector(15 downto 0);
|
48 |
|
|
data_out : out std_logic_vector(15 downto 0);
|
49 |
|
|
full : out std_logic;
|
50 |
|
|
empty : out std_logic;
|
51 |
|
|
level : out std_logic_vector(7 downto 0)
|
52 |
|
|
);
|
53 |
|
|
end component fifo_cc;
|
54 |
|
|
end package fifo_cc_pckg;
|
55 |
|
|
|
56 |
|
|
|
57 |
9 |
zuofu |
library IEEE, unisim;
|
58 |
|
|
use IEEE.std_logic_1164.all;
|
59 |
|
|
use IEEE.numeric_std.all;
|
60 |
|
|
use unisim.vcomponents.all;
|
61 |
|
|
use work.common.all;
|
62 |
|
|
|
63 |
|
|
entity vga is
|
64 |
|
|
generic (
|
65 |
|
|
FREQ : natural := 50_000; -- master clock frequency (in KHz)
|
66 |
|
|
CLK_DIV : natural := 1; -- FREQ / CLK_DIV = pixel clock
|
67 |
20 |
esands |
PIXEL_WIDTH : natural := 8; -- pixel width: 1, 2, 4, 8, or 16 bits
|
68 |
|
|
PIXELS_PER_LINE : natural := 320; -- pixels per video scan line
|
69 |
|
|
LINES_PER_FRAME : natural := 200; -- scan lines per video frame
|
70 |
9 |
zuofu |
NUM_RGB_BITS : natural := 2; -- width of R, G and B color output buses
|
71 |
|
|
FIT_TO_SCREEN : boolean := true -- fit width x length to monitor screen
|
72 |
|
|
);
|
73 |
|
|
port (
|
74 |
|
|
rst : in std_logic; -- reset
|
75 |
|
|
clk : in std_logic; -- master clock
|
76 |
|
|
wr : in std_logic; -- write-enable for pixel buffer
|
77 |
|
|
pixel_data_in : in std_logic_vector(15 downto 0); -- input databus to pixel buffer
|
78 |
|
|
full : out std_logic; -- pixel buffer full
|
79 |
|
|
eof : out std_logic; -- end of vga frame
|
80 |
|
|
r, g, b : out std_logic_vector(NUM_RGB_BITS-1 downto 0); -- R,G,B color output buses
|
81 |
|
|
hsync_n : out std_logic; -- horizontal sync pulse
|
82 |
|
|
vsync_n : out std_logic; -- vertical sync pulse
|
83 |
|
|
blank : out std_logic -- blanking signal
|
84 |
|
|
);
|
85 |
|
|
end entity vga;
|
86 |
|
|
|
87 |
|
|
|
88 |
|
|
architecture vga_arch of vga is
|
89 |
|
|
constant NORM : natural := 1000; -- normalization factor for us * KHz
|
90 |
|
|
|
91 |
|
|
-- video timing parameters for FIT_TO_SCREEN mode
|
92 |
|
|
constant HSYNC_START_F : natural := (NORM * PIXELS_PER_LINE * CLK_DIV)/FREQ + 1; -- start of horiz. sync pulse with a scanline (us)
|
93 |
|
|
constant HSYNC_PERIOD_F : natural := HSYNC_START_F + 6; -- horizontal scanline period (us)
|
94 |
|
|
constant HSYNC_WIDTH_F : natural := 4; -- width of horiz. sync pulse (us)
|
95 |
|
|
constant HSYNC_FREQ_F : natural := NORM / HSYNC_PERIOD_F; -- scanline frequency (KHz)
|
96 |
|
|
constant VSYNC_START_F : natural := HSYNC_PERIOD_F * LINES_PER_FRAME + 340; -- start of vert. sync pulse within a frame (us)
|
97 |
|
|
constant VSYNC_PERIOD_F : natural := VSYNC_START_F + 1084; -- video frame period (us)
|
98 |
|
|
constant VSYNC_WIDTH_F : natural := 64; -- width of vert. sync pulse (us)
|
99 |
|
|
|
100 |
|
|
-- video timing for 31 KHz horizontal, 60 Hz vertical screen refresh
|
101 |
|
|
constant HSYNC_START : natural := 26; -- start of horiz. sync pulse with a scanline (us)
|
102 |
|
|
constant HSYNC_PERIOD : natural := 32; -- horizontal scanline period (us)
|
103 |
|
|
constant HSYNC_WIDTH : natural := 4; -- width of horiz. sync pulse (us)
|
104 |
|
|
constant HSYNC_FREQ : natural := NORM / HSYNC_PERIOD; -- scanline frequency (KHz)
|
105 |
|
|
constant VSYNC_START : natural := 15_700; -- start of vert. sync pulse within a frame (us)
|
106 |
|
|
constant VSYNC_PERIOD : natural := 16_784; -- video frame period (us)
|
107 |
|
|
constant VSYNC_WIDTH : natural := 64; -- width of vert. sync pulse (us)
|
108 |
|
|
|
109 |
|
|
signal clk_div_cnt : unsigned(7 downto 0);
|
110 |
|
|
signal cke : std_logic;
|
111 |
|
|
signal line_cnt, pixel_cnt : unsigned(15 downto 0); -- current video line and pixel within line
|
112 |
|
|
signal fifo_rst : std_logic;
|
113 |
|
|
signal fifo_level : std_logic_vector(7 downto 0);
|
114 |
|
|
signal eof_i, eof_x, eof_r : std_logic;
|
115 |
|
|
signal v_gate, cke_v_gate : std_logic;
|
116 |
|
|
signal h_blank, v_blank, visible : std_logic;
|
117 |
|
|
constant PIX_PROC_DELAY : natural := 3; -- time delay to read a pixel from the FIFO and colormap it
|
118 |
|
|
signal hsync_x, hsync_r : std_logic_vector(PIX_PROC_DELAY downto 1);
|
119 |
|
|
signal blank_x, blank_r : std_logic_vector(PIX_PROC_DELAY downto 1);
|
120 |
|
|
signal cke_rd, rd_x, rd_r : std_logic;
|
121 |
|
|
signal pixel : std_logic_vector(PIXEL_WIDTH-1 downto 0);
|
122 |
|
|
signal pixel_data_x, pixel_data_r : std_logic_vector(15 downto 0);
|
123 |
|
|
signal pixel_data_out : std_logic_vector(15 downto 0);
|
124 |
|
|
signal rgb_x, rgb_r : std_logic_vector(3*NUM_RGB_BITS-1 downto 0);
|
125 |
|
|
component fifo_cc
|
126 |
|
|
port (
|
127 |
|
|
clk : in std_logic;
|
128 |
|
|
rst : in std_logic;
|
129 |
|
|
rd : in std_logic;
|
130 |
|
|
wr : in std_logic;
|
131 |
|
|
data_in : in std_logic_vector(15 downto 0);
|
132 |
|
|
data_out : out std_logic_vector(15 downto 0);
|
133 |
|
|
full : out std_logic;
|
134 |
|
|
empty : out std_logic;
|
135 |
|
|
level : out std_logic_vector(7 downto 0)
|
136 |
|
|
);
|
137 |
|
|
end component fifo_cc;
|
138 |
|
|
component sync
|
139 |
|
|
generic (
|
140 |
|
|
FREQ : natural := 50_000; -- master clock frequency (in KHz)
|
141 |
|
|
PERIOD : natural := 32; -- period of sync pulse (in us)
|
142 |
|
|
START : natural := 26; -- time sync pulse starts within the period (in us)
|
143 |
|
|
WIDTH : natural := 4; -- width of sync pulse (in us)
|
144 |
|
|
VISIBLE : natural := 1024 -- number of visible pixels/line or lines/frame
|
145 |
|
|
);
|
146 |
|
|
port (
|
147 |
|
|
rst : in std_logic; -- reset
|
148 |
|
|
clk : in std_logic; -- master clock
|
149 |
|
|
cke : in std_logic; -- clock-enable
|
150 |
|
|
sync_n : out std_logic; -- sync pulse
|
151 |
|
|
gate : out std_logic; -- single-clock pulse at start of sync pulse
|
152 |
|
|
blank : out std_logic; -- blanking signal
|
153 |
|
|
cnt : out unsigned(15 downto 0) -- output the timing counter value
|
154 |
|
|
);
|
155 |
|
|
end component sync;
|
156 |
|
|
|
157 |
|
|
begin
|
158 |
|
|
|
159 |
|
|
-- clock divider for reducing the pixel clock rate
|
160 |
|
|
process(clk, rst)
|
161 |
|
|
begin
|
162 |
|
|
if rst = YES then
|
163 |
|
|
clk_div_cnt <= (others => '0');
|
164 |
|
|
cke <= YES;
|
165 |
|
|
elsif rising_edge(clk) then
|
166 |
|
|
if clk_div_cnt = CLK_DIV-1 then
|
167 |
|
|
clk_div_cnt <= (others => '0');
|
168 |
|
|
cke <= YES;
|
169 |
|
|
else
|
170 |
|
|
clk_div_cnt <= clk_div_cnt + 1;
|
171 |
|
|
cke <= NO;
|
172 |
|
|
end if;
|
173 |
|
|
end if;
|
174 |
|
|
end process;
|
175 |
|
|
|
176 |
|
|
-- pixel data buffer
|
177 |
|
|
cke_rd <= rd_x and cke;
|
178 |
|
|
fifo : fifo_cc
|
179 |
|
|
port map (
|
180 |
|
|
clk => clk,
|
181 |
|
|
rd => cke_rd,
|
182 |
|
|
wr => wr,
|
183 |
|
|
data_in => pixel_data_in,
|
184 |
|
|
rst => fifo_rst,
|
185 |
|
|
data_out => pixel_data_out,
|
186 |
|
|
full => open,
|
187 |
|
|
empty => open,
|
188 |
|
|
level => fifo_level
|
189 |
|
|
);
|
190 |
|
|
full <= YES when fifo_level(7 downto 3) = "11111" else NO;
|
191 |
|
|
|
192 |
|
|
-- the clock enable for the vertical sync module is also combined with a gate signal
|
193 |
|
|
-- that is generated at the end of every scanline by the horizontal sync module
|
194 |
|
|
cke_v_gate <= cke and v_gate;
|
195 |
|
|
|
196 |
|
|
-- generate the horizontal and vertical sync pulses for FIT_TO_SCREEN mode
|
197 |
|
|
gen_syncs_fit : if FIT_TO_SCREEN = true generate
|
198 |
|
|
hsync : sync
|
199 |
|
|
generic map (
|
200 |
|
|
FREQ => FREQ / CLK_DIV, -- master pixel-clock frequency
|
201 |
|
|
PERIOD => HSYNC_PERIOD_F, -- scanline period (32 us)
|
202 |
|
|
START => HSYNC_START_F, -- start of horizontal sync pulse in scan line
|
203 |
|
|
WIDTH => HSYNC_WIDTH_F, -- width of horizontal sync pulse
|
204 |
|
|
VISIBLE => PIXELS_PER_LINE
|
205 |
|
|
)
|
206 |
|
|
port map (
|
207 |
|
|
rst => rst,
|
208 |
|
|
clk => clk, -- master clock
|
209 |
|
|
cke => cke, -- a new pixel is output whenever the clock is enabled
|
210 |
|
|
sync_n => hsync_x(1), -- send pulse through delay line
|
211 |
|
|
gate => v_gate, -- send gate signal to increment vertical sync pulse generator once per scan line
|
212 |
|
|
blank => h_blank, -- blanking signal within a scan line
|
213 |
|
|
cnt => pixel_cnt -- current pixel within the scan line
|
214 |
|
|
);
|
215 |
|
|
|
216 |
|
|
vsync : sync
|
217 |
|
|
generic map (
|
218 |
|
|
FREQ => HSYNC_FREQ_F, -- scanline frequency
|
219 |
|
|
PERIOD => VSYNC_PERIOD_F, -- image frame period
|
220 |
|
|
START => VSYNC_START_F, -- start of vertical sync pulse in frame
|
221 |
|
|
WIDTH => VSYNC_WIDTH_F, -- width of vertical sync pulse
|
222 |
|
|
VISIBLE => LINES_PER_FRAME
|
223 |
|
|
)
|
224 |
|
|
port map (
|
225 |
|
|
rst => rst,
|
226 |
|
|
clk => clk, -- master clock
|
227 |
|
|
cke => cke_v_gate, -- enable clock once per horizontal scan line
|
228 |
|
|
sync_n => vsync_n, -- send pulse through delay line
|
229 |
|
|
gate => eof_x, -- indicate the end of a complete frame
|
230 |
|
|
blank => v_blank, -- blanking signal within a frame
|
231 |
|
|
cnt => line_cnt -- current scan line within a frame
|
232 |
|
|
);
|
233 |
|
|
end generate;
|
234 |
|
|
|
235 |
|
|
-- generate the horizontal and vertical sync pulses for 31 KHz horizontal, 60 Hz vertical screen refresh
|
236 |
|
|
gen_syncs_nofit : if FIT_TO_SCREEN = false generate
|
237 |
|
|
hsync : sync
|
238 |
|
|
generic map (
|
239 |
|
|
FREQ => FREQ / CLK_DIV, -- master pixel-clock frequency
|
240 |
|
|
PERIOD => HSYNC_PERIOD, -- scanline period (32 us)
|
241 |
|
|
START => HSYNC_START, -- start of horizontal sync pulse in scan line
|
242 |
|
|
WIDTH => HSYNC_WIDTH, -- width of horizontal sync pulse
|
243 |
|
|
VISIBLE => PIXELS_PER_LINE
|
244 |
|
|
)
|
245 |
|
|
port map (
|
246 |
|
|
rst => rst,
|
247 |
|
|
clk => clk, -- master clock
|
248 |
|
|
cke => cke, -- clock always enabled so there is a new pixel output on every clock pulse
|
249 |
|
|
sync_n => hsync_x(1), -- send pulse through delay line
|
250 |
|
|
gate => v_gate, -- send gate signal to increment vertical sync pulse generator once per scan line
|
251 |
|
|
blank => h_blank, -- blanking signal within a scan line
|
252 |
|
|
cnt => pixel_cnt -- current pixel within the scan line
|
253 |
|
|
);
|
254 |
|
|
|
255 |
|
|
vsync : sync
|
256 |
|
|
generic map (
|
257 |
|
|
FREQ => HSYNC_FREQ, -- scanline frequency (KHz)
|
258 |
|
|
PERIOD => VSYNC_PERIOD, -- image frame period
|
259 |
|
|
START => VSYNC_START, -- start of vertical sync pulse in frame
|
260 |
|
|
WIDTH => VSYNC_WIDTH, -- width of vertical sync pulse
|
261 |
|
|
VISIBLE => LINES_PER_FRAME
|
262 |
|
|
)
|
263 |
|
|
port map (
|
264 |
|
|
rst => rst,
|
265 |
|
|
clk => clk, -- master clock
|
266 |
|
|
cke => cke_v_gate, -- enable clock once per horizontal scan line
|
267 |
|
|
sync_n => vsync_n, -- send pulse through delay line
|
268 |
|
|
gate => eof_x, -- indicate the end of a complete frame
|
269 |
|
|
blank => v_blank, -- blanking signal within a frame
|
270 |
|
|
cnt => line_cnt -- current scan line within a frame
|
271 |
|
|
);
|
272 |
|
|
end generate;
|
273 |
|
|
|
274 |
|
|
eof_i <= eof_x and not eof_r; -- shorten end-of-frame signal to a single clock cycle
|
275 |
|
|
eof <= eof_i;
|
276 |
|
|
fifo_rst <= eof_i or rst; -- clear the contents of the pixel buffer at the end of every frame
|
277 |
|
|
|
278 |
|
|
visible <= h_blank nor v_blank; -- pixels are visible when horiz. & vertical blank are inactive
|
279 |
|
|
blank_x(1) <= not visible; -- send blanking signal through delay line
|
280 |
|
|
|
281 |
|
|
-- pass the horiz. and vert. syncs and blanking signal through delay lines to compensate for the
|
282 |
|
|
-- processing delays incurred by the pixel data
|
283 |
|
|
hsync_x(hsync_x'high downto 2) <= hsync_r(hsync_r'high-1 downto 1);
|
284 |
|
|
hsync_n <= hsync_r(hsync_r'high);
|
285 |
|
|
blank_x(blank_x'high downto 2) <= blank_r(blank_r'high-1 downto 1);
|
286 |
|
|
blank <= blank_r(blank_r'high);
|
287 |
|
|
|
288 |
|
|
-- get the current pixel from the word of pixel data or read more pixel data from the buffer
|
289 |
|
|
get_pixel : process(visible, pixel_data_out, pixel_data_r, rd_r, pixel_cnt)
|
290 |
|
|
begin
|
291 |
|
|
rd_x <= NO; -- by default, don't read next word of pixel data from the buffer
|
292 |
|
|
|
293 |
|
|
-- shift pixel data depending on its width so the next pixel is in the LSBs of the pixel data shift register
|
294 |
|
|
case PIXEL_WIDTH is
|
295 |
|
|
when 1 => -- 1-bit pixels, 16 per pixel data word
|
296 |
|
|
if (visible = YES) and (pixel_cnt(3 downto 0) = 0) then
|
297 |
|
|
rd_x <= YES; -- read new pixel data from buffer every 16 clocks during visible portion of scan line
|
298 |
|
|
end if;
|
299 |
|
|
pixel_data_x <= "0" & pixel_data_r(15 downto 1); -- left-shift pixel data to move next pixel to LSB
|
300 |
|
|
when 2 => -- 2-bit pixels, 8 per pixel data word
|
301 |
|
|
if (visible = YES) and (pixel_cnt(2 downto 0) = 0) then
|
302 |
|
|
rd_x <= YES; -- read new pixel data from buffer every 8 clocks during visible portion of scan line
|
303 |
|
|
end if;
|
304 |
|
|
pixel_data_x <= "00" & pixel_data_r(15 downto 2); -- left-shift pixel data to move next pixel to LSB
|
305 |
|
|
when 4 => -- 4-bit pixels, 4 per pixel data word
|
306 |
|
|
if (visible = YES) and (pixel_cnt(1 downto 0) = 0) then
|
307 |
|
|
rd_x <= YES; -- read new pixel data from buffer every 4 clocks during visible portion of scan line
|
308 |
|
|
end if;
|
309 |
|
|
pixel_data_x <= "0000" & pixel_data_r(15 downto 4); -- left-shift pixel data to move next pixel to LSB
|
310 |
|
|
when 8 => -- 8-bit pixels, 2 per pixel data word
|
311 |
|
|
if (visible = YES) and (pixel_cnt(0 downto 0) = 0) then
|
312 |
|
|
rd_x <= YES; -- read new pixel data from buffer every 2 clocks during visible portion of scan line
|
313 |
|
|
end if;
|
314 |
|
|
pixel_data_x <= "00000000" & pixel_data_r(15 downto 8); -- left-shift pixel data to move next pixel to LSB
|
315 |
|
|
when others => -- any other width, then 1 per pixel data word
|
316 |
|
|
if (visible = YES) then
|
317 |
|
|
rd_x <= YES; -- read new pixel data from buffer every clock during visible portion of scan line
|
318 |
|
|
end if;
|
319 |
|
|
pixel_data_x <= pixel_data_r;
|
320 |
|
|
end case;
|
321 |
|
|
|
322 |
|
|
-- store the pixel data from the buffer instead of shifting the pixel data
|
323 |
|
|
-- if a read operation was initiated in the previous cycle.
|
324 |
|
|
if rd_r = YES then
|
325 |
|
|
pixel_data_x <= pixel_data_out;
|
326 |
|
|
end if;
|
327 |
|
|
|
328 |
|
|
-- the current pixel is in the lower bits of the pixel data shift register
|
329 |
|
|
pixel <= pixel_data_r(pixel'range);
|
330 |
|
|
end process get_pixel;
|
331 |
|
|
|
332 |
|
|
-- map the current pixel to RGB values
|
333 |
|
|
map_pixel : process(pixel, rgb_r, blank_r)
|
334 |
|
|
begin
|
335 |
|
|
if NUM_RGB_BITS=2 then
|
336 |
|
|
case PIXEL_WIDTH is
|
337 |
|
|
when 1 => -- 1-bit pixels map to black or white
|
338 |
|
|
rgb_x <= (others => pixel(0));
|
339 |
|
|
when 2 => -- 2-bit pixels map to black, 2/3 gray, 1/3 gray, and white
|
340 |
|
|
rgb_x <= pixel(1 downto 0) & pixel(1 downto 0) & pixel(1 downto 0);
|
341 |
|
|
when 4 => -- 4-bit pixels map to 8 colors (ignore MSB)
|
342 |
|
|
rgb_x <= pixel(2) & pixel(2) & pixel(1) & pixel(1) & pixel(0) & pixel(0);
|
343 |
|
|
when 8 => -- 8-bit pixels map directly to RGB values
|
344 |
|
|
rgb_x <= pixel(7 downto 6) & pixel(4 downto 1);
|
345 |
|
|
when others => -- 16-bit pixels maps directly to RGB values
|
346 |
|
|
rgb_x <= pixel(8) & pixel(7) & pixel(5) & pixel(4) & pixel(2) & pixel(1);
|
347 |
|
|
end case;
|
348 |
|
|
else -- NUM_RGB_BITS=3
|
349 |
|
|
case PIXEL_WIDTH is
|
350 |
|
|
when 1 => -- 1-bit pixels map to black or white
|
351 |
|
|
rgb_x <= (others => pixel(0));
|
352 |
|
|
when 2 => -- 2-bit pixels map to black, 5/7 gray, 3/7 gray, and 1/7 gray
|
353 |
|
|
rgb_x <= pixel(1 downto 0) & '0' & pixel(1 downto 0) & '0' & pixel(1 downto 0) & '0';
|
354 |
|
|
when 4 => -- 4-bit pixels map to 8 colors (ignore MSB)
|
355 |
|
|
rgb_x <= pixel(2) & pixel(2) & pixel(2) & pixel(1) & pixel(1) & pixel(1) & pixel(0) & pixel(0) & pixel(0);
|
356 |
|
|
when 8 => -- 8-bit pixels map to RGB with reduced resolution in green component
|
357 |
|
|
rgb_x <= pixel(7 downto 5) & pixel(4 downto 3) & '0' & pixel(2 downto 0);
|
358 |
|
|
when others => -- 16-bit pixels map directly to RGB values
|
359 |
|
|
rgb_x <= pixel(8 downto 0);
|
360 |
|
|
end case;
|
361 |
|
|
end if;
|
362 |
|
|
|
363 |
|
|
-- just blank the pixel if not in the visible region of the screen
|
364 |
|
|
if blank_r(blank_r'high-1) = YES then
|
365 |
|
|
rgb_x <= (others => '0');
|
366 |
|
|
end if;
|
367 |
|
|
|
368 |
|
|
-- break the pixel into its red, green and blue components
|
369 |
|
|
r <= rgb_r(3*NUM_RGB_BITS-1 downto 2*NUM_RGB_BITS);
|
370 |
|
|
g <= rgb_r(2*NUM_RGB_BITS-1 downto NUM_RGB_BITS);
|
371 |
|
|
b <= rgb_r(NUM_RGB_BITS-1 downto 0);
|
372 |
|
|
end process map_pixel;
|
373 |
|
|
|
374 |
|
|
-- update registers
|
375 |
|
|
update : process(rst, clk)
|
376 |
|
|
begin
|
377 |
|
|
if rst = YES then
|
378 |
|
|
eof_r <= '0';
|
379 |
|
|
rd_r <= NO;
|
380 |
|
|
hsync_r <= (others => '1');
|
381 |
|
|
blank_r <= (others => '0');
|
382 |
|
|
pixel_data_r <= (others => '0');
|
383 |
|
|
rgb_r <= (others => '0');
|
384 |
|
|
elsif rising_edge(clk) then
|
385 |
|
|
eof_r <= eof_x; -- end-of-frame signal goes at full clock rate to external system
|
386 |
|
|
if cke = YES then
|
387 |
|
|
rd_r <= rd_x;
|
388 |
|
|
hsync_r <= hsync_x;
|
389 |
|
|
blank_r <= blank_x;
|
390 |
|
|
pixel_data_r <= pixel_data_x;
|
391 |
|
|
rgb_r <= rgb_x;
|
392 |
|
|
end if;
|
393 |
|
|
end if;
|
394 |
|
|
end process update;
|
395 |
|
|
|
396 |
|
|
end architecture vga_arch;
|
397 |
|
|
|
398 |
|
|
|
399 |
|
|
|
400 |
|
|
library IEEE, unisim;
|
401 |
|
|
use IEEE.std_logic_1164.all;
|
402 |
|
|
use IEEE.numeric_std.all;
|
403 |
|
|
use unisim.vcomponents.all;
|
404 |
|
|
use work.common.all;
|
405 |
|
|
|
406 |
|
|
-- Generate a sync pulse within a waveform PERIOD.
|
407 |
|
|
-- Also output the value of the counter used for timing so that
|
408 |
|
|
-- it can be used in generating an address for a video RAM.
|
409 |
|
|
|
410 |
|
|
entity sync is
|
411 |
|
|
generic (
|
412 |
|
|
FREQ : natural := 50_000; -- master clock frequency (in KHz)
|
413 |
|
|
PERIOD : natural := 32; -- period of sync pulse (in us)
|
414 |
|
|
START : natural := 26; -- time sync pulse starts within the period (in us)
|
415 |
|
|
WIDTH : natural := 4; -- width of sync pulse (in us)
|
416 |
|
|
VISIBLE : natural := 1024 -- number of visible pixels/line or lines/frame
|
417 |
|
|
);
|
418 |
|
|
port (
|
419 |
|
|
rst : in std_logic; -- reset
|
420 |
|
|
clk : in std_logic; -- master clock
|
421 |
|
|
cke : in std_logic; -- clock-enable
|
422 |
|
|
sync_n : out std_logic; -- sync pulse
|
423 |
|
|
gate : out std_logic; -- single-clock pulse at start of sync pulse
|
424 |
|
|
blank : out std_logic; -- blanking signal
|
425 |
|
|
cnt : out unsigned(15 downto 0) -- output the timing counter value
|
426 |
|
|
);
|
427 |
|
|
end entity sync;
|
428 |
|
|
|
429 |
|
|
|
430 |
|
|
architecture sync_arch of sync is
|
431 |
|
|
constant NORM : natural := 1000; -- normalization factor for us * KHz
|
432 |
|
|
constant CYC_PERIOD : natural := (PERIOD * FREQ)/NORM; -- sync wave PERIOD in clock cycles
|
433 |
|
|
constant CYC_START : natural := (START * FREQ)/NORM; -- sync pulse START in cycles
|
434 |
|
|
constant CYC_WIDTH : natural := (WIDTH * FREQ)/NORM; -- sync pulse WIDTH in cycles
|
435 |
|
|
constant CYC_END : natural := CYC_START + CYC_WIDTH; -- sync pulse end in cycles
|
436 |
|
|
signal cnt_r, cnt_x : unsigned(cnt'range); -- counter for timing sync pulse waveform
|
437 |
|
|
signal sync_r, sync_x : std_logic; -- sync register
|
438 |
|
|
signal gate_r, gate_x : std_logic; -- gate register
|
439 |
|
|
signal blank_r, blank_x : std_logic; -- blank register
|
440 |
|
|
begin
|
441 |
|
|
|
442 |
|
|
-- increment counter and wrap around to zero at end of period
|
443 |
|
|
cnt_x <= (others => '0') when cnt_r = CYC_PERIOD-1 else cnt_r+1;
|
444 |
|
|
|
445 |
|
|
-- generate sync pulse within waveform period
|
446 |
|
|
sync_x <= LO when cnt_r = CYC_START-1 else
|
447 |
|
|
HI when cnt_r = CYC_END-1 else
|
448 |
|
|
sync_r;
|
449 |
|
|
sync_n <= sync_r;
|
450 |
|
|
|
451 |
|
|
-- generate gate signal at start of sync pulse
|
452 |
|
|
gate_x <= YES when cnt_r = CYC_START-1 else NO;
|
453 |
|
|
gate <= gate_r;
|
454 |
|
|
|
455 |
|
|
-- generate blank signal after initial visible period
|
456 |
|
|
blank_x <= YES when cnt_r = VISIBLE-1 else
|
457 |
|
|
NO when cnt_r = CYC_PERIOD-1 else
|
458 |
|
|
blank_r;
|
459 |
|
|
blank <= blank_r;
|
460 |
|
|
|
461 |
|
|
-- output counter value
|
462 |
|
|
cnt <= cnt_r;
|
463 |
|
|
|
464 |
|
|
-- update counter and registers
|
465 |
|
|
update : process(rst, clk)
|
466 |
|
|
begin
|
467 |
|
|
if rst = YES then
|
468 |
|
|
cnt_r <= (others => '0');
|
469 |
|
|
sync_r <= HI;
|
470 |
|
|
gate_r <= NO;
|
471 |
|
|
blank_r <= YES;
|
472 |
|
|
elsif rising_edge(clk) then
|
473 |
|
|
if cke = YES then
|
474 |
|
|
cnt_r <= cnt_x;
|
475 |
|
|
sync_r <= sync_x;
|
476 |
|
|
gate_r <= gate_x;
|
477 |
|
|
blank_r <= blank_x;
|
478 |
|
|
end if;
|
479 |
|
|
end if;
|
480 |
|
|
end process update;
|
481 |
|
|
|
482 |
|
|
end architecture sync_arch;
|
483 |
|
|
|
484 |
|
|
|
485 |
|
|
|
486 |
|
|
library ieee, unisim;
|
487 |
|
|
use ieee.std_logic_1164.all;
|
488 |
|
|
use ieee.std_logic_unsigned.all;
|
489 |
|
|
use unisim.vcomponents.all;
|
490 |
|
|
|
491 |
|
|
entity fifo_cc is
|
492 |
|
|
port (
|
493 |
|
|
clk : in std_logic;
|
494 |
|
|
rst : in std_logic;
|
495 |
|
|
rd : in std_logic;
|
496 |
|
|
wr : in std_logic;
|
497 |
|
|
data_in : in std_logic_vector(15 downto 0);
|
498 |
|
|
data_out : out std_logic_vector(15 downto 0);
|
499 |
|
|
full : out std_logic;
|
500 |
|
|
empty : out std_logic;
|
501 |
|
|
level : out std_logic_vector(7 downto 0)
|
502 |
|
|
);
|
503 |
|
|
end entity fifo_cc;
|
504 |
|
|
|
505 |
|
|
architecture arch of fifo_cc is
|
506 |
|
|
signal full_i : std_logic;
|
507 |
|
|
signal empty_i : std_logic;
|
508 |
|
|
signal rd_addr : std_logic_vector(7 downto 0) := "00000000";
|
509 |
|
|
signal wr_addr : std_logic_vector(7 downto 0) := "00000000";
|
510 |
|
|
signal level_i : std_logic_vector(7 downto 0) := "00000000";
|
511 |
|
|
signal rd_allow : std_logic;
|
512 |
|
|
signal wr_allow : std_logic;
|
513 |
|
|
begin
|
514 |
|
|
|
515 |
|
|
bram1 : RAMB4_S16_S16 port map (addra => rd_addr, addrb => wr_addr,
|
516 |
|
|
dia => (others => '0'), dib => data_in, wea => '0', web => '1',
|
517 |
|
|
clka => clk, clkb => clk, rsta => '0', rstb => '0',
|
518 |
|
|
ena => rd_allow, enb => wr_allow, doa => data_out );
|
519 |
|
|
|
520 |
|
|
rd_allow <= rd and not empty_i;
|
521 |
|
|
wr_allow <= wr and not full_i;
|
522 |
|
|
|
523 |
|
|
process (clk, rst)
|
524 |
|
|
begin
|
525 |
|
|
if rst = '1' then
|
526 |
|
|
rd_addr <= (others => '0');
|
527 |
|
|
wr_addr <= (others => '0');
|
528 |
|
|
level_i <= (others => '0');
|
529 |
|
|
elsif rising_edge(clk) then
|
530 |
|
|
if rd_allow = '1' then
|
531 |
|
|
rd_addr <= rd_addr + '1';
|
532 |
|
|
end if;
|
533 |
|
|
if wr_allow = '1' then
|
534 |
|
|
wr_addr <= wr_addr + '1';
|
535 |
|
|
end if;
|
536 |
|
|
if (wr_allow and not rd_allow and not full_i) = '1' then
|
537 |
|
|
level_i <= level_i + '1';
|
538 |
|
|
elsif (rd_allow and not wr_allow and not empty_i) = '1' then
|
539 |
|
|
level_i <= level_i - '1';
|
540 |
|
|
end if;
|
541 |
|
|
end if;
|
542 |
|
|
end process;
|
543 |
|
|
|
544 |
|
|
full_i <= '1' when level_i = "11111111" else '0';
|
545 |
|
|
full <= full_i;
|
546 |
|
|
empty_i <= '1' when level_i = "00000000" else '0';
|
547 |
|
|
empty <= empty_i;
|
548 |
|
|
level <= level_i;
|
549 |
|
|
|
550 |
|
|
end architecture arch;
|