Boolean Algebra, Logic Gates, and the ALU
These slides are adapted from ECE/CS 250 Computer Architecture (Duke University) by Tyler Bletsch, which is derived from work by Daniel J. Sorin, Alvy Lebeck, and Drew Hilton.
10010, set this bit to 1 (tell the adder to subtract instead of add)| Processor | Transistors |
|---|---|
| Pentium III (processor core: 9.5 million) | 28 million total |
| Pentium 4 | 42 million |
| Core 2 Duo (2 cores) | 290 million |
| Core 2 Extreme (4 cores, 8 MB cache) | 590 million |
| Core i7 (6 cores) | 2.27 billion |
How do engineers design such a thing? Carefully! …and with abstraction.
Abstraction is the key to designing any large system:
Today: steps 1 and 2.
| Operator | Ways to write it | In C/C++ |
|---|---|---|
| NOT | !A = ~A = \(\overline{A}\) = \(\neg A\) |
!A |
| AND | A & B = \(A \cdot B\) = A*B = AB = \(A \land B\) |
A && B |
| OR | A | B = A + B = \(A \lor B\) |
A || B |
| XOR | A ^ B = \(A \oplus B\) |
A ^ B |
Plus NAND, NOR, XNOR, …: the NOT of AND, OR, XOR.
A truth table shows the output for every combination of inputs.
| a | NOT(a) |
|---|---|
| 0 | 1 |
| 1 | 0 |
| a | b | AND(a,b) |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
| a | b | OR(a,b) |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
| a | b | XOR(a,b) |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
| a | b | NAND(a,b) |
|---|---|---|
| 0 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
| a | b | NOR(a,b) |
|---|---|---|
| 0 | 0 | 1 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 0 |
| a | b | XNOR(a,b) |
|---|---|---|
| 0 | 0 | 1 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
| a | b | c | f₁ | f₂ |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 | 1 |
| 0 | 1 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 0 |
| 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 1 | 0 |
| 1 | 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 |
With n inputs there are \(2^n\) rows: count from 000 to 111 in binary.
Example: (A & B) | !C
1. Start with an empty truth table
one column per input, one column per output
2. Fill in the inputs
counting in binary: 000, 001, 010, …
3. Compute the output, one row at a time:
(0 & 0) | !0 = 0 | 1 = 1(0 & 0) | !1 = 0 | 0 = 0(0 & 1) | !0 = 0 | 1 = 1(0 & 1) | !1 = 0 | 0 = 0(1 & 0) | !0 = 0 | 1 = 1(1 & 0) | !1 = 0 | 0 = 0(1 & 1) | !0 = 1 | 1 = 1(1 & 1) | !1 = 1 | 0 = 1Done! Every possible input has an output.
| A | B | C | Output |
|---|---|---|---|
| 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 |
Given a truth table, find the formula?
Idea: write down every true row as an AND term, then OR them together.
This is called sum of products.
| A | B | C | Output |
|---|---|---|---|
| 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 |
| A | B | C | Output |
|---|---|---|---|
| 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 |
AND rules
A & A = AA & 0 = 0A & 1 = AA & !A = 0OR rules
A | A = AA | 0 = AA | 1 = 1A | !A = 1!!A = A& and | are both commutative and associative.A & (B | C) = (A & B) | (A & C)A | (A & B) = APush a NOT inside the parentheses and flip & ↔︎ |:
\[\overline{A \cdot B} = \overline{A} + \overline{B} \qquad\qquad \overline{A + B} = \overline{A} \cdot \overline{B}\]
!(A & B) = !A | !B !(A | B) = !A & !B
Check it yourself: build truth tables for both sides and compare.
| Name | AND form | OR form |
|---|---|---|
| Identity | 1 & A = A |
0 | A = A |
| Null | 0 & A = 0 |
1 | A = 1 |
| Idempotent | A & A = A |
A | A = A |
| Inverse | A & !A = 0 |
A | !A = 1 |
| Commutative | A & B = B & A |
A | B = B | A |
| Associative | (A & B) & C = A & (B & C) |
(A | B) | C = A | (B | C) |
| Distributive | A | (B & C) = (A | B) & (A | C) |
A & (B | C) = (A & B) | (A & C) |
| Absorption | A & (A | B) = A |
A | (A & B) = A |
| De Morgan | !(A & B) = !A | !B |
!(A | B) = !A & !B |
| Double negation | !!A = A |
Come up with a formula for this truth table.
Simplify as much as possible.
Sum of products:
↑ Simplify the green part first
| A | B | C | Output |
|---|---|---|---|
| 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 |
| 1 | 1 | 1 | 1 |
After simplifying the green part:
You can simplify the purple part the same way… (factor out A & C)
Final answer: (!A & !C) | (A & C)
Output is 1 exactly when A equals C (this is XNOR).
| A | B | C | Output |
|---|---|---|---|
| 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 |
| 1 | 1 | 1 | 1 |
Come up with a formula for this truth table. Simplify as much as possible.
| A | B | C | Output |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 0 |
Write a product term for each row with output 1:
Factor out !A & C:
Factor out A & !C:
The variable B disappears because the output does not depend on its value.
Because every Boolean operator is a physical gate made of transistors. Simplifying the expression = fewer gates = a smaller, faster, cheaper, lower-power chip.
Gates are electronic devices that implement simple Boolean functions: the building blocks of hardware.
A NOT gate takes just two transistors:
Circuits are networks of gates. Here is our answer from before, (!A & !C) | (A & C):
Think of an HDMI switch 🎮📺: two game consoles (inputs A and B), one TV (the output), and a button (the selector S) that decides which console the TV shows.
Think of an HDMI switch 🎮📺: two game consoles (inputs A and B), one TV (the output), and a button (the selector S) that decides which console the TV shows.
Next: sum of products
(!A & B & S) |(A & !B & !S) |(A & B & !S) |(A & B & S)
Simplify: (A & !S) | (B & S)
| A | B | S | Output |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 |
MUX(A, B, S) = (A & !S) | (B & S). It is so common that it gets its own symbol: a trapezoid.
Three 2-to-1 muxes make a 4-to-1 mux. The 2-bit selector picks one of 4 inputs: s₀ picks within each pair, s₁ picks the pair.
add, sub, and, or, not, shifts, …Add the two bits plus the carry-in from the column to the right, and pass the carry-out to the left:
| 0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | |
| 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | |
| + | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 |
| 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
109 + 44 = 153 ✓ Each column adds three bits: a, b and the carry-in.
So we need to add three bits (a, b and the carry-in). The 2-bit result is the carry-out and the sum:
Turn it into an expression, simplify, build it from gates…
Sum = a ^ b ^ Cin Cout = (a & b) | (Cin & (a ^ b))
Chain 4 full adders: each carry-out feeds the next adder’s carry-in (a ripple-carry adder).
\[X - Y = X + (-Y) = X + (\overline{Y} + 1)\]
Example (4 bits): \(6 - 3\)
| \(X = 6\) | 0110 |
\(\overline{Y}\) (flip the bits of 0011) |
1100 |
| \(+1\) (use the carry-in!) | 1 |
| Sum | 1 0011 → keep 4 bits: 0011 = 3 ✓ |
Hardware trick: XOR each bit of B with Add/Sub (flips B when it is 1), and feed Add/Sub into the first carry-in (the +1).
Example (4-bit signed): 0111 (7) + 0001 (1) = 1000 (−8)?! The carry into the top bit is 1 and the carry out is 0, so they differ → overflow.
One bit of an Arithmetic Logic Unit: compute every operation in parallel, then use a mux (controlled by F) to pick the result.
Chain the slices like the adder. Two extra outputs are cheap to add: overflow (XOR of the top carries) and non-zero? (OR of all result bits).
<< and >>? How would we implement them?Option 1: a truth table? 8 + 3 = 11 inputs → \(2^{11}\) = 2048 rows. Yuck. It works, but the sum-of-products expression for even one output bit fills a whole slide.
Option 2: build it from muxes, one shift amount at a time. 👇
A simpler problem: a shift-by-one circuit. Eight 2-to-1 muxes, all controlled by the same bit s₀:
The same idea, but each mux’s “1” input comes from two rows below (controlled by s₁):
And from four rows below (controlled by s₂):
Put the three stages in a row. Any shift 0–7 is a sum of 4, 2 and 1, so s₂ s₁ s₀ is just the shift amount in binary! Try 000, then 011 (shift by 3).