Akcelerator grafiki 2D na FPGA i STM32F429

Główne komponenty

Nie da się zrealizować tych wszystkich funkcji za pomocą samego mikrokontrolera i mocy CPU. Wymagające zadania, w tym obsługa wielu grafik, wymaga użycia koprocesora. Tytuł artykułu mówi, że do tej roli został wybrany układ FPGA. Dlaczego FPGA? Akcelerator grafiki musi bezpośrednio współpracować z zewnętrznymi elementami na wysokich częstotliwościach, przy zachowaniu nanosekundowej dokładności. Natomiast złożoność potrzebnej logiki kombinacyjnej jest względnie mała, zatem FPGA jest oczywistym wyborem.

Układ FPGA nie będzie jedynym procesorem na tej płytce. Gry też potrzebują kontrolera i musi to być wydajny model, który zdąży wykonać obliczenia silnika gry w ograniczonym czasie między ramkami. Zdecydowałem się użyć mikrokontrolera umieszczonego na płytce, zamiast wyprowadzać interfejs FPGA na zewnątrz przez gniazdo, ponieważ magistrale równoległe na wysokich częstotliwościach nie będą działały dobrze podczas transmisji przez wiszące przewody.

Gry potrzebują grafiki, dużo grafiki. Zapewni ją karta SD, na której będą przechowywane grafiki i inne dane obsługiwane przez kontroler. Układ FPGA nie będzie komunikował się bezpośrednio z kartą SD, ponieważ interfejs karty SD (SDIO) nie zapewnia stałej i przewidywalnej szybkości transferu. Użyję zatem pojemnej pamięci Flash, z której FPGA będzie mogła wczytywać grafiki z dużą szybkością.

FPGA potrzebuje bufora RAM, który przechowywałby renderowane ramki. Układy FPGA mają wbudowane bardzo szybkie pamięci RAM różnych typów, ale są one zdecydowanie zbyt małe na bufor ramki – trzeba zatem dodać własną pamięć. Asynchroniczna, statyczna pamięć RAM (SRAM) zapewnia najprostszy interfejs oraz możliwość uzyskania dużej przepustowości w transmisji sekwencyjnej, zatem użyję jej zamiast SDRAM. Ta druga opcja jest tańsza i zapewnia bardzo dużą gęstość zapisu, ale kontroler SDRAM jest dużo bardziej skomplikowany w obsłudze – pamięć SDRAM nie przyniesie zatem żadnych korzyści w tym projekcie.

Oczywiście potrzebuję też samego wyświetlacza LCD do wyświetlania obrazu. Zamierzam wybrać model o największej rozdzielczości, który będą w stanie obsłużyć pozostałe komponenty – i który zmieści się na płytce.

Ostatnim elementem będzie pamięć EEPROM, która pozwala trwale zapisać dane o niewielkiej objętości po wyłączeniu zasilania – przydatna do zapamiętywania najlepszych wyników gry i podobnych danych.

Poniżej znajduje się schemat blokowy tego, co zamierzam zbudować:

04

Wybór elementów

Po ustaleniu ogólnej struktury systemu trzeba wybrać odpowiednie komponenty, które posłużą do budowy płytki.

Wyświetlacz LCD

 

LCD Sony Vivaz o przekątnej 3,2 cala
LCD Sony Vivaz o przekątnej 3,2 cala

Podobnie jak w moim poprzednim projekcie – halogenowym piecu lutowniczym – wykorzystałem wyświetlacz LCD o rozdzielczości 640×360 z telefonu Sony Vivaz U5. Opis całej mojej pracy włożony w poznanie tego wyświetlacza jest opisany w tym artykule.

Przedstawiony wyświetlacz spełnia wszystkie istotne wymagania projektu. Tanie części zamienne są dostępne na Ebayu. Pracowałem już z tym układem, więc wiem, że jest niezawodny, a parametry czasowe i rozdzielczość pasują doskonale.

Zasilacz będzie sterowany w trybie 16-bitowym (5-6-5) RGB, co oznacza, że na każdy piksel są potrzebne 2 bajty. Zatem bufor ramki potrzebuje przynajmniej 4 Mb pamięci SRAM. Gdyby rozdzielczość byłą wyższa, musiałbym wykorzystać droższy model 8 Mb i prawdopodobnie wybrany układ FPGA nie byłby w stanie zapewnić wystarczających parametrów czasowych, przez co koszt i złożoność projektu byłyby zbyt duże.

Zatrzask

06

