Čeština / English
Login

Aplikace / Pexeso

Autor: Vojtěch Mrázek ()

Abstrakt: Jednoduchá hra Pexeso naprogramovaná pouze v FPGA, bez použití MCU

Update: 20110427

1. Popis aplikace

Tato hra má velmi jednoduchá pravidla. Náhodně se rozmístí 8 párů karet stejné barvy do matice 4x4 a karty se otočí rubem nahoru. Hráč má za úkol najít tyto páry. Každý výběr spočívá ve vybrání první karty a potom druhé. Pokud jsou obě dvě karty shodné, tak hráč může vybírat dál. Pokud však shodné nejsou, tak se zobrazí obě dvě karty a po chvíli se zase skryjí a hráč může opakovat výběr.

pexeso.png

Obrázek 1.1: Náhled hry

Hra je ukončena nalezením všech párů. Cílem hry je dojít do konce s nejmenším počtem otočených karet (minimum je 8, ale tento výsledek je prakticky nedosažitelný). Hráč musí v každou chvíli vědět, kolik již vyčerpal pokusů. Dále musí být schopen hru restartovat bez toho, že by restartoval celý kit. Pro jednodušší použití se budou používat pouze barevné karty, aby nebylo nutné nahrávat obrázky do paměti FLASH přes aplikaci QDevKit.

Zdrojové kódy pro FPGA je možné shlédnout zde.

2. Implementace

2.1. Použité moduly z knihovny FITKitu

Pro snadnou práci s FITkitem jsem použil 2 základní knihovny, které jsou distribuovány s hardwarem pod licencí open-source. Jedná se o ovladač VGA a klávesnice. Ovládání grafického výstupu zajišťuje konečný automat vga_controller. Umožňuje zobrazovat výsledek na monitoru v rozlišení 640x480. Počet barev je také dostačující - každá ze složek RGB má 3 bity. Z toho plyne, že můžeme použít 2^9=512 barev.

Dalším blokem je ovladač maticové klávesnice keyboard_controller. Ten funguje na principu multiplexovaného snímání - aktivuje jeden řádek a zjišťuje, který sloupec byl zmáčknutý. Tento princip se využívá kvůli maticovému zapojení klávesnice (již od výroby) a také z důvodu pouhých 8 vodičů pro 16 tlačítek. Tento blok vrací na výstupu vektor zmáčknutých tlačítek (kdy 1 bit znamená 1 tlačítko) a také signál značící platnost dat na výstupu.

2.2. Schéma zapojení

Celý systém bylo nejjednodušší řešit metodou dekompozice. K popisu byl použit bahavioární popis, protože pomocí RLT by to bylo téměř neřešitelné. Základními bloky se stal konečný automat pro řízení celé hry a zobrazovací jednotka.

schema.png

Obrázek 2.1: Blokové schéma aplikace

Vnější signály jsou připojeny k blokům z knihovny FITkitu.

2.3. Grafický výstup

Celý grafický výstup je pouhou implementací funkce RGB getColor(int x,int y). Celý tento proces je zjedodušený tím, že podle specifikace VGA se začíná od bodu [0,0] a potom souřadnice X roste rychleji než souřadnice Y.

Ovladač je modelovaný pouze jako samostatný proces v hlavním modulu pexeso_top.vhd. Zobrazuje tedy kartu 64x64 pixelů, mřížku a počítadlo obrácení. Celé zobrazování je řešeno pomocí speciální modifikace konečného automatu. Jeden konečný automat je pro řádky a druhý automat je pro sloupce. Při překročení určité hodnoty si uložím do speciální proměnné ve které sekci jsem a potom podle logického součinu těchto proměnných určím, co se má vykreslovat.

Řádky

Začátek

Konec

Název proměnné

Popis sekce

128

386

in_row

řádek s kartami

400

416

in_nmr_row

řádek s počtem otočení

Sloupce

Začátek

Konec

Název proměnné

Popis sekce

192

450

in_col

sloupec s kartami

431

438

in_sym_1

1 . znak počítadla

439

446

in_sym_2

2 . znak počítadla

Mřížka pro karty se vykresluje tak, že všechny bity řádku nebo sloupce (kromě posledního - pro šířku 2 pixely) musí být nulové. V tomto okamžiku vykreslíme šedou barvu, jinak kreslíme podle dekodéru symbolů. Kurzor je dělaný podobným způsobem - každé 4 pixely jsou červené a další jsou brané z dekodéru symbolů.

2.4. Řízení klávesnice

Nevýhodou ovladače klávesnice pro naše použití je to, že data nejsou platná jediný tak CLK, ale o něco déle. To je způsobeno také tím, že se má pro taktování ovladače používat signál SMCLK. Proto je celý ovladač modelován také jako konečný automat bez jakýchkoliv latch obvodů. Při stisku klávesi a aktivování potvrzovacího signálu se na výstupu ovladače aktivuje příslušný signál nebo se změní stav kurzoru. Automat přejde do stavu čekání na uvolnění, výstupní signály jsou v této fázi neaktivní. Až se teprve potvrzovací signál uvolní, tak je možné příjmout jinou klávesu.

