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 wrzesień 2020

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio wrzesień 2020

Świat Radio

Magazyn użytkowników eteru

Automatyka Podzespoły Aplikacje wrzesień 2020

Automatyka Podzespoły Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna wrzesień 2020

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Praktyczny Kurs Elektroniki 2018

Praktyczny Kurs Elektroniki

24 pasjonujące projekty elektroniczne

Elektronika dla Wszystkich sierpień 2020

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów