Akceleracja grafiki 2D STM32F429, część 2

Artykuł publikujemy dzięki uprzejmości Andy’ego Browna, autora bloga AnydsWorkshop.

Znając elementy (patrz część 1), które zamierzam wykorzystać, mogę stworzyć schemat łączący jest wszystkie razem.

Schemat jest dość duży i zgodnie z przewidywaniami zdominowany przez FPGA oraz mikrokontroler. Znacznie łatwiej zrozumieć go, omawiając poszczególne moduły.

 

Zasilacz

Wejścia trzech głównych stabilizatorów napięcia są podłączone przez wtyczkę jack do zewnętrznego zasilacza 5 V. Zasilacz 2,8 V jest fizycznie umieszczony daleko od wejścia 5 V, zatem wygodniej było zasilić go z linii 3,3 V. Tantalowe kondensatory 10 uF i 22 uF wygładzające napięcie są umieszczone bardzo blisko stabilizatora, z którym będą pracować.

 

Kondensatory elektrolityczne C26, C18 i C23 zapewniają zgrubne odsprzęganie niskich częstotliwości na płytce. W jednym z licznych artykułów projektowych Xilinx są zalecane kondensatory odsprzęgające co dekadę do wartości 100 uF, zatem trzymam się tej rekomendacji.

Opornik 120 ? między linią 2,5 V a masą jest kolejnym rozwiązaniem Xilinx. W nocie aplikacyjnej Xilinx XAPP453 jest wyjaśniony sposób konfiguracji (programowania) FPGA za pomocą mikrokontrolera pracującego z poziomami 3,3 V. Jednym z ważnych kroków jest dodanie opornika bocznikującego 120 ? między linią 2,5 V a masą, aby regulator napięcia nie obserwował ujemnego prądu na swoim wyjściu. Wadą tego rozwiązania jest powstanie stałego prądu 20,8 mA (strata 50 mW) płynącego nawet wówczas, gdy układ nie pracuje.

Warto przyjrzeć się charakterystykom temperaturowym w karcie katalogowej regulatora napięcia. Podczas wstępnych eksperymentów uruchomiłem projekt z napięciem zasilającym 12 V zamiast 5 V. Po pewnym czasie zauważyłem, że system samoistnie się resetuje. Byłem zaskoczony, dopóki nie dotknąłem płytki. Była bardzo nagrana w pobliżu zasilacza AMS1117. Ten układ wyłączał się z powodu przegrzania, aby zapobiec spaleniu. Zajrzałem do karty katalogowej, aby przekonać się, dlaczego.

We fragmencie karty katalogowej poświęconym wpływie temperatury znajduje się wzór na wydzielaną moc: PD = (VIN – VOUT) * IOUT. Przy zasilaniu 12 V i prądzie 400 mA oznacza to w najgorszym wypadku wydzielanie 3,48 W. Przekłada się to na temperaturę złącza 233°C, podczas gdy maksymalna dozwolona wynosi 125°C. Nie jest więc zaskakujące, że układ powodował problemy. Zmniejszenie napięcia wejściowego oznacza spadek wydzielanej mocy do 0,68 W, przy której maksymalna temperatura złącza wynosi 65°C. Teraz układ pracuje znacznie lepiej.

 

FPGA

Poniżej widać układ FPGA – kondensatory odsprzęgające nie są widoczne, aby oszczędzić miejsce. Pełna sieć odsprzęgająca jest widoczna na powiększonym pliku PDF. Odsprzęganie FPGA jest bardzo ważne i zostało zrealizowane w oparciu o notę aplikacyjną Xilinx Power Distribution System (PDS) Design.  

W tym projekcie wykorzystuję 62 spośród 63 dostępnych wejść/wyjść – wszystko, czego potrzebuję, ledwo mieści się w tym układzie. Zamierzam umieścić komponenty obsługiwane sygnałami wysokiej szybkości jak najbliżej FPGA, aby nie było konieczności stosowania przelotek. Jest to projekt przeznaczony dla hobbysty – realizowany na płytce dwuwarstwowej, zatem muszę starannie poprowadzić sygnały.

