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

.. Ż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`.