Cyfrowe układy arytmetyczne służą do wykonywania działań arytmetycznych na liczbach binarnych. W podrozdziale tym omawiamy przykładowe, proste układy sumatorów. Zwracamy natomiast uwagę na ważne pojęcie kodu U2, w którym wykonywane są praktycznie wszystkie operacje na liczbach ze znakiem. Następnym ważnym pojęciem jest układ jednostki arytmetyczno-logicznej (ALU, ang. algebraic-logic unit). Układ ten pojawia się w dalszych rozdziałach jako jeden z bardzo ważnych elementów mikroprocesora.
Pożądaną sytuacją byłby stan, w którym operacje dodawania i odejmowania liczb binarnych ze znakiem (czyli zarówno dodatnich, jak i ujemnych) dałoby się sprowadzić do prostych do wykonywania (dla układów cyfrowych) operacji. Takimi operacjami są: dodawanie, które poznaliśmy powyżej, i negacja wszystkich bitów liczby (słowa). Kodem, który umożliwia takie rozwiązanie, jest kod uzupełnienia do dwóch (U2).
Definicja
Kodem uzupełnienia do dwóch (kodem U2) nazywamy kod wagowy, który dowolnej, całkowitej liczbie dziesiętnej przyporządkowuje słowo binarne
an-1,,,,,,,,,,,a0
takie, że spełniony jest poniższy wzór:
an-1........a0 = – an-1 * 2n-1 + an-2 * 2n-2 + ................ + a0 * 20
Nie będziemy dokładnie wyjaśniać, jak został skonstruowany kod U2, natomiast poniżej podamy niektóre ciekawe własności.
Załóżmy, że wykonywać będziemy działania na liczbach czterobitowych (jak się niedługo okaże, założenie długości słów, na których wykonujemy działania w kodzie U2, ma bardzo duże znaczenie).
Najpierw zwracamy uwagę, że jeżeli najstarszy (czwarty bit) liczby zapisanej w kodzie U2 jest równy 1, to mamy do czynienia z liczbą ujemną. Prosimy jednak zauważyć, że bit ten nie jest wyłącznie bitem znaku, lecz niesie wraz ze swoją wagą (całą) wartość ujemną.
Przykład:
Liczba 1101U2 zgodnie ze wzorem podanym w definicji odpowiada liczbie dziesiętnej –3, bo:
1101U2 = – 1 * 23 + 1 * 22 + 0 * 21 + 1 * 20 = – 8 + 4 + 1 = – 3D
Następnie łatwo zauważyć, że zapis liczb dodatnich w kodzie U2 i w kodzie NKB jest identyczny.
Przykład:
Liczba 7D w kodzie NKB i w czterobitowym kodzie U2 reprezentowana jest przez ciąg 0111, bo:
0111NKB = 0 * 23 + 1 * 22 + 1 * 21 + 0 * 20 = 4 + 2 + 1 = 7D
0111U2 = – 0 * 23 + 1 * 22 + 1 * 20 = 4 + 2 + 1 = 7D
Na przykładzie tym łatwo zauważyć, dlaczego istotne jest założenie, na jakiej długości słów operujemy. Bez niego nie dałoby się stwierdzić dla kodu U2, który bit niesie wartość ujemną.
Kolejną bardzo ważną własnością kodu U2 jest łatwość wyliczenia przez procesor liczby przeciwnej (o przeciwnym znaku) do liczby danej. Operacja ta sprowadza się do użycia dwóch wyżej wymienionych działań, czyli do dodawania i negowania bitów (operację negacji oznaczamy w przykładzie poniżej znakiem ~). W celu otrzymania w kodzie U2 liczby przeciwnej do danej liczby negujemy wszystkie bity tej liczby i do otrzymanego wyniku dodajemy 1. Własność tę ilustruje kolejny przykład.
Przykład:
Podaną metodą obliczymy liczbę przeciwną do liczby 0111U2, reprezentująca dla czterobitowego kodu U2 liczbę 7D:
~0111
---------U2
1000
+ 1
------------
1001
U2
i sprawdzamy:
1001U2 = – 1 * 23 + 0 * 22 + 0 * 21 + 0 * 20 = – 8 + 1 = – 7D
Jak widzimy, zgodnie z oczekiwaniem, otrzymaliśmy liczbę –7. Czytelnik może sprawdzić, że ponowne przeprowadzenie tej procedury na liczbie 1001U2 doprowadzi do otrzymania kodu U2 liczby 7D.
Umiejętność wykonywania dodawania i obliczania liczby przeciwnej do danej pozwala na wykonywanie dowolnych działań dodawania lub odejmowania na liczbach ze znakiem, gdyż przykładowo:
a – b = a + ( – b)
– a + b = ( – a) + b
– a – b = ( – a) + (– b)
i tak dalej.
Symbol (– b) oznacza liczbę przeciwną do b (nie musi to być liczba ujemna, na przykład liczbą przeciwną do –7 jest liczba 7).
Na zakończenie prezentacji kodu U2 podamy sposób doboru długość słów kodu U2 do żądanego zakresu liczb, dla których chcemy wykonywać działania oraz podamy kilka przykładów działań w kodzie U2.
Zależność zakresu liczb dziesiętnych, jakie można zapisać przy pomocy słów kodu U2, od ilości bitów w tym słowie, podaje następujący wzór:
– 2n-1 x 2n-1 – 1
gdzie: XU2 = an-1............a0
ai {0,1}, n – ilość bitów słowa kodu U2,
XU2 – kod U2 liczby dziesiętnej.
Przykładowo, dla n = 5, możemy zapisać w kodzie U2 liczby od –16D (10000D) do +15D (01111U2). Zwracamy uwagę, że w wyliczonym zakresie powinny się zmieścić tylko argumenty, ale także wynik.
Oto przykład wyjaśniający, dlaczego istotne jest jaką długością słów kodu U2 posługujemy się przy wykonywaniu działań:
– 9 – 6 – 9D 10111U2 |10111U2
– 6 11010U2 |11010U2
D --|------------
10001U2 – 15D 1 | 10001U2
bit poza zakresem odrzucamy
W kodzie U2, podobnie jak na przykład w kodzie NKB, istnieją reguły, które pozwalają stwierdzić przekroczenie zakresu w wyniku wykonania działania. W kodzie NKB jest to wystąpienie przeniesienia z najstarszego bitu. W kodzie U2 będą dwa takie przypadki, gdyż zakres możemy przekroczyć od strony liczb dodatnich (liczba „za duża”) lub od strony liczb ujemnych (liczba „zbyt ujemna” – liczba ujemna o zbyt dużej wartości bezwzględnej). Poniżej podajemy obydwie reguły. Zgodnie z tymi regułami jest ustawiany w procesorach tak zwany znacznik przepełnienia OV (ang. overflow), sygnalizujący przekroczenie zakresu przy wykonywaniu działań w kodzie U2.
Zakładamy, że wykonujemy działania na słowach n-bitowych, czyli na ciągach an-1................a0.
• Przekroczenie zakresu od strony liczb dodatnich ma miejsce, gdy występuje przeniesienie z bitu n-2 na bit n-1, ale nie ma przeniesienia z bitu n-1 na bit n.
• Przekroczenie zakresu od strony liczb ujemnych ma miejsce, gdy występuje przeniesienie z bitu n-1 na bit n, ale nie ma przeniesienia z bitu n-2 na bit n-1.
Czytelnik może na samodzielnie dobranych przykładach sprawdzić funkcjonowanie tych reguł.
Definicja
Jednostką arytmetyczno – logiczną (ALU, ang. Algebraic-Logic Unit) nazywamy uniwersalny układ cyfrowy do wykonywania operacji arytmetycznych i logicznych.
Przykładowy symbol oznaczający jednostkę arytmetyczno–logiczną (niestety istnieje tu pewna dowolność) przedstawiono na poniższym rysunku.
Słowo „uniwersalny” w definicji ALU oznacza, że zestaw operacji, które potrafi zrealizować jednostka arytmetyczno-logiczna, powinien być funkcjonalnie pełny. Zestaw operacji jest funkcjonalnie pełny, jeżeli za jego pomocą jesteśmy w stanie zrealizować dowolny algorytm przetwarzania informacji.
Do zestawu operacji wykonywanych przez jednostkę arytmetyczno-logiczną należą najczęściej: dodawanie i odejmowanie algebraiczne, przesuwanie bitów słowa w prawo i w lewo, porównywanie ( komparacja) wartości dwóch słów, operacje iloczynu i sumy logicznej, negacji i alternatywy wykluczającej. Oczywiście dokładna lista wykonywanych operacji zależy od konkretnego typu jednostki arytmetyczno-logicznej. W naszej książce interesujemy się jednostką arytmetyczno-logiczną głównie jako elementem składowym mikroprocesora. Wówczas jej „umiejętności” decydują o dość dużym fragmencie tak zwanej listy rozkazów procesora.
Aby możliwe było dokonanie wyboru operacji realizowanej w danym momencie przez jednostkę arytmetyczno-logiczną, musi ona posiadać zestaw wejść zwanych wejściami sterującymi. Pozwalają one dokonać tego wyboru na drodze elektrycznej, przez podanie na te wejścia określonej kombinacji zer i jedynek przyporządkowanej żądanej operacji.
Jednostka arytmetyczno-logiczna nie ma własnych układów pamiętających, dlatego musi współpracować z pewnym zestawem rejestrów. Dwa z nich pełnią szczególne funkcje i dlatego też mają swoje nazwy. Rejestr, który zawiera jeden z argumentów operacji i do którego ładowany jest wynik wykonywanej operacji, zwany jest akumulatorem. Rejestr zawierający pewne dodatkowe cechy wyniku wykonywanej operacji, takie jak przeniesienie czy też przekroczenie zakresu dla działań w kodzie U2 są przechowywane w postaci określonych bitów (np. o nazwach CY czy OV) w rejestrze flagowym. Dokładniej o tych rejestrach piszemy w rozdziale 4 poświęconym rejestrom roboczym mikroprocesora.