Kość SRAM jest najbardziej wymagającym układem – potrzebnych jest 28 wejść/wyjść, aby obsłużyć adres, dane i sygnał kontrolny WE. Zaoszczędziłem dwa wyprowadzenia, zwierając piny CS oraz OE do masy – według karty katalogowej SRAM jest to dozwolone. Pamięć Flash, jako układ sterowany przez SPI, wymaga w sumie tylko 6. wyprowadzeń. Nie mogę niestety zewrzeć wyprowadzenia CS, ponieważ jest używane przez protokół SPI do zakończenia pewnych ciągów poleceń.

Wejścia sygnałów z mikrokontrolera to 10-bitowa szyna danych D0..9, sygnał strobujący WR i wejście reset (aktywne w stanie wysokim). Wyjścia dla mikrokontrolera to sygnał busy i wyjście debugujące używane podczas projektowania, aby zakomunikować wystąpienie określonych stanów. Debugowanie samego układu FPGA byłoby niezwykle trudne.

Wszystkie sygnały programujące: PROG_B, INIT_B, CCLK, DIN i DONE są widoczne. Będę programował FPGA za pomocą trybu nazywanego przez Xilinx „slave serial mode”, w którym mikrokontroler taktuje dane przesyłane do FPGA i monitoruje sygnały wyjściowe, aby określić, czy operacja zakończyła się sukcesem. Skompilowany plik projektowy w formacie .bit zajmuje około 55 KB, a jego załadowanie z mikrokontrolera zajmuje ułamek sekundy.

Plik projektowy .bit umieściłem wewnątrz programu mikrokontrolera podczas kompilacji. Jest on ładowany do FPGA po uruchomieniu. Konfiguracja FPGA jest przechowywana w wewnętrznej pamięci ulotnej SRAM, zatem jest tracona po wyłączeniu zasilania i musi zostać przywrócona po uruchomieniu systemu. Niektóre układy FPGA zawierają wewnętrzną pamięć konfiguracji Flash, ale ta rodzina nie daje takiej możliwości.

Sygnały przeznaczone dla wyświetlacza LCD obejmują 8-bitową szynę danych, kontrolę zatrzasku (LE) oraz linie RS i WR. Do FPGA wchodzi kluczowy sygnał TE, który pozwala zsynchronizować generację ramki LCD.

Linie VCCO[0..7] są wejściami poziomu 3,3 V, jedna przypada na każdy bank wejść/wyjść FPGA. VCCINT są wejściami 1,2 V, a VCCAUX – 2,5 V. Daje to dużą liczbę wejść zasilania i towarzyszących im kondensatorów odsprzęgających. Sytuacja mogłaby się tylko pogorszyć w przypadku większych obudów FPGA. Jest to kolejny powód, aby w projektach hobbystycznych wykorzystywać mniejsze układy.

 

Mikrokontroler

Mikrokontroler jest w tym projekcie uzupełnieniem FPGA. Łatwo jest zauważyć przeciwne końce niektórych linii sygnałowych. Przykładowo, przypisałem całą 10-bitową szynę danych i sygnał WR do portu E.

Dzięki temu będę mógł ustawić dane oraz sygnał strobujący WR w jednej operacji zapisu do portu. Przycisk reset jest tylko po to, abym w razie potrzeby mógł ponownie uruchomić płytkę.

Sygnały SDIO są zmapowane do wyjść peryferyjnych SDIO mikrokontrolera, co pozwala łatwo zapisywać i odczytywać karty SD. Sygnały SCAl i SDA interfejsu I2C są podłączone do układu peryferyjnego I2C#2 mikrokontrolera. Przeznaczyłem dwie diody LED do sygnalizowania statusu i innych funkcji ogólnego przeznaczenia. 18 spośród pinów GPIO jest wyprowadzonych na zewnętrzne gniazdo wyjściowe, dzięki czemu mogę w celach testowych podłączyć urządzenia peryferyjne, takie jak joystic. Wyprowadzone piny nie są przypadkowe – zostały wybrane tak, aby móc obsłużyć różne układy peryferyjne umieszczone na płytce, które mogłyby być przydatne na etapie projektowania.

