This is an old revision of the document!
10 Jednostka arytmetyczno-logiczna
Jednostka arytmetyczno-logiczna (z ang. arithmetic and logical unit lub arithmetic logic unit, ALU) – układ cyfrowy, wykonujący operacje arytmetyczne (takie jak dodawanie, odejmowanie itp.), operacje logiczne na dwóch liczbach oraz operacje jednoargumentowe, takie jak przesunięcie bitów, negacja. ALU jest podstawowym blokiem centralnej jednostki obliczeniowej komputera.
Typowa ALU ma dwa wejścia odpowiadające parze argumentów i jedno wyjście na wynik. Operacje jakie prowadzi to:
- operacje logiczne AND, OR, NOT, XOR,
- dodawanie,
- przesunięcia bitowe o jeden bit, stałą liczbę bitów, czasem też o zmienną liczbę,
- często też, odejmowanie, negacja liczby, dodawanie z przeniesieniem, zwiększanie/zmniejszanie o 1
- dość często mnożenie i czasem dzielenie/modulo
Przyczyną dla której operacje te grupuje się w ALU jest to, że bramek logicznych potrzebnych do zaimplementowania wszystkich operacji z zestawu: dodawanie (z przeniesieniem i bez), odejmowanie (z przeniesieniem i bez), negacja liczby, zwiększanie i zmniejszanie o 1, AND, OR, NOT, XOR jest niewiele więcej od zaimplementowania samego dodawania. Szybkie mnożenie wymaga znacznie więcej, a dzielenie jeszcze więcej bramek w porównaniu do tych operacji.
Historia: Architektura von Neumanna
Matematyk John von Neumann zaproponował model ALU w 1945 roku, kiedy to sporządził spis założeń dla nowego komputera EDVAC (z ang. Electronic Discrete Variable Automatic Computer, czyli elektroniczny komputer maszynowy o zmiennych nieciągłych). Później w 1946 r. pracował ze swoimi kolegami nad stworzeniem komputera dla Princeton Institute of Advanced Studies (IAS). Komputer IAS stał się prototypem dla wielu późniejszych komputerów. W swoim projekcie von Neumann nakreślił, co według niego będzie niezbędne w komputerze uwzględniając ALU.
Von Neumann stwierdził, iż ALU jest niezbędna dla komputera, ponieważ pewnym jest, że komputer będzie musiał wykonywać podstawowe operacje matematyczne obejmujące dodawanie, odejmowanie, mnożenie oraz dzielenie. Dlatego też twierdził, że „rozsądnym jest, aby komputer mieścił w sobie wyspecjalizowane organy dla tych operacji”.
Przykład "bardzo prostego" Alu
(wzięty z https://www.nand2tetris.org/ https://www.coursera.org/learn/build-a-computer)
Mamy w nim w sumie 8 wejść.
X i Y które są naszymi liczbami. W zależności od implementacji mogą być one np 16 bitowe każda. (ja jeśli zbuduje to w aplikacji logisim zrobię po prostu tak że są 1 bitowe ( co nie ma sensu przy dodawaniu bo 1 + 1 da mi 0, bo odrzucamy carry ale tak dla prostoty)
Mamy 6 bitów sterujących:
zx - zero x (zeruje nam x)
nx - negate x ( neguje nam x)
zy - zero y (zeruje nam y)
ny - negate y ( neguje nam y)
f - wybiera nam operację dodawania x + y (również odejmowania, ponieważ liczba minus + liczba plus to takie “odedjmowanie” ( 9 Zapisy Liczby dwójkowej ze znakiem )jeśli jest równe 1 lub iloczynu logicznego x i y jeśli jest równe 0
no - negate output ( neguje nam wyjście)
Aby zrozumieć implementację,trzeba napewno wiedzieć co to multiplekser. Będzie nam służył do wybrania jednego z dwóch sygnałów. Bity sterujące np zx będą selectem w multiplekserze. 5 Multiplekser I Demultiplekser
najpierw wybór możliwośći wyzerowania wejść
input false zawsze ma wartość 0 bo to pomiędzy nią, a jednym inputem wybieramy. Jeśli input to 0 i wyzerujemy go - to dalej zero
Następnie kolejnym multiplekserem wybieramy czy “przetworzona” wcześniej wartość ma zostać zanegowana
wykonujemy operacje and i dodawanie half adderem ( 8 Adder (Sumator)
Multiplekserem z pomocą f znowu wybieramy jaka operacja ma pojawić się na wyjściu
Następnie możliwość zanegowania wyjścia już po wykonaniu wszystkich operacji
implementacja tego AlU z 16 bitowymi wejściami W HDL
https://pl.wikipedia.org/wiki/Hardware_Description_Language
CHIP ALU { WEJŚCIE x[16], y[16], // Liczby wejściowe po 16 bitów każda zx, // Czy wyzerować wejście x? nx, // Czy zanegować wejście x? zy, // Czy wyzerować wejście y? ny, // Czy zanegować wejście y? f, // Czy wykonać dodawanie (1) czy operację AND (0)? no; // Czy zanegować wyjście? WYJŚCIE out[16], // Wynik operacji, 16 bitów CZĘŚCI: // Zerowanie wejścia Mux16(a=x, b=false, sel=zx, out=x1); Mux16(a=y, b=false, sel=zy, out=y1); // Negacja wejścia Not16(in=x1, out=nx1); Mux16(a=x1, b=nx1, sel=nx, out=x2); Not16(in=y1, out=ny1); Mux16(a=y1, b=ny1, sel=ny, out=y2); // Wykonywanie funkcji And16(a=x2, b=y2, out=aAndB); Add16(a=x2, b=y2, out=aPlusB); Mux16(a=aAndB, b=aPlusB, sel=f, out=out0); // Negacja wyjścia Not16(in=out0, out=nout0); Mux16(a=out0, b=nout0, sel=no, out=out); }