การทำงานขอจอภาพระบบ VGA
การควบคุมจอภาพระบบ VGA ใช้สัญญาณ 5 เส้น
R ควบคุมค่าความสว่างของจุดสีแดง มีค่าได้ตั้งแต่ 0V ถึง 0.7 V คิดเป็นเปอร์เซ็นต์ความสว่าง 0 % - 100%
G ควบคุมค่าความสว่างของจุดสีเขียว มีค่าได้ตั้งแต่ 0V ถึง 0.7 V คิดเป็นเปอร์เซ็นต์ความสว่าง 0 % - 100%
B ควบคุมค่าความสว่างของจุดสีน้ำเงิน มีค่าได้ตั้งแต่ 0V ถึง 0.7 V คิดเป็นเปอร์เซ็นต์ความสว่าง 0 % - 100%
Horizontal Synchronization (Hsync) ควบคุมการแสดงจุดภาพในแนวราบจากขอบซ้ายสุด ไปขอบขวาสุด ของจอภาพ แล้วกลับ ไปเริ่มต้นที่ขอบซ้ายสุดมาใหม่
Vertical Synchronization (Vsync) ควบคุมการแสดงจุดภาพในแนวดิ่งจากด้านบนสุด ไปล่างสุด ของจอภาพ แล้วกลับ ไปเริ่มต้นที่ด้านบนใหม่
ลักษณะการวาดจุดสีเพื่อให้เกิดเป็นภาพเมื่อเทียบกับสัญญาณ Hsync กับ Vsync
สัญญาณซิงค์ (Synchronous Signal)
จากการทำงานข้างต้น สัญญาณควบคุมจุดสี RGB ต้องมีช่วงควบคุมให้เกิดการแสดง (ลอจิก 1) กับควบคุมไม่ให้เกิดการแสดง(ลอจิก 0) เพื่อให้เกิดความเข้าใจของช่วงเวลาต่างๆขอยกตัวอย่างการควบคุมให้เกิดการแสดงภาพขนาด 640 x 480 จุด Zpixel) และ fram rate 60 Hz
แนวระดับ (Horizontal)
horizontal display 640 จุด (ช่วงแสดงจุดภาพ)
hsync front porch 16 จุด (ช่วงไม่แสดงจุดภาพ)
hsync back porch 48 จุด (ช่วงไม่แสดงจุดภาพ)
hsync retrace 96 จุด (ช่วงไม่แสดงจุดภาพ)
แนวดิ่ง (Vertical)
vertical display 480 เส้น (ช่วงแสดงจุดภาพ)
vsync front porch 11 เส้น (ช่วงไม่แสดงจุดภาพ)
vsync back porch 31 เส้น (ช่วงไม่แสดงจุดภาพ)
vsync retrace 2 เส้น (ช่วงไม่แสดงจุดภาพ)
กรณีถ้าเป็นการแสดงภาพรูปแบบอื่นๆ จะมีค่าตามตารางนี้
การสร้างจุดสี
จุดสีเกิดจากการผสมสีของ สีแดง (R: Red) เขียว (G: Green) และสีน้ำเงิน (B: Blue)
ถ้าใช้ 8 บิต แทนแต่ละสี จะได้ ระดับความสว่างของแต่ละสีเป็น 256 ระดับ เมื่อเอามารวมกันทั้ง 3 สี จุดสีที่สามารถจะสร้างได้เป็น 256 x 256 x 256 = 16,777,216 สี
สำหรับการทดลองนี้ แต่ละสีใช้เพี่ยง 1 บิต จึงมีค่าความสว่างของแต่ละสีเพียง 2 ระดับคือ มืดกับสว่างสุด เมื่อนำมาผสมกันจึงได้เท่ากับ 2 x 2 x 2 = 8 สี
ความสว่างของสีแต่ละสีเมื่อเทียบกับแรงดันที่ป้อนเข้าที่ขา R G และ B
วงจร
ความต้านทานภายในของ ขา R G B ของ VGA แต่ละขา = 75 ohms
แรงดันที่ FPGA จ่ายเมื่อเป็นลอจิก '1' = 3.3 V
แรงดันที่ต้องการเพื่อให้ความสว่าง 100 % = 0.7 V
ดังนั้นต้องใช้ความต้านทานต่ออนุกรมระหว่า FPGA กับขา RGB แต่ละขาเท่ากับ
ในที่นี้ใช้ 250 โอหม์ หรือ 270 โอหม์
โมดูล VGA Controller
โมดูลสร้างสัญญาณซิงค์
-- Engineer: Narong Buabthong
--
-- Create Date: 12/12/2015
-- Design Name: :VGA Controller
-- Module Name: : VGA Sync Generator
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity vga_sync is
port (clk, rst_n: in std_logic;
hsync : out std_logic;
h_on_p : out std_logic;
vsync : out std_logic;
v_on_p : out std_logic;
row : out natural;
col : out natural
);
end vga_sync;
architecture arch of vga_sync is
constant HF: integer:= 16; -- hsync front porch
constant HR: integer:= 96; -- hsync retrace
constant HB: integer:= 48; -- hsync back porch
constant HD: integer:= 640; -- horizontal display
constant VF: integer:= 11; -- vsync front porch
constant VR: integer:= 2; -- vsync retrace
constant VB: integer:= 31; -- vsync back porch
constant VD: integer:= 480; -- vertical display
signal v_freq, h_freq: std_logic;
signal v_on, h_on: std_logic;
signal reset: std_logic;
signal x : natural := 0;
signal y : natural := 0;
begin
-- Frequency dividre--
DIVIDER1 : entity work.DIVIDER
generic map(fin => 50000000,
fout => 21000000
)
port map (CLK=>clk,
Q => h_freq
);
reset <= not rst_n;
row <= y;
col <= x;
h_on_p <= h_on;
v_on_p <= v_on;
---------Process การสร้างสัญญาณ Hor sync และ สัญญาณ ON/OFF Pixel ในแนวราบ--------------
h_gen: process(h_freq,reset)
variable h_count : natural := 0;
begin
if(reset = '1') then h_count := 0; end if;
if h_freq'event and h_freq = '1' then
if h_count <= HF then
h_on <= '0';
hsync <= '1';
elsif (h_count > HF) and (h_count <= HF+HR) then
h_on <= '0';
hsync <= '0';
elsif (h_count > HF+HR) and (h_count <= HF+HR+HB) then
h_on <= '0';
hsync <= '1';
elsif (h_count > HF+HR+HB) and (h_count <= HF+HR+HB+HD) then
h_on <= '1';
hsync <= '1';
elsif (h_count > HF+HR+HB+HD) then
h_count := 0;
h_on <= '0';
hsync <= '1';
end if;
h_count := h_count + 1;
end if;
end process;
---------Process การสร้างสัญญาณ Ver sync และ สัญญาณ ON/OFF Pixel ในแนวดิ่ง --------------
v_gen: process(h_on,h_freq,reset)
variable v_count : natural := 0;
begin
if(reset = '1') then v_count := 0; end if;
if h_on'event and h_on = '0' then
if v_count <= VF then
v_on <= '0';
vsync <= '1';
elsif (v_count > VF) and (v_count <= VF+VR) then
v_on <= '0';
vsync <= '0';
elsif (v_count > VF+VR) and (v_count <= VF+VR+VB) then
v_on <= '0';
vsync <= '1';
elsif (v_count > VF+VR+VB) and (v_count <= VF+VR+VB+VD) then
v_on <= '1';
vsync <= '1';
elsif (v_count > VF+VR+VB+VD) then
v_count := 0;
v_on <= '0';
vsync <= '1';
end if;
v_count := v_count + 1;
end if;
end process;
-----------------------Process การสร้าง ตำแหน่ง row และ column ของจุดสี---------------------------
xy_gen: process(v_on,reset)
begin
if h_freq'event and h_freq = '1' then
if((h_on='0') and (v_on='0')) then
x<=0;
y<=0;
elsif((h_on='1')and (v_on='1')) then
x <= x+1;
if(x>=639) then
x <= 0;
y <= y+1;
if(y>=479) then
y<=0;
end if;
end if;
end if;
end if;
end process;
end arch;
การทดลองแบบที่ 1
แบบที่ 1 สร้างสี่เหลี่ยมสีแดงขนาด 50x50 pixel ที่ตำแหน่ง row = 50 col = 50
พื้นหลังสีขาว
vga_controller_1.vhd
-- Engineer: Narong Buabthong
--
-- Create Date: 12/12/2015
-- Design Name: :VGA Controller
-- Module Name: : Pixel Generator and top module type 1
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity vga_controller is
port (clk, rst_n: in std_logic;
hsync : out std_logic;
vsync : out std_logic;
r_pin : out std_logic;
g_pin : out std_logic;
b_pin : out std_logic
);
end vga_controller;
architecture arch of vga_controller is
signal x : natural := 0;
signal y : natural := 0;
signal h_on : std_logic;
signal v_on : std_logic;
signal s_r : std_logic;
signal s_g : std_logic;
signal s_b : std_logic;
begin
---------เชื่อมต่อกับ โมดูล Sync Generator -------------
vga_sync : entity work.vga_sync
port map (clk => clk,
rst_n => rst_n,
hsync => hsync,
h_on_p => h_on,
vsync => vsync,
v_on_p => v_on,
row => y,
col => x
);
---------Process การสร้างสัญญาณ pixel R G และ B ในแต่ละตำแหน่ง (row col) -------------
r_pin <= s_r and h_on and v_on; --สัญญาณ R เกิดจากค่า pixel R and h_on and V_on (เพื่อการ blank)
g_pin <= s_g and h_on and v_on;--สัญญาณ G เกิดจากค่า pixel G and h_on and V_on (เพื่อการ blank)
b_pin <= s_g and h_on and v_on;--สัญญาณ B เกิดจากค่า pixel B and h_on and V_on (เพื่อการ blank)
gen_pix: process(clk,x,y)
begin
if clk'event and clk = '1' then
if ((x>=50) and (x<100) and (y>=50) and (y<100)) then
s_r <= '1';
s_g <= '0';
s_b <= '0';
else
s_r <= '1';
s_g <= '1';
s_b <= '1';
end if;
end if;
end process;
end arch;
VGA_Controller.ucf
NET "clk" TNM_NET = clk;
TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%;
NET "clk" LOC = P56 | IOSTANDARD = LVTTL;
NET "rst_n" LOC = P38 | PULLUP;
NET "hsync" LOC = P33 | IOSTANDARD = LVTTL;
NET "vsync" LOC = P30 | IOSTANDARD = LVTTL;
NET "r_pin" LOC = P51 | IOSTANDARD = LVTTL;
NET "g_pin" LOC = P41 | IOSTANDARD = LVTTL;
NET "b_pin" LOC = P35 | IOSTANDARD = LVTTL;
การทดลองแบบที่ 2
แบบที่ 2 สร้างสี่เหลี่ยมสีแดงขนาด 50x50 pixel ที่ตำแหน่งเริ่มต้น row = 50 col = 50 แล้วให้เลื่อนไปที่ละ 1 pixel จากซ้ายไปขวา จากบนลงล่าง
พื้นหลังสีเหลือง
vga_controller_2.vhd
-- Engineer: Narong Buabthong
--
-- Create Date: 12/12/2015
-- Design Name: :VGA Controller
-- Module Name: : Pixel Generator and top module type 2
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity vga_controller_2 is
port (clk, rst_n: in std_logic;
hsync : out std_logic;
vsync : out std_logic;
r_pin : out std_logic;
g_pin : out std_logic;
b_pin : out std_logic
);
end vga_controller_2;
architecture arch of vga_controller_2 is
signal x : natural := 0;
signal y : natural := 0;
signal h_on : std_logic;
signal v_on : std_logic;
signal s_r : std_logic;
signal s_g : std_logic;
signal s_b : std_logic;
signal fm : std_logic;
signal x_move : natural := 0;
signal y_move : natural := 0;
begin
---------เชื่อมต่อกับ โมดูล Sync Generator -------------
vga_sync : entity work.vga_sync
port map (clk => clk,
rst_n => rst_n,
hsync => hsync,
h_on_p => h_on,
vsync => vsync,
v_on_p => v_on,
row => y,
col => x
);
-- Gen pixel --
r_pin <= s_r and h_on and v_on; --สัญญาณ R เกิดจากค่า pixel R and h_on and V_on (เพื่อการ blank)
g_pin <= s_g and h_on and v_on;--สัญญาณ G เกิดจากค่า pixel G and h_on and V_on (เพื่อการ blank)
b_pin <= s_b and h_on and v_on;--สัญญาณ B เกิดจากค่า pixel B and h_on and V_on (เพื่อการ blank)
---------เชื่อมต่อกับ โมดูล Divider เพื่อนำมาทำเป็น clk ควบคุมความเร็วในการเคลื่อนที่ -------------
DIVIDER1 : entity work.DIVIDER
generic map(fin => 50000000,
fout => 500
)
port map (CLK=>clk,
Q => fm
);
---------Process การเปลี่ยนตำแหน่งค่าเริ่มต้นของวัตถุที่ต้องการให้เคลื่อนที่ -------------
move_pixel: process(fm,x_move,y_move)
begin
if fm'event and fm = '1' then
x_move <= x_move+1;
if(x_move>=(640-50)) then
y_move <= y_move+5;
x_move <= 0;
if(y_move>= (480-50)) then
y_move <= 0;
end if;
end if;
end if;
end process;
---------Process การสร้างสัญญาณ pixel R G และ B ในแต่ละตำแหน่ง (row col) -------------
gen_pix: process(clk,x,y)
begin
if clk'event and clk = '1' then
if ((x>=x_move) and (x<x_move+50) and (y>=y_move) and (y<y_move+50)) then
s_r <= '1';
s_g <= '0';
s_b <= '0';
else
s_r <= '1';
s_g <= '1';
s_b <= '0';
end if;
end if;
end process;
end arch;
**ไฟล์กำหนดตำแหน่งขาใช้แบบเดียวกับ ตัวอย่างที่ 1