Można zauważyć brak oscylatora – ten mikrokontroler go nie potrzebuje. Jeśli tylko dokładność 1% jest dopuszczalna, można wykorzystać wewnętrzny zegar dużej szybkości (HSI) 16 MHz doprowadzony do pętli PLL, która generuje zegar 180 MHz taktujący rdzeń. Tolerancja 1% moim zdaniem jest wystarczająca, zatem używam HSI.

W odróżnieniu od skomplikowanych wymagań zasilania FPGA, zasilanie mikrokontrolera jest bardzo proste. Odsprzężenie (nie pokazane na obrazku) jest zgodne z wytycznymi ST – ceramiczny kondensator dla każdego wyprowadzenia i dodatkowy kondensator „chemiczny” 4,7 uF. Kondensatory elektrolityczne zaliczają się do chemicznych, zatem takich użyłem. Osobiście preferuję tantalowe ze względu na ich niską rezystancję szeregową, ale nie miałem akurat żadnego pod ręką.

Debugowanie i programowanie odbywa się przez interfejs SWD, dwuprzewodowy protokół zaprojektowany jako bardziej efektywny następca JTAG. Sygnały SWDIO i SWCLK są wyprowadzone na złącze debugujące, dzięki czemu można je podłączyć bezpośrednio do taniego i skutecznego debuggera ST-Link/v2.

 

Pamięć Flash

Pamięć Flash to najszybszy układ peryferyjny na tej płytce, który będzie pracował z częstotliwością zegara 100 MHz. W tym zakresie mogą zdarzyć się problemy z integralnością sygnałów spowodowane przez przestrzały lub zbyt niski poziom sygnału, odbicia, a nawet wszystkie te zjawiska naraz – jeśli nie będę ostrożny. Z tego powodu wszystkie linie wejścia/wyjścia i linie zegara mają szeregowy rezystor terminujący 33 ?, który ma tłumić odbicia, zanim będą w stanie popsuć sygnał użyteczny. Te linie będą również bardzo krótkie na płytce PCB.

Skąd wynika wartość 33 ?? Niestety, to tzw. reguła kciuka. Nie mam żadnego przyrządu, który pozwalałby zmierzyć i wybrać odpowiednią wartość, więc zaczynam od 33 ?. Jeśli pojawią się problemy, wyciągnę podręczny oscyloskop i ocenię, czy rezystancję należy zwiększyć.

 

Pamięć SRAM

Układy pamięci nie są zbyt interesujące. To jedynie dwie szyny, kilka sygnałów sterujących i zasilanie. Aby oszczędzić wyprowadzenia, podłączyłem piny CS oraz OE bezpośrednio do masy – według dokumentacji jest to dozwolone. Muszę jedynie sterować sygnałem WE, gdy chcę zapisać dane.

Linie adresu i danych będą się zmieniały co najwyżej z częstotliwością 50 MHz, ale linia WE będzie przełączana z częstotliwością 100 MHz. Nie przejmuję się liniami adresowymi ani danych, dopóki będą one krótkie i pozbawione przelotek – przy 50 MHz nie powinny sprawiać problemów. Po dłuższym namyśle doszedłem do wniosku, że powinienem zostawić chociaż miejsce na rezystor terminujący 33 ? na linii WE. Gdybym miał okazję tworzyć nową wersję płytki, zrobiłbym to.

 

Oscylator

Oscylatora nie trzeba uruchamiać zewnętrznym układem – zacznie on sam pracować w momencie, gdy zostanie zasilony. W moim projekcie umieściłem rezystor terminujący 33 ? również na linii zegara, choć to zapewne przesada. Zegar jest krytycznym elementem i zapewnia działanie całej reszty systemu, zatem warto przewidzieć dodatkowe zabezpieczenie.

 

Ekran LCD

Schemat podłączenia ekranu LCD powinien być znajomy dla każdego, kto czytał moje artykuły dotyczące inżynierii wstecznej lub halogenowego pieca lutowniczego.

