.. _basys2: ========================== Instrukcje używania płytki ========================== .. toctree:: .. contents:: O płytce ======== Płytka Basys 2 ma następujący sprzęt: 1. Układ FPGA Xilinx Spartan 3E, model XC3S100E w obudowie CP132, speed grade 4, zakres temperatur C (i takie parametry należy wybrać w ISE). 2. Układ Xilinx platform flash XCF02S, pozwalający na zapisanie konfiguracji FPGA. 3. Włącznik zasilania. 4. Mikrokontroler AVR obsługujący port USB, umożliwiający programowanie FPGA oraz platform flash, a także komunikację z płytką przez protokół EPP. 5. Zworkę wybierającą uruchomienie FPGA z platform flash bądź czekanie na zaprogramowanie bezpośrednio przez USB. 6. 8 przełączników ogólnego przeznaczenia. 7. 4 przyciski ogólnego przeznaczenia. 8. 8 diod ogólnego przeznaczenia. 9. 4-cyfrowy wyświetlacz 7-segmentowy. 10. 4 złącza PMod (można do nich podłączyć moduły z dodatkową funkcjonalnością). 11. Oscylator ok. 50MHz (dość niedokładny). 12. Miejsce na włożenie lepszego oscylatora (których mamy 5 sztuk). 13. Port VGA. 14. Port PS/2, umożliwiający podłączenie klawiatury bądź myszy. Dokumentacja płytki: https://reference.digilentinc.com/reference/programmable-logic/basys-2/reference-manual Przypisania pinów ================= Aby wejścia/wyjścia naszego kodu zostały poprawnie przypisane do wyprowadzeń układu FPGA, potrzebujemy pliku :download:`basys2.ucf`, w którym jest opisane mapowanie. Niestety, przed użyciem tego pliku należy go zmodyfikować tak, żeby odkomentowane były te wyprowadzenia, których używamy (niestety, ISE zgłasza błąd, gdy w ``.ucf`` jest mapowanie dla nieużywanego wyprowadzenia, ale nie zgłasza błędu, gdy mamy w Verilogu niezmapowane wejście/wyjście -- wybiera wtedy losowo wyprowadzenie). Maszyna wirtualna ================= Na stacjach laboratoryjnych mamy przygotowany obraz maszyny wirtualnej z całym potrzebnym oprogramowaniem. Aby go użyć, należy: 1. Utworzyć swój własny obraz dysku, jako obraz copy-on-write bazowany na obrazie wzorcowym (tylko raz):: qemu-img create -f qcow2 -o backing_file=/home/dokstud/mwk/pul2018.qcow2 pul2018_cow.qcow2 2. Utworzyć katalog współdzielony (raz):: mkdir pul2018-share 3. Uruchomić qemu:: qemu-system-x86_64 -enable-kvm -drive file=pul2018_cow.qcow2,if=virtio -usb -net nic,model=virtio -net user -m 1G -fsdev local,id=pul2018-share,path=pul2018-share/,security_model=none -device virtio-9p-pci,fsdev=pul2018-share,mount_tag=pul2018-share -device usb-host,vendorid=0x1443,productid=0x0007 -display sdl Na obrazie maszyny zainstalowany jest Debian oraz następujące narzędzia: - Xilinx ISE - Digilent Adept utilities - Yosys - Icarus verilog (aka iverilog) - Verilator Można się zalogować nazwą użytkownika ``pul`` z hasłem ``pul``. W ``/mnt/share`` będzie widoczna (do odczytu i zapisu) zawartość katalogu współdzielonego ``pul2018-share`` z hosta. Jeśli chcemy użyć tego obrazu na własnej maszynie, należy pamiętać o zapewnieniu qemu dostępu do odpowiedniego urządzenia USB (plik ``/dev/bus/usb//``). .. Żeby zmienić rozdzielczość ekranu w maszynie wirtualnej:: .. xrandr --output Virtual-0 --mode 1920x1080 Od Veriloga do bitstreamu ========================= Przykładowe pliki: - :download:`abc.v` (źródło w Verilogu) - :download:`abc.ucf` (mapowanie wejść/wyjść na fizyczne wyprowadzenia) Musimy napisać dwa pliki sterujące pracą xst. W pliku ``abc.prj`` umieszczamy listę plików w projekcie:: verilog work "abc.v" W pliku ``abc.xst`` umieszczamy listę poleceń sterujących syntezą:: run -ifn abc.prj -p xc3s100e-4-cp132 -top abc -ofn abc Żeby otrzymać plik .bit należy wykonać następujące komendy:: # Synteza (.v -> .ngc) xst -ifn abc.xst # Linkowanie (.ngc -> .ngd) ngdbuild abc -uc abc.ucf # Tłumaczenie na prymitywy dostępne w układzie Spartan 3E (.ngd -> .ncd) map abc # Place and route (.ncd -> lepszy .ncd) par -w abc.ncd abc_par.ncd # Generowanie finalnego bitstreamu (.ncd -> .bit) bitgen -w abc_par.ncd -g StartupClk:JTAGClk Opcja ``-g StartupClk:JTAGClk`` wybiera uruchomienie FPGA używając sygnału zegarowego z programatora (używane przy bezpośrednim programowaniu FPGA). W przypadku uruchamiania FPGA z kości platform flash, należałoby użyć ``-g StartupClk:CCLK``. Na koniec otrzymujemy plik ``abc_par.bit``. Jeżeli chcemy się przyjrzeć wynikowi syntezy (zobaczyć prymitywy użyte przez syntezator), możemy użyć polecenia ``ngc2edif``, by otrzymać netlistę w tekstowym formacie EDIF. Programowanie układu FPGA ========================= Układ FPGA może uruchamiać się z konfiguracji zapisanej w platform flash, bądź bezpośrednio z portu USB. Na zajęciach będziemy używać uruchamiania z portu USB. W pamięci platform flash jest zapisany (i powinien pozostać tam zapisany) bitstream diagnostyczny, pozwalający na przetestowanie funkcjonalności płytki. Polecenie do przesłania pliku ``.bit`` bezpośrednio do układu FPGA używając narzędzi producenta to:: djtgcfg -d Basys2 prog -i 0 -f abc_par.bit Alternatywnie, można użyć otwartego narzędzia (https://github.com/koriakin/adepttool):: ./basys2_prog.py abc_par.bit Sprzęt na płytce ================ Diody, przełączniki, przyciski ------------------------------ Mamy 8 diod, ``led[7:0]``. Wyprowadzenia powinny odpowadać ``output``-om w Verilogu. Dioda świeci, jeśli na wyjściu jest stan 1. Mamy 8 przełączników, ``sw[7:0]``. Powinny odpowiadać ``input``-om w Verilogu. Przełącznik przełączony w górę daje stan 1, przełączony w dół daje stan 0. Mamy 4 przyciski, ``btn[3:0]``. Przycisk naciśnięty daje stan 1, nienaciśnięty daje stan 0. Zegary ------ Mamy dwa zegary: ``mclk`` oraz ``uclk``. ``mclk`` jest podłączony do oscylatora na płytce, generującego sygnał o częstotliwości mniej-więcej 50MHz. ``uclk`` jest podłączony do gniazdka na lepszy oscylator i musimy tam taki oscylator włożyć, żeby go użyć. Mamy do dyspozycji 2 sztuki oscylatora 32Mhz oraz 2 sztuki oscylatora 20MHz. Wyświetlacz 7-segmentowy ------------------------ Mamy 4-cyfrowy wyświetlacz 7-segmentowy. Wyświetlacz jest sterowany za pomocą 4 anod (``an[3:0]``, po jednej na każdą cyfrę) oraz 8 katod (po jednej na każdy z siedmiu segmentów -- ``seg[6:0]`` oraz jedna na kropkę -- ``dp``). Dany segment wyświetlacza świeci się, gdy na odpowiadającej katodzie i anodzie jest jednocześnie stan logiczny 0. Nie możemy więc w danym momencie wyświetlać kilku różnych cyfr. Żeby obejść to ograniczenie, należy skonstruować układ synchroniczny zmieniający co jakiś czas (na skali setek mikrosekund) aktualnie wyświetlaną cyfrę. Każda cyfra będzie świeciła 4 razy ciemniej niż teoretyczne maksimum, ale nie jest to problemem w praktyce. Segmenty są następujące: - 0: górny poziomy - 1: prawy górny pionowy - 2: prawy dolny pionowy - 3: dolny poziomy - 4: lewy dolny pionowy - 5: lewy górny pionowy - 6: środkowy poziomy Wzorce bitowe dla poszczególnych cyfr i innych wyświetlalnych znaków (najwyższy bit to segment 6): - 0 lub O: ``7'h40`` - 1 lub I: ``7'h79`` - 2: ``7'h24`` - 3: ``7'h30`` - 4: ``7'h19`` - 5: ``7'h12`` - 6: ``7'h02`` - 7: ``7'h78`` - 8: ``7'h00`` - 9: ``7'h10`` - A: ``7'h08`` - b: ``7'h03`` - c: ``7'h27`` - C lub [: ``7'h46`` - d: ``7'h21`` - E: ``7'h06`` - F: ``7'h0e`` - h: ``7'h0b`` - H: ``7'h09`` - J: ``7'h71`` - L: ``7'h47`` - o: ``7'h23`` - P: ``7'h0c`` - q: ``7'h18`` - u: ``7'h63`` - U: ``7'h41`` - ]: ``7'h70`` - -: ``7'h3f`` - _: ``7'h77`` - spacja: ``7'h7f`` Możemy wyświetlać cyfry bezpośrednio po sobie, ale spowoduje to lekkie "przeciekanie" cyfr między sobą (ze względu na czas potrzebny na propagację sygnałów przez oporniki na płytce). Nie jest to zbyt poważny problem, ale jeśli nam on przeszkadza, polecam następującą procedurę: 1. Przez 1024 cykle zegara: wystawiamy 1 na wszystkich anodach, wystawiamy segmenty cyfry X na katodach (ładujemy katody). 2. Przez 14336 cykle zegara: wystawiamy 0 na anodzie cyfry X, 1 na pozostałych anodach, wystawiamy segmenty cyfry X na katodach (wyświetlamy cyfrę). 3. Przez 1024 cykle zegara: wystawiamy 1 na wszystkich anodach, dalej trzymamy segmenty cyfry X na katodach (pozwalamy anodzie się rozładować). 4. Zmieniamy cyfrę na kolejną, wracamy do punktu 1. Podane czasy są tylko orientacyjne -- można je spokojnie zmienić o rząd wielkości w górę bądź w dół. Klawiatura/mysz PS/2 -------------------- Obsługa klawiatury i myszy PS/2 opisana jest tu: :ref:`ps2`. Na płytce mamy sygnały ``PS2D`` (dane) i ``PS2C`` (zegar) podłączone do złącza PS/2 przez prosty konwerter napięć. Monitor VGA ----------- Obsługa monitora VGA opisana jest tu: :ref:`vga`. Na płytce mamy wyprowadzone bezpośrednio sygnały ``HSYNC`` i ``VSYNC`` ze złącza VGA, natomiast sygnały ``R``, ``G`` i ``B`` są podłączone przez prosty konwerter cyfrowo-analogowy (3 bity na ``R`` i ``G``, 2 bity na ``B``). Złącza PMod ----------- Płytka ma 4 złącza PMod służące do podłączania modułów rozszerzających jej funkcjonalność. Złącza nazywają się (od lewej) JA, JB, JC, JD. Każde złącze ma 6 pinów (od lewej): - ``Jx1``: programowalne, należy skonsultować się z dokumentacją modułu. - ``Jx2``: j/w - ``Jx3``: j/w - ``Jx4``: j/w - ``GND``: masa, 0V - ``VCC``: zasilanie, 3.3V Na chwilę obecną nie mamy żadnych modułów PMod, ale mamy dwa kable USB<->UART, które możemy podłączyć do złącza PMod za pomocą drutów. Komunikacja z komputerem (EPP) ============================== Obsługa portu EPP opisana jest tu: :ref:`epp`.