2.5. Řízení hry

Řízení hry je tvořeno jednoduchým konečným automatem. Tento automat se skládá z těchto stavů:

  • INIT - inicializační stav, vymaže RAM paměť

  • WAITFIRST - čekání na otočení první karty, tato karta musí být obrácená rubem

  • WAITSECOND - čekání na otočení druhé karty, tato karta musí být obrácená rubem a nesmí být stejná jako první

  • WAITTIME - čekání na proběhnutí časovače pro krátké zobrazení 2 vybraných rozdílných karet

  • HIDEFIRST - skrytí první karty

  • HIDESECOND - skrytí druhé karty

Stavy WAITTIME, HIDEFIRST a HIDESECOND proběhnou pouze ve chvíli, kdy vybrané karty neseděly. Započítání tahu do počtu otočení se provádí při otočení první karty (přechodu z HIDEFIRST do HIDESECOND).

2.6. Generování náhodných čísel

Je velmi složité generovat náhodná čísla přímo. My však definujeme čísla pseudonáhodná. Při aktivaci časovače CLK se provede matematická operace nad výstupem. Aby byla řada ještě náhodnější (data čtu téměř v každém taktu), tak je registr, do kterého čísla generuji, o něco širší, než požadované číslo.

Pro tento element existuje testovací soubor. V souboru tb_random.vhd se nachází hlavní entita a v ModelSimu stačí spustit příkaz do sim.fdo.

2.7. RAM paměť

Tato paměť je jednou z hlavních částí programu. Obsahuje 2 čtecí vstupy a 1 zapisovací. Dále se sama umí inicializovat na náhodné hodnoty. Data jsou čtyřbitová, kde MSB určuje, zda je karta rubem nahoru (hodnota 1) a nebo lícem nahoru (hodnota 0).

Výstup A je připojený k ovladači hry, tento ovladač také řídí zápisy do paměti a spouští její inicializaci. Port B je určený pro komunikaci s grafickým ovladačem. Výstup z tohoto portu jde ještě do dekodéru karet a ten pak ovladači VGA řekne, kterou barvu použít.

Inicializace se provádí jednoduchým cyklem od 0 do 15. Při tomto cyklu ovšem jsou platné poslední 3 bity, nejvyšší se zahazuje. Na začátku se celá paměť inicializuje na hodnotu "0000". Poté v cyklu procházím adresy k zápisu. Zkusí se náhodná. Pokud je již obsazená (MSB je 1), tak zkusí následující, potom zkusí další atd, než dané číslo umístí a inkrementuje čítač. Díky tomu, že tento zápis netrvá vždy pouze 1 takt, tak mohu bez problémů použít systém generování náhodných čísel. Z paměti není veden žádný signál ve stylu BUSY, protože celá inicializace trvá do pár desítek taktů, což je při této rychlosti FPGA zanedbatelné.

2.8. BCD čítač

Pro počítání tahů je implementovaný dvoumístný BCD čítač. Časovací signál je vedený pouze z řízení hry, protože zápis se provádí pouze jednou za čas. Také resetovací vstup není spojený s RESET, protože uživatel musí být schopen resetovat hru (tímpádem i čítač) bez použití restartu celého čipu.

2.9. Dekódování znaků čísel

Jelikož zbývalo hodně volných SLICE na čipu, tak dekódování jsem implementoval pouhou ROM pamětí. Je to sice náročnější na plochu čipu, než je třeba využití FLASH, ale zase tento způsob pak neklade žádné nároky na uživatele pro zprovoznění.

Dekodér je schopen rozpoznat pouze symboly 0-9 (znaky A-F jsou nastaveny jako ''don't care''). Při nastavení adresy z VGA ovladače a BCD čísla řekne, jestli je pixel aktivní nebo neaktivní. Ovladač mu podle tohoto výstupu musí určit barvu.

Znaky jsou definovány v rozměru 8x16. To znamená, že každý znak zabírá 128 bitů.

Písmo jsem získal pomocí jednoduchého programu v Microsoft Visual C# 2010. Tento program mi do bitmapy vykreslil text (s vypnutými filtry) a pak jsem tuto bitmapu pouze v cyklu prošel a snímal barvy a zapsal do 128 bitového vektoru.

3. Zprovoznění aplikace a ovládání

  1. přeložte aplikaci

  2. aktivujte propojku J6 pro povolení periferií PC

  3. naprogramujte MCU a FPGA a spusťte terminálový program

  4. pomocí klávesnice obvládejte hru

    • 2 Posun kurzoru nahoru

    • 4 Posun kurzoru doleva

    • 6 Posun kurzoru doprava

    • 8 Posun kurzoru dolů

    • A Restart hry

Zobrazeno: 1302x Naposledy: 11.11.2017 01:28:16