Sterownik VGA w układzie FPGA

Sterownik VGA w układzie FPGA
Pobierz PDF Download icon
Zastosowanie monitora VGA w aplikacji zrealizowanej w układzie FPGA nie jest trudne. Przekonamy się o tym po lekturze artykułu, w którym zaprezentowano projekt układu, opisanego w językach VHDL i Verilog, umożliwiającego wyświetlenie jakiegoś obiektu na ekranie monitora. Dobry wzorzec dla uczących się VHDL\'a czy Verilog\'a.
90 ELEKTRONIKA PRAKTYCZNA 3/2011 NOTATNIK KONSTRUKTORA Dodatkowe materiały na CD/FTP: ftp://ep.com.pl, user: 10460, pass: 0646g3n0 ? listingi do artukułu Jako przykład implementacji w  ukła- dach programowalnych prostego sterow- nika VGA przedstawiamy projekt układu, którego zadaniem jest wyświetlanie na ekranie monitora poruszającego się i odbi- jającego od czterech krawędzi ekranu pro- stego obiektu zwanego dalej kulką. Kulka w  rzeczywistości jest kwadratem o  boku o zadanej liczbie pikseli. Kulka podczas po- ruszania się po ekranie dodatkowo zmienia cyklicznie swój rozmiar, sprawiając wraże- nie pulsowania i przy każdym odbiciu od górnej krawędzi ekranu zmienia również swój kolor na jeden z trzech kolorów pod- stawowych (czerwony, niebieski, zielony). Obraz wyświetlany jest w  standardowej rozdzielczości VGA (640×480) z częstotli- wością odświeżania równą 60 Hz. W  projekcie wykorzystano fragmenty kodów źródłowych w języku VHDL analo- gicznego projektu autorstwa Douga Hod- sona, opublikowanego na stronie www. retromicro.com. Układ opisany w udo- stępnionym tam projekcie umożliwia wy- świetlanie obrazu kulki o stałej wielkości, poruszającej się po ekranie jedynie w  osi pionowej. Opisywany w artykule układ składa się z dwóch modułów (komponentów): genera- tora sygnałów synchronizacji oraz modułu odpowiedzialnego za animację ruchu kul- ki na ekranie. W opisie projektu w języku VHDL występuje jeszcze trzeci nadrzędny moduł, który definiuje jedynie strukturę połączenia wspomnianych wcześniej kom- ponentów. Generator sygnałów synchronizacji Zadaniem tego modułu jest wytwo- rzenie sygnałów synchronizacji pionowej i  poziomej oraz udostępnienie bieżących zawartości liczników określających współ- rzędne położenia wybieranego w  danej chwili punktu (plamki) na ekranie moni- tora. Sposób działania tego modułu jest zdeterminowany strukturą ramki w  stan- Sterownik VGA w układzie FPGA Zastosowanie monitora VGA w  aplikacji zrealizowanej w  układzie FPGA nie jest trudne. Przekonamy się o  tym po lekturze artykułu, w  którym zaprezentowano projekt układu, opisanego w  językach VHDL i  Verilog, umożliwiającego wyświetlenie jakiegoś obiektu na ekranie monitora. Dobry wzorzec dla uczących się VHDL?a  czy Verilog?a. dardzie VGA. Ramka sygnału VGA była już wielokrotnie opisywana na łamach Elek- troniki Praktycznej (np. w EP 4/2007 przy okazji projektu testera monitorów VGA), dlatego nie będzie omawiana. Na listingu 1 przedstawiono kod w ję- zyku VHDL opisujący generator sygnałów synchronizacji. Oprócz wyjść sygnałów synchronizacji poziomej (horiz_sync_out) i pionowej (vert_sync_out) oraz stanu licz- nika kolumn ? punktów w linii (pixel_co- lumn) i licznika wierszy ? linii (pixel_row), moduł ma również wejścia sygnałów kolo- rów podstawowych (red, green, blue) oraz wyjścia tych sygnałów (red_out, green_out, blue_out). Na wyjściach sygnałów kolorów podstawowych pojawia się ten sam sygnał co na analogicznych wejściach wtedy, gdy liczniki kolumn i wierszy wskazują na ak- tywny obszar ekranu (sygnały video_on_h oraz video_on_v mają poziom wysoki). W czasie trwania przednich i tylnych prze- działów wyrównawczych, jak również pod- czas trwania samych impulsów synchroni- zacji, wyjścia kolorów podstawowych są wyzerowane (obraz jest wygaszany). Moduł animacji ruchu kulki Moduł jest głównym elementem pro- jektu realizującym wszystkie efekty zwią- zane z ruchem kulki na ekranie monitora. Do modułu musi być dostarczony z genera- tora sygnałów synchronizacji impuls syn- chronizacji pionowej oraz stanu liczników wierszy i kolumn. Z kolei wyjścia kolorów podstawowych red, green, blue tego modu- łu powinny być połączone z  analogiczny- mi wejściami modułu generatora sygnałów synchronizacji. Kod opisujący moduł ani- macji ruchu kulki przestawiono na listin- gu 2. W procesie nazwanym RGB_Dsiplay, jest wyliczana wartość sygnału Ball_on, którego poziom wysoki, przy danych war- tościach liczników kolumn i wierszy ozna- cza, że aktualnie wybierany (wyświetlany na ekranie) punkt nie jest punktem tła lecz należy do obszaru zajmowanego przez kul- kę. Sygnał ten jest wyliczany na podstawie koniunkcji stanów odpowiednich relacji (narzędzia syntezy wywnioskują z  tego opisu zespół komparatorów) uwzględnia- jących bieżące położenie kulki (środka kwadratu ? współrzędne Ball_X_pos oraz Ball_Y_pos), rozmiar kulki (bok kwadratu - sygnał Size) oraz stan liczników wierszy i kolumn (współrzędne aktualnie wybiera- nego punktu). Kolejny proces (Move_Ball) aktywo- wany podczas każdego narastającego zbocza sygnału synchronizacji pionowej (vert_sync_out) odpowiada za sterowanie ruchem kulki. W  kolejnych instrukcjach warunkowych sprawdzane są współrzędne położenia środka kulki ? oddzielnie współ- rzędna pozioma i  pionowa oraz uwzględ- niany jest rozmiar kulki. Jeżeli kulka osią- gnęła którąś z krawędzi ekranu nadawana jest odpowiednia wartość zmiennym Bal- l_X_motion oraz Ball_Y_motion. Wartości tych sygnałów następnie służą do wylicze- nia następnego (podczas trwania następnej ramki obrazu) położenia kulki ? następ- nych pionowych i  poziomych współrzęd- nych położenia środka kulki. Na przykład, jeżeli kulka poruszając się w  górę ekranu znalazła się na jego górnej krawędzi (czy- li współrzędna pionowa położenia kulki Ball_Y_pos jest równa rozmiarowi kuli Size ? lewy górny róg ekranu ma współrzędne [0,0]), wówczas sygnałowi Ball_Y_motion nadawana jest wartość pewnej stałej, któ- ra definiuje szybkość poruszania się kulki po ekranie (a  dokładniej szybkość zmian położenia w  osi pionowej). W  przedsta- wionym kodzie na list.  2, wartość tej sta- łej otrzymywana jest poprzez wywołanie funkcji conv_std_logic_vector (w  języku VHDL wielkość liter jest nieistotna), która jedynie dokonuje konwersji liczby całko- witej (pierwszy argument funkcji) o zada- nej liczbie bitów (drugi argument funkcji) do typu standardowego std_logic_vector. Zamiast wywoływania tej funkcji można również wpisać stałą wartość w  kodzie dziesiętnym. W przypadku, gdy kulka osią- gnęła dolną krawędź ekranu, zmiennej Ball_Y_motion nadawana jest wartość tej Dodatkowe materiały na CD/FTP 91ELEKTRONIKA PRAKTYCZNA 3/2011 Sterownik VGA w układzie FPGA Listing 1. Kod opisujący moduł generatora sygnałów synchronizacji library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity VGA_SYNC is port(clock_25Mhz, red, green, blue : in std_logic; red_out, green_out, blue_out, horiz_sync_out, vert_sync_out: out std_logic; pixel_row, pixel_column: out std_logic_vector(9 downto 0)); end VGA_SYNC; architecture sync_gen of VGA_SYNC is signal horiz_sync, vert_sync : std_logic; signal video_on, video_on_v, video_on_h : std_logic; signal h_count, v_count :std_logic_vector(9 downto 0); begin -- video_on przyjmuje poziom wysoki, gdy ma być wyświetlony obraz video_on <= video_on_H and video_on_V; pixel_row <= v_count; pixel_column <= h_count; process begin wait until (clock_25Mhz?EVENT) and (clock_25Mhz=?1?); -- h_count zlicza piksele poziomo (640 + dodatkowe dla sygnału synchronizazji) if h_count = 799 then h_count <= ?0000000000?; else h_count <= h_count + 1; end if; -- v_count zlicza wiersze pikseli (480 + dodatkowe dla sygnału synchronizacji) if (v_count >= 524) and (h_count >= 699) then v_count <= ?0000000000?; elsif h_count = 699 then v_count <= v_count + 1; end if; -- Synchronizacja zmian wybranych sygnałów z sygnałem zegarowym red_out <= red and video_on; green_out <= green and video_on; blue_out <= blue and video_on; horiz_sync_out <= horiz_sync; vert_sync_out <= vert_sync; end process; process (h_count) begin -- Generowanie sygnału synchronizacji poziomej z użyciem h_count -- horiz_sync ------------------------------------__________-------- -- h_count 0 640 659 755 799 if (h_count <= 755) and (h_count >= 659) then horiz_sync <= ?0?; else horiz_sync <= ?1?; end if; -- Generowanie sygnału okreśaljącego obszar aktywny ekranu (H) if (h_count <= 639) then video_on_h <= ?1?; else video_on_h <= ?0?; end if; end process; process (v_count) begin -- Generowanie sygnału synchronizacji pionowej z użyciem v_count -- vert_sync --------------------------------------_____------------ -- v_count 0 480 493-494 524 if (v_count <= 494) and (v_count >= 493) then vert_sync <= ?0?; else vert_sync <= ?1?; end if; -- Generowanie sygnału okreśaljącego obszar aktywny ekranu (V) if (v_count <= 479) then video_on_v <= ?1?; else video_on_v <= ?0?; end if; end process; end sync_gen; samej stałej co poprzednio lecz z zanego- wanym każdym z jej bitów. Nowa składowa pionowa współrzędnej położenia kulki ob- liczana jest poprzez zsumowanie jej bieżą- cej wartości z wartością Ball_Y_motion. Po- nieważ zgodnie z arytmetyką dwójkową dla n-bitowych liczb A i B, A ? B = A + B? +1 (?prim? oznacza negację), gdy kulka osią- gnęła dolną krawędź ekranu (Ball_Y_pos + Size = 479), to od jej pionowej współ- rzędnej jest odejmowana stała wartość (+1 można tutaj zaniedbać) i kulka porusza się w  górę ekranu. Analogicznie oblicza się położenie współrzędnej poziomej kulki. Dodatkowo, wraz z  instrukcjami wa- runkowymi związanymi ze sprawdzaniem pionowego położenia kulki, zaimplemento- wano rejestr przesuwający, który przesuwa o jeden bit w lewo trzybitowy sygnał RGB podczas każdego odbicia kulki od górnej krawędzi ekranu. Sygnał ten odpowiada za kolor wyświetlanej kulki (czerwony, zielony i niebieski). Jest to uwarunkowane zastosowaniem dla sygnału RGB rejestru przesuwającego pracującego w trybie licz- nika pierścieniowego (?krążąca jedynka?). Takie użycie rejestru przesuwającego wy- maga, aby po włączeniu zasilania (zała- dowaniu pliku konfigurującego do układu FPGA) w rejestrze została ustawiona jedyn- ka na wybranej pozycji bitu. Domyślnie po załadowaniu pliku konfigurującego wszyst- kie rejestry (przerzutniki) są zerowane. W  przypadku wykorzystania środowiska projektowego Xilinx ISE i narzędzia synte- zy XST, w celu nadania wartości początko- wej dla wybranych przerzutników, można posłużyć się atrybutem INIT ? tak jak po- kazano to na list.  2 (tuż przed instrukcją begin opisu architektury). Ostatnia sekcja kodu w procesie Move_ Ball odpowiada za modulację rozmiaru wy- świetlanego obiektu. Rozmiar kulki oscylu- je pomiędzy dwiema wartościami granicz- nymi (2 i  24 piksele ? stałe, argumenty funkcji conv_std_logic_vector) i zmienia się o jeden punkt wraz z każdym narastającym zboczem impulsu synchronizacji piono- wej. Implementacja Układ projektu można zrealizować wykorzystując np. zestaw ewaluacyjny ZL9PLD wraz z modułem dipPLD ZL10PLD z układem XC3S200. Ponieważ w zestawie dostępny jest generator sygnału zegarowe- go o częstotliwości 3,6864 MHz, a genera- tor impulsów synchronizacji wymaga do- starczenia sygnału zegarowego o częstotli- wości ok. 25 MHz (dokładnie 25,125 MHz ? ale częstotliwość ta nie jest krytyczna, niewielkie odchyłki od tej częstotliwości mogą spowodować jedynie pewne zmia- ny rozmiarów obrazu na ekranie moni- tora i  ułamkowe zmiany częstotliwości odświeżania), dlatego istnieje potrzeba od- powiedniego powielenia częstotliwości ge- neratora z modułu dipPLD, albo wymiany tego generatora. W  pierwszym przypadku z  pomocą przychodzi blok syntezera czę- stotliwości (DCM) wbudowany w  układ XC3S200. Syntezer można zaprogramo- wać tak, aby jego częstotliwość wyjściowa była iloczynem częstotliwości wejściowej i pewnej liczby wymiernej, której wielkość określana jest poprzez nadanie wartości odpowiednim atrybutom. Taki sposób za- stosowano w  omawianym projekcie. Plik o nazwie chipIO.vhd, którego fragment po- kazano na list. 3 zawiera również, oprócz definicji struktury połączenia modułu ge- neratora impulsów synchronizacji i modu- łu animacji ruchu kulki, opis implemen- tacji syntezera DCM wraz definicją odpo- wiednich atrybutów. Dzięki temu uzysku- je się częstotliwość sygnału zegarowego bardzo bliską właściwej. Dokładnie jest to 24,88  MHz ? ze względu na ograniczenia zakresu odpowiednich współczynników, przy danej częstotliwości wejściowej, nie jest możliwe uzyskanie częstotliwości wyj- ściowej bliższej nominalnej 25,125 MHz. Jak to zrobić w Verilogu Dla tych, którzy preferują język opisu sprzętu Verilog (do grona tych osób zalicza się również autor niniejszego artykułu), podajemy także wersję projektu opisaną w tym właśnie języku. Verilog jest językiem opisu sprzętu, któ- ry powstał nieco później niż VHDL. Począt- 92 ELEKTRONIKA PRAKTYCZNA 3/2011 NOTATNIK KONSTRUKTORA kowo służył jedynie do symulacji układów cyfrowych i dopiero później został zaadap- towany do celów syntezy logicznej. Skład- nia języka Verilog oparta jest na szeroko rozpowszechnionym języku C, podczas gdy składnia VHDL bazuje na obecnie rzadko używanym języku ADA. Język VHDL ma zaawansowane konstrukcje i  abstrakcyjne typy danych, które nie występują w Verilo- gu. Dzięki czemu VHDL znacznie bardziej nadaje się do modelowania behawioral- nego. Jednak tylko stosunkowo niewielki podzbiór instrukcji VHDL akceptowany jest przez narzędzia syntezy. Język Verilog z ko- lei uważany jest za znacznie bliższy sprzę- towi niż VHDL. Przyglądając się kodom w  języku VHDL i  Verilog opisującym ten sam projekt, można odnieść wrażenie, że zazwyczaj kod w języku Verilog jest krótszy, bardziej zwarty i przejrzystszy w porówna- niu do kodu w języku VHDL. Na listingach 4...6 (do pobrania z serwe- ra FTP) przedstawiono kolejno opisy w  ję- zyku Verilog modułu generatora impulsów synchronizacji, modułu animacji ruchu kul- ki oraz modułu nadrzędnego, definiującego połączenia dwóch pierwszych wymienio- nych modułów. Podstawową jednostką projektową w ję- zyku Verilog jest moduł (module), który za- wiera zarówno opis interfejsu jak również opis wnętrza modułu (jego funkcji logicz- nych). Nie ma tu podziału tak jak w języku VHDL, na jednostkę projektową ? interfejs (entity) oraz architekturę (architecture). W Verilogu, podobnie jak w języku C, rozróż- nine są duże i małe litery alfabetu. W Verilogu występują dwa podstawowe typy danych: wire (i  pochodne typu wand, wor, tri) oraz reg. Typ danych wire nie prze- chowuje swojej wartości (tak jak zmienna) lecz reprezentuje fizyczne połączenia w mo- delowanym układzie i zwykle stosowany jest w  kontekście opisu strukturalnego. Danej typu wire można przypisać wynik tzw. przy- pisania ciągłego (continuous assignment ? in- strukcja assign) lub sygnał wyjściowy innego modułu lub bramki logicznej. Typ reg repre- zentuje zmienne w języku Verilog. W  opisie układów kombinacyjnych w  przedstawionym projekcie zastosowano dwie zasadnicze techniki kodowania: wy- korzystanie przypisania do sygnału (signal assignment) w  VHDL (np.: pixel_row <= v_coint;) i odpowiadającemu mu przypisania ciągłe (continuous assignment) w  Verilogu (np.: assign pixel_row = v_count;) oraz wyko- rzystanie sekcji proceduralnej always w Veri- logu i instrukcji process w VHDL, wraz z od- powiednio sformułowanymi listami wrażli- wości (sensitivity list). Lista wrażliwości blo- ku always (Verilog) i process (VHDL) musi zawierać nazwy wszystkich sygnałów, które są wejściami opisywanego układu kombina- cyjnego (wyjście układu kombinacyjnego jest Listing 2. Kod opisujący moduł animacji ruchu kulki library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity ball is port(red,green,blue: out std_logic; vert_sync_out: in std_logic; pixel_row, pixel_column: in std_logic_vector(9 downto 0)); end ball; architecture behavior of ball is signal dir,shift_en, Ball_on : std_logic; signal Ball_Y_motion : std_logic_vector(9 downto 0); signal Ball_X_motion, Size : std_logic_vector(9 downto 0); signal Ball_Y_pos, Ball_X_pos : std_logic_vector(9 downto 0); signal RGB : std_logic_vector(2 downto 0); attribute INIT : string; attribute INIT of RGB : signal is ?001?; begin Red <= RGB(0) when Ball_on = ?1? else ?1?; Green <= RGB(1) when Ball_on = ?1? else ?1?; Blue <= RGB(2) when Ball_on = ?1? else ?1?; -- Ball_on przyjmuje stan wysoki, gdy ma być wyświetlona ?kulka? RGB_Display: process (Ball_X_pos, Ball_Y_pos, pixel_column, pixel_row, Size) begin if (?0? & Ball_X_pos <= pixel_column + Size) and (Ball_X_pos + Size >= ?0? & pixel_column) and (?0? & Ball_Y_pos <= pixel_row + Size) and (Ball_Y_pos + Size >= ?0? & pixel_row ) then Ball_on <= ?1?; else Ball_on <= ?0?; end if; end process RGB_Display; Move_Ball: process begin -- Realizuje przesunięcie kulki raz na każdy przedział sychr. V wait until vert_sync_out?event and vert_sync_out = ?1?; -- odbicie od góry i dołu ekranu if (Ball_Y_pos + Size) >= CONV_STD_LOGIC_VECTOR(479,10) then Ball_Y_motion <= not CONV_STD_LOGIC_VECTOR(2,10); shift_en <= ?0?; elsif Ball_Y_pos <= Size then Ball_Y_motion <= CONV_STD_LOGIC_VECTOR(2,10); if shift_en = ?0? then -- realizacja rejestru przesuwnego RGB <= RGB(1 downto 0) & RGB(2); shift_en <= ?1?; end if; end if; -- wyliczenie następnego pionowego położenia ?kulki? Ball_Y_pos <= Ball_Y_pos + Ball_Y_motion; -- odbicie od lewej i prawej krawędzi ekranu if (Ball_X_pos + Size) >= CONV_STD_LOGIC_VECTOR(639,10) then Ball_X_motion <= not CONV_STD_LOGIC_VECTOR(2,10); elsif Ball_X_pos <= Size then Ball_X_motion <= CONV_STD_LOGIC_VECTOR(2,10); end if; -- wyliczenie następnego poziomego położenia ?kulki? Ball_X_pos <= Ball_X_pos + Ball_X_motion; -- zmiana rozmiaru ?kulki? if Size >= CONV_STD_LOGIC_VECTOR(24,10) then dir <= ?0?; end if; if Size <= CONV_STD_LOGIC_VECTOR(2,10) then dir <= ?1?; end if; if dir = ?1? then Size <= Size + 1; else Size <= Size - 1; end if; end process Move_Ball; end behavior; funkcją bieżącego stanu wejść tego układu). Dla symulatora kod zawarty w bloku always oraz instrukcji process wykonywany jest wówczas, gdy nastąpi zmiana wartości sy- gnału znajdującego się na liście wrażliwości. Drugim istotnym warunkiem opisu układu kombinacyjnego jest to, aby tak organizować przypisania wartości do sygnału reprezentu- jącego wyjście układu kombinacyjnego, aby w każdej ścieżce procesu (bloku always) war- tość tego wyjścia była określona (w układach kombinacyjnych nic nie może być pamięta- ne z poprzedniego stanu). Niespełnienie tego warunku spowoduje, że narzędzia syntezy wywnioskują z  takiego opisu, dla danego wyjścia, przerzutnik typu zatrzask. Przykładem drugiego z  wymienionych sposobów opisu układu kombinacyjnego w omawianym projekcie jest fragment kodu w  module animacji ruchu kulki, opisujący sygnał Ball_on (proces RGB_Display w  opi- sie VHDL ? list. 2 i analogiczny blok always w  opisie Verilog ? list.  5). Należy zwrócić uwagę na znaczenie poszczególnych opera- torów w  języku Verilog. Postać operatorów jak i ich znaczenie są tutaj niemal identyczne jak w języku C. W języku VHDL operator ?&? jest operatorem sklejania (konkatenacji ? ten sam operator w Verilogu ma postać ?{...}?). W  Verilogu ?&?, podobnie jak w  języku C, oznacza operator iloczynu bitowego. Użycie operatora sklejania w  kontekście takim jak w procesie RGB_Display oznacza ?poszerze- nie? sygnału (wektora) Ball_X_pos do 11 bi- tów (?doklejany? bit MSB jest wyzerowany). Taki zabieg nie jest konieczny, jeżeli zapew- 93ELEKTRONIKA PRAKTYCZNA 3/2011 Sterownik VGA w układzie FPGA zegarowy (ogólnie: niezależnie od języka HDL, dla opisu układów sekwencyjnych lista wrażliwości może zawierać jedynie sygnał zegarowy, zerujący lub ustawiający) i  pierwszą instrukcją procesu w  postaci: if (clock_25Mhz?event) and (clock_25Mhz = ?1?) then. W  języku Verilog również można modelować układy sekwencyjne wykorzy- stując blok always z pustą listą wrażliwości. Wówczas wewnątrz bloku always stosuje się instrukcję (jedną lub więcej ? kod pomiędzy tymi instrukcjami opisuje pojedynczy stan automatu) w postaci: @(posedge clk), której skutkiem jest zwieszenie wykonywania in- strukcji bloku do momentu wystąpienia na- rastającego zbocza sygnału clk (podobnie jak wait until (clk?event) and (clk = ?1?) w VHDL). Taki sposób opisu w Verilogu określa się jako projektowanie z  dokładnością cyklu (cycle accurate design). Jednak ten sposób nie jest wspierany przez niektóre narzędzia syntezy, w tym również przez XST Xilinxa. Dlatego też w projekcie zastosowano klasyczny spo- sób opisu układu sekwencyjnego z blokiem always w  postaci: always @(posedge cloc- k_25Mhz) begin ... end. W takim przypadku instrukcje bloku wykonywane są za każdym razem, gdy wystąpi narastające zbocze sy- gnału clock_25Mhz. W języku Verilog warto również zwrócić uwagę na dwa rodzaje przypisań procedural- nych: blokujące (operator ?=?) oraz nieblo- kujące (operator ?<=?). Analogiczne typy przypisań nie występują w VHDL, a począt- kującym użytkownikom Veriloga sprawiają pewne kłopoty. W  dużym skrócie przypi- sanie blokujące (?=?) możemy traktować jako przypisanie natychmiastowe. Wartość zmiennej, której przypisano wartość z  uży- ciem operatora ?=?, jest znana już w  na- stępnej linijce kodu (następnej instrukcji). Przypisanie nieblokujące z operatorem ?<=? używane jest w kontekście zdarzeń związa- nych ze zboczem narastającym lub opadają- cym wybranego sygnału (zazwyczaj zegara lub sygnału zerującego) i odnosi skutek do- piero wówczas gdy to zdarzenie wystąpi. Podsumowanie Tworzenie aplikacji z układami FPGA, w których do wizualizacji danych wyko- rzystuje się monitor VGA, jest stosunkowo nieskomplikowane. Omawiany projekt nie- wielkim nakładem pracy można uatrakcyj- nić budując prostą grę zręcznościową na wzór znanej gry komputerowej ?Arkanoid?. Na przykładzie projektu pokazano również możliwość użycia dwóch języków opisu sprzętu: VHDL i Verilog. Przejście od opisu układu w  jednym języku do opisu w drugim ? w typowych przypadkach ? nie jest skomplikowane, ale wymaga jednak pewnej wiedzy. Zbigniew Hajduk zhajduk@prz-rzeszow.pl sujący układ sekwencyjny (VHDL ? list.  1, Verilog ? list. 4). W języku VHDL mamy in- strukcję process z  pustą listą wrażliwości, ale na początku znajduje się instrukcja wait. Dalsze instrukcje procesu są wykonywane tylko wówczas, gdy warunek po instrukcji wait będzie prawdziwy ? w  tym przypad- ku, gdy wystąpi narastające zbocze sygnału zegara (clock_25MHz). Alternatywny opis w VHDL, dający w wyniku syntezy taki sam układ, składałby się z instrukcji process z li- stą wrażliwości zawierającą tylko sygnał Listing 3. Kod opisujący moduł nadrzędny projektu entity chipIO is port( pin_sysclk : in std_logic; pin_vga_red : out std_logic; pin_vga_green : out std_logic; pin_vga_blue : out std_logic; pin_vga_hsync_n : out std_logic; pin_vga_vsync_n : out std_logic ); end chipIO; architecture arch of chipIO is signal sysClk : std_logic; component VGA_SYNC port( clock_25Mhz : in std_logic; red, green, blue : in std_logic; red_out, green_out, blue_out : out std_logic; horiz_sync_out, vert_sync_out : out std_logic; pixel_row, pixel_column : out std_logic_vector(9 downto 0)); end component; signal vga_pixel_row : std_logic_vector(9 downto 0); signal vga_pixel_column : std_logic_vector(9 downto 0); signal vga_vert_sync_out : std_logic; component ball port( signal red,green,blue : OUT std_logic; signal vert_sync_out : in std_logic; signal pixel_row, pixel_column : in std_logic_vector(9 downto 0)); end component; component DCM port(CLKFX: out std_logic; CLKIN: in std_logic); end component; attribute CLKFX_MULTIPLY: integer; attribute CLKFX_DIVIDE: integer; attribute CLK_FEEDBACK: string; attribute CLKIN_PERIOD: integer; attribute CLK_FEEDBACK of VGA_clock: label is ?NONE?; attribute CLKFX_MULTIPLY of VGA_clock: label is 27; attribute CLKFX_DIVIDE of VGA_clock: label is 4; attribute CLKIN_PERIOD of VGA_clock: label is 275; signal ball_red : std_logic; signal ball_green : std_logic; signal ball_blue : std_logic; begin vgadriver: VGA_SYNC port map( clock_25Mhz => sysClk, red => ball_red, green => ball_green, blue => ball_blue, red_out => pin_vga_red, green_out => pin_vga_green, blue_out => pin_vga_blue, horiz_sync_out => pin_vga_hsync_n, vert_sync_out => vga_vert_sync_out, pixel_row => vga_pixel_row, pixel_column => vga_pixel_column ); pin_vga_vsync_n <= vga_vert_sync_out; balldriver: ball port map(red => ball_red, green => ball_green, blue => ball_blue, vert_sync_out => vga_vert_sync_out, pixel_row => vga_pixel_row, pixel_column => vga_pixel_column); -- pin_sysclk=3.6864MHz, sysClk=24.88MHz VGA_clock : DCM port map(CLKIN => pin_sysclk,CLKFX => sysClk); end arch; nimy, że prawa strona operatora relacji nie przekroczy rozmiaru 10 bitów. W  omawia- nym projekcie tak jest (maksymalna wartość pixel_column + Size to 824 ? liczba, którą można bez problemu zapisać na 10 bitach), dlatego też w kodzie w języku Verilog, w tym przypadku zrezygnowano z użycia operatora sklejania. Instrukcja process oraz blok always może służyć również do opisu układów sekwen- cyjnych. Rozważmy fragment kodu modułu generatora impulsów synchronizacji opi-
Artykuł ukazał się w
Marzec 2011
DO POBRANIA
Pobierz PDF Download icon

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik kwiecień 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio marzec - kwiecień 2024

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka, Podzespoły, Aplikacje marzec 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna kwiecień 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich kwiecień 2024

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów