Instrukcje używania płytki

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 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/<szyna>/<adres>).

Od Veriloga do bitstreamu

Przykładowe pliki:

  • abc.v (źródło w Verilogu)

  • 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: PS/2.

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: VGA, DVI, HDMI.

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: EPP.