Popularny post Elvis Napisano Grudzień 25, 2017 Popularny post Udostępnij Napisano Grudzień 25, 2017 W niniejszym artykule chciałbym opisać krótko jak za pomocą zestawu ElbertV2 uzyskać obraz na monitorze VGA. Moje rozwiązanie nie jest idealne, pojawiają się problemy z pierwszą linią i kolumną, o czym pisałem w wątku: https://www.forbot.pl/forum/topics51/przesuniety-obraz-na-monitorze-vga-vt14911.htm, więc jeśli ktoś ma pomysł na rozwinięcie, udoskonalenie, czy zwykłe poprawienie kodu, proszę śmiało pisać Warto przy okazji zwrócić uwagę, że ten projekt pokazuje zalety FPGA w porównaniu z mikrokontrolerami. Przykładowy sterownik zrealizujemy za pomocą niewielkiej części zasobów naszego i tak niewielkiego układu. Wygenerowanie obrazu za pomocą mikrokontrolera, o ile w ogóle możliwe zajmowałoby ogromną ilość jego zasobów. Projekt początkowo bazował na blogu, którego link podaje producent płytki (Numato): https://langster1980.blogspot.co.uk/2015/08/driving-vga-port-using-elbert-v2-and_7.html Zachęcam do porównania obu rozwiązań. Interfejs VGA Standard VGA używa sygnału analogowego do sterowania wyświetlaniem obrazu (w odróżnieniu od np. HDMI). Aby wyświetlić obraz musimy odpowiednio wysterować linie: • hsync - synchronizacja pozioma • vsync - synchronizacja pionowa • red, green, blue - kolor aktualnego piksela Podłączenie do zestawu ElbertV2 znajdziemy w jego dokumentacji: Rezystory na liniach kolorów realizują prosty przetwornik cyfrowo-analogowy. Obraz na monitorze VGA Tradycyjne monitory używały kineskopów, gdzie obraz był generowany na warstwie luminoforu za pomocą wiązki elektronow. W danej chwili wiązka elektronów była z ogniskowana w jednym punkcie ekranu tworzącym piksel. Elekromagnesy pozwalały na odchylenie tej wiązki i skierowanie w konkretny punkt na ekranie. Cykliczne "przemiatanie" obrazu sprawiało, że użytkownik widział stailny obraz. Obecnie monitory LCD właściwie wyparły tradycyjne CRT, jednak sposób sterowania pozostał niezmieniony. Obraz składa się z poziomych linii, każda linia z jednakowej liczby pikseli. Po wyświetleniu linii generowane są odpowiednie sygnały synchronizacji poziomej (hsync), a po narysowaniu ostatniej linii, sygnał synchronizacji pionowej (vsync). Aby uzyskać obraz na monitorze musimy więc wygenerować odpowiednie sygnały na liniach hsync, vsync oraz sam obraz za pomocą linii koloru. Dokładniejszy opis sterowania liniami znajdziemy na stronie: https://eewiki.net/pages/viewpage.action?pageId=15925278. Poniżej widzimy obrazek pobrany właśnie stamtąd: Sygnał synchronizacji ma ujemną polaryzację, czyli aktywny stan to logiczne "0". Jak widzimy podczas rysowania linii najpierw generowane są piksele obrazu, następnie mała przerwa (Front Porch), sygnał synchronizacji (Sync Pulse) oraz kolejna przerwa (Back Porch). Po niej rysowana jest kolejna linia. Synchronizacja pionowa przebiega podobnie, chociaż czasy są znacznie dłuższe. Rozdzielczość obrazu Obraz na ekranie może być generowany w różnych trybach - z różną częstotliwością odświerzania oraz rozdzielczością. Jako przykład wykorzystamy tryb o rozdzielczości 640 x 480 pikseli, z odświerzaniem 60Hz. Parametry dla tego trybu znajdziemy w tabeli na stronie podlinkowanej wyżej oraz w bardzo wielu miejscach w sieci. W każdym razie chcielibyśmy uzyskać następujące parametry: • Pixel clock: 25.175 MHz Synchronizacja pozioma: • Front Porch: 16 • Sync Pulse: 96 • Back Porch: 48 Synchronizacja pionowa: • Front Porch: 10 • Sync Pulse: 2 • Back Porch: 33 Pętla PLL W dokumentacji zestawu ElbertV2 znajdziemy informację o częstotliwości zegara taktującego, wynosi ona 12 MHz. Jak widzimy jest to za mało, ponieważ do wyświetlania potrzebny jest nam zegar o wyższej częstotliwości. Na szczęście Spartan3A, w który nasz zestaw jest wyposażony w moduły pętli PLL, dzięki której możemy zwiększyć częstotliwość pracy układu. Tworzymy nowe projekt, a następnie dodajemy nowy plik źródłowy (New Source). Jako typ projektu wybieramy "IP (CORE Generator & Architecture Wizard)". Następnie odnajdujemy komponent "Single DCM_SP". Przechodzimy przez kolejne opcja generatora. Następnie otworzy się nowe okno, tym razem z opcjami konfiguracji modułu. W pierwszym oknie wprowadzamy częstotliwość zegara, czyli 12MHz. Wybieramy również sygnał CLKFX: Opcje w kolejnych oknach możemy zostawić niezmienione, aż dojdziemy do ustawień generowanego zegara. Tutaj wprowadzamy docelową częstotliwość, czyli 25.175 MHz. Teraz możemy zakończyć konfigurację komponentu, powinniśmy zobaczyć nowy plik dodany do projektu. Jeśli będziemy chcieli, zawsze możemy zmienić konfigurację dwukrotnie klikając na tym pliku. Konfiguracja pinów Każdy projekt zawiera definicję używanych pinów. Do sterowania VGA musimy zdefinować podłączenia linii synchornizacji, kolorów oraz zegara dla samego układu Spartan. Plik ma postać: NET "clk" LOC = P129 | IOSTANDARD = LVCMOS33 | PERIOD = 12MHz; NET "hsync" LOC = P93 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "vsync" LOC = P92 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "blue[2]" LOC = P98 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "blue[1]" LOC = P96 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "green[2]" LOC = P102 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "green[1]" LOC = P101 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "green[0]" LOC = P99 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "red[2]" LOC = P105 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "red[1]" LOC = P104 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; NET "red[0]" LOC = P103 | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 12; Generowanie obrazu Zacznijmy niejako od końca, czyli od generowania danych obrazu. Moduł, który potrzebujemy będzie dostawał współrzęne piksela i zwracał jego kolor: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity display is port( clk : in std_logic; x : in integer range 0 to 1023; y : in integer range 0 to 1023; color : out std_logic_vector(7 downto 0)); end display; architecture Behavioral of display is begin process (clk) is begin if rising_edge(clk) then if (x < 640) and (y < 480) then if (x = 0) or (x = 639) or (y = 0) or (y = 479) then -- biala ramka color <= x"ff"; else if (y < 160) then -- czerwony pasek na gorze color <= x"e0"; elsif (y < 320) then -- zielony w srodku color <= x"1c"; else -- niebieski na dole color <= x"03"; end if; end if; else color <= x"00"; end if; end if; end process; end Behavioral; Aktualny kod to pierwszy i prosty test. W przyszłości należałoby go zastąpić czymś bardziej użytecznym, np. wyświetlaniem stanu gry (jeśli np. napiszemy grę w pong-a), albo użyć pamięci blokowej i wyświetlać zgromadzone w niej dane. Na razie na sztywno zapisany "obraz kontrolny" musi nam wystarczyć. Sygnały synchronizacji Kolejny krok to napisanie modułu generującego sygnały synchronizacji oraz zliczającego pozycję aktualnego piksela. Na ekranie rysowane są 640 piksele w linii, ale zliczanie współrzędnej x odbywa się od 0 do 799 - nadmiarowe wartości są używane do stwerowania sygnałem synchronizacji. Podobnie jest w przypadku synchronizacji pionowej: zmienna y obejmuje wartości od 0 do 525, ale tylko 480 linii jest widocznych. Warto zwrócić uwagę na "sztuczkę" ze zmiennymi next_x oraz next_y. Moduł odpowiedzialny za określanie kolorów pikseli musi ustawić dane niejako kolejnego piksela, podczas gdy wyświetlany jest poprzedni. Stąd użycie dwóch par zmiennych (z next_ i bez). library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity timings is port( clk : in std_logic; hsync : out std_logic; vsync : out std_logic; red : out std_logic_vector(2 downto 0); green : out std_logic_vector(2 downto 0); blue : out std_logic_vector(2 downto 1) ); end timings; architecture Behavioral of timings is signal x : integer range 0 to 1023; signal y : integer range 0 to 1023; signal next_x : integer range 0 to 1023; signal next_y : integer range 0 to 1023; signal rgb : std_logic_vector(7 downto 0); begin timings: process (clk) is begin if rising_edge(clk) then if (next_x = 799) then next_x <= 0; if (next_y = 525) then next_y <= 0; else next_y <= next_y + 1; end if; else next_x <= next_x + 1; end if; if (y >= 490) and (y < 492) then vsync <= '0'; else vsync <= '1'; end if; if (x >= 656) and (x < 752) then hsync <= '0'; else hsync <= '1'; end if; x <= next_x; y <= next_y; end if; end process; fb: entity display port map (clk => clk, x => next_x, y => next_y, color => rgb); red <= rgb(7 downto 5); green <= rgb(4 downto 2); blue <= rgb(1 downto 0); end Behavioral; Główny moduł Teraz gdy mamy już wszystkie elementy układanki przygotowane pozostaje połączyć je w moduł główny. Musimy w nim utorzyć instancje komponentu zegara (pll) oraz sterownika obrazu (timinig). Kod jest krótki i chyba nie wymaga komentarza: library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity vga_disp is port( clk : in std_logic; hsync : out std_logic; vsync : out std_logic; red : out std_logic_vector(2 downto 0); green : out std_logic_vector(2 downto 0); blue : out std_logic_vector(2 downto 1)); end vga_disp; architecture Behavioral of vga_disp is component pll is port ( CLKIN_IN : in std_logic; CLKFX_OUT : out std_logic); end component; signal clk_pll : std_logic; begin pixel_clock : pll port map (CLKIN_IN => clk, CLKFX_OUT => clk_pll); display : entity timings port map (clk => clk_pll, hsync => hsync, vsync => vsync, red => red, green => green, blue => blue); end Behavioral; Teraz pozostaje zsyntetyzować projekt, wgrać i cieszyć się obrazem na monitorze VGA. Dalsze plany Opisany projekt można dalej rozbudowywać. Użycie zasobów Elbert-a jest na poziomie 2%, więc jeszcze sporo można byłoby dodać, np. wbudowany mikrokontroler, obsługę UART-a, pamięć obrazu itd. 4
FlyingDutch Grudzień 25, 2017 Udostępnij Grudzień 25, 2017 Warto przy okazji zwrócić uwagę, że ten projekt pokazuje zalety FPGA w porównaniu z mikrokontrolerami. Przykładowy sterownik zrealizujemy za pomocą niewielkiej części zasobów naszego i tak niewielkiego układu. Wygenerowanie obrazu za pomocą mikrokontrolera, o ile w ogóle możliwe zajmowałoby ogromną ilość jego zasobów. Cześć Elvis, nawet nie wiesz jak się cieszę, że ktoś to w końcu napisał Wszyscy moi znajomi uważają, że mikro-kontrolery są najlepsze do wszystkiego, a układy programowalne są dla maniaków i nie mają żadnych realnych zastosowań. Dzięki za bardzo ciekawy artykuł, jutro postaram się poćwiczyć kod który napisałeś , może będę miał jakieś uwagi (jak już wspomniałem muszę trochę poczytać o temacie). Udało mi się zsyntetyzować PicoBlaze (z UARTem) tak, że mikro-kontroler do twojego projektu VGA będzie gotowy (walczę tylko z generacją zawartości ROM dla programu PicoBlaze bo dostarczony z projektem assembler "KCPSM3.EXE" to program DOS i nie mogę go uruchomić pod Windows 10), a linki do "pBlazeIDE" prowadzą w próżnię. Pozdrawiam
FlyingDutch Luty 5, 2018 Udostępnij Luty 5, 2018 Cześć Elvis, dzisiaj miałem czas, żeby pobawić się twoim kodem. To dziwne, ale u mnie białą ramkę prawidłowo rysuje przy takich warunkach w entity display: entity display is port( clk : in std_logic; x : in integer range 0 to 1023; y : in integer range 0 to 1023; color : out std_logic_vector(7 downto 0)); end display; architecture Behavioral of display is begin process (clk) is begin if rising_edge(clk) then if (x < 640) and (y < 480) then if (x = 3) or (x = 639) or (y = 0) or (y = 478) then -- biala ramka color <= x"ff"; else if (y < 160) then -- czerwony pasek na gorze color <= x"e0"; elsif (y < 320) then -- zielony w srodku color <= x"1c"; else -- niebieski na dole color <= x"03"; end if; end if; else color <= x"00"; end if; end if; end process; end Behavioral; Pozdrawiam
JTyburski Luty 13, 2018 Udostępnij Luty 13, 2018 VGA to jak to ujmują zwłaszcza na Politechnice Warszawskiej "wymierający standard" (bo taka prawda) - niemniej jak jużto potraficie to zróbcie HDMI (jako ciekawostkę dodam, że jednym z jego elementów składowych jest właśnie sterownik VGA, a więc już połowa roboty wykonana - teraz tylko podłączyć do VGA kodery TMDS i do tych koderów rejestry przesuwne i macie HDMI - jak widać zatem jest to w rzeczywistości "udoskonalone" VGA, albo też "obudowane" czy też "rozszerzone" VGA - dzięki temu nie trzeba nie wiadomo jakich modyfikacji wprowadzać - ot starczy rozszerzyć to co istnieje. Podejście do zastosowania zarówno w FPGA jak w ogóle w samej elektronice (jak ma się VGA na scalaku jakimś to można na FPGA tylko dorobić kodery z rejestrami, spiąć to i mamy już przystosowany np: stary sprzed 20 lat generator obrazów kontrolnych czy starą kartę graficzną, też sprzed 20 lat do współczesnych odbiorników - i tyle - prawda że zajebiście proste? ))
FlyingDutch Luty 13, 2018 Udostępnij Luty 13, 2018 VGA to jak to ujmują zwłaszcza na Politechnice Warszawskiej "wymierający standard" (bo taka prawda) - niemniej jak jużto potraficie to zróbcie HDMI (jako ciekawostkę dodam, że jednym z jego elementów składowych jest właśnie sterownik VGA, a więc już połowa roboty wykonana - teraz tylko podłączyć do VGA kodery TMDS i do tych koderów rejestry przesuwne i macie HDMI - jak widać zatem jest to w rzeczywistości "udoskonalone" VGA, albo też "obudowane" czy też "rozszerzone" VGA - dzięki temu nie trzeba nie wiadomo jakich modyfikacji wprowadzać - ot starczy rozszerzyć to co istnieje. Podejście do zastosowania zarówno w FPGA jak w ogóle w samej elektronice (jak ma się VGA na scalaku jakimś to można na FPGA tylko dorobić kodery z rejestrami, spiąć to i mamy już przystosowany np: stary sprzed 20 lat generator obrazów kontrolnych czy starą kartę graficzną, też sprzed 20 lat do współczesnych odbiorników - i tyle - prawda że zajebiście proste? )) Cześć, dzięki za podpowiedź, jak będzie chwila czasu to popróbuję Na razie to w pracy mam większe obciążenie. Pozdrawiam
JTyburski Luty 13, 2018 Udostępnij Luty 13, 2018 Drobiazg - ja tylko mówię to jako ciekawostka jaka kryje się za tą całą magią HDMI (która szybko pryska jak się odkryje, że to w istocie VGA, tylko ulepszone!) - a także dobre to wskazanie, że stary sprzęt wcale nie taki stary i lekko można go przystosować do współczesnych realiów
Szałszanin Styczeń 6, 2019 Udostępnij Styczeń 6, 2019 (edytowany) Cześć, Udało mi się dziś powtórzyć wasz sukces i mój Elbert też wygenerował 3 pasy z białą ramką na 23" LCD-ku firmy LG. W pierwszym podejściu też bez białej linii ramki na liniach 0. Kombinowałem z czasami, przeliczałem, a na końcu wyszło, że wystarczy wcisnąć przycisk automatycznej korekty pozycji/skali monitora i ramka jest jak trzeba za wszystkich stron... :-). Da się ją wycentrować niezależnie czy czasu impulsów synchronizacji są nieco przesunięte w lewo lub w prawo. Pewnie więc u Elvisa też wystarczyło poprawić pozycję/skalowanie monitora. Pozdrawiam! Edytowano Styczeń 7, 2019 przez Szałszanin 2
Pawel13 Maj 17, 2019 Udostępnij Maj 17, 2019 Witam. Do kodu Elwisa (swoją drogą bardzo pouczającego) dodałem w ramach ćwiczenia funkcjonalność przesuwania granic kolorów, przy pomocy przycisków SW1..SW4. Trochę ciekawiej. Pozdrawiam Elwisa za ciekawy post. VGA.zip 2
monsiw Sierpień 17, 2021 Udostępnij Sierpień 17, 2021 A takie pytanie, jest możliwość wyświetlić obraz na ekranie laptopa przez przejściówkę VGA-HDMI?
H1M4W4R1 Sierpień 17, 2021 Udostępnij Sierpień 17, 2021 6 minut temu, monsiw napisał: A takie pytanie, jest możliwość wyświetlić obraz na ekranie laptopa przez przejściówkę VGA-HDMI? Zacznijmy od tego, że VGA to standard analogowy, a HDMI to standard cyfrowy. Większość przejściówek to kłamstwa, a działające są oparte na specjalnych układach albo FPGA właśnie. Jeżeli już to DVI->HDMI jest możliwe ze względu na kompatybilność wsteczną standardu HDMI. Wracając do pytania - tak da się, ale trzeba trafić w dobrej jakości przejściówkę opartą na jakimś sensownym układzie. Źródła: VGA, HDMI
monsiw Sierpień 17, 2021 Udostępnij Sierpień 17, 2021 5 minut temu, H1M4W4R1 napisał: Zacznijmy od tego, że VGA to standard analogowy, a HDMI to standard cyfrowy. Większość przejściówek to kłamstwa, a działające są oparte na specjalnych układach albo FPGA właśnie. Jeżeli już to DVI->HDMI jest możliwe ze względu na kompatybilność wsteczną standardu HDMI. Wracając do pytania - tak da się, ale trzeba trafić w dobrej jakości przejściówkę opartą na jakimś sensownym układzie. Źródła: VGA, HDMI Ja właśnie próbowałam poprzez przejście w windowsie do Project->second screen only i nic nie pokazało. A jeżeli użyć DVI->HDMI to rozumiem, że by to wygłądało tak, że kabel od FPGA do przejściówki VGA-DVI podłączyć, a ją z kolei do przejściówki DVI-HDMI?
bjrk Sierpień 17, 2021 Udostępnij Sierpień 17, 2021 (edytowany) @monsiw Używałem przelotki VGA->HDMI, była zasilana przez USB i miała kabelek jack do podłączenia dźwięku. Cena (o ile dobrze pamiętam) około 80zł. Te HDMI->VGA były znacznie tańsze. Więc wyświetlić obraz na ekranie monitora z wejściem HDMI można. @H1M4W4R1 Jak spowodować aby gniazdo HDMI w komputerze (laptopie) pracowało jako wejście? EDIT HDMI to sygnał cyfrowy, więc może się jakoś da (gdzieś spotkałem ofertę na na nagrywarkę z wejściem HDMI i zapisem na dysku w jakimś "zjadliwym" formacie). Edytowano Sierpień 17, 2021 przez bjrk Uzupełnienie
H1M4W4R1 Sierpień 17, 2021 Udostępnij Sierpień 17, 2021 3 godziny temu, bjrk napisał: Jak spowodować aby gniazdo HDMI w komputerze (laptopie) pracowało jako wejście? W większości się nie da i jest podpięte jako output. Czasami laptop ma w ustawieniach możliwość przełączenia tej opcji. 4 godziny temu, monsiw napisał: A jeżeli użyć DVI->HDMI to rozumiem, że by to wygłądało tak, że kabel od FPGA do przejściówki VGA-DVI podłączyć, a ją z kolei do przejściówki DVI-HDMI? Nie, to tylko nadmienienie, że HDMI i DVI są kompatybilne, ale z VGA już potrzebujesz przejściówki za ~100zł.
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »