Teorie
Obr.1 Zobrazení na monitoru
|
Funkce VGA
Pro vykreslení obrazce na monitor je třeba vědět několik důležitých informací o fungovaní VGA signálu. VGA video signál má 5 aktivních signálů. Dva jsou kompatibilní s logickými úrovněmi TTL logiky, horizontální a vertikální synchronizace, a používají se pro synchronizaci obrazu. Tři analogové signály s 0.7 až 1.0 V špička-špička úrovní jsou použity pro ovládání barev. Barevné signály jsou Red, Green, Blue. Změnou analogových hodnot všech tří signálů dochází k vykreslení všech možných barev.
Technologie zobrazení
Způsob ovládaní monitoru nemá cenu detailně popisovat. Takže jen zmíním základní poznatky. Electronový svazek prochází po řadcích celou plochu obrazovky. Tento svazek je vychylován pomocí magnetické nebo elektrostatického pole. RGB signál je použit pro ovládání síly elektronového svazku. Světlo je generováno, když je aktivní video signál a toto světlo dopadne na stínítko obrazovky čímž vytvoří obraz tečky (případně řádku). Každá obrazovka obsahuje tři různé fotoemitory, každý pro jednu složku RGB signálu.
Ve standartním VGA je má obrazovka rozlišení 640 na 480 pixelů. Video signál musí celou obrazovku překreslit alespoň 60krát za vteřinu. Tomu se říká "refresh-rate". Lidské oko potřebuje frekvenci alespoň 30Hz aby vidělo normální obraz.
K odstranění blikání z interferencí z flourescenčních světelných zdrojů se používá v monitorech "refresh-rate" vyšší než 60 Hz. Barva každého pixelu monitoru je určena hodnotou RGB signálů když elektronový paprsek přechází přes dané místo. V režimu 640 x 480 s 60 Hz frekvencí je to zhruba 40 ns na pixel. A hodiny s 25MHz frekvencí mají tuto periodu.
|
Vykreslování
Proces vykreslování začína v levém horním rohu a po řádcích postupuje do pravého spodního rohu. Na konci řádky se resetuje číslo vykreslovaného sloupce a číslo řádky se nastaví na další. Jakmile je vykreslena celá obrazovka, proces začíná znovu. Vertikální synchronizace říká monitoru ať začne kreslit nový obraz a monitor začne kreslit v levém horním rohu. Horizontální synchronizace říká monitoru, ať "zalomí" řádek. Po vykreslení 480 řad pixelů pomocí 480 signálů na horizontální synchronizaci, signál vertikální synchronizace řekne monitoru, ať posune vychylování na bod 0,0. Během doby, kdy se nezobrazují pixely a paprsek se vrací zpět do levého horního rohu, by měl být RGB signál vynulován.
Časování signálů synchronizace viz následující dva obrázky.
|
Obr.2 Zobrazení na monitoru II.
|
Obr.3 Časování vertikální synchronizace
|
Obr.4 Časování horizontální synchronizace
|
Řešení
Hlavní entita
Obr.5 Entita
|
Entita pro vykreslování se skládá z hlavní entity a jedné komponenty o které bude řeč později. Entita má jeden vstupní signál - hodiny (50 MHz) a několik výstupních, jak dokládá následující obrázek. Signály:
- red_out - ovládá R složku pixelu
- blue_out - ovládá B složku pixelu
- green_out - ovládá G složku pixelu
- horiz_sync_out - signál horizontální synchronizace
- vert_sync_out - signál horizontální synchronizace
|
Časování
Pro vykreslování obrazců na monitoru se používá 25MHz frekvence, ale protože Xilinx Spartan 3 používá hodiny s vyšší frekvencí (50 MHz), museli jsme pomocí DCM (Digital Clock Manager) snížit frekvenci pro zobrazování na polovinu. Pro tuto potřebu jsme si naimportovali následující
kus kódu přímo od firmy Xilinx, který slouží k ovládání DCM. DCM u Spartanu podporuje mnohem větší rozsah aplikací než jsme potřebovali, umí posouvat fázi o 90, 180, 270 stupnů a podobné hrátky, nám však stačilo použít pouze možnost pro dělení hodinového signálu 2. Následujícím příkazem sme naportovali tuto komponentu do našeho kódu.
CLK_DIV2: clk_div port map (CLKIN_IN => clock_50Mhz, CLKDV_OUT => CLK, RST_IN => '0');
Nyní již na signálu CLK máme 25 MHz hodiny, které můžeme použít pro vykreslování grafiky.
Ovládání grafiky
Při vykreslování je třeba zajistit následující věci:
- generování signálu pro horizontální synchronizace
Zde je třeba zajistit nulování a posun, proto máme vytvořený pomocný čítač h_count, který slouží pro ovládání signálu horiz_sync, který se pak používá jako ovládací prvek monitoru.
IF (h_count = 799) THEN
h_count <= "0000000000";
ELSE
h_count <= h_count + 1;
END IF;
IF (h_count <= 775) AND (h_count >= 679) THEN
horiz_sync <= '0';
ELSE
horiz_sync <= '1';
END IF;
- generování signálu pro vertikální synchronizace
Opět je třeba zajistit nulování a posun, tentokrát však za jiných podmínek, a na to opět máme pomocný čitač v_count, který ovládá signál vert_sync
IF (v_count >= 524) AND (h_count >= 699) THEN
v_count <= "0000000000";
ELSIF (h_count = 699) THEN
v_count <= v_count + 1;
END IF;
IF (v_count <= 494) AND (v_count >= 493) THEN
vert_sync <= '0';
ELSE
vert_sync <= '1';
END IF;
- nulování signálu RGB při zpětném chodu paprsku
O to se stará následující úsek kódu
video_on <= video_on_H AND video_on_V;
Vlastní grafika
Entita umožňuje vykreslovat několik různých obrazců, které lze přepínat pomocí tlačítka na PCB desce. Zárověň indikuje rozsvícenými diodami svůj stav, tj. který obrazec je právě zobrazen, toto bylo vytvořeno z důvodu testování, pro vlastní funkci nemá svícení diod žádný vliv.
Obrazce
Obrazce zobrazené na monitor jsou celkem 4.
- Různobarevné svislé pruhy široké 79 pixelů - jsou tvořeny pomocí následujícího kódu:
IF (h_count <= 639) THEN
video_on_h <= '1';
pixel_column <= h_count;
ELSE
video_on_h <= '0';
bar_counter := 80;
row_counter := row_counter + 1;
END IF;
IF (v_count <= 479) THEN
video_on_v <= '1';
pixel_row <= v_count;
ELSE
video_on_v <= '0';
END IF;
IF (h_count = bar_counter) THEN
bar_counter := bar_counter + 79;
red_chan <= color(1);
green_chan <= color(2);
blue_chan <= color(0);
color <= color - 1;
END IF;
- Různobarevné svislé pruhy široké 4 pixely - jsou tvořeny pomocí následujícího kódu:
IF (h_count = 0) then
p_color :=color;
end if;
IF (h_count <= 639) THEN
video_on_h <= '1';
pixel_column <= h_count;
ELSE
video_on_h <= '0';
bar_counter := 4;
-- row_counter := 4;
color <= p_color;
END IF;
IF (v_count <= 479) THEN
video_on_v <= '1';
pixel_row <= v_count;
ELSE
video_on_v <= '0';
row_counter := 4;
END IF;
IF (h_count = bar_counter) THEN
bar_counter := bar_counter + 4;
red_chan <= color(1);
green_chan <= color(2);
blue_chan <= color(0);
color <= color - 1;
END IF;
IF (v_count = row_counter) THEN
row_counter := row_counter + 4;
color <= color + 1;
END IF;
Dva překrývající se trojúhelníky jsou tvořeny takto:
IF (h_count <= 639) THEN
video_on_h <= '1';
ELSE
video_on_h <= '0';
END IF;
IF (v_count <= 479) THEN
video_on_v <= '1';
ELSE
video_on_v <= '0';
END IF;
red_chan <= '0';
green_chan <= '0';
blue_chan <= '0';
IF (h_count < v_count) THEN
red_chan <= '1' ;
END IF;
IF (h_count > (640 - v_count)) THEN
blue_chan <= '1';
END IF;
- Zobrazení skupiny čtverců různých barev je tvořeno následujícím kódem:
IF (h_count <= 639) THEN
video_on_h <= '1';
ELSE
video_on_h <= '0';
END IF;
IF (v_count <= 479) THEN
video_on_v <= '1';
ELSE
video_on_v <= '0';
END IF;
IF (h_count >= 0 ) AND (h_count < 639 ) AND (v_count >= 0 ) AND (v_count < 492 ) THEN
red_chan <= h_count(5)
and v_count(5);
green_chan <= h_count(4)
and v_count(4);
blue_chan <= h_count(3)
and v_count(3);
ELSE
red_chan <= '0';
green_chan <= '0';
blue_chan <= '0';
END IF;
Celý kód
Celý kód entity je ke stažení
zde.
Celý projekt je ke stažení
zde.