Wszystkie sygnały kontrolne są podłączone do FPGA – poza LCD_RES, który jest sygnałem resetującym sterowanym przez mikrokontroler. Nie ma sensu obciążać układu FPGA obsługą sekwencji resetującej wyświetlacz, tym zadaniem najlepiej zajmie się mikrokontroler.

 

Podświetlenie LED

Podświetlenie ekrany LED składa się z sześciu białych diod LED połączonych szeregowo. Do ich zasilania potrzebna jest przetwornica podwyższająca napięcie, która uzyska poziom odpowiadający sumie spadków napięć na poszczególnych diodach LED.

Układ AP5724 firmy Diode Inc. Jest dedykowanym sterownikiem podświetlenia pracującym w trybie prądowym, który zawiera przetwornicę podwyższającą napięcie. Wystarczy dodać kilka zewnętrznych elementów, takich jak opornik służący do pomiaru prądu, a sterownik zapewni stabilny prąd wyjściowy tak długo, jak pin EN jest w stanie wysokim. Zaletą tego rozwiązania jest brak potrzeby dostarczania sygnału z modulacją PWM do wejścia EN, aby kontrolować jakość podświetlenia – ponieważ ekran LCD ma funkcję, która robi to za nas. Takie rozwiązanie pozwala zaoszczędzić jedno wyprowadzenie i układ czasomierza mikrokontrolera.

 

Zatrzask

Zatrzask jest umieszczony między FPGA a wyświetlaczem LCD, pozwalając za pomocą 8 pinów FPGA wysterować 16-bitową magistralę.

      

Gdy sygnał LE jest w stanie wysokim, zatrzask jest przezroczysty. Dane przechodzą z wejść D do wyjść Q. Kilka nanosekund po wyłączeniu sygnału LE zatrzask przestaje reagować na wejścia i wysterowuje wyjścia ostatnimi zapamiętanymi wartościami.

Trik polega na tym, aby zapisać bezpośrednio pierwszym 8 bitów danych, następnie zablokować zatrzask, po czym zapisać kolejnych 8 bitów. Jak wynika ze schematu, w wyniku tej operacji wszystkie 16 bitów zostanie poprawnie wysterowanych. Dodatkowo pomaga przy tym fakt, że FPGA pozwala na wystawienie dowolnego bitu na dowolnym wyjściu. Dzięki temu mogę dopracować projekt tak, aby linie danych biegły równolegle na płytce PCB bez żadnych przelotek.

 

Pamięć EEPROM

Pamięć EEPROM jest prostym układem przechowującym dane w sposób trwały.

Układ Rohm o pojemności 32 Kb jest sterowany przez dwuprzewodowy interfejs I2C. Niewiele więcej można tu powiedzieć – pamięć jest dołączona do układu peryferyjnego I2C mikrokontrolera. I2C jest dwukierunkowa, jednoliniową magistralą. Rozwiązanie typu otwarty dren zapewnia zabezpieczenie przed nieoczekiwanym wysterowaniem przez kilka układów. Oznacza to, że magistrala (i linia zegara) muszą mieć rezystory podciągające. Umieściłem rezystory o wartości 4,7 k? blisko mikrokontrolera, co widać na schemacie.

 

Gniazdo SD

Gniazdo SD ALPS SCHD3A0100 pozwala podłączyć kartę micro SD. Ten model pozwala wsunąć kartę SD, która następnie jest zatrzaskiwana po cofnięciu o około milimetr. Dzięki temu będzie utrzymana w miejscu i nie wypadnie sama z siebie.

Przewiduję, że dane dotyczące grafiki zajmą znacznie więcej, niż dostępna pamięć mikrokontrolera – potrzebny jest zatem zewnętrzny interfejs, który mógłby je pomieścić. Karty SD są najwygodniejsze. Na dodatek mikrokontroler ma już odpowiedni układ peryferyjny SDIO, który pozwala na dostęp do karty w szybkim trybie 4-bitowym. SDIO jest kolejną magistralą, która wymaga rezystorów podciągających na linii danych i komend, ponieważ także pracuje w konfiguracji z otwartym drenem. Dodałem rezystory 10 k? widoczne na schemacie mikrokontrolera.

 