To mały, ale niezwykle ważny element. Jeśli chcę zmieścić cały projekt w liczbie 63 wejść FPGA dostępnych dla użytkownika, muszę ograniczyć liczbę wyprowadzeń tam, gdzie to tylko możliwe. 8-bitowy zatrzask pozwoli zmniejszyć liczbę wyprowadzeń potrzebnych do obsługi magistrali LCD z 16 do 9 (w dodatkowy pin obsługuje sygnał LE).

Praca zatrzasku jest kluczowa dla sukcesu projektu. Ograniczenia czasowe sprawiają, że linia LE może być w stanie wysokim tylko przez około 10 ns, zatem wybrany model musi reagować odpowiednio szybko. Układ Texas Instruments SN74ABT573APW mieści się w kosztorysie i wymaga impulsu w stanie wysokim trwającego tylko 3,3 ns. Układ jest nie tylko wystarczająco szybki, ale ma też dobry rozkład wyprowadzeń – wyjścia znajdują się po przeciwnej stronie, niż wejścia, co jest wygodne w przypadku magistrali. Wiele zatrzasków z wieloma wejściami ma bardzo dziwny układ wyprowadzeń – na przykład wejść umieszczonych obok wyjść, co prowadzi do skomplikowanych kombinacji przelotek na płytce PCB.

FPGA

07

Wybrałem model FPGA Xilinx Spartan 3 XCS50 z kategorii -5 (wysokiej szybkości). Jest to najmniejszy, najtańszy i najbardziej przyjazny dla użytkownika model FPGA w ofercie Xilinx. Mimo to ma 100 wyprowadzeń, jak przystało na układy FPGA znane z dużych możliwości. Więcej wyprowadzeń mają tylko budowy BGA.

Dwaj głowni dostawcy układów FPGA to Xilinx i Altera. Xilinx pierwszy wszedł na rynek FPGA i ma największy udział w rynku. Wybór tej firmy zamiast Altery wynika z dostępności układów w mojej okolicy. Dostawcą układów Xilinx jest Farnell UK, co sprawia, że wybór był dla mnie prosty. Obaj dostawcy zapewniają darmowe oprogramowanie do syntezy logicznej i symulacji, również ich oferta produktów jest podobna. Jeśli w Twojej okolicy łatwiej jest zdobyć układy Altery, ta firma będzie równie dobrym wyborem.

Układ XC3S50 ma według specyfikacji 50000 bramek logicznych – ale to łączna liczba, która nie przekłada się na wykorzystane zasoby po syntezie projektu. Istotne parametry to liczba 1356 przerzutników flip-flop, 768 komórek slice i 1536 4-wejściowych komórek LUT.

Oprócz komórek logicznych również inne dostępne zasoby są ważne dla powodzenia projektu. W układzie znajduje się 73728 bitów dwuportowej, blokowej pamięci RAM (BRAM), 12228 bitów rozproszonej pamięci RAM, 4 dedykowane układy mnożące i 2 cyfrowe układy zarządzania zegarem (DCM).

Warto pamiętać, że rozproszona pamięć RAM nie stanowi osobnego zasobu, jak pamięć blokowa. Rozproszona pamięć RAM jest zrealizowana za pomocą komórek LUT, tym samym zmniejszając liczbę zasobów dostępnych dla układów logicznych w projekcie. Wykorzystam pamięć blokową RAM, aby przechować rekordy bitmap, rozproszoną pamięć RAM do realizacji kolejki FIFO przechowującej polecenia z mikrokontrolera, a układ DCM posłuży do syntezy zegara wysokiej częstotliwości z zewnętrznego oscylatora.

Spośród 100 wyprowadzeń układu FPGA 63 są dostępne dla użytkownika. Wydaje się, że to dużo, ale po zsumowaniu linii adresowych SRAM, magistral danych interfejsu mikrokontrolera i magistrali LCD okazuje się, że nie ma ich tak wiele. W dalszej części artykułu będzie opisane, w jaki sposób udało mi się zmieścić wszystkie te linie sygnałów.

Ostatnia kwestia – duża kropka w prawym górnym rogu obudowy sugeruje, że tam znajduje się pin z numerem 1. Otóż tak nie jest, pin 1. znajduje się w prawym dolnym rogu tuż obok znacznie mniejszej kropki. Przekonałem się o tym metodą prób i błędów. Zgodnie z konwencją po obróceniu układu scalonego zgodnie z orientacją napisu pin z numerem 1 powinien znajdować się na dole po lewej.

O autorze