Ten artykuł koncentruje się na nauce projektowania rdzenia mikrokontrolera i jest przeznaczony wyłącznie do użytku edukacyjnego. Zapraszamy do odwiedzenia www.zilog.com i sprawdź linię produktów producenta, aby wybrać mikrokontroler, który pasuje do Twoich potrzeb projektowych (od ośmiobitowego Z8 Encores! i eZ80 Acclaims do 32-bitowego ARM Cortex-M3 oparte ZNEO32! który obejmuje zaawansowane możliwości sterowania silnikiem).
moja miłość do mikrokontrolerów i mikroprocesorów rozpoczęła się w 1988 roku, kiedy pracowałem nad dyplomem technicznym w CEFET-PR (czteroletniej brazylijskiej szkole średniej/technicznej i Uniwersytecie zlokalizowanym w Kurytybie). Zacząłem od nauki podstaw podczas zwiedzania klasycznego Ziloga z-80 (rysunek 1a).
rysunek 1a. Zilog Z-80A (dzięki uprzejmości Wikimedia Commons).
przewiń do przodu przez karierę programistyczną, która obejmowała napisanie kilku książek na temat programowania mikrokontrolerów (patrz zasoby), rozpoczęcie małego domu projektowego (ScTec) i Ukończenie studiów podyplomowych na CEFET-SC (innym brazylijskim Uniwersytecie znajdującym się w Florianopolis). To było w 2008 roku, kiedy miałem większy kontakt z programowalną logiką i VHDL i moja ciekawość była szczytowa. Wiele lat później, w 2016 roku, znalazłem bardzo przystępny cenowo zestaw FPGA (Field-Programmable Gate Array) i postanowiłem dać mu szansę i zacząłem uczyć się więcej o technologii FPGA.
co byłoby lepsze niż zaprojektowanie softcore ’ a, aby dowiedzieć się więcej o VHDL (vhsic hardware description language), FPGA i samych rdzeniach mikroprocesorowych? Skończyło się na wyborze nowoczesnego z-80: Zilog Z8 Encore! (Alias eZ8; rys. 1B).
rysunek 1B. Zilog eZ8.
to ośmiobitowy rdzeń mikrokontrolera z prostym-ale potężnym — zestawem instrukcji i bardzo ładnym debuggerem na chipie. Dzięki lekkiemu IDE (integrated development environment) i darmowemu kompilatorowi ANSI C, jest to doskonały projekt do nauki (a także nauczania) o systemach wbudowanych.
zanim zanurzymy się w głębiny podstawowej eksploatacji, VHDL i FPGA, rzućmy okiem na Zilog Z8 Encore! funkcje.
rysunek 1C. FPz8 na FPGA.
Zilog Z8 Bis!
eZ8 to ośmiobitowa rodzina mikrokontrolerów oparta na udanej rodzinie Z8 Ziloga i na wielkim dziedzictwie Z-80. Posiada maszynę Harvard CISC z maksymalnie 4096 bajtami pamięci RAM (rejestr plików i obszar rejestrów specjalnych funkcji), do 64 KB pamięci programu (Zwykle pamięci Flash) i do 64 KB pamięci danych (RAM). Rdzeń eZ8 zawiera również wektorowy kontroler przerwań z programowalnym priorytetem i debugger na chipie, który komunikuje się z komputerem głównym za pomocą asynchronicznej komunikacji szeregowej. Te mikrokontrolery są wyposażone w bardzo ładny zestaw peryferyjny, od wszechstronnych 16-bitowych timerów do timerów sterowania silnikiem, od wielu UART (IrDA ready) do urządzeń USB i wiele więcej (odwiedź www.zilog.com aby sprawdzić pełną linię produktów).
jedną z głównych cech modelu programowania eZ8 jest brak stałego akumulatora. Zamiast tego dowolny z 4096 możliwych adresów pamięci RAM może działać jako akumulatory. Procesor traktuje swoją główną PAMIĘĆ RAM (plik i SFRs — special function registers — area) jako duży zestaw rejestrów procesora. Aby to osiągnąć, RAM jest podzielony na grupy rejestrów (istnieje 256 grup po 16 działających rejestrów). Instrukcja zwykle działa w obrębie jednej działającej grupy rejestrów, która jest wybierana przez SFR o nazwie RP (register pointer). Zauważ, że wszystkie SFR znajdują się na ostatniej stronie PAMIĘCI RAM (adresy od 0xF00 do 0xfff).
jeśli chodzi o zestaw instrukcji, istnieją 83 różne instrukcje podzielone na dwie strony kodu opcode. Zawiera on zwykłe instrukcje dla podstawowych operacji, takich jak dodawanie, odejmowanie, operacje logiczne, instrukcje manipulacji danymi, instrukcje przesuwania, instrukcje zmiany przepływu, niektóre instrukcje 16-bitowe, Testowanie i manipulowanie bitami, mnożenie 8×8 itp.
obszar pamięci programu jest zorganizowany tak, że pierwsze adresy są dedykowane do specjalnych celów. Adresy 0x0000 i 0x0001 są dedykowane do opcji konfiguracyjnych; adresy 0x0002 i 0x0003 przechowują wektor resetowania; i tak dalej. Tabela 1 pokazuje organizację pamięci programu.
0x0000 | Option bytes |
0x0002 | Reset vector |
0x0004 | WDT vector |
0x0006 | Illegal instruction vector |
0x0008 to 0x0037 | Interrupt vectors |
0x0038 to 0xFFFF | User program memory area |
TABLE 1. Simplified program memory organization.
niektóre urządzenia zawierają również drugą przestrzeń danych (do 65 536 adresów), do której można uzyskać dostęp tylko za pomocą instrukcji LDE/LDEI. Ten obszar może być wykorzystany do przechowywania mniej używanych danych (ponieważ Odczyt/Zapis do niego jest wolniejszy niż obszar RAM/SFR).
FPz8
pierwsza implementacja FPz8 wykorzystuje bardzo konserwatywne podejście do projektowania z dwoma głównymi magistralami: jedną dla pamięci programu, a drugą dla pamięci rejestru. Ponieważ zdecydowałem się nie zawierać obszaru pamięci danych, instrukcje LDE/LDEI nie są zaimplementowane.
szyny pamięci programu obejmują 16-bitową magistralę adresową instrukcji (IAB), ośmiobitową magistralę danych instrukcji (IDB do odczytu danych z pamięci programu), ośmiobitową magistralę danych instrukcji zapisu (IWDB do zapisu danych do pamięci programu) oraz sygnał PGM_WR sterujący zapisem do pamięci programu. FPz8 zawiera 16,384 bajtów pamięci programu zaimplementowanej przy użyciu synchronicznego bloku RAM (co oznacza, że zawartość pamięci programu jest tracona, gdy urządzenie jest wyłączone).
pięć szyn obszaru rejestru składa się z trzech dla obszaru rejestru plików (user RAM), a kolejne dwa dla specjalnych rejestrów funkcji. Istnieje główna 12-bitowa szyna adresu rejestru plików (FRAB), ośmiobitowa szyna danych wejściowych rejestru plików (FRIDB), ośmiobitowa szyna danych wyjściowych rejestru plików (FRODB), ośmiobitowa szyna danych wejściowych rejestru (RIDB) i wreszcie ośmiobitowa szyna danych wyjściowych rejestru (RODB) do zapisu do SFR. Fpz8 zawiera 2048 bajtów pamięci RAM użytkownika zaimplementowanej przy użyciu synchronicznego bloku RAM.
Rysunek 2 przedstawia schemat blokowy fpz8; możesz zobaczyć procesor, dwie jednostki pamięci (jedna do przechowywania programów, a druga do przechowywania danych), a także zewnętrzny moduł timera.
rysunek 2. SCHEMAT BLOKOWY FPz8.
zauważ, że nie używam dwukierunkowych autobusów do żadnych połączeń w tym projekcie. Autobusy jednokierunkowe są prostsze w użyciu, choć zajmują mniej miejsca.
opis VHDL FPz8 jest duży i nieco złożony, więc zamierzam podzielić jego działanie na kilka modułów, aby ułatwić zrozumienie:
- Silnik kolejkowania instrukcji
- dekodowanie instrukcji
- przerywanie przetwarzania
- Debugger
Silnik kolejkowania instrukcji
pobieranie instrukcji jest podstawowym zadaniem każdego procesora. Architektura Harvard FPz8 umożliwia jednoczesne pobieranie i dostęp do danych (dzięki oddzielnym magistralom instrukcji i danych). Oznacza to, że procesor może pobrać nową instrukcję, podczas gdy inna czyta lub zapisuje do pamięci danych.
eZ8 ma słowo instrukcji o zmiennej długości (Długość instrukcji waha się od jednego bajtu do pięciu bajtów); niektóre instrukcje są długie, ale działają szybciej niż inne. W ten sposób Instrukcja BRK ma długość jednego bajtu i działa w dwóch cyklach, podczas gdy LDX im, ER1 ma długość czterech bajtów i działa w dwóch cyklach zegara.
więc jak możemy pomyślnie zdekodować wszystkie te instrukcje? Z kolejką instrukcji, czyli mechanizmem, który pobiera bajty z pamięci programu i zapisuje je do ośmiobajtowej tablicy:
if (CAN_FETCH=’1′) then
if (iQueue.FETCH_STATE=F_ADDR) then
fetch_addr := PC;
IAB <= PC;
IQUEUE.WRPOS: = 0;
IQUEUE.RDPOS: = 0;
IQUEUE.CNT := 0;
IQUEUE.FETCH_STATE: = F_READ;
else
if (IQUEUE.FULL= '0′) then
IQUEUE.KOLEJKA (IQUEUE.WRPOS): = IDB;
FETCH_ADDR:= FETCH_ADDR + 1;
IAB < = FETCH_ADDR;
IQUEUE.WRPOS: = IQUEUE.WRPOS + 1;
IQUEUE.CNT: = IQUEUE.CNT + 1;
end if;
end if;
end if;
if (IQUEUE.CNT=7) Następnie IQUEUE.FULL:= '1′; else IQUEUE.FULL:= '0′;
end if;
LISTING 1. Silnik kolejki instrukcji.
pobieranie jest kontrolowane przez główny sygnał enable (CAN_FETCH), który może być wyłączony w niektórych szczególnych przypadkach (przetwarzanie przerwań, przez instrukcje LDC/LDCI lub dostęp do debuggera). Istnieje również struktura (iQueue), która przechowuje kilka wewnętrznych parametrów (stan pobierania, wskaźniki odczytu i zapisu, sama tablica kolejki, licznik i pełny wskaźnik).
licznik kolejek (CNT) służy do określenia liczby bajtów dostępnych do użycia (odczytu) w kolejce. Etap dekoder używa tej liczby do sprawdzenia, czy żądana liczba bajtów instrukcji jest już dostępna w kolejce.
dekodowanie instrukcji
tutaj dzieje się prawdziwa magia. Dekoder instrukcji odczytuje opcody z kolejki instrukcji i przekłada je na odpowiednie operacje.
projekt dekodera instrukcji rozpoczął się od ustalenia relacji między wszystkimi instrukcjami i trybami adresowania. Na pierwszy rzut oka łatwo zauważyć, że niektóre instrukcje (Rysunek 3) są pogrupowane według kolumn (DJNZ,JR cc, X,LD r1, IM,JP cc, DA I INC R1). Dekodowanie instrukcji INC r1 jest proste: w tych jednobajtowych instrukcjach, wysoka końcówka określa rejestr źródłowy / docelowy, a niższa końcówka określa samą instrukcję (0xE).
Rysunek 3. Opcodes by groups.
Większość instrukcji można sklasyfikować według kilku podstawowych zasad:
- kolumny (dolna część kodu opcode) zwykle określają tryb adresowania: Na przykład instrukcje kolumny 0x9 w większości używają trybu adresowania IM, ER1 i mają długość czterech bajtów(drugi bajt to natychmiastowy argument, a dwa ostatnie bajty to docelowy Rozszerzony adres).
- wiersze (wyższe skubanie kodu opcode) zwykle określają operację: instrukcje wiersza 0x0 są głównie operacjami dodawania; instrukcje wiersza 0x2 są głównie operacjami odejmowania i tak dalej.
jeśli spojrzymy na wiersz 0x1, widzimy, że kolumny 0x0 i 0x1 są instrukcjami RLC, a kolumny 0x2 do 0x9 są instrukcjami ADC. Tak więc, możemy zaprojektować ALU, które bierze skubanie jako wejście (wyższe skubanie z opcode) i odpowiednio je dekoduje. Chociaż działałoby to dla kolumn 0x2 do 0x9, potrzebowalibyśmy innego podejścia dla pierwszych dwóch kolumn.
dlatego skończyło się na napisaniu dwóch jednostek: jednej Alu, która koncentruje się na większości instrukcji arytmetycznych i logicznych; i drugiej jednostki (Jednostka logiczna 2 lub LU2), która wykonuje inne operacje pokazane w kolumnach 0x0 i 0x1 (nie wszystkie operacje widoczne na tych kolumnach są wykonywane przez LU2). Kody operacji zarówno dla ALU, jak i LU2 zostały dobrane tak, aby pasowały do wierszy kodu opcode pokazanych na fig.3.
innym ważnym szczegółem jest to, że wszystkie instrukcje w tej samej kolumnie i grupie mają ten sam rozmiar w bajtach, więc mogą być dekodowane w tej samej sekcji dekodera.
konstrukcja dekodera wykorzystuje dużą maszynę skończonego stanu (FSM), która rozwija się na każdym tiku zegara. Każda instrukcja rozpoczyna się w stat CPU_DECOD. W tym miejscu dekoder dekoduje kody opcodes, przygotowuje szyny i wewnętrzne sygnały wspierające oraz kroki do innych stanów wykonania. Spośród wszystkich tych stanów, dwa są powszechnie używane przez wiele instrukcji: CPU_OMA i CPU_OMA2. Wiesz dlaczego? Jeśli powiedziałeś, ponieważ są one związane z ALU i LU2, masz całkowitą rację!
OMA jest skrótem od One Memory Access i jest ostatnim stanem dla wszystkich instrukcji związanych z ALU (ADD, ADC, ADDX, ADCX, SUB, SBC, SUBX, SBCX, OR, ORX, AND, ANDX, XOR, XORX, CP, CPC, TCM, TCMX, TM, TMX oraz niektóre warianty LD i LDX). Z drugiej strony, CPU_OMA2 jest ostatnim stanem dla wszystkich instrukcji związanych z LU2 (RLC, INC, DEC, DA, COM, RL, CLR, RRC, SRA, SRL, RR i SWAP).
teraz rzućmy okiem na stan CPU_DECOD. Patrz rysunek 4.
rysunek 4. Stan CPU_DECOD.
w stanie CPU_DECOD widzimy, że wiele akcji ma miejsce. Na początku niektóre zmienne tymczasowe są inicjowane do stanu domyślnego. Zauważ, że NUM_BYTES jest bardzo ważne, ponieważ kontroluje ile bajtów zostało pochłoniętych przez dekoder instrukcji. Jego wartość jest używana w ostatniej części tego etapu, aby zwiększyć komputer (licznik programu), przyspieszyć wskaźnik odczytu kolejki i zmniejszyć liczbę dostępnych bajtów w kolejce.
po sekcji inicjalizacji możemy zobaczyć sekcję przetwarzania przerwań. Jest on odpowiedzialny za wykrywanie przerwań oczekujących i odpowiednio przygotowuje procesor. Omówię to w następnej sekcji.
rzeczywisty blok dekodowania instrukcji sprawdza, czy tryb niskiego zasilania nie jest aktywny, a także czy tryb debuggera jest wyłączony (OCDCR.DBGMODE=0). Lub, w trybie debugowania, wydano jednoetapowe polecenie debugowania (OCDCR.DBGMODE=1 i OCD.SINGLE_STEP=1). Następnie sprawdza dostępne bajty w kolejce i kontynuuje dekodowanie.
niektóre instrukcje (głównie jednobajtowe) są wypełniane w stanie CPU_DECOD, podczas gdy inne potrzebują wielu stanów, dopóki nie zostaną w pełni wypełnione.
zauważ, że niektóre instrukcje dekodowania mogą korzystać z kilku funkcji i procedur napisanych specjalnie dla FPz8:
- DATAWRITE-ta procedura przygotowuje szyny do operacji zapisu. Wybiera, czy miejscem docelowym jest wewnętrzny SFR, zewnętrzny SFR, czy lokalizacja pamięci RAM użytkownika.
- DATAREAD-jest to funkcja odwrotna dla DATAWRITE. Jest używany do odczytu adresu źródłowego i automatycznie wybiera, czy jest to wewnętrzny SFR, zewnętrzny SFR, czy lokalizacja pamięci RAM użytkownika.
- CONDITIONCODE-używany dla instrukcji warunkowych (takich jak JR i JP). Pobiera 4-bitowy kod warunku, testuje go i zwraca wynik.
- ADDRESSER4, ADDRESSER8 i ADDRESSER12-funkcje te zwracają 12-bitowy adres ze źródła cztero-, ośmio-lub dwunastobitowego. Wykorzystują zawartość rejestru RP do wygenerowania ostatecznego 12-bitowego adresu. ADDRESSER8 i ADDRESSER12 również sprawdzają, czy nie ma żadnego trybu adresowania Escape.
- ADDER16 — jest to 16-bitowy adder do obliczania przesunięcia adresu. Pobiera 8-bitowy operand ze znakiem, Sign rozszerza go, dodaje do 16-bitowego adresu i zwraca wynik.
- ALU i LU2-te były wcześniej omawiane i wykonują większość operacji arytmetycznych i logicznych.
przetwarzanie przerwań
jak powiedziałem wcześniej, eZ8 ma wektorowy kontroler przerwań z programowalnym priorytetem. Na początku myślałem, że ta sekcja nie będzie tak trudna, ponieważ przerwy to nic wielkiego, prawda? Cóż, kiedy zacząłem zastanawiać się, jak wykonać wszystkie potrzebne zadania (zapisywanie kontekstu, wektorowanie, zarządzanie priorytetami itp.), Zdałem sobie sprawę, że będzie trudniej niż początkowo myślałem. Po kilku godzinach wymyśliłem obecny projekt.
system przerwań FPz8 okazał się prosty. Posiada osiem wejść (od INT0 do INT7); globalne włączanie przerwań (bit IRQE znajdujący się w rejestrze IRQCTL); dwa rejestry do ustawiania priorytetów (IRQ0ENH i IRQ0ENL); i jeden rejestr dla FLAG przerwań (IRQ0). Konstrukcja wykorzystuje zagnieżdżony łańcuch IF, który generuje adres wektorowy po wykryciu zdarzenia przerwania dotyczącego włączonego przerwania.
Rysunek 5 przedstawia skompresowany widok systemu przerwań. Uwaga istnieje instrukcja first IF z symbolem ATM_COUNTER. Jest to prosty licznik używany przez instrukcję ATM (wyłącza przerwania na trzy cykle instrukcji, umożliwiając operacje atomowe).
rysunek 5. System przerwań FPz8.
ostatni komentarz dotyczący przerwań: Rejestr znaczników przerwań (irq0) sampluje przerwanie wejścia każdej rosnącej krawędzi zegara systemowego. Istnieją również dwie zmienne bufora (IRQ0_LATCH i OLD_IRQ0), które przechowują bieżący i ostatni stan FLAG. Pozwala to na wykrywanie przerwań, a także synchronizuje Zewnętrzne wejścia z wewnętrznym zegarem (FPGA nie działają dobrze z asynchronicznymi sygnałami wewnętrznymi).
On-Chip Debugger
jest to prawdopodobnie najfajniejsza funkcja tego softcore, ponieważ pozwala na komercyjne zintegrowane środowisko programistyczne (IDE; ZDS-II Ziloga) do komunikacji, programowania i debugowania oprogramowania działającego na FPz8. On-chip debugger (OCD) składa się z UART z funkcją autobaud i dołączonym do niego procesorem poleceń. UART wykonuje komunikację szeregową z komputerem hosta i dostarcza polecenia i dane do maszyny stanu debuggera, która przetwarza polecenia debugera (przetwarzanie poleceń debuggera FSM znajduje się wewnątrz stanu CPU_DECOD).
rysunek 6. On-chip debugger UART (zwróć uwagę na synchronizator DBG_RX).
mój projekt OCD implementuje prawie wszystkie polecenia dostępne na prawdziwym sprzęcie, z wyjątkiem poleceń związanych z pamięcią danych (polecenia debugowania 0x0C i 0X0D); licznik read runtime (0x3); I read program memory CRC (0X0E).
jedną z rzeczy, na którą chciałbym zwrócić uwagę, jest potrzeba ostrożności w przypadku sygnałów asynchronicznych wewnątrz układów FPGA. Mój pierwszy projekt nie uwzględniał tego podczas przetwarzania sygnału wejściowego DBG_RX. Wynik był absolutnie dziwny. Mój projekt działał bezbłędnie w symulacji. Pobrałem go do FPGA i zacząłem bawić się interfejsem szeregowym debugowania za pomocą terminala szeregowego (moja płyta FPGA ma wbudowany konwerter szeregowo-USB).
ku mojemu zdziwieniu, chociaż przez większość czasu mogłem z powodzeniem wysyłać polecenia i otrzymywać oczekiwane rezultaty, czasami projekt po prostu zamarzał i przestał odpowiadać. Miękki reset sprawiłby, że wszystko wróciłoby do prawidłowego działania, ale to mnie intrygowało. Co się stało?
po wielu testach i odrobinie googlowania doszedłem do wniosku, że jest to prawdopodobnie związane z asynchronicznymi krawędziami szeregowego sygnału wejściowego. Następnie włączyłem kaskadowy zatrzask, aby zsynchronizować sygnał z moim wewnętrznym zegarem i wszystkie problemy zniknęły! Jest to trudny sposób, aby dowiedzieć się, że zawsze musisz zsynchronizować sygnały zewnętrzne przed wprowadzeniem ich w złożoną logikę!
muszę powiedzieć, że debugowanie i udoskonalanie kodu debuggera było najtrudniejszą częścią tego projektu; głównie dlatego, że współdziała ze wszystkimi innymi podsystemami, w tym autobusami, dekoderem i kolejką instrukcji.
synteza i testowanie
po pełnej kompilacji (użyłem Quartus II V9.1 sp2), rdzeń FPz8 zużył 4900 elementów logicznych, 523 rejestry, 147 456 bitów pamięci na chipie i jeden wbudowany dziewięciobitowy mnożnik. Ogólnie rzecz biorąc, FPz8 wykorzystuje 80% dostępnych zasobów EP4CE6. Chociaż jest to dużo, nadal dostępnych jest około 1200 elementów logicznych dla urządzeń peryferyjnych (mój prosty 16-bitowy timer sumuje się do około 120 elementów logicznych i 61 rejestrów). Pasuje nawet do najmniejszego FPGA Cyclone IV – ep4ce6-czyli tego zamontowanego na taniej płycie mini, której tutaj użyłem (rys. 7).
rysunek 7. Płyta Altera Cyclone IV EP4CE6 mini.
mini płyta zawiera (wraz z urządzeniem EP4CE6): pamięć konfiguracji szeregowej EPCS4 (zamontowana na dolnej stronie); układ konwertera FTDI serial-to-USB, a także moduł oscylatora kwarcowego 50 MHz; niektóre przyciski, Diody LED i nagłówki pinów, aby uzyskać dostęp do pinów FPGA. Nie ma zintegrowanego USB-blastera (do programowania FPGA), ale pakiet, który kupiłem, zawierał również zewnętrzny klucz sprzętowy.
co do prawdziwych testów to nie trzeba dodawać, że FPz8 nie zadziałał za pierwszym razem! Po zastanowieniu się trochę i przeczytaniu komunikatów wyjściowych kompilatora, zorientowałem się, że prawdopodobnie był to problem z czasem. Jest to bardzo powszechny dylemat przy projektowaniu z programowalną logiką, ale ponieważ był to mój drugi projekt FPGA w historii, nie zwróciłem na niego wystarczającej uwagi.
sprawdzając komunikaty analizy czasu, zauważyłem ostrzeżenie, że maksymalny zegar powinien wynosić około 24 MHz. Na początku próbowałem użyć dzielnika przez 2 do wygenerowania zegara procesora 25 MHz, ale nie było to niezawodne. Następnie użyłem dzielnika przez 3. Wszystko zaczęło działać idealnie!
dlatego FPz8 pracuje obecnie na częstotliwości 16,666 MHz. Możliwe jest osiągnięcie wyższych prędkości poprzez użycie jednego z wewnętrznych PLL do mnożenia/dzielenia głównego zegara w celu uzyskania zegara niższego niż 24 MHz, ale wyższego niż 16,666 MHz.
programowanie i debugowanie
Korzystanie z FPz8 jest bardzo proste i proste. Po pobraniu projektu do układu FPGA procesor uruchomi dowolny program załadowany do pamięci. Możesz dostarczyć plik szesnastkowy i użyć menedżera wtyczek MegaWizard, aby zmienić plik inicjalizacji pamięci programu. W ten sposób kod aplikacji zacznie działać po sygnale resetowania.
możesz użyć Zilog ZDS-II IDE do napisania kodu Assembly lub C i wygenerowania niezbędnych plików hex (zwykle wybieram Z8F1622 jako moje urządzenie docelowe, ponieważ ma również 2 KB pamięci RAM i 16 KB pamięci programu). Dzięki wbudowanemu debugerowi możliwe jest również użycie ZDS-II IDE do pobrania kodu do FPz8 za pomocą szeregowego połączenia debugowania (w naszym przypadku USB).
przed połączeniem upewnij się, że ustawienia debuggera są takie same jak na rysunku 8. Odznacz opcję ” Użyj Wymaż stronę przed flashowaniem „i wybierz” SerialSmartCable ” jako bieżące narzędzie do debugowania. Nie zapomnij również sprawdzić, czy wirtualny port COM FTDI jest poprawnie wybrany jako port Debugowania (użyj przycisku Setup). Możesz również ustawić żądaną prędkość komunikacji; 115,200 bps działa bardzo dobrze dla mnie.
rysunek 8. Ustawienia debuggera.
zauważ, że podczas łączenia się z FPz8, IDE ZDS-II wyświetli komunikat ostrzegawczy informujący, że urządzenie docelowe nie jest tym samym, co projekt. Dzieje się tak, ponieważ nie zaimplementowałem niektórych obszarów pamięci ID. Po prostu zignoruj Ostrzeżenie i kontynuuj sesję debugowania.
po pomyślnym pobraniu kodu możesz uruchomić aplikację (przycisk GO), instrukcje krok, sprawdzić lub edytować rejestry, ustawić punkty przerwania itp. Jak w przypadku każdego innego dobrego debugera, możesz na przykład wybrać rejestr PAOUT (w sekcji PORTS group), a nawet zmienić stan diod LED podłączonych do PAOUT.
kilka prostych przykładów kodu C można znaleźć w plikach do pobrania.
pamiętaj tylko, że fpz8 ma niestabilną pamięć programu. Tak więc każdy program pobrany do niego jest tracony, gdy FPGA jest wyłączony.
zamykanie
ten projekt zajął mi kilka tygodni, ale wspaniale było zbadać i zaprojektować rdzeń mikrokontrolera.
mam nadzieję, że ten projekt może być przydatny dla każdego, kto chce dowiedzieć się o podstawach obliczeniowych, mikrokontrolerach, programowaniu wbudowanym i/lub VHDL. Wierzę — że-w połączeniu z tanią płytą FPGA-FPz8 może zapewnić fantastyczne narzędzie do nauki (i nauczania). Miłej zabawy! NV
CEFET-PR:
www.utfpr.edu.br
ScTec:
www.sctec.com.br
HCS08 Unleashed:
https://www.amazon.com/HCS08-Unleashed-Designers-Guide-Microcontrollers/dp/1419685929
Instrukcja obsługi procesora Zilog eZ8 (UM0128):
www.zilog.com/docs/UM0128.pdf
Zilog Z8F64xx Product Specification (PS0199):
www.zilog.com/docs/z8encore/PS0199.pdf
Zilog ZDS II IDE User Manual (UM0130):
www.zilog.com/docs/devtools/UM0130.pdf
Zilog ZDS-II Software Download:
https://www.zilog.com/index.php?option=com_zcm&task=view&soft_id=7&Itemid=74
Zilog Microcontroller Product Line:
http://zilog.com/index.php?option=com_product&task=product&businessLine=1&id=2&parent_id=2&Itemid=56
Project Files available at:
https://github.com/fabiopjve/VHDL/tree/master/FPz8
FPz8 at Opencores.org:
http://opencores.org/project,fpz8