Wtyki złącz

Dwa złącza o rozstawie wyprowadzeń 2,54 mm pozwalają na debugowanie i podłączenie urządzeń do wejść GPIO.

Układ wyprowadzeń gniazda debuggera odpowiada wymaganiom podanym przez STMicroelectronics dla protokołu SWD i programatora/debuggera ST-Link/v2. Ten model naprawdę przypadł mi do gustu i używam go teraz cały czas wraz z aplikacją obsługującą debugger OpenOCD – nigdy się nie zawiodłem.

Gniazdo GPIO jest połączone z kilkoma wyprowadzeniami mikrokontrolera i może pełnić różne funkcje. Upewniłem się, że może obsłużyć kilka typów często używanych urządzeń peryferyjnych, w tym urządzeń I2S – które mogę wykorzystać w przyszłości, aby zrealizować obsługę audio.

 

Projekt płytki

Zdecydowałem się na tanią dwuwarstwową płytkę o wymiarach 10 x 10 cm – rozwiązanie, które hobbysta może tanio zamówić u chińskich dostawców prototypów. Poprowadzenie wszystkich ścieżek zajęło dużo czasu.

Pierwszym komponentem było złącze LCD – musi ono być fizycznie umieszczone w odpowiednim miejscu, aby ekran LCD dało się zamontować w określonej pozycji umożliwiającej rozmieszczenie innych złącz wokół niego. Złącze LCD jest faktycznie umieszczone na spodzie płytki, patrząc od strony, którą widać na biurku.

Następnym komponentem jest układ FPGA, który umieściłem blisko środka – ale z rozwagą, aby kolejny układ z setką wyprowadzeń dało się zmieścić w bliskiej odległości.

Następne są pamięci Flash i SRAM umieszczone tak blisko FPGA, jak to możliwe. Ich ścieżki muszą być poprowadzone szczególnie ostrożnie.

Kolejnymi elementami są zasilacze FPGA i odsprzęgane ścieżki. Te ścieżki są szersze, niż większość odsprzęgających kondensatorów ceramicznych i umieszczone tak blisko wyprowadzeń FPGA, jak to możliwe. Oznacza to użycie bardzo małych elementów, w niektórych przypadkach o wymiarze 0402. Pozostałe ścieżki są odsprzężone z drugiej strony płytki za pomocą większych elementów w rozmiarach 0603 i 0805.

Po rozmieszczeniu układów o szczególnych wymaganiach wystarczy umieścić mikrokontroler w najlepszym miejscu, jakie pozostało i poprowadzić resztę sygnałów. Ten etap nie był trudny, ale czasochłonny.

Ostatnie czynności obejmują przejrzyste logo, otwory montażowe M3 i zaokrąglone rogi płytki PCB do dekoracji. Otwory montażowe są w rzeczywistości dość ważne, ponieważ płytka będzie pracować z komponentami umieszczonymi na dole, zatem muszę zadbać o podpórki zapewniające odpowiedni prześwit.

Przyjrzyjmy się kompletnej płytce PCB. Usunąłem z grafiki pola masy, aby lepiej pokazać ścieżki i elementy.

Do wykonania płytki wybrałem firmę Elecrow, jednego z chińskich dostawców, który za rozsądna cenę wydrukuje 10 kopii płytek zamówionych przez internet. Dwa-trzy tygodnie później płytki dotarły i wyglądają bardzo dobrze.

Warto zwrócić uwagę, że wszystkie ważne ścieżki biegną z FPGA do docelowych układów jako magistrala bez przelotek. Jedną z zalet pracy z układami FPGA jest to, że można samemu wybrać funkcję każdego z pinów. Odpowiednie planowanie pozwala zaprojektować elegancką i przejrzystą płytkę.

