Akademia Górniczo Hutnicza im. Stanisława Staszica w Krakowie Wydział EAIiE Katedra Elektroniki Technika Cyfrowa Wprowadzenie do laboratorium komputerowego http://www.fpga.agh.edu.pl
1. Wstęp Celem niniejszego ćwiczenia jest zapoznanie z różnymi sposobami projektowania cyfrowych układów kombinacyjnych przy użyciu języków opisu sprzętu (Hardware Description Languages). Do tego celu wykorzystany zostanie język VHDL. Ponadto Uczestnicy kursu zostaną zapoznani z dedykowanym środowiskiem programistycznym firmy Xilinx narzędziem ISE oraz zaimplementują prostą funkcję logiczną w układzie Spartan 3, który stanowi serce systemu developerskiego Spartan-3 firmy Digilent. 2. Wprowadzenie do narzędzia ISE Web Pack Korzystając z Menu Start systemu Windows proszę uruchomić narzędzie ISE Project Navigator firmy Xilinx. Menu Start Xilinx ISE Design Suite 14.x ISE Design Tools Project Navigator Program można uruchomić alternatywnie korzystając z ikony znajdującej się na Pulpicie. 2
Otworzy się okno narzędzia ISE Project Navigator. W jego lewej górnej części znajduje się schierarchizowane drzewo aktualnie używanego projektu (1) oraz dwa dostępne widoki implementacji oraz symulacji (2). Poniżej znajduje się okienko pozwalające wybrać szereg działań dla aktualnie używanego projektu, np. jego syntezę i implementację (3). Poniżej okienka znajduje się pasek zakładek (4) sterujący widokiem drzewa projektu. Centralnie na dole umieszczono okno konsoli (5). Z prawej strony znajduje się natomiast główne okno programu (6). 2 1 3 6 4 5 3
Tworzenie nowego projektu sprowadza się do wyboru z zakładki File opcji New Project File New Project 4
W nowootwartym oknie czarodzieja proszę stosownie nazwać projekt, a następnie określić katalog, w którym zostanie on utworzony. UWAGA! Narzędzie ISE nie toleruje znaku spacji w ścieżce dostępu do katalogu roboczego projektu. Należy o tym każdorazowo pamiętać tworząc/przenosząc projekt na różnych maszynach. Name: Projekt1 Location: C:\MyXilinx\Projekt1 (przykładowo) Na koniec proszę kliknąć na przycisku Next. Next 5
W nastepnym oknie należy wybrac docelowy układ, w którym projekt ma zostać zaimplementowany. Ponieważ w trakcie kursu do celów implementacyjnych wykorzystywana będzie płytka Nexys3, toteż proszę wybrać układ docelowy taki, jaki znajduje się na płytce. Family Spartan3 Device XC3S200 Package FT256 Speed -5 Proszę dopilnować również, aby wybrane zostały stosowne (domyślne) narzędzia do syntezy i implmentacji. Synthesis Tool XST (VHDL/Verilog) Simulator ISim (VHDL/Verilog) Preferred Language VHDL VHDL Source Analysis Standard VHDL-93 Po wybraniu wszystkich opcji proszę kliknąc na przycisku Next. Next 6
Ostatnie okno czarodzieja stanowi podsumowanie nowoutworzonego projektu. Po zapoznaniu się z nim proszę kliknąć na przycisku Finish. 7
3. Funkcja dokładnie jeden z trzech Funkcja typu dokładnie jeden z N zwraca wartość 1 wtedy i tylko wtedy, gdy dokładnie jeden argument wejściowy przyjmuje wartość 1. Schemat ideowy kombinacyjnego układu cyfrowego o takiej funkcjonalności oraz jego tablicę prawdy przedstawiono poniżej. x 1 x 2 x 3 y 0 0 0 0 0 0 1 1 0 1 0 1 0 1 1 0 1 0 0 1 1 0 1 0 1 1 0 0 1 1 1 0 Zmienne x 1, x 2 i x 3 z tablicy powyżej odpowiadają wejściom układu, podczas gdy zmienna y odpowiada jego wyjściu. Przystąpimy teraz do opisania trójargumentowej funkcji dokładnie jeden z trzech w języku VHDL na kilka różnych, równoważnych sposobów, tak by zaznajomić się z różnymi konstrukcjami tego języka. 3.1. Operatory boolowskie W języku VHDL wyróżnić można 6 następujących operatorów logiki dwuargumentowej (tzw. operatory boolowskie) AND, NAND, OR, NOR, XOR i XNOR oraz 1 operator jednoargumentowy NOT. Przy ich pomocy stworzymy element o funkcjonalności dokładnie jeden z trzech. Proszę kliknąć prawym przyciskiem myszy w oknie drzewa projektu i z menu kontekstowego wybrać opcję New Source New Source 8
W oknie czarodzieja proszę wybrać moduł VHDL, nazwać go stosownie i kliknąć przysick Next. VHDL Module File name: podejscie1 (przykładowo) Next Czarodziej pozwala na przyspieszenie etapu projektowania modułu poprzez zdefiniowanie wszystkich wejść i wyjść elementu. Z opcji tej można skorzystać (co też uczynimy teraz) lub pominąć ten etap klikająć Next. Proszę zdefiniować 3 porty wejściowe oraz jeden wejściowy, po czym kliknąć przycisk Next. Port Name: x1 in (przykładowo) x2 in (przykładowo) x3 in (przykładowo) y out (przykładowo) Next 9
Ostatnie okno czarodzieja stanowi podsumowanie stworzonego elementu. Po zapoznaniu się z nim proszę kliknąć przycisk Finish. W oknie głównym narzędzia ISE otwarta została zawartość pliku podejscie1.vhd, w którym wyróżnić można trzy główne partie deklarację dołączonych bibliotek (1); entity elementu (2), czyli definicję jego wejść i wyjść (interfejs komunikacyjny); architekturę elementu wraz z opisem jego funkcjonalności (3). Ta ostatnia część pozostaje na razie pusta. library IEEE; use IEEE.STD_LOGIC_1164.ALL; 1 entity podejscie1 is Port ( x1 : in STD_LOGIC; x2 : in STD_LOGIC; x3 : in STD_LOGIC; y : out STD_LOGIC); end podejscie1; 2 architecture Behavioral of podejscie1 is begin 3 end Behavioral; Proszę umieścić pomiędzy klauzulą begin, oznaczającą początek opisu działania elementu, a klauzulą end nazwa_architektury, kod opisujący działanie trójargumentowej funkkcji dokładnie jeden z N. UWAGA! Język VHDL nie należy do grupy języków case sensitive, co oznacza że wielkość liter nie odgrywa żadnego znaczenia. Proszę o tym pamiętać przy nazywaniu komponentów, portów, zmiennych, itp. Proszę zwrócić uwagę na konieczność użycia nawiasów w celu wskazania kolejności wykonywania działań. y <= ((not x1) and (x2 xor x3)) or (x1 and (x2 nor x3)); Plik po wprowadzeniu zmian proszę zapisać, a następnie wykonać syntezę elementu w celu sprawdzenia jego poprawności. Proszę kliknąć prawym przyciskiem myszy na opcji Synthesize XST i z menu kontekstowego wybrać opcję Run. Synthesize XST Run Syntezę można również przeprowadzić klikając dwukronie na opcji Syntesize XST. 10
Bezbędnie zakończona synteza objawia się stosownym komentarzem w oknie konsoli oraz zielonym znaczkiem obok opcji Synthesize XST 3.2. Konstrukcja with select Konstrukcja with select jest jednym z najbardziej podstawowych instrumentów opisu funkcjonalności układu cyfrowego z użyciem języka VHDL. Dobrze zaprojektowana, uwzględnia wszystkie możliwe do wystąpienia stany wejściowe i reakcję układu na nie. W sposób identyczny jak poprzednio proszę dodać do projektu nowy moduł. Powinien on posiadać 3 wejścia i 1 wyjście. Proszę go stosownie nazwać (np. podejscie2). Wewnątrz architektury nowego elementu, ale przed klauzulą begin proszę zadeklarować nowy sygnał pomocniczy tmp (1). Sygnał ten powinien być wektorem co oznacza, że składać się będzie z więcej niż jednego bitu. W tym konkretnym przypadku sygnał tmp powinien mieć szerokość 3 bitów. Po zadeklarowaniu sygnał jest gotowy do użycia. Zaraz po klauzuli begin proszę przypisać do sygnału tmp wektor składający się ze sklejonych ze sobą trzech danych wejściowych x 3, x 2 i x 1 (konkatenacja bitów). Do tego celu proszę wykorzystać operator & (2). Mając już przygotowany sygnał pomocniczy, przystąpmy do opisu układu przy użyciu tablicy prawdy. O stanie wyjścia y decyduje stan wejść x 1-3. Na wyjściu y powinien wystąpić stan 1, gdy w sygnale pomocniczym tmp wystąpi choć jedna wartość 1. Wykorzystując konstrukcję with select przypisujemy do wyjścia y wartość 1 wtedy, gdy w sygnale tmp pojawia się dokładnie jedna jedynka. W każdym innym przypadku wartość wyjścia y wynosi 0 (3). Oczywiście można zdefiniować wszystkich 8 warunków niezależnie, jednak znacznie prościej i szybciej ograniczyć się do zdefiniowania dokładnie tylko tych, których jest mniej (w naszym przypadku warunków wystąpienia 1 na wyjściu), a wszystkie pozostałe opisać przy użyciu dyrektywy when others. architecture Behavioral of podejscie2 is signal tmp : STD_LOGIC_VECTOR(2 downto 0); 1 begin tmp <= x3 & x2 & x1; with tmp select y <= '1' when "001", '1' when "010", '1' when "100", '0' when others; 2 3 end Behavioral; Czasami w literaturze anglosaskiej konstrukcja with select bywa nazywana tablicą prawdy (truth table), ze względu na są specyficzną budowę. Proszę zwrócić uwagę na sposób opisu funkcjonalności implementowanego w języku VHDL elementu. We wcześniejszym przypadku została użyta funkcja zawierająca 5 różnych operatorów boolowskich. Osiągnięta w ten sposób funkcjonalność była identyczna z zamierzoną. W przypadku konstrukcji when select wykorzystano postać kanoniczną, którą w prosty sposób można odczytać z tablicy prawdy przedstawionej na samym początku punktu 3. niniejszej instrukcji. W tym przypadku również osiągnięto funkcjonalność identyczną z zamierzoną. 11
Proszę kliknąć prawym przyciskiem myszy na nazwie pliku podejscie2 i z menu kontekstowego wybrać opcję Set as Top Module. Moduł o nazwie podejscie2 jest teraz modułem nadrzędnym i wszystkie operacje, które będziemy wykonywać w programie ISE, odnosić się będą właśnie do niego. Proszę wykonać syntezę elementu. podejscie2 Set as Top Module Pojawi się ostrzeżenie o utracie danych z syntezy w następstwie zmiany modułu nadrzędnego. Proszę je zignorować klikając przycisk Yes. Yes 3.3. Konstrukcja when else Konstrukcja when else ma zbliżoną budowę do poznanej poprzednio konstrukcji with select. Tak jak poprzednio proszę dodać do projektu nowy moduł składający się z 3 wejść i 1 wyjścia, a także stosownie go nazwać (np. podejscie3). Po klauzuli begin proszę umieścić konstrukcję jak poniżej. Opisuje ona warunek, dla jakiego wyjście y przyjmuje wartość logicznego 1. Dla wszystkich pozostałych przypadków wyjście przyjmuje wartość 0. y <= '1' when ((x1 and (x2 nor x3)) or (x2 and (x1 nor x3)) or (x3 and (x1 nor x2))) = '1' else '0'; Moduł proszę ustawić jako nadrzędny, po czym zweryfikować poprawność użytej składni poddając go operacji syntezy. 12
3.4. Instrukcja warunkowa if Instrukcja warunkowa if jest bodajże najczęściej stosowaną instrukcją języka VHDL. W przeciwieństwie do poprzednio poznanych klauzul, instrukcja if pojawić się może jedynie wewnątrz procesu. Poznane poprzednio klauzule należały do grupy tzw. concurent statements, tzn. w przypadku wystąpienia więcej niż jednej klauzuli concurent statement wewnątrz architektury modułu, każda z nich zostanie zsyntezowana jako osobny, niezależny od innych blok logiczny. Tylko wewnątrz procesu mogą wystąpić tzw. sequential statements, a wszystkie wykonujące się w nim instrukcje są uzależnione od zmiany stanu sygnału, od którego proces jest uzależniony. Identycznie jak uprzednio proszę utworzyć nowy moduł VHDL, który będzie opisywał trójargumentową funkcję dokładnie jeden z N, ale tym razem z wykorzystaniem funkcji procesu i instrukcji warunkowej if. Zaraz po pierwszej klauzuli begin (odnoszącej się do architektury) proszę zadeklarować nowy proces o nazwie main (1). Proces nie musi posiadać żadnej nazwy, jednak dobre nawyki programistyczne wymuszają nadawanie indywidualnych nazw poszczególnym procesom (bardziej przejrzysty i łatwiejszy w debugowaniu kod). Proces należy uzależnić od zmian stanów na portach x 1, x 2 i x 3. Proszę zdefiniować pierwszy warunek if (2), dla którego wartość na wyjściu y wyniesie 0. Następnie proszę przepisać kod wg poniższego wzorca. W kodzie specjalnie zdefiniowano jedynie 6, a nie 7 warunków. Proszę wykorzystać klauzulę elsif (3) będącą połączniem klauzul else i if. Listę warunków if kończy się klauzulą end if. Przed końcem opisu architektury pozostaje jeszcze tylko zakończyć proces main. Proszę zwrócić uwagę na fakt, że użycie nawiasów okazało się niezbędnym w celu wskazania poprawnej kolejności wykonania poszczególnych operacji. architecture Behavioral of podejscie4 is begin main : process(x1, x2, x3) begin if(((not x1) and (not x2) and (not x3)) = '1') then y <= '0'; elsif((x1 and (not x2) and (not x3)) = '1') then y <= '1'; elsif(((not x1) and x2 and (not x3)) = '1') then y <= '1'; elsif(((not x1) and (not x2) and x3) = '1') then y <= '1'; elsif((x1 and (not x2) and x3) = '1') then y <= '0'; elsif(((not x1) and x2 and x3) = '1') then y <= '0'; elsif((x1 and x2 and x3) = '1') then y <= '0'; end if; 1 2 3 end process main; end Behavioral; W trakcie korzystania z instrukcji warunkowej if bardzo łatwo wygenerować tzw. latch (zatrzask). Zatrzask nigdy nie zostanie stworzony, jeśli tworząc listę instrukcji if uwzględni się 13
wszystkie możliwe do wystąpienia stany lub też (co prostsze) przypisze się pewną domyślną wartość dla wszystkich nieistotnych z punktu widzenia programisty stanów. Plik vhd proszę zapisać i zsyntezować. Przy opcji syntezy pojawi się znak ostrzeżenia, a w oknie konsoli komunikat o tym, że narzędzie do syntezy XST odnalazło 1 bitowy zatrzask na wyjściu y. Problemom jakie stwarza powstały zatrzask oraz sposobem jego eliminacji zajmiemy się później. W 90% przypadków zatrzask jest tworem niepożądanym i należy go eliminować, istnieją jednak takie przypadki, gdy jest on jak najbardziej upragniony (np. wyzwolenie jakiegoś modułu, który od chwili wyzwolenia powinien działać nieprzerwanie). 3.5. Instrukcja warunkowa case Składnię zbliżoną do konstrukcji with select, ale zarezerwowaną jedynie dla procesu posiada klauzula case is. Tak jak poprzednio proszę dodać do projektu nowy moduł składający się z 3 wejść i 1 wyjścia, a także stosownie go nazwać (np. podejscie5). Po klauzuli begin proszę umieścić konstrukcję jak poniżej. W procesie main uzależnionym od stanu wejść x 1-3 proszę zdefiniować zmienną Q (variable) o szerokości bitowej równej 3 (1). W odróżnieniu od sygnałów, zmienne definiuje się i używa wewnątrz tylko jednego procesu. Poprzez analogię do innych języków programowania, signal należy traktować jako zmienną globalną, a variable jako zmienną lokalną. Różnic pomiędzy oboma jest oczywiście znacznie więcej. Następnie proszę utworzyć trójargumentowy wektor złożony z wejść x 1-3 i przypisać go do zmiennej Q (2). Proszę zdefiniować stan wyjścia y w zależności od stanu zmiennej Q, wykorzystując do tego instrukcję case (3). main : process(x1, x2, x3) variable Q : STD_LOGIC_VECTOR(2 downto 0); 1 begin Q := x1 & x2 & x3; case Q is when "001" => y <= '1'; when "010" => y <= '1'; when "100" => y <= '1'; when others => y <= '0'; end case; 2 3 end process main; Moduł proszę ustawić jako nadrzędny, po czym zweryfikować poprawność użytej składni poddając go operacji syntezy. 14
3.6. Schematic Tak jak poprzednio proszę dodać do projektu nowy plik schematic, a także stosownie go nazwać (np. podejscie6). Pojawią się dwa nowe okna. Po prawej stronie otworzyło się okno do edycji schematu (1). Po lewej stronie pojawiło się okno z listą dostępnych do wykorzystania symboli (2) 2 1 Z kategorii symboli należy wybrać logic, a wśród samych symboli należy wyszukać potrzebne do realizacji schematu bramki 15
Połączenia pomiędzy bramkami proszę zrealizować za pomocą ikonki (1). Za dodawanie wejść i wyjść odpowiada (2) 1 2 Nazwę odpowiedniego wejścia lub wyjścia nadajemy podpisując nazwę połączenia pomiędzy bramką a danym wejściem/ wyjściem. W tym celu proszę dwukrotnie kliknąć myszką na połączeniu. Pojawi się okno parametrów danego połączenia. 16
Schemat układu po połączeniu bramek i wejść i wyjścia przedstawia się jak na rysunku po prawej stronie. W celu zweryfikowania schematu proszę przeprowadzić syntezę. 4. Test bench Podstawowym krokiem poprzedzającym fizyczne uruchomienie modułu jest jego symulacja. W przypadku języków HDL takich jak VHDL i Verilog, symulacja poprawności ich działania sprowadza się do napisania tzw. test bencha. Test bench przygotowuje się również w którymś z tych języków. Wykorzystując czarodzieja proszę dodać do projektu plik nowego test bencha w języku VHDL, nazwać go stosownie, po czym kliknąć na przycisku Next. VHDL Test Bench File name: testb Location: C:\MyXilinx\Projekt1 (przykładowo) Next 17
W następnym oknie podejmuje się decyzję, z którym z modułów napisanym w języku VHDL skojarzony zostanie nowotworzony test bench. Proszę go skojarzyć z pierwszym z modułów po czym kliknąć na przycisku Next. podejscie4 Next Ostatnie okno stanowi podsumowanie do nowoutworzonego pliku test bencha. Po zapoznaniu się z nim proszę kliknąć na przycisku Finish. Nowoutworzony plik zostanie automatycznie otwarty w oknie głównym aplikacji ISE. Przed dokładniejszym zapoznaniem się z nim, proszę wpierw przełączyć widok drzewa projektu z widoku implementacji na widok symulacji. View: Simulation W widoku hierarchii drzewa projektu widoczne jest skojarzenie pliku test bencha z modułem podejscie4. Całość nazywa się uut (Unit Under Test). 18
Test bench wygenerowany przez czarodzieja powstaje w oparciu o uniwersalny szablon, przez co nie jest od razu gotowy do użycia. Należy go zatem dostosować do własnych potrzeb. Wzorzec przedstawiono poniżej. Test bench rozpoczyna się od deklaracji dołączonych bibliotek (1). Wewnątrz jego architektury (2) zdefiniowane zostają komponenty poddane symulacji, wejścia i wyjścia do test bencha oraz wielkości pomocnicze (jeśli takie są potrzebne). Następnie pojawia się mapa portów (3), czyli zestawienie połączeń pomiędzy portami używanych komponentów a sygnałami używanymi jako wejścia i wyjścia z test bencha. W procesie definiuje się wymuszenia oraz momenty ich wystąpienia (4). Korzystając z instrukcji wait for oraz występującego zaraz po niej czasu przez jaki wymuszenie ma trwać, proszę zadeklarować wewnątrz procesu symulacji wszystkich 8 możliwych do wystąpienia stanów wejściowych. LIBRARY ieee; USE ieee.std_logic_1164.all; 1 ENTITY testb IS END testb; ARCHITECTURE behavior OF testb IS 2 -- Component Declaration for the Unit Under Test (UUT) COMPONENT podejscie4 PORT( x1 : IN std_logic; x2 : IN std_logic; x3 : IN std_logic; y : OUT std_logic ); END COMPONENT; BEGIN --Inputs signal x1 : std_logic := '0'; signal x2 : std_logic := '0'; signal x3 : std_logic := '0'; --Outputs signal y : std_logic; constant period : time := 10 ns; -- Instantiate the Unit Under Test (UUT) uut: podejscie4 PORT MAP ( x1 => x1, x2 => x2, 3 x3 => x3, y => y ); -- Stimulus process stim_proc: process begin -- hold for 50 ns. wait for 50 ns; x1 <= '0'; x2 <= '0'; 4 19
END; x3 <= '0'; wait for period; x1 <= '1'; x2 <= '0'; x3 <= '0'; wait for period; x1 <= '0'; x2 <= '1'; x3 <= '0'; wait for period; x1 <= '1'; x2 <= '1'; x3 <= '0'; wait for period; x1 <= '0'; x2 <= '0'; x3 <= '1'; wait for period; x1 <= '1'; x2 <= '0'; x3 <= '1'; wait for period; x1 <= '0'; x2 <= '1'; x3 <= '1'; wait for period; x1 <= '1'; x2 <= '1'; x3 <= '1'; wait; end process; Po wprowadzeniu wszystkich zmian do pliku i zapisaniu go, proszę sprawdzić poprawność jego składni klikając prawym przyciskiem myszy na opcji Behavioral Chceck Synteax i wybierając z menu kontekstowego opcję Run. Behavioral Check Syntax Run Alternatywna forma uruchomienia checkera to dwukrotne kliknięcie myszką na opcji Behavioral Check Syntax. Jeśli wszystko zostało wpisane bezbłędnie, program nie wykryje żadnych błędów składni i można przejść do kolejnego kroku. 20
Przed uruchomieniem symulacji pozostaje jeszcze tylko ustawić poprawnie jej opcje. W tym celu proszę kliknąć prawym przyciskiem myszy na opcji Simulate Behavioral Model i z menu kontekstowego wybrać opcję Process Properties Simulate Behavioral Model Process Properties W oknie właściwości symulacji proszę zmienić czas trwania symulacji z domyślnej wartości 1000 [ns] na 150 [ns]. Simulation Run Time 150 ns Następnie proszę kolejno kliknąć na przyciskach Apply i OK. Apply OK 21
Proszę uruchomić symulację klikając na opcji Simulate Behavioral Model prawym przyciskiem myszy i wybierając z menu kontekstowego opcję Run. Simulate Behavioral Model Run Symulację można uruchomić alternatywnie poprzez dwukrotne kliknięcie myszą na opcji Simulate Behavioral Model. Otwarty zostanie symulator ISim. W jego dolnej części, centralnie pośrodku znajduje się okno konsoli Console (1). Z lewej strony znajdują się dwa małe okna (2) zawierające shierarchizowane drzewo procesów podlegających symulacji oraz listę wszystkich wejść, wyjść, sygnałów, stałych i zmiennych występujących w symulowanych komponentach. Z lewej strony widnieje okno główne symulatora ISim (3). 2 3 1 22
W oknie głównym ISim widoczne będą przebiegi zadeklarowanych przez nas wymuszeń dla portów wejściowych oraz odpowiedź na te wymuszenia dla portu wyjściowego. Przebiegi są zazwyczaj niedopasowane do okna symulatora, toteż proszę kliknąć na ikonie Zoom to Full View, Zoom to Full View a następnie przyjrzeć się wyświetlonym przebiegom. Przez pierwszych 50 [ns] na wszystkich trzech wejściach panuje stan niski 0. Pojawienie się wartości 1 najpierw tylko na wejściu x 1, a zaraz potem tylko na wejściu x 2 wymusza stan 1 na wyjściu y. Ponieważ dla komponentu podejscie4 nie został zdefiniowany warunek dla jednoczesnego pojawienia się stanu 1 na wejściach x 1-2, co doprowadziło do powstania zatrzasku, układ nie wie jak się zachować i przepisuje na wyjście y ostatni stan. Innymi słowy na wyjściu y zostaje wystawiony ostatni, zatrzaśnięty stan. Dla wszystkich kolejnych stanów wejściowych układ działa poprawnie. Obserwowane przebiegi wskazują, że nie osiągnięto zamierzonej funkcjonalności elementu. Wszystkie wymuszenia zostały zdefiniowane poprawnie, a więc należy wyeliminować błąd w opisie symulowanego modułu. Błąd można usunąć dopisując jeden, brakujący warunek lub też (co prostsze) definiując stan domyślny. Wewnątrz architektury komponentu podejście4 proszę umieścić kod jak poniżej. architecture Behavioral of podejscie4 is begin main : process(x1, x2, x3) begin end process main; end Behavioral; if((x1 and (not x2) and (not x3)) = '1') then y <= '1'; elsif(((not x1) and x2 and (not x3)) = '1') then y <= '1'; elsif(((not x1) and (not x2) and x3) = '1') then y <= '1'; else y <= '0'; end if; 23
Stan domyślny został utworzony poprzez dodanie warunku else, który definiuje, że dla wszystkich przypadków nie ujętych przy użyciu instrukcji warunkowej if, na wyjściu y wystąpi stan 0. Po wprowadzeniu zmian plik podejscie4.vhd proszę zapisać, po czym moduł poddać syntezie. W przypadku braku jakichkolwiek błędów uruchomić ponocnie symulator ISim. Wygenerowane przebiegi wejściowe i wyjściowy powinny być identyczne z zamierzonymi, tj. stan 1 na wyjściu powinien wystąpić wtedy i tylko wtedy, gdy na dokładnie jednym wejściu pojawia się stan 1. 24
5. Płyta ewaluacyjna Spartan-3 Wykonana zostanie teraz sprzętowa implementacja funkcji dokładnie jeden z trzech z użyciem układu FPGA z rodziny Spartan-3, który znajduje się na płycie ewaluacyjnej firmy Digilent. Płyta będzie zasilana i programowana z komputera PC przy pomocy interfejsu USB 2.0. Przewód USB, który do tego posłuży dołączono do zestawu. Proszę dopilnować, aby został on poprawnie dołączony do komputera oraz płyty Spartan 3, tj. złączem USB do gniazda w komputerze, a złączem mini USB do gniazda mini USB znajdującego się na płycie Spartan 3, oznaczonego jako J7 (2). 2 1 25
Wejścia implementowanego modułu zostaną dołączone do 3 kolejnych przełączników DIP SWITCH (1), oznaczonych na płycie jako SW0, SW1 i SW2. Zmiana ich położenia z górnego na dolne spowoduje zmianę stanu na porcie wejściowym z wysokiego ( 1 ) na niski ( 0 ). Wyjście z modułu zostanie dołączone go diody LED oznaczonej jako LD7 (2). Jej zapalenie sygnalizować będzie stan wysoki ( 1 ), podczas gdy wygaszenie odpowiada stanowi niskiemu ( 0 ). 2 1 26
6. Plik ucf Przed przystąpieniem do sprzętowej implementacji projektu musi zostać wykonane jeszcze odpowiednie przypisanie portów wejścia i wyjścia do fizycznych wyprowadzeń układu FPGA. Przy większości z elementów znajdujących się na płytce Spartan-3 widnieją prócz nazw również oznaczenia w nawiasach okrągłych (np. BTNL jest oznaczony dodatkowo jako (C4)). Symbole w nawiasach odnoszą się do wyprowadzenia układu FPGA, do którego fizycznie podłączony jest dany element. Informacja ta jest niezbędna dla etapu sprzętowej implementacji. Korzystając z poznanego już czarodzieja, proszę dodać do projektu nowy plik Implementation Constaints File i nazwać go stosownie, po czym kliknąć przycisk Next. Implementation Constaraits File File name: pins Next Następnie okno stanowi podsumowanie do nowoutworzonego pliku. Po zapoznaniu się z nim proszę kliknąć przycisk Finish. 27
W oknie głównym narzędzia ISE otwarty został nowy, pusty plik ucf, który nie jest widoczny w drzewie projektu. Proszę zmienić widok drzewa projektu z Simulation na Implementation. Implementation Plik ucf został przypisany do ostatniego z utworzonych przez nas wcześniej modułów VHDL. Przypisanie to jest niepoprawne, toteż plik należy usunąć z drzewa projektu. Proszę klikając na jego nazwie prawym przyciskiem myszy i wybierając z menu kontekstowego opcję Remove. pins.ucf Remove Zabieg ten spowoduje jedynie odłączenie pliku z projektu, a nie jego fizyczne usunięcie z dysku. Pojawi się okno potwierdzenia odłączenia, w którym należy kliknąć na opcję Yes. Yes 28
Proszę ustawić plik o nazwie podejscie1.vhd jako nadrzędny, po czym dodać do projektu nowe źródło. podejscie1 Set as Top Module podejscie1 Add Source W nowo otwartym oknie proszę wybrać plik pins.ucf i kliknąć na przycisku Otwórz. pins.ucf Otwórz 29
Pojawi się okno statusu dołączanego pliku, w którym proszę kliknąć przycisk OK. OK Po wprowadzeniu wszystkich zmian drzewo projektu powinno przypominać to, zamieszczone obok. 30
W pliku ucf proszę umieścić treść jak poniżej (http://www.fpga.agh.edu.pl/tc/?download=plik.ucf). Tak przygotowany plik ucf jest oryginalną wersją pliku przygotowanego przez firmę Digilent dla płytki Spartan-3. # Clock #Net "Clk50Mhz" LOC = "T9"; #NET "Clk50Mhz" PERIOD = 20ns; # 20ns = 50Mhz # User Switches #NET "SW0" #NET "SW1" #NET "SW2" #NET "SW3" #NET "SW4" #NET "SW5" #NET "SW6" #NET "SW7" # User Buttons #NET "BTN0" #NET "BTN1" #NET "BTN2" #NET "BTN3" # LEDs #NET "LD0" #NET "LD1" #NET "LD2" #NET "LD3" #NET "LD4" #NET "LD5" #NET "LD6" #NET "LD7" # 7 Segment #NET "AN0" #NET "AN1" #NET "AN2" #NET "AN3" #NET "CA" #NET "CB" #NET "CC" #NET "CD" #NET "CE" #NET "CF" #NET "CG" #NET "CDP" LOC = "F12"; LOC = "G12"; LOC = "H14"; LOC = "H13"; LOC = "J14"; LOC = "J13"; LOC = "K14"; LOC = "K13"; LOC = "M13"; LOC = "M14"; LOC = "L13"; LOC = "L14"; LOC = "K12"; LOC = "P14"; LOC = "L12"; LOC = "N14"; LOC = "P13"; LOC = "N12"; LOC = "P12"; LOC = "P11"; LOC = "D14"; LOC = "G14"; LOC = "F14"; LOC = "E13"; LOC = "E14"; LOC = "G13"; LOC = "N15"; LOC = "P15"; LOC = "R16"; LOC = "F13"; LOC = "N16"; LOC = "P16"; Znak krzyżyka # oznacza komentarz. Proszę usunąć komentarze w liniach odnoszących się do diody LD7 oraz przełączników SW0, SW1 i SW2. 31
Składnia każdej linijki pliku ucf jest praktycznie identyczna i wygląda jak poniżej: Net nazwa portu LOC = XXX Część pierwsza składni odnosi się do portu, który ma zostać podpięty do danego pinu układu FPGA. Część druga odnosi się do pinu układu FPGA, do którego ma zostać dołączony ten port. Jeśli port nie jest w postaci pojedynczej linii, a całej magistrali, to używa się nawiasów ostrych <> do określenia, którą dokładnie linię z magistrali przypisujemy do danego pinu wejściowego/wyjściowego układu FPGA. Proszę przypisać porty x1, x2 i x3 kolejno do przełączników SW0, SW1 i SW2. Proszę przypisać port y do diody LD7. Po wykonaniu wszystkich zmian plik ucf proszę zapisać. 32
7. Synteza i sprzętowa implementacja Projekt jest już gotowy do uruchomienia. Proszę przeprowadzić operacje syntezy, implementacji i generacji pliku konfiguracyjnego. Najprościej kliknąć prawym przyciskiem myszy na opcji Generate Programming File i z menu kontekstowego wybrać opcję Run. Uruchomiony zostanie wtedy cały łańcuch i przeprowadzone kolejno synteza, implementacja i generacja pliku konfigurującego. Generate Programming File Run Alternatywnie można dwukrotnie kliknąć na opcji Generate Programming File lub też kolejno uruchamiać wszystkie opcje, tj. Synthesize XST, Implement Design, Generate Programming File. Po kilku minutach cały proces powinien zostać zakończony sukcesem. Proszę przyjrzeć się raportowi Design Summary z wyszczególnioną listą zużytych zasobów logicznych. 33
8. Uruchomienie projektu Przystąpmy do uruchomienia projektu na płycie ewaluacyjne Nexys 3. Proszę rozwinąć opcję Configure Target Device i kliknąć prawym przyciskiem myszy na opcji Manage Configuration Project (impact), po czym wybrać z menu kontekstowego opcję Run. Manage Configuration Project Run Otwarte zostanie zewnętrzna narzędzie o nazwie impact, które służy do ładowania pliku konfiguracyjnego do układu programowalnego FPGA. Proszę dwukrotnie kliknąć na opcji Boundary Scan. Boundary Scan 34
W oknie głównym narzędzia impact otworzy się zakładka Boundary Scan. Proszę kliknąć wewnątrz niej prawym przyciskiem myszy i z menu kontekstowego wybrać opcję Initialize Chain. Initialize Chain Otwarte zostanie nowe okno wyboru pliku konfiguracyjnego. Proszę zaznaczyć odpowiedni plik konfiguracyjny bit, po czym kniknąć na przycisku Open. UWAGA! Proszę dopilnować, aby ustawiona została ścieżka do własnego katalogu roboczego. podejscie1.bit Open Pojawi się okno informujące o możliwości rekonfiguracji układu FPGA z pamięci nieulotnej PROM. Proszę pominąć tą możliwość klikając na przycisku No. 35
W oknie Boundary Scan pojawił się symbol kości FPGA wraz z jej typem (xc3s200) oraz nazwą pliku, który posłuży do jej rekonfiguracji (podejscie1.bit). Przy aktywnym symbolu układu FPGA (kolor zielony) proszę kliknąć prawym przyciskiem myszy w dowolnym obszarze zakładki Boundary Scan i z menu kontekstowego wybrać opcję Program. Jeśli kość nie jest aktywna (kolor szary), proszę na niej kliknąć raz lewym lub prawym przyciskiem myszy, aby stała się aktywna. Program Poprawnie przeprowadzona rekonfiguracja zostanie zakończona stosownym komunikatem. Zmieniając położenie przełączników SW0 SW2 i obserwując zachowanie diody LD7, proszę zweryfikować poprawność pracy zaimplementowanego komponentu. 36