UKŁADY MIKROPROGRAMOWANE Spis treści 1. WPROWADZENIE DO MIKROPROGRAMOWANIA...2 2. PRZYKŁADOWY UKŁAD MIKROPROGRAMOWANY...3 2.1. UKŁAD STERUJĄCY...3 2.2. UKŁAD WYKONAWCZY...5 2.3. FORMAT MIKROROZKAZU...8 3. ASEMBLER MIKROINSTRUKCJI ELMA...9 3.1. WPROWADZENIE...9 3.2. PLIK DEFINICYJNY.DEF...10 3.3. PLIK MIKROPROGRAMU.ASM...10 3.4. PRZYKŁAD PLIKU DEFINICYJNEGO...11 3.5. PRZYKŁADY...12 5. ZESTAW LABORATORYJNY...15 5.1 MODUŁ FGPA...15 5.2 MODUŁ WYŚWIETLACZA LCD...16 Warszawa 17.11.05
Układy mikroprogramowane 1. Wprowadzenie do mikroprogramowania Mikroprogramowane układy cyfrowe składają się z dwóch części: - części wykonującej operacje na danych wejściowych (układ wykonawczy), - części sterującej wykonywaniem tych operacji (układ sterujący). Schemat takiego układu przedstawia rysunek 1. Układ sterujący kontroluje pracę układu wykonawczego poprzez linie sterowania S i. Liniami tymi przesyłane są sygnały wybierające rodzaj operacji, która ma być wykonana przez układ wykonawczy oraz sygnały wskazujące skąd mają być pobrane argumenty dla tej operacji. Układ wykonawczy informuje o swoim stanie za pomocą sygnałów przesyłanych liniami warunków W i. Pojawiają się tam np. sygnały mówiące o wyniku ostatniej operacji. Sygnały te wpływają na dalsze działanie jednostki sterującej. Laboratoryjny układ wykonawczy posiada dwa ośmiobitowe wejścia danych WE1 i WE0 i ośmiobitowe wyjście danych WY. WE1 WE0 Układ Wykonawczy S i Układ sterujący W i WY Rysunek 1. Schemat blokowy układu mikroprogramowanego Układ sterujący można zaprojektować na dwa różne sposoby: jako automat synchroniczny lub jako układ z pamięcią. Pierwszy sposób polega na zaprojektowaniu takiego automatu synchronicznego, którego działanie (przejścia ze stanu do stanu) jest określone przez algorytm wykonywany przez układ wykonawczy. Na podstawie algorytmu buduje się tabelę przejść i wyjść automatu. Jednym z rozwiązań może być automat zwany rozdzielaczem sterującym, w którym stany kodowane są w kodzie 1 z n (przerzutników jest tyle ile stanów). Drugi sposób polega na utworzeniu odpowiedniego programu działającego zgodnie z wymaganym algorytmem i zapisaniu go w pamięci. Układ taki nazywany jest mikroprogramowanym układem sterującym. Kolejne rozkazy programu nazywane są mikrorozkazami lub mikroinstrukcjami. Mikroinstrukcje składają się z mikrooperacji czyli zestawu bitów przeznaczonych do sterowania poszczególnymi blokami układu. Układ mikroprogramowany wyróżnia się prostotą i przejrzystością budowy. Zastosowanie mikroprogramowania pozwala na łatwą modyfikację działania jednostki sterującej poprzez wymianę mikroprogramu bez konieczności modyfikowania struktury sprzętowej układu. 2/17
Układy mikroprogramowalne 2. Przykładowy układ mikroprogramowany 2.1. Układ sterujący Przykładowy układ sterujący przestawiono na rysunku 2. W skład układu sterującego wchodzi: - pamięć stała ROM, - układ adresowania (licznik mikrorozkazów LA i multiplekser warunku skoku JC), - licznik pętli LP. S..S 2 0 0 0 S..S 10 3 1 1 P 8 2 C 8 P 8 C 8 3 4 5 JC LD Reset LA 6 7 A-A 7 0 ROM 256x40 S 11 S 12 S..S 39 16 E Preset LP Z Rysunek 2. Schemat blokowy układu sterującego Pamięć ROM W pamięci ROM (w układzie laboratoryjnym o pojemności 256 słów 40 bitowych) przechowywane są mikrorozkazy. Każdy mikrorozkaz składa się z 40 bitów (słowo w tej pamięci) i jest dzielony na dwie części. Jedna z nich (bity od S 16 do S 39 ) jest przeznaczona do sterowania pracą układu wykonawczego, a druga z nich (bity od S 0 do S 12 ) odpowiada za sterowanie pracą układu sterującego (bity od S 13 do S 15 są nieużywane). Wybór komórki pamięci następuje poprzez podanie (z układu adresowania) adresu na wejścia A 7 A 0 pamięci ROM. 3/17
Układy mikroprogramowane 4/17 Układ adresowania Wartość sygnału na wyjściu multipleksera JC określa sposób wyznaczenia adresu kolejnego mikrorozkazu pobieranego z pamięci. Jeśli wartość na wyjściu multipleksera JC jest zero (na wejściu LD licznika adresowego LA), to pobrany zostanie mikrorozkaz umieszczony pod kolejnym (następnym w stosunku do aktualnego) adresem w pamięci ROM. Licznik LA jest wtedy inkrementowany. Jeśli na wyjściu JC jest jedynka, to pobrany zostanie mikrorozkaz umieszczony pod adresem zapisanym na bitach S 10 do S 3 mikrorozkazu. W tym przypadku mówimy, że w programie wykonuje się skok. Jeśli bity S 2 do S 0 mają wartość 000, to na wyjściu multipleksera jest zero (wejście oznaczone 0 multipleksera) i jako następny wykonywany jest mikrorozkaz umieszczony pod kolejnym adresem w pamięci ROM. Jeśli bity S 2 do S 0 przyjmują wartość 001, to na wyjściu JC jest jedynka (wejście multipleksera oznaczone 1) i wykonuje się skok bezwarunkowy. Jeśli bity S 2 do S 0, mają wartość inną niż 000 lub 001, to wartość na wyjściu multipleksera JC zależy od podanych warunków, czyli stanów na wejściach 2, 3, 4, 5 i 7 multipleksera. Jeśli wartość warunku będzie równa 1, to wykonany zostanie skok warunkowy. Warunków może być pięć: w układzie wykonawczym powstają cztery warunki (P 8, C 8, P 8, C 8 ), a jeden jest brany z wyjścia Z licznika pętli LP (jedno z wejść multipleksera JC jest nieużywane). W tabeli 1 zestawiono wszystkie warunki. Tabela 1. Sterowania multipleksera warunków JC Sterowanie Wyjście układu JC Opis S 2 do S 0 Warunek (wejście LD licznika adresów) 000 0 Inkrementacja licznika adresów 001 1 Ładowanie licznika wartością S 10 do S 3 010 P 8 Wartość wysuwanego bitu 011 C 8 Przeniesienie sumatora 100 P8 Negacja wartości wysuwanego bitu 101 C8 Przeniesienie sumatora 110 - Nie używany 111 Z Wyzerowanie licznika Licznik LA wykonuje 2 mikrooperacje: 1. ładowanie wpis równoległy wartości zapisanej w mikroprogramie na bitach S 10 do S 3 (wykonanie skoku LD=1), 2. inkrementacja zwiększanie zawartości o jeden (wybór kolejnego mikrorozkazu, LD=0), Licznik może zostać także wyzerowany przez operatora, który uruchomi przełącznik Reset. Tabela 2. Sterowania licznika adresów LA LD Reset Opis 1 1 Ładowanie wartościami zapisanymi na bitach S 9 do S 3 0 1 Inkrementacja X 0 Reset asynchroniczny Licznik pętli LP Licznik LP służy do implementacji w programie pętli o 8 iteracjach. Jest to 3 bitowy licznik poprzednikowy z synchronicznym wpisywaniem stanu 111 (wejście Preset) oraz wejściem E zezwolenia na liczenie. Wyjście Z ma wartość 0, wtedy i tylko wtedy, gdy licznik ma wartość 0. Gdy aktywne jest wejście E licznika (bit S 12 słowa mikrorozkazu), to w każdym cyklu zegara zmniejsza on swoją zawartość o jeden.
Układy mikroprogramowalne Tabela 3. Sterowania licznik pętli LP Sterowanie S 12 do S 11 Operacja Opis x1 LP:=111 Ładowanie 10 LP:=LP-1 Dekrementacja 2.2. Układ wykonawczy Schemat układu wykonawczego przedstawiony został na rysunku 3. Jest to prosty procesor składający się z: - jednostki arytmetyczno-logicznej ALU, - rejestru znaczników RZN, - rejestru akumulatora A, - multipleksera argumentów MA, - banku 8 rejestrów pomocniczych BR, - rejestru wyjściowego RWY. WE1 (WE..WE) 15 8 WE0 (WE..WE) 7 0 S 23 S..S 22 20 Zapis R..R 2 0 BR S..S 33 26 0 1 2 MA 3 S..S 25 24 A..A 7 0 B..B 7 0 Operacja S..S 19 16 ALU C 8 P 8 C 0 P 0 C 8 P 8 C 0 P 0 RZN Sel Cs S 35 S 34 A P 8 C 8 s 36 LD RWY WYNIK Rysunek 3 Układ wykonawczy 5/17
Układy mikroprogramowane 6/17 Blok Arytmetyczno-logiczny ALU Jednostka ALU może wykonywać operacje arytmetyczne: przesuwanie, dodawanie, odejmowanie oraz operacje logiczne AND, OR i NOT (przy czym operacje przesuwania i operacja NOT są jednoargumentowe) Jednym z argumentów ALU jest zawartość rejestru akumulatora A. Drugi argument ALU jest podawany poprzez multiplekser MA. W zależności od wartości bitów sterujących multiplekserem S 25 i S 24 może to być: 1. zawartość jednego z ośmiu rejestrów banku rejestrów BR, 2. wartość podana na wejście zewnętrzne WE1 (WE 15 do WE 8 ), 3. wartość na drugim wejściu zewnętrznym WE0 (WE 7 do WE 0 ), 4. wartość zapisana w mikroprogramie na bitach S 33 do S 26. Wynik z układu ALU jest zawsze zapisywany do rejestru akumulatora A. Poprzez ustawienie bitu S 36 na wartość 1 można przepisać zawartość akumulatora do rejestru wyjściowego RWY. Operacje wykonywane przez blok ALU uwzględniają bity wejściowe C 0 i P 0 z rejestru znaczników RZN. Bit C 0 jest używany przy operacji dodawania (przeniesienie wejściowe) i odejmowania (pożyczka). Bit P 0 jest używany przy operacjach przesuwania w lewo (bit wchodzący na najmniej znaczącą pozycję) i w prawo (bit wchodzący na najbardziej znaczącą pozycję). W tabeli 4 zestawiono mikrooperacje wykonywane przez układ ALU. Tabela 4. Działanie jednostki arytmetyczno logicznej (ALU) Sterowanie Wyjścia s 19 do s 16 ALU P 8 C 8 Opis 0000 A 6..A 0, P 0 A 7 C 0 Przesunięcie w lewo (z bitem P 0 ) 0001 P 0,A 7.. A 1 A 0 C 0 Przesunięcie w prawo (z bitem P 0 ) 0011 A+B+C 0 P 0 Przeniesienie Dodawanie w NKB 0010 A-B-C 0 P 0 Pożyczka Odejmowanie w NKB 0100 A P 0 C 0 Przepisanie wyjścia A (NOP) 0101 B P 0 C 0 Przepisanie wejścia B (np.ład. stałej) 1000 A OR B P 0 C 0 Operacja OR 1010 A AND B P 0 C 0 Operacja AND 1100 A XOR B P 0 C 0 Operacja XOR Rejestr znaczników RZN Rejestr znaczników RZN jest rejestrem dwubitowym. Zależnie od rodzaju wykonywanej operacji może zostać zapisany jeden z bitów lub ich wartość może pozostać nie zmieniona. Podczas wykonywania przez blok ALU operacji dodawania lub odejmowania pierwszy bit zapisywany jest wartością C 8. Podczas wykonywania przez blok ALU operacji przesuwania drugi bit zapisywany jest wartością P 8. Wyjścia rejestru znaczników (C 0 i P 0 ) mogą przyjmować wartości w zależności od jego wysterowania. Jeśli na wejściu SEL jest sygnał jeden, to na wyjściach rejestru pojawiają się wartości pamiętane w rejestrze. Jeśli SEL=0, to na obu wyjściach rejestru C 0 i P 0 pojawia się wartość bitu S 34. Powyższe ilustruje tabela 5. Tabela 5. Sterowania rejestrem znaczników RZN (bity S 19 do S 16 i S 35 ) Sterowanie Wyjścia S 35 C 0 P 0 Opis 0 S 34 S 34 Zapisanie obydwu bitów rejestru wartością S 34 1 C 8 P 8 Zapisanie rejestru znaczników wartością C 8 jeśli wykonywana jest operacja dodawania lub odejmowania albo P 8 przy operacji przesuwania
Układy mikroprogramowalne Bank rejestrów BR Rejestry banku ponumerowane są od 0 do 7. Bank rejestrów ma trzy wejścia R 2..R 0 wyznaczające numer rejestru, który ma być aktywny (por. tabela 6). Zawartość wybranego rejestru pojawia się na wyjściach banku rejestrów BR. Zapisanie rejestru następuje gdy bit S 23 słowa mikrorozkazu jest równy jeden. Tabela 6. Mikrooperacje wykonywane przez bank rejestrów Sterowanie Opis S 23 S 22 do S 20 0 numer rejestru Na wyjście banku podawana jest zawartość rejestru o numerze określonym na wejście R 2..R 0 1 numer rejestru Zapis zawartości akumulatora A do rejestru o numerze zapisanym w R 2..R 0 Rejestr akumulatora A Akumulator A jest to ośmiobitowy rejestr, którego wartość jest uaktualniana w każdym (takcie) mikrorozkazie. W celu pozostawienia wartości akumulatora bez zmiany, ALU musi wykonać operację pustą NOP (przepisanie wyjścia A). Multiplekser danych wejściowych MA Multiplekser danych wejściowych MA umożliwia wybór danej, która będzie podana jako drugi argument (wejście B) bloku ALU (jako pierwszy argument zawsze podawana jest zawartość akumulatora A). Multiplekser MA pozwala wybrać jedno z czterech źródeł danych jak pokazano w tabeli 6. Tabela 8. Mikrooperacje wykonywane przez multiplekser danych wejściowych MUX Sterowanie Wyjście S 25 S 24 MA Opis 00 BR Dana pobierana z Banku Rejestrów BR 01 WE1 Dana pobierana z WE1 10 WE0 Dana pobierana z WE0 11 S 33..S 26 Dana pobierana z pamięci ROM (bity S 33..S 26 ) Rejestr wyjściowy RWY Rejestr wyjściowy RWY umożliwia wyprowadzenie wyniku działania układu. Jest to 8 bitowy rejestr z wejściem zezwolenia na zapis (LD). Po ustawieniu zezwolenia na zapis w stan aktywny nastąpi przepisanie wartości z akumulatora do rejestru wyjściowego RWY. Tabela 9. Mikrooperacje wykonywane przez RWY Sterowanie Wyjście S 36 RWY Opis 0 RWY Bez zmian 1 A Zapis zawartości akumulatora A 7/17
Układy mikroprogramowane 2.3. Format mikrorozkazu Mikrorozkazy to słowa 40 bitowe. Format mikrorozkazu przedstawia tabela 10. Tabela 10. Przypisanie bitów mikrorozkazu poszczególnym mikrooperacjom Bity S 2..S 0 S 10..S 3 S 11 S 12 S 15..S 13 S 19..S 16 S 22..S 20 S 23 S 25..S 24 S 33..S 26 S 34 S 35 S 36 S 39..S 37 Tabela 11. Słowo mikrorozkazu Nieużywane Znaczenie Wybór warunku skoku(wejście sterujące JC) Adres docelowy skoku(wejście danych JC) Załadowanie licznika pętli LP wartością 7 (wejście Preset) Zmniejszenie o 1 wartości licznika pętli LP Nieużywane Kod operacji wykonywanej przez ALU Adres rejestru w banku rejestrów BR Zapis rejestru w banku rejestrów BR wartością akumulatora A Wybór drugiego argumentu (B) dla ALU Stała natychmiastowa podawana na wejście 3 multipleksera MA Wejście rejestru znaczników Sterowanie rejestrem znaczników Zapisanie wartości akumulatora A do rejestru wyjściowego RWY Nieużywane Ładowanie RWY Wejścia RZN Argument natychmiastowy Argument B Zapis A do BR Wybór rejestru BR S 39 S 38 S 37 S 36 S 35 S 34 S 33 S 32 S 31 S 30 S 29 S 28 S 27 S 26 S 25 S 24 S 23 S 22 S 21 S 20 Operacja ALU Nieużywane Dekrementacja LP Ładowanie LP Adres skoku Wybór warunku S 19 S 18 S 17 S 16 S 15 S 14 S 13 S 12 S 11 S 10 S 9 S 8 S 7 S 6 S 5 S 4 S 3 S 2 S 1 S 0 8/17
Układy mikroprogramowalne 3. Asembler mikroinstrukcji ELMA 3.1. Wprowadzenie ELMA to program, który umożliwia przekształcenie pliku z mnemonicznym zapisem mikroprogramu w plik z binarnym obrazem pamięci ROM mikroprogramu. Plik mikroprogramu składa się z wielu mikroinstrukcji. Każdą mikroinstrukcję zapisuje się w osobnym wierszu. Jedna mikroinstrukcja odpowiada jednemu słowu sterującemu w pamięci mikroprogramu. Mikroinstrukcja składa się z jednej lub kilku mikrooperacji. Przykładowo można zdefiniować mikrooperację ADD która ustawia bity odpowiedzialne za operację wykonywaną przez ALU tak, że wykonane zostanie dodawanie. Podobnie można zdefiniować mikrooperację SUB tak, żeby wykonane zostało odejmowanie. Można zdefiniować mikrooperację JMP, która ustawi część słowa mikroinstrukcji związaną z częścią sterującą układu tak, że wykonany zostanie skok czy też mikrooperacje NXT powodującą przejście do następnej instrukcji. Definicje tych mikrooperacji dla prezentowanego układu mikroprogramowanego: ADD (19, 16,!0011) #mikrorozkaz dodawania SUB (19, 16,!0010) #mikrorozkaz odejmowania NXT (2,0,!000) #incrementacja licznika LA JMP (2,0,!001) {10,3} #mikrorozkaz skoku (parametr {10,3} okre śla adres #skoku) Powyższy zapis oznacza, że mikrooperacja ADD ustawia bity od 19 do 16 na wartość 0011, mikrooperacja SUB ustawia te same bity na wartość 0010. Mikrooperacja NXT ustawia bity od 2 do 0 na wartość 000. Mikrooperacja JMP ustawia bity od 2 do 0 na wartość 001, bity od 10 do 3 zostaną ustawione wartością przekazaną jako argumentu tej mikrooperacji (por. tekst dalej). Powyższe operacje powinny znaleźć się w pliku definicji mikrooperacji (.def). Mikrooperacje ADD oraz SUB ustawiają te same bity słowa mikroprogramu lecz na różne ich wartości. Nie można ich więc połączyć w jednej mikroinstrukcji. Natomiast operacja JMP ustawia inne bity, może więc zostać połączona z operacją ADD lub SUB. Łączenia mikrooperacji w mikrorozkazy dokonuje się w pliku z mikroprogramem. W każdym wierszu tego pliku zapisana jest jedna mikroinstrukcja. Mikrooperacje, które mają być złączone w ramach jednej mikroinstrukcji wpisuje się w jednym wierszu oddzielając je od siebie średnikiem. Przykładowy mikroprogram może wyglądać następująco (poniższy mikroprogram służy wyłącznie ilustracji działania mikroasemblera): ADD(); NXT(); SUB(); JMP(4); ADD(); JMP(2); W powyższym mikroprogramie zdefiniowane są trzy mikrorozkazy. Pierwszy powoduje połączenie mikrooperacji ADD z mikrooperacją NXT. Pierwszym słowem w pamięci mikroprogramu będzie więc słowo, w którym bity 19 do 16 będą ustawione na wartość 0011, a bity od 2 do 0 na wartość 000. W drugim mikrorozkazie bity od 19 do 16 będą ustawione na wartość 0010, bity od 2 do 0 będą miały wartość 001, a bity od 10 do 3 zostaną ustawione jako wartość 0000100 odpowiadająca dziesiętnej liczbie 4. Pozostałe bity przyjmą wartość nieokreśloną. Podobnie zdefiniowany będzie trzeci mikrorozkaz. Każda mikrooperacja może mieć dowolną liczbę argumentów. Wartości tych argumentów podawane są przy użyciu mikrooperacji w pliku mikroprogramu z rozszerzeniem.asm. 9/17
Układy mikroprogramowane Rozszerzenie wprowadzonej wcześniej operacji ADD na operacje 3 argumentową może mieć postać: ADD (19,16,!0011) {22,20} {33,26} {25,24} Użycie tej mikrooperacji powoduje ustawienie bitów od 19 do 16 na wartość 0011 oraz zapisanie na pozycje 22-20, 33-26 oraz 25-24 odpowiednio pierwszego, drugiego i trzeciego argumentu. Argumentami wywołania mikrooperacji mogą być liczby zapisane w systemie dziesiętnym. Przykładowe wywołanie takiej mikrooperacji może mieć postać: ADD(2,5,0); W wyniku translacji mikrooperacji powstanie słowo z wpisaną w bity 19-16 wartością 0011, w bity 22-20 wartością 010, w bity 33-26 wartością 00000101 oraz wartością 00 zapisaną w bitach 25-24. W wyniku translacji całego pliku mikroprogramu powstanie obraz pamięci ROM zapisany w pliku wynikowym z rozszerzeniem.mif. Załóżmy, że operacje.def jest plikiem, w którym zdefiniowane są mikrooperacje, a program.asm jest plikiem z mikroprogramem. Translacji dokonuje się mikroasemblerem ELMA uruchamianym poleceniem java Elma operacje.def program.asm Obraz pamięci mikroprogramu zapisany zostanie w pliku program.mif. W każdym rodzaju pliku tekst począwszy od znaku # do końca linii traktowany jest jak komentarz i niema wpływu na działanie programu ELMA. 3.2. Plik definicyjny.def Pierwszą linią w pliku.def musi być linia wordlength=liczba gdzie liczba określa długość słowa mikrorozkazu. Następnie następuje dowolnie wiele definicji mikrooperacji. Każda definicja mikrooperacji składa się z identyfikatora mikrooperacji, jednego lub wielu napisów postaci (x,y,!z) oznaczającego że w bity od x do y należy wpisać wartość z oraz zero lub więcej wpisów postaci {x,y} określających miejsca, w które należy wpisać kolejne argumenty. Dodatkowo można definiować stałe, które mogą być użyte w pliku.asm jako argumenty wywołania mikrooperacji. Stałe definiujemy w następujący sposób: :nazwa=wartość wartość jest liczbą w systemie dziesiętnym. 3.3. Plik mikroprogramu.asm W pliku.asm, podobnie jak w pliku.def, można zdefiniować stałe w postaci nazwa=wartość. Mikrorozkaz definiuje się umieszczając w jednym wierszu mikrooperacje, które mają być złączone, podając w nawiasach argumenty i oddzielając mikrooperacje średnikiem. Można również definiować etykiety. Poprzez rozpoczęcie wiersza napisem nazwa: definiujemy etykietę o nazwie nazwa. Użycie etykiety jako argumentu mikrooperacji powoduje zastąpienie jej wartością adresu mikrorozkazu znajdującego się bezpośrednio za definicją etykiety. 10/17
Układy mikroprogramowalne 3.4. Przykład pliku definicyjnego Poniżej przedstawiono pliki z definicjami mikrooperacji dla omawianego układu mikroprogramowanego. WordLength = 40 #stałe dla multipleksera JC wyboru warunków skoku #długość słowa mikrorozkazu :W_1=1 :W_S8=2 :W_C8=3 :W_NS8=4 :W_NC8=5 :W_NZ=7 #skok bezwarunkowy, wejście 1 multipleksera JC #skok gdy S8=1, wejście 2 multipleksera JC #skok gdy C8=1, wejście 3 multipleksera JC #skok gdy S8=0, wejście 4 multipleksera JC #skok gdy C8=0, wejście 5 multipleksera JC #skok gdy Z=0, wejście 7 multipleksera JC JMPC (0,0,!x) {2,0} {10,3} #mikrorozkaz skoku warunkowego o dwóch #argumentach (warunek, adres) JMP (2,0,!001) {10,3} #mikrorozkaz skoku bezwarunkowego (adres) NXT (2,0,!000) #mikrorozkaz inkrementacji LA LDCNT (11,11,!1) #załadowanie licznika LP wartością 111 NXT (12,12,!1) #dekrementacja licznika LP #stałe (numery rejestrów z banku rejestrów BR) :r0=0 :r1=1 :r2=2 :r3=3 #stałe do wyboru argumentu B dla ALU :reg=0 #argument pobierany z banku rejestrów BR :WE1=1 #argument pobierany z WE1 :WE0=2 #argument pobierany z WE0 :imm=3 #argument pobierany z pamięci mikroprogramu ROM #mikrorozkazy ALU ADD (19,16,!0011) {22,20} {33,26} {25,24} #dodawanie(nr rejestru, sta ła #z mikroprogramu, wybór #argumentu B) ADDR (19,16,!0011) (25,24,!00) {22,20} #dodawanie rejestru (nr #rejestru) ADDI (19,16,!0011) (25,24,!11) {33,26} #dodanie stałej z #mikroprogramu ADDW1 (19,16,!0011) (25,24,!01) #dodanie argumentu z WE1 ADDW0 (19,16,!0011) (25,24,!10) #dodanie argumentu z WE0 SUB (19,16,!0010) {22,20} {32,25} {25,24} #odejmowanie(nr rejestru, #stała z mikroprogramu, wybór #argumentu B) SUBR (19,16,!0010) (25,24,!00) {22,20} SUBI (19,16,!0010) (25,24,!11) {33,26} #odejmowanie rejestru #odejmowanie sta łej SHL (19,16,!0000) #przesuwanie w lewo SHR (19,16,!0001) #przesuwanie w prawo 11/17
Układy mikroprogramowane NOP (19,16,!0100) #operacja pusta LDA (19,16,!0101) {22,20} {33,26} {25,24} #załadowanie akumulatora #(nr rejestru, stała z #mikroprogramu, wybór #argumentu B) A2R (23,23,!1) {22,20} #ładowanie rejestru #zawartością akumulatora #sterowanie rejestrem znaczników RZN SIN (0,0,!x) {34,34} #ustawianie bitem s34 wyjść C0 i P0 rejestru #znaczników podczas operacji przesuwania CIN (0,0,!x) {34,34} #ustawianie bitem s34 wyjść C0 i P0 rejestru #znaczników podczas operacji dodawania lub #odejmowania SREG (0,0,!x) {35,35} CREG (0,0,!x) {35,35}` #zapis RZN podczas operacji przesuwania #zapis RZN podczas operacji dodawania BOR (19,16,!100x) {22,20} {33,26} {25,24} #mikrorozkaz OR z wyborem #argumentu B BAND (19,16,!101x) {22,20} {33,26} {25,24} BXOR (19,16,!110x) {22,20} {33,26} {25,24} DISP (36,36,!1) #mikrorozkaz AND z wyborem #argumentu B #mikrorozkaz XOR z wyborem #argumentu B #mikrorozkaz zapisu RWY 3.5. Przykłady Program 1 Poniżej przedstawiono mikroprogram, który zwiększa wartość akumulatora o wartość odczytaną z WE1 i po każdym dodaniu zapisuje nową wartość w rejestrze wyniku. Dodawanie powtarzane jest w nieskończoność. Start: ADD(0,0,1); DISP(); JMP(Start); Program 2 Poniżej przedstawiono mikroprogram, który odczytuje dwie ośmiobitowe liczby z wejścia WE1 i WE0, umieszcza je w rejestrach 1 i 2, oblicza ich sumę i umieszcza wynik w rejestrze 3 oraz zapisuje go w rejestrze wyjściowym. #wczytywanie argumentów do rejestrów r1 i r2 LDA(0,0,WE1); A2R(r1); NOP(); LDA(0,0,WE0); A2R(r2); NOP(); ADDR(r1); 12/17
Układy mikroprogramowalne end: DISP(); NOP(); JMP(end) Program 2a Powyższy program można uprościć. W tym celu zauważmy, że można jednocześnie ładować do akumulatora nową wartość i zapisywać wartość bieżącą do rejestru. Wobec tego instrukcje: A2R(r1); NOP(); LDA(0,0,WE0); można zastąpić jedną instrukcją: A2R(r1); LDA(0,0,WE0); Program 3 Mikroprogram mnożenia liczb w NKB Poniżej przedstawiono listing programu mnożenia dwóch liczb w kodzie NKB. rd1=1 rd2=2 rcrc=3 LDA(00, 00, WE1); #wczytywanie argumentów do rejestrów r0 i r1 A2R(r0);NOP(); LDA(00, 00, WE0); A2R(r1);NOP(); LDCNT();NOP(); LDA(00,0,imm); A2R(r2);NOP(); SHR(); SIN(0); SREG(0); ADDI(0); #zerowanie licznika pętli #zerowanie rejestru r2 #zerowanie rejestru znaczników #rozpoczyna się właściwy mikroprogram mnożenia mulloop: LDA(r1,00,reg); SHR(); SIN(0); SREG(0); JMPC(W_S8, doadd);nop(); shift: LDA(r2,00,reg); JMPC(W_C8,c1);NOP(); c0: SHR(); SIN(0); SREG(0); #załadowanie r1 do akumulatora #przesuniecie w prawo z uzupe łnieniem lewego bitu #wartością 0 #jeśli wysunięty bit (najmłodszy bit r1) był #ustawiony to skaczemy do doadd (umieszczony #tam mikroprogram dodaje do r0 zawartość r2 i #wraca do etykiety shift). #załaduj r2 do akumulatora #jeśli przy ostatnim dodawaniu było #przeniesienie to skok do c1, #przesunięcie akumulatora (w którym jest r2) w #prawo, uzupełnienie zerem z lewej strony 13/17
Układy mikroprogramowane JMP(next);NOP(); c1: SHR(); SIN(1); SREG(0); next: A2R(r2);NOP(); LDA(r1,00,reg); SHR(); SIN(00); SREG(1); A2R(r1);NOP(); ADDI(0);CIN(0); CREG(0); #skok do etykiety next #przesunięcie akumulatora (w którym jest r2) w #prawo, uzupełnienie jedynka z lewej strony #zapisanie akumulatora (przesuniętego w c1 lub #c2) do rejestru r2 #załadowanie r2 do akumulatora #przesunięcie r1 w prawo, uzupełnione z lewej #strony tym co zostało wysunięte z prawej strony #w poprzednim przesuwaniu #zapisanie przesuniętego r1 w r1 #wyczyszczenie znaczników NXT(); JMPC(W_NZ, mulloop);nop(); #jeśli jeszcze nieskończone mnożenie to #skok do mulloop JMP(endLoop);NOP(); #w przeciwnym przypadku do endloop. #podprogram dodawania wykorzystywany na początku mullop i tam opisany doadd: LDA(r0,00,reg); ADDR(r2); CIN(0); CREG(0); A2R(r2);NOP(); JMP(shift);NOP(); # koniec mnożenia endloop: #wyświetlenie r1 na zewnętrznym wyświetlaczu w nieskończonej pętli LDA(r1,00,reg); DISP();NOP(); LDA(r2,00,reg); JMP(endLoop);NOP(); 14/17
Układy mikroprogramowalne 5. Zestaw laboratoryjny Zestaw laboratoryjny przedstawiony na Rysunku 4, składa się z dwóch podstawowych modułów SML3: modułu FPGA i moduł wyświetlacza LCD (opisanych poniżej), pozostałe moduły (używane przez mikroprogram mnożenia) służą do ustawiania argumentów i wyświetlania wyniku. 5.1 Moduł FGPA Moduł z układem FPGA zawiera: Rysunek 4. Zestaw laboratoryjny z pakietem FPGA układ FPGA EP1k30, programator ByteBlasterMV ze złączem portu równoległego, oscylator, gniazdo BNC, 9 gniazd w standardzie systemu SML3 (SV1- SV9), 16 diod LED, 4 przyciski (BT1-BT4), 3 przełączniki (SW1-SW3). Rysunek 5. Pakiet z układem FPGA 15/17
Układy mikroprogramowane Gniazda SV1 do SV7 są gniazdami uniwersalnymi. Podczas ćwiczenia z mikroprogramowania ich wykorzystanie jest następujące: 16/17 SV1 złącze dla wejścia WE1, SV2 złącze dla wejścia WE0, SV3 złącze wyjściowe WY, SV4 sterowanie wyświetlaczem LCD (wyjście), SV5 SV8 nieużywane, SV9 zasilacz. Zwory dostępne na pakiecie powinny mieć następujące ustawienie: OSC zwarte z CLK1 (ustawione w pozycji górnej), BNC zwarte z CLK2 (ustawione w pozycji dolnej), Vosc zwarte z +5V (ustawione w pozycji prawej), zwora 2.5V zwarta (jeśli nie jest zwarta należy obowiązkowo zgłosić to prowadzącemu ćwiczenie). Przełączniki na pakiecie są następujące: SW1 praca krokowa (1-góra) / ciągła (0-dół), BT1 reset. BT2 jeden krok podczas pracy krokowej, Przełączniki SW2, SW3 oraz BT3 i BT4 są nieużywane. Diody sygnalizacyjne Dla ułatwienia uruchamiania i śledzenia pracy układu mikroprogramowanego na płytce umieszczono 16 diod LED. Pozwala to obserwować na nich stan niektórych linii układu (pozostałe informacje wyświetlane są na module wyświetlacza LCD) przy czym diody LED*B (dolny rząd) prezentują stan obecny układu, LED*A (górny rząd) stan z poprzedniego cyklu. Sygnał wyświetlane na diodach LED: LED8 wartość P 0, LED7 wartość P 8 LED6 wartość C 0, LED5 wartość C 8, LED4 wartość wybranego warunku skoku (wejście LD licznika adresowego LA), LED3 linia S 23 zapisanie wartości akumulatora do rejestru, LED2, LED1 wartość 1. 5.2 Moduł wyświetlacza LCD Dwuwierszowy wyświetlacz LCD 2x16 wraz z ze sterownikiem ułatwia śledzenie pracy układu mikroprogramowanego. Dzięki niemu można zaprezentować stan układu w chwili bieżącej (wiersz dolny), jak również stan poprzedni (wiersz górny). W połączeniu z możliwością pracy krokowej umożliwia to dokładną obserwację działania układu. Jest to szczególnie cenne, gdy układ nie działa w zamierzony sposób. W oparciu o znajomość stanu poprzedniego można wtedy stosunkowo prosto wyjaśnić przyczynę takiego zachowaniu układu. Wyświetlacz LCD prezentuje stan układu z bieżącego i poprzedniego cyklu zegarowego (Rysunek 7). W jednym wierszu wyświetlacza LCD prezentowane są następujące wielkości (począwszy od lewej strony): - wartość wyjścia licznika adresowania LA (2 znaki) - bity S 9..S 3 (wartość adresu skoku) (2 znaki) - wartość akumulatora (2 znaki)
Układy mikroprogramowalne - wartość wejścia B ALU (2 znaki) - bity S 19 do S 13 (operacja wykonywana przez ALU) (1 cyfra) - wartość bitów S 2 do S 0 (wybór warunku skoku) (1cyfra) - wartość bitów S 22 do S 20 (wybór rejestru) (1 cyfra). Wartość licznika adresu Adres skoku Wartość akumulatora Wejście B ALU Operacja wykonywana przez ALU Warunek skoku Adres rejestru Rysunek 7. Opis pozycji wyświetlacza Wszystkie wartości prezentowane są w systemie szesnastkowym. 17/17