Obejrzałem płytkę PCB pod lupą i znalazłem tylko jeden problem, który był z pewnością moją winą. Wywiercone otwory na wtyczkę zasilacza były za wąskie o około 1 mm. Wprowadziłem złe wartości do programu i nie zauważyłem tego podczas wcześniejszych obserwacji. Na szczęście ten problem dało się łatwo rozwiązać – wystarczyło przypiłować nóżki złącza zasilającego, aby wszystko zaczęło do siebie pasować.

 

Montaż płytki PCB

Złożenie tego wszystkiego wymagało nieco planowania naprzód. Chciałem przylutować większość elementów w moim halogenowym piecu lutowniczym. Problem stanowiło jednak 34-pinowe złącze LCD o rozstawie 0,4 mm po drugiej stronie, które też należało przylutować.

Ostatecznie nie było to takie trudne. Zakryłem obszar pod złączem LCD, który na szczęście zawierał tylko kilka małych układów scalonych dla sterownika podświetlenia, a następnie przylutowałem pozostałe elementy w moim piecu lutowniczym. W drugim etapie odwróciłem płytkę na drugą stronę i przylutowałem tylko złącze LCD za pomocą płyty grzewczej – nad płytą znajdował się tylko zakryty wcześniej obszar.

Teraz mogłem powrócić do zakrytego obszaru i przylutować pozostałe elementy SMD ręcznie z użyciem gorącego powietrza. Na końcu za pomocą zwykłej lutownicy przymocowałem elementy przewlekane. Po krótkiej kąpieli w spirytusie na płytce nie ma zanieczyszczeń i jest gotowa do zdjęć:

Powyżej strona ze wszystkimi rozmieszczonymi układami. To pierwsze moje lutowanie poważnego projektu w halogenowym piecu. Wszystko odbyło się bezproblemowo, mimo to wolałem poprawić niektóre połączenia za pomocą lutownicy pod mikroskopem.

Spodnia strona, która faktycznie będzie znajdować się na górze – jeszcze bez dołączonego wyświetlacza LCD. Widoczne są liczne kondensatory odsprzęgające w pobliżu FPGA.

Ta sama strona płytki, tym razem z podłączonym ekranem LCD. Sam ekran jest za pomocą dwustronnej taśmy samoprzylepnej umocowany tak, aby znajdował się nieco ponad płytką PCB i kondensatorami. Kabel debuggera mieści się zaledwie kilka milimetrów od kondensatora.

Warstwa sprzętowa była łatwiejszą częścią. Teraz czas na programowanie mikrokontrolera i projekt FPGA. To powinno być ciekawe.

 

Testowanie

Oczywiście pierwszym krokiem podczas testów jest podłączenie napięcia i uruchomienie urządzenia. Zapaliła się czerwona dioda LED – to już sukces. Następnie trzeba sprawdzić, czy mikrokontroler pracuje za pomocą debuggera ST-Link/v2 i spróbować połączyć się z układem za pomocą OpenOCD.

Wykorzystuję dostarczony przez producenta skrypt, który konfiguruje interfejs i wybrany mikrokontroler tak, jak gdyby była to płytka testowa F4 Discovery. Operacja zakończyła się sukcesem, zatem mikrokontroler powinien być teraz gotowy do zaprogramowania.

 

Kod testowy mikrokontrolera

Napisałem kilka małych programów testowych, aby sprawdzić różne funkcje płytki. Wszystkie kody są dostępne na Githubie. Kody wykorzystują bibliotekę stm32plus, która pozwala wykorzystać bogate funkcje układów peryferyjnych STM32. Choć biblioteka stm32plus nie obsługuje bezpośrednio mikrokontrolerów z serii F42x, wystarczy wykorzystać kod zbudowany dla serii F40x i nie używać żadnych funkcji związanych z dodatkowymi układami peryferyjnymi dostępnymi w modelu F429

Jest to kod migający naprzemiennie diodami LED.

Jednym z drobnych problemów, które trzeba było ominąć, było uruchomienie kodu i skonfigurowanie częstotliwości rdzenia na 180 MHz, używając tylko wewnętrznego oscylatora.  Po resecie i przed wywołaniem funkcji main() każdy program STM32 wywołuje procedurę, która konfiguruje drzewo zegara i ustala szybkości różnych szyn.

