VGA(Video Graphics Array), IBM tarafında geliştirilen ve bilgisayarlarda görüntüyü analog olarak aktarmakta kullanılan bir protokoldür. Görüntü sinyali R, G, B, HSync ve VSync olmak üzere 5 tel üzerinde gerçekleşir. RGB sinyalleri 0.7Vpp aralığında analog sinyallerdir. HSync ve VSync sinyalleri ise TTL yapıdadır. RGB sinyallerinin analog yapıda olmasından dolayı uzun mesafelerde ve yüksek çözünürlük, yenileme oranı, renk derinliğinde dijital protokollere göre başarısız kalmıştır.
HSync(Horizontal Sync) ve VSync(Vertical Sync) sinyalleri RGB sinyallerini senkronize etmek için kullanılır. Aşağıda bir frame görüntü oluşturulurken HSync ve VSync sinyallerinin durumu görülebilir.
Yukarıda da görüdüğü gibi HSync ve VSync sinyalleri belirli zamanlarda ve belirli polaritede pulse sinyalleri üreterek RGB sinyallerini senkronize etmiş olur.
Bütün zamanlama ve polarite parametreleri istenilen çözünürlüğe ve yenileme süresine göre belirlenmiştir. Bütün parametrelere buradan ulaşabilirsiniz.
HVA ve VVA alanlarında görüntü RGB sinyallerinden gönderilir.
FPGA VGA Modülü:
--Kütüphaneler library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; entity VGA is generic(RGBLength : integer := 1); --R, G, B sinyallerinin genişliği --(Renk derinliği) port(Clk : in std_logic; --Clk girişi X, Y : out std_logic_vector(15 downto 0); --X,Y koordinatları --Bu sinyaller o an hangi pixelin DAC'ye --gönderileceğini belirtir. Rin, Gin, Bin : in std_logic_vector(RGBLength - 1 downto 0); --R, G, B bilgileri --Okunan X, Y sinyallerine göre istenen --RGB verisi bu sinyaller tarafında gönderilir. --Monitöre giden sinyaller R, G, B : out std_logic_vector(RGBLength - 1 downto 0); --DAC'ye gönderilercek RGB sinyalleri HSync, VSync : out std_logic); --Yatay ve Dikey senkronizasyon sinyalleri end VGA; architecture Behavioral of VGA is --108Mhz'e ayarlanmış PLL (1024x1280 @60Hz) component pll PORT ( inclk0 : IN STD_LOGIC := '0'; c0 : OUT STD_LOGIC ; locked : OUT STD_LOGIC ); end component; signal PixelClk, PLLLocked : std_logic; signal HSyncSignal, VSyncSignal : std_logic; --Timing Parametreleri (1024x1280 @60Hz) constant HorizontalVisibleArea : integer := 1280; constant HorizontalFrontPorch : integer := 48; constant HorizontalSyncPulse : integer := 112; constant HorizontalBackPorch : integer := 248; constant VerticalVisibleArea : integer := 1024; constant VerticalFrontPorch : integer := 1; constant VerticalSyncPulse : integer := 3; constant VerticalBackPorch : integer := 38; constant HorizontalSyncPolarity : std_logic := '1'; --Sync polariteleri pozitif constant VerticalSyncPolarity : std_logic := '1'; constant HorizontalWholeLine : integer := HorizontalVisibleArea + HorizontalFrontPorch + HorizontalSyncPulse + HorizontalBackPorch; constant VerticalWholeLine : integer := VerticalVisibleArea + VerticalFrontPorch + VerticalSyncPulse + VerticalBackPorch; begin --Sync Polarity '1' ise Sync sinyali terslenir with HorizontalSyncPolarity select HSync <= HSyncSignal when '0', not HsyncSignal when others; with VerticalSyncPolarity select VSync <= VSyncSignal when '0', not VsyncSignal when others; VGAPLL : pll port map(Clk, PixelClk, PLLLocked); process(PixelClk) variable H, V : integer range 0 to 2047 := 0; begin --PixelClk'un yükselen kenarı ile H değişkeninin --değeri 1 arttırılır. H değeri toplam Horizontal zamanına --ulaşınca H değişkeni resetlenir ve V değeri 1 arttırılır. --V değeri toplam Vertical zamana ulaşınca resetlenir. if rising_edge(PixelClk) and PLLLocked = '1' then if H < HorizontalWholeLine - 1 then H := H + 1; else H := 0; if V < VerticalWholeLine - 1 then V := V + 1; else V := 0; end if; end if; end if; --HSync kontrolü --Visible area if H < HorizontalVisibleArea - 1 then HSyncSignal <= '1'; --Front porch elsif H < HorizontalVisibleArea + HorizontalFrontPorch - 1 then HSyncSignal <= '1'; --Sync pulse elsif H < HorizontalVisibleArea + HorizontalFrontPorch + HorizontalSyncPulse - 1 then HSyncSignal <= '0'; --Back porch elsif H < HorizontalWholeLine - 1 then HSyncSignal <= '1'; end if; --VSync kontrolü --Visible area if V < VerticalVisibleArea - 1 then VSyncSignal <= '1'; --Front porch elsif V < VerticalVisibleArea + VerticalFrontPorch - 1 then VSyncSignal <= '1'; --Sync pulse elsif V < VerticalVisibleArea + VerticalFrontPorch + VerticalSyncPulse - 1 then VSyncSignal <= '0'; --Back porch elsif V < VerticalWholeLine - 1 then VSyncSignal <= '1'; end if; --H ve V değerleri görüntü alanı içerisinde ise --R, G, B sinyalerine görüntü bilgileri gönderilir. if H < HorizontalVisibleArea and V < VerticalVisibleArea then R <= Rin; G <= Gin; B <= Bin; X <= std_logic_vector(to_unsigned(H, X'length)); Y <= std_logic_vector(to_unsigned(V, X'length)); else R <= (others => '0'); G <= (others => '0'); B <= (others => '0'); X <= (others => '0'); Y <= (others => '0'); end if; end process; end Behavioral;
Quartus II programı tarafından oluşturulan RTL şeması:
1-Bit Renk Paleti Oluşturma:
--Kütüphaneler library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; entity VGA_Test is generic(RGBLength : integer := 1); port(Clk : in std_logic; --Clk girişi R, G, B : out std_logic_vector(RGBLength - 1 downto 0); --VGA R, G, B sinyalleri HSync, VSync : out std_logic); --VGA HSync, VSync sinyalleri end VGA_Test; architecture Behavioral of VGA_Test is --VGA sürücü componenti component VGA generic(RGBLength : integer := 1); --R, G, B sinyallerinin genişliği --(Renk derinliği) port(Clk : in std_logic; --Clk girişi X, Y : out std_logic_vector(15 downto 0); --X,Y koordinatları --Bu sinyaller o an hangi pixelin DAC'ye --gönderileceğini belirtir. Rin, Gin, Bin : in std_logic_vector(RGBLength - 1 downto 0); --R, G, B bilgileri --Okunan X, Y sinyallerine göre istenen --RGB verisi bu sinyaller tarafında gönderilir. --Monitöre giden sinyaller R, G, B : out std_logic_vector(RGBLength - 1 downto 0); --DAC'ye gönderilercek RGB sinyalleri HSync, VSync : out std_logic); --Yatay ve Dikey senkronizasyon sinyalleri end component; signal Xs, Ys : std_logic_vector(15 downto 0); signal X, Y : integer range 0 to 2**20-1; signal Rin, Gin, Bin : std_logic_vector(0 downto 0); begin --Xs, Xs sinyalleri integer'a dönüştürülür X <= to_integer(unsigned(Xs)); Y <= to_integer(unsigned(Ys)); VGADriver : VGA generic map(1) port map(Clk, Xs, Ys, Rin, Gin, Bin, R, G, B, HSync, VSync); process(X, Y) begin --Renk Paleti Bin(0) <= std_logic_vector(to_unsigned(X / 160, 3))(0); Gin(0) <= std_logic_vector(to_unsigned(X / 160, 3))(1); Rin(0) <= std_logic_vector(to_unsigned(X / 160, 3))(2); end process; end Behavioral;
Daireler:
--Kütüphaneler library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; entity VGA_Test is generic(RGBLength : integer := 1); port(Clk : in std_logic; --Clk girişi R, G, B : out std_logic_vector(RGBLength - 1 downto 0); --VGA R, G, B sinyalleri HSync, VSync : out std_logic); --VGA HSync, VSync sinyalleri end VGA_Test; architecture Behavioral of VGA_Test is --VGA sürücü componenti component VGA generic(RGBLength : integer := 1); --R, G, B sinyallerinin genişliği --(Renk derinliği) port(Clk : in std_logic; --Clk girişi X, Y : out std_logic_vector(15 downto 0); --X,Y koordinatları --Bu sinyaller o an hangi pixelin DAC'ye --gönderileceğini belirtir. Rin, Gin, Bin : in std_logic_vector(RGBLength - 1 downto 0); --R, G, B bilgileri --Okunan X, Y sinyallerine göre istenen --RGB verisi bu sinyaller tarafında gönderilir. --Monitöre giden sinyaller R, G, B : out std_logic_vector(RGBLength - 1 downto 0); --DAC'ye gönderilercek RGB sinyalleri HSync, VSync : out std_logic); --Yatay ve Dikey senkronizasyon sinyalleri end component; signal Xs, Ys : std_logic_vector(15 downto 0); signal X, Y : integer range 0 to 2**20-1; signal Rin, Gin, Bin : std_logic_vector(0 downto 0); type integer_array is array (7 downto 0) of integer range 0 to 2**10-1; begin --Xs, Xs sinyalleri integer'a dönüştürülür X <= to_integer(unsigned(Xs)); Y <= to_integer(unsigned(Ys)); VGADriver : VGA generic map(1) port map(Clk, Xs, Ys, Rin, Gin, Bin, R, G, B, HSync, VSync); process(Clk) variable ClkCnt : integer range 0 to 2**18-1 := 0; --Çemberlerin yarıçaplarının tutulduğu dizi variable R : integer_array := (0, 100, 200, 300, 400, 500, 600, 700); --O anki X ve Y değerlerinde çemberlerin bir noktasının --olup olmadığını tutan dizi variable N : std_logic_vector(7 downto 0); begin --Her 10ms'de çemberlerin yarıçapı 1 arttırılır if rising_edge(Clk) then if ClkCnt < 249999 then ClkCnt := ClkCnt + 1; else ClkCnt := 0; --Her bir çemberin yarıçapı 1 arttırılır for i in 0 to 7 loop if R(i) < 800 then R(i) := R(i) + 1; --Eğer yarıçap 799 dan büyük ise resetlenir. else R(i) := 0; end if; end loop; end if; end if; --Her bir çemberin o anki X, Y değerleri üzerinde bir --noktası olup olmadığını hesaplayan döngü for i in 0 to 7 loop if ((R(i) - 5)**2) < ((X - 640)**2 + (Y - 512)**2) and ((X - 640)**2 + (Y - 512)**2) < ((R(i) + 5)**2) then N(i) := '1'; else N(i) := '0'; end if; end loop; --O anki X, Y koordinatlarında, herhangi bir çemberin --noktası bulunuyor ise kırmızı rengi gönderilir. if N /= X"00" then Rin <= "1"; Gin <= "0"; Bin <= "0"; --Bulunmuyor ise cam göbeği rengi gönderilir. else Rin <= "0"; Gin <= "1"; Bin <= "1"; end if; end process; end Behavioral;
Yeni Versiyon (4.10.2017):
----------------------------- VGA.vhd -------------------------------- -- Bertan Taşkın -- 4.10.2017 -- Versiyon 2.0 -- -- VGA kontrolcüsü. Zamanlama parametreleri generic kısmından ayarlanabilir. -- BufferAddress sinyali o anki pixelin buffer'daki adresini belirtir. -- BufferAddress belirtildikten 1 cycle sonra BufferData'dan veriler okunur. -- -- -- Versiyon Notları: -- -- Versiyon 1.0 (23.4.2017): İlk sürüm. -- -- Versiyon 2.0 (4.10.2017): HSync ve VSync'deki zamanlama hataları -- düzeltildi. -- Zamanlama parametreleri generic kısmına taşındı. -- DE(Data Enabe) çıkışı eklendi. -- BufferAddress(eski X, Y) ile BufferData(eski R, G, B) arasına -- 1 cycle eklendi. -- Kod daha sade bir şekilde tekrar yazıldı. -- --Kütüphaneler library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; entity VGA is generic(HorizontalVisibleArea : natural := 1440; --Zamanlama Parametreleri HorizontalFrontPorch : natural := 80; HorizontalSyncPulse : natural := 152; HorizontalBackPorch : natural := 232; VerticalVisibleArea : natural := 900; VerticalFrontPorch : natural := 1; VerticalSyncPulse : natural := 3; VerticalBackPorch : natural := 28; HorizontalSyncPolarity : std_logic := '1'; --Sync Polariteleri VerticalSyncPolarity : std_logic := '1'; RGBLength : integer := 8); port(PixelClk, Enable : in std_logic; --Pixel Clock ve Enable Girişi Red, Green, Blue : out unsigned(RGBLength - 1 downto 0); --RGB Çıkışları HSync, VSync : out std_logic; --HSync ve VSync Çıkışı DE : out std_logic; --Data Enable Çıkışı BufferAddress : out std_logic_vector(31 downto 0); --Buffer Address Çıkışı BufferData : in std_logic_vector(RGBLength * 3 - 1 downto 0)); --Buffer Data Girişi end VGA; architecture Behavioral of VGA is --Toplam yatay pixel constant HorizontalWholeLine : integer := HorizontalVisibleArea + HorizontalFrontPorch + HorizontalSyncPulse + HorizontalBackPorch; --Toplam dikey pixel constant VerticalWholeLine : integer := VerticalVisibleArea + VerticalFrontPorch + VerticalSyncPulse + VerticalBackPorch; signal HCount : natural range 0 to HorizontalWholeLine - 1 := 0; signal VCount : natural range 0 to VerticalWholeLine - 1 := 0; signal HPulse, VPulse : std_logic; signal HVisible, VVisible : std_logic; begin --BufferAddress'in hesaplanması BufferAddress <= std_logic_vector(to_unsigned(VCount * HorizontalVisibleArea + HCount, 32)); process(PixelClk) begin if rising_edge(PixelClk) and Enable = '1' then --HCount arttırılır if HCount < HorizontalWholeLine - 1 then HCount <= HCount + 1; else --HCount sona ulaştığında resetlenir ve VCount arttırılır HCount <= 0; if VCount < VerticalWholeLine - 1 then VCount <= VCount + 1; else VCount <= 0; end if; end if; --HCount visible area içindeyse HVisible setlenir if HCount < HorizontalVisibleArea then HPulse <= '0'; HVisible <= '1'; elsif HCount < HorizontalVisibleArea + HorizontalFrontPorch then HPulse <= '0'; HVisible <= '0'; --HCount pulse alanı içindeyse HPulse setlenir. elsif HCount < HorizontalVisibleArea + HorizontalFrontPorch + HorizontalSyncPulse then HPulse <= '1'; HVisible <= '0'; elsif HCount < HorizontalWholeLine then HPulse <= '0'; HVisible <= '0'; end if; --VCount visible area içindeyse VVisible setlenir if VCount < VerticalVisibleArea then VPulse <= '0'; VVisible <= '1'; elsif VCount < VerticalVisibleArea + VerticalFrontPorch then VPulse <= '0'; VVisible <= '0'; --VCount pulse alanı içindeyse VPulse setlenir. elsif VCount < VerticalVisibleArea + VerticalFrontPorch + VerticalSyncPulse then VPulse <= '1'; VVisible <= '0'; elsif VCount < VerticalWholeLine then VPulse <= '0'; VVisible <= '0'; end if; --Horizontal pulse üretimi if HPulse = '1' then HSync <= HorizontalSyncPolarity; else HSync <= not HorizontalSyncPolarity; end if; --Vertical pulse üretimi if VPulse = '1' then VSync <= VerticalSyncPolarity; else VSync <= not VerticalSyncPolarity; end if; --Her iki yönde de visible alan içindeyse RGB sinyalleri gönderilir ve --Data Enable setlenir if HVisible = '1' and VVisible = '1' then Red <= unsigned(BufferData(RGBLength * 3 - 1 downto RGBLength * 2)); Green <= unsigned(BufferData(RGBLength * 2 - 1 downto RGBLength)); Blue <= unsigned(BufferData(RGBLength - 1 downto 0)); DE <= '1'; --Her iki yönde en az biri visible alan dışındaysa RGB ve Data Enable --resetlenir else Red <= to_unsigned(0, RGBLength); Green <= to_unsigned(0, RGBLength); Blue <= to_unsigned(0, RGBLength); DE <= '0'; end if; end if; end process; end Behavioral;
Merhabalar bitirme projesinde fpga üzerinden görüntü alma işlemi olarak belirledik bize yardımcı olursanız seviniriz iyi çalışmalar dileriz. osmanavsar69@gmail.com
Merhabalar, aşağıdaki mail adresinden bana ulaşabilirsiniz.
bertantaskin@hotmail.com
İyi günler.
Bu faydalı paylaşımınız için teşekkür ederim.
Acaba pll kodunuzu paylaşır mısınız?
Merhaba, pll Quartus tarafından oluşturulmuş bir ip çekirdek.
Hocam elinize sağlık çok açıklayıcı olmuş teşekkür ederim 🙂