After implementing all the logic and arithmetic circuits, we can now combine them into a powerful machine called the Arithmetic Logic Unit or ALU. For our ALU, it will be able to do addition, subtraction, negation, and, or, and not. More precisely, given two 16-bit inputs x and y, the ALU can do:
The ALU logic manipulates the x and y inputs and operates on the resulting values, as follows:
if (zx == 1) set x = 0 16-bit constant
if (nx == 1) set x = !x bitwise not
if (zy == 1) set y = 0 16-bit constant
if (ny == 1) set y = !y bitwise not
if (f == 1) set out = x + y integer 2's complement addition
if (f == 0) set out = x & y bitwise and
if (no == 1) set out = !out bitwise not
According to the final out value, we will compute two 1-bit outputs:
if the ALU output == 0, zr is set to 1; otherwise zr is set to 0;
if the ALU output < 0, ng is set to 1; otherwise ng is set to 0.
Here's the header of the ALU:
alu
x[16] y[16] -- 16-bit inputs
zx -- zero the x input?
nx -- negate the x input?
zy -- zero the y input?
ny -- negate the y input?
f -- compute out = x + y if f == 1 or x & y if f == 0
no -- negate the output?
->
{ out[16] -- 16-bit output
, zr -- 1 if out == 0, 0 otherwise
, ng -- 1 if out < 0, 0 otherwise
}
The ALU seems very complicated at first sight. However, it only uses the functions we defined earlier and apply the operations that depend on the control bits sequentially.
If you get stuck, click on "See Hints".
Fill in the blanks below:
alu
x[16] y[16] -- 16-bit inputs
zx -- zero the x input?
nx -- negate the x input?
zy -- zero the y input?
ny -- negate the y input?
f -- compute out = x + y if f == 1 or x & y if f == 0
no -- negate the output?
->
{ out[16] -- 16-bit output
, zr -- 1 if out == 0, 0 otherwise
, ng -- 1 if out < 0, 0 otherwise
} =
let
x1 =
____ ____ ____ zx
x2 =
____ ____ ____ nx
y1 =
____ ____ ____ zy
y2 =
____ ____ ____ ny
out1 =
____ ____ ____ f
out2 =
____ ____ ____ no
zr =
____ ___________________
ng =
___________________
in
{ out = out2, zr = zr, ng = ng }