Nie mogłem znaleźć żadnego przykładowe kodu ST inicjalizującego model F429 przy użyciu wewnętrznego zegara wysokiej szybkości (HSI) o częstotliwości 16 MHz. Firma dostarcza arkusz Excela przeznaczony dla modeli F40x. Wykorzystałem go jako punkt wyjścia i skonfigurowałem mnożnik PLL tak, aby uzyskać taktowanie rdzenia 180 MHz. Przy okazji uporządkowałem kod ST – każdy, kto widział kiedyś dostarczony przez ST kod w języku C zrozumie, dlaczego. Gotowy kod uruchomieniowy jest dostępny na Githubie.

Sprawdziłem po kolei wszystkie układy peryferyjne – nie było żadnych problemów. Wyjścia GPIO, EEPROM oraz najważniejsze SDIO działały poprawnie. W tym momencie byłem bardzo zadowolony, choć nie dotknąłem nawet układu FPGA.

 

Konfiguracja FPGA

Konfiguracja FPGA przebiega analogicznie do programowania mikrokontrolera. Należy utworzyć skompilowany plik i korzystając z protokołu opracowanego przez producenta przesłać go do układu, o ile jest on już w stanie rozpocząć pracę. Różnica między FPGA a mikrokontrolererem jest taka, że ich konfiguracja jest ulotna – znika po wyłączeniu zasilania, zatem FPGA należy rekonfigurować za każdym razem po włączeniu zasilania.

Firma Xilinx zapewnia wiele różnych metod konfiguracji, które są świetnie udokumentowane. Wybrałem metodę o nazwie „slave serial”, która polega na wgraniu strumienia bitów przez zewnętrzny układ (mikrokontroler) za pomocą łącza szeregowego. Poniżej widać schemat z dokumentacji Xilinx, który przedstawia możliwy sposób konfiguracji. Usunąłem z niego wyprowadzenia JTAG, z których nie korzystam.

Problem polega na tym, że interfejs konfiguracji FPGA jest zasilany z napięcia VCCAUX o wartości 2,5 V, a mikrokontroler z napięcia 3,3 V. Na szczęście Xilinx to przewidział i opracował dokument referencyjny, który opisuje bezpieczny sposób konfiguracji FPGA z mikrokontrolera zasilanego napięciem 3,3 V.

Pełny sens dodatkowych układów został szczegółowo opisany przez Xilinx, natomiast postaram się go krótko streścić. Rezystory ograniczające prąd i rezystor bocznikujący obok stabilizatora 2,5 V pochłaniają nadmierny prąd, dzięki czemu stabilizator nie zobaczy prądu wpływającego do jego wejść, który potencjalnie mógłby uszkodzić układ.

 

Szybkość konfiguracji

Skompilowany i nieskompresowany plik binarny dla XC3S50 ma rozmiar 440.096 bitów. Maksymalna szybkość linii danych szeregowych dopuszczana przez Xilinx to 66 MHz, w przypadku kompresji – 20 MHz. Te wartości są podane w specyfikacji układu jako FCCSER.

Mój projekt wykorzysta niemal cały układ FPGA, zatem kompresja w czasie transmisji zapewniana przez FPGA nie jest użyteczna – mogę skorzystać z maksymalnej częstotliwości transmisji 66 MHz. Teoretycznie mogę zaprogramować FPGA w ciągu 440.096 / 66.000.000 * 1000 = około 7 ms. W praktyce występuje dodatkowy narzut na przesuwanie bitów na wyjściu i monitorowanie zmiany stanu pinów INIT_B oraz DONE. Ostatecznie wersja debug oprogramowania producenta może zaprogramować układ w ciągu około pół sekundy.

Kod źródłowy klasy odpowiedzialnej za konfigurację jest dostępny na Githubie. Kod wykorzystuje plik binarny skompilowany wewnątrz programu mikrokontrolera i umieszczony razem z nim w pamięci Flash. Sposób realizacji tej techniki jest przedstawiony tu.

 

Testowanie FPGA

Gdy mogę już skonfigurować FPGA, czas sprawdzić, czy montaż układu domową metodą powiódł się. Oczywiście w tym celu spróbuję zamigać diodą, co w elektronice stanowi odpowiednik „Hello World”.

 

Programowanie układów Xilinx

Gdy decydowałem się na naukę języka opisu sprzętu (HDL), dostępne do wyboru języki ograniczały się do dwóch opcji: VHDL lub Verilog. VHDL przypominał trochę takie stare języki, jak Pascal lub Ada. Verilog przypominał z kolei nieco C (to błędne wrażenie). Wolałem ścisłą i zrozumiałą składnię VHDL. Ponieważ pod względem możliwości między tymi językami nie ma różnicy, wybrałem VHDL. Zawodowi projektanci FPGA często znają obydwa te języki.

Xilinx oferuje darmowe środowisko projektowe ISE Webpack, które wymaga aż 17 GB miejsca na dysku. Środowisko zawiera narzędzia, które są jednocześnie rozbudowane i skomplikowane. Początkujący projektanci mogą preferować zintegrowane środowisko, które pomaga zrozumieć przebieg pracy – Xilinx oferuje takie dwa.

ISE Design Suite jest pierwszą opcją, którą polecam początkującym. Jest stworzone w języku skompilowanym do kodu maszynowego, zatem pracuje dość szybko i nie zużywa zbyt wielu zasobów podczas pracy narzędzi syntezy.

Nawigator projektu ISE jasno pokazuje przebieg syntezy. Łatwy w użyciu interfejs pozwala tworzyć i uruchamiać symulacje. Co ważne, pomaga zrozumieć znaczenie wielu dostępnych opcji linii komend.

Drugą możliwością jest stworzenie projektu za pomocą narzędzia Plan Ahead, którego nie polecam. Plan Ahead jest najwyraźniej napisane w Javie i z tego powodu bardzo obciąża system podczas syntezy. Na słabszym laptopie zauważyłem, ze zużycie procesora sięga 100% nawet podczas przeglądania plików wyjściowych pod kątem zmian. Jednak Plan Ahead jest wygodnym narzędziem do planowania rozkładu wyprowadzeń I/O – wyświetla wizualizację obudowy podczas wyboru pinów.

Jakiś czas temu rozpocząłem pracę z ISE Design Suite. Gdy przyzwyczaiłem się do metody pracy i opcji linii komend, przeszedłem na środowisko obsługiwane w całości z linii komend z użyciem mojego ulubionego edytora tekstu i narzędzia do budowy SCons. W tym projekcie nie używałem GUI ISE.

Jedną rzeczą, nad którą Xilinx zupełnie nie panuje, jest możliwość pracy z narzędziami z linii komend wraz z narzędziami do kontroli wersji. Narzędzia będą tworzyły dziesiątki plików wyjściowych, pośrednich i raportów w wielu podkatalogach katalogu źródłowego. Trzeba zmienić zasady za pomocą plików SConcript i .gitignore, aby opanować ten bałagan. Co więcej, program coregen.exe popełnia kardynalny błąd, modyfikując swój plik wejściowy. Przez to git zawsze widzi, że plik został zmodyfikowany. Zadaję sobie pytanie, czy zespoły piszące te narzędzia same faktycznie pracują z systemem kontroli wersji.

 

Miganie diodą FPGA

Oto kod VHDL realizujący przełączanie FPGA:

To projekt synchroniczny, w którym cały proces jest taktowany sygnałem clk pochodzącym z oscylatora 40 MHz. Każdy takt oscylatora zwiększa wskazanie licznika, a po upływie sekundy jest przełączny sygnał led_out.

Układ FPGA nie jest połączony z diodą LED, zatem wyprowadziłem sygnał led_out na wyjście DEBUG i użyłem analizatora logicznego, aby sprawdzić efekt migania. Wszystko działa – zatem FPGA pracuje poprawnie i została prawidłowo przez mikrokontroler. Działają przynajmniej dwa wyprowadzenia i oscylator. Ten prosty kod przetestował duży fragment układu.

Andy Brown