Lecture 9: Combinational Logic

Boolean Algebra, Logic Gates, and the ALU

Babafemi Sorinolu

Reading and Credits

  • Reading: textbook Appendix B (Basics of Logic Design): sections 1–3 and 5–10.
  • Many slides are interactive: click the purple input boxes to flip bits, and click table cells to fill them in.

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.

What We’ve Done, Where We’re Going

Application Operating System Compiler Firmware CPU Memory I/O system Digital Design ← today Circuit Design Top down (Almost) bottom up to the CPU Software Interface: Instruction Set Architecture, Memory, I/O Hardware

A Computer Is a Machine That Manipulates Bits

  • Everything is in binary (0s and 1s): instructions, numbers, memory locations, …
  • A computer is a machine that operates on bits: executing an instruction = operating on bits.
  • Computers are physically made of transistors: electrically controlled switches.
  • We use transistors to build logic, for example:
    • if this bit is 0 and that bit is 1, then set some other bit to 1
    • if the first 5 bits of the instruction are 10010, set this bit to 1 (tell the adder to subtract instead of add)

How Many Transistors Are We Talking About?

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!

Abstraction is the key to designing any large system:

  1. Put a few (2–8) transistors into a logic gate (AND, OR, XOR, …)
  2. Combine gates into logical functions (add, select, …)
  3. Combine adders, shifters, etc. into modules: units with well-defined interfaces (e.g., decode)
  4. Combine a dozen of those into a core…
  5. Put 4 cores on a chip…

Today: steps 1 and 2.

Boolean Algebra

Boolean Algebra

  • The first step to logic: Boolean algebra, the math of True / False (1 / 0).
  • Given input variables A, B, C, … compute outputs using logical operators:
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.

Truth Tables

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

Any Inputs, Any Outputs

  • A function can have any number of inputs and any number of outputs.
  • It can be any mapping you like. Here are 3 inputs and 2 outputs:
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.

Let’s Write a Truth Table for a Function

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 = 1

Done! 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

Practice: Level 1 — Basic Operators

Fill in the truth table: click a cell to enter 0/1, then Check. Stuck? Add helper columns for the sub-expressions.

Practice: Level 2 — Three Variables

Fill in the truth table: click a cell to enter 0/1, then Check. Stuck? Add helper columns for the sub-expressions.

Practice: Level 3 — Intermediate

Fill in the truth table: click a cell to enter 0/1, then Check. Stuck? Add helper columns for the sub-expressions.

Practice: Level 4 — Challenging

Fill in the truth table: click a cell to enter 0/1, then Check. Stuck? Add helper columns for the sub-expressions.

Suppose I Turn It Around…

Given a truth table, find the formula?

Idea: write down every true row as an AND term, then OR them together.

(!A & !B & !C) |
(!A & !B & C) |
(!A & B & !C) |
(A & B & !C) |
(A & B & C)

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

Sum of Products: Works, but Ugly

  • Works every time
  • Result is right…
  • …but really ugly
(!A & !B & !C) |
(!A & !B & C) |
(!A & B & !C) |
(A & B & !C) |
(A & B & C)
(!A & !B & !C) |
(!A & !B & C) |

(!A & B & !C) |
(A & B)
(!A & !B) |
(!A & B & !C) |
(A & B)
Rows 110 and 111: C doesn’t matter → could just be (A & B)?
Rows 000 and 001: C doesn’t matter → could just be (!A & !B)
Looks nicer… can we do better?
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

We Did That by Intuition… but

  • That was a somewhat intuitive approach to simplifying.
  • This is math, so there are formal rules, just like “regular” algebra.

Boolean Function Simplification

AND rules

  • A & A = A
  • A & 0 = 0
  • A & 1 = A
  • A & !A = 0

OR rules

  • A | A = A
  • A | 0 = A
  • A | 1 = 1
  • A | !A = 1
  • Double negation: !!A = A
  • & and | are both commutative and associative.
  • They distribute: A & (B | C) = (A & B) | (A & C)
  • Absorption (subsumption): A | (A & B) = A

De Morgan’s Laws

Push 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.

Summary of the Boolean Axioms

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

Simplification Example

!(!A | !(A & (B | C)))
De Morgan's law
!!A & !!(A & (B | C))
Double negation
A & (A & (B | C))
Associativity of &
(A & A) & (B | C)
Idempotent law: A & A = A
A & (B | C)

You Try This

Come up with a formula for this truth table.
Simplify as much as possible.

Sum of products:

(!A & !B & !C) |
(!A & B & !C) |

(A & !B & C) |
(A & B & C)

↑ 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

You Try This: Simplify the First Part

Simplify:
(!A & !B & !C) | (!A & B & !C)
Regroup (associative / commutative):
((!A & !C) & !B) | ((!A & !C) & B)
Un-distribute (factor out !A & !C):
(!A & !C) & (!B | B)
Inverse law: !B | B = 1
(!A & !C) & 1
Identity law: X & 1 = X
(!A & !C)

You Try This: Finish It

After simplifying the green part:

(!A & !C) |
(A & !B & C) |
(A & B & C)
(!A & !C) |
(A & C)

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

Practice Question 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

Solution: Sum of Products

Step 1: Select rows where Output = 1

Write a product term for each row with output 1:

(!A & !B & C) |
(!A & B & C) |
(A & !B & !C) |
(A & B & !C)

Solution: Sum of Products

Step 2: Simplify the first two terms

Factor out !A & C:

(!A & !B & C) | (!A & B & C)
= (!A & C) & (!B | B)
= !A & C

Solution: Sum of Products

Step 3: Simplify the last two terms

Factor out A & !C:

(A & !B & !C) | (A & B & !C)
= (A & !C) & (!B | B)
= A & !C

Solution: Sum of Products

Step 4: Write the simplified answer

(!A & C) | (A & !C)

The variable B disappears because the output does not depend on its value.

Logic Gates

Applying the Theory

  • Lots of good theory: we can reason about complex Boolean expressions.
  • But why is this useful?

Because every Boolean operator is a physical gate made of transistors. Simplifying the expression = fewer gates = a smaller, faster, cheaper, lower-power chip.

Boolean Gates

Gates are electronic devices that implement simple Boolean functions: the building blocks of hardware.

Guide to Remembering Your Gates

Brief Interlude: Building an Inverter

A NOT gate takes just two transistors:

Boolean Functions, Gates, and Circuits

Circuits are networks of gates. Here is our answer from before, (!A & !C) | (A & C):

A Few More Words About Gates

  • Gates have inputs and outputs.
  • Never connect two outputs together: if one drives 1 and the other drives 0, bad things happen (your processor catches fire 🔥).
  • If you leave an input unconnected, it behaves kind of randomly. Also not good, but not set-your-chip-on-fire bad.

Multiplexers

Introducing the Multiplexer (“mux”)

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.

Example of a Multiplexer

Introducing the Multiplexer (“mux”)

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.

Let’s Make a Useful Circuit: the 2-to-1 Mux

  • Pick between 2 inputs: S = 0 → A, S = 1 → B.
  • What might we do first? Make a truth table!

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

Circuit Example: 2-to-1 Mux in Gates

MUX(A, B, S) = (A & !S) | (B & S). It is so common that it gets its own symbol: a trapezoid.

Example: 4-to-1 Mux

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.

Adders

Arithmetic and Logical Operations

  • What operations does the ISA need? add, sub, and, or, not, shifts, …
  • How do we implement them in gates?
  • Let’s start with the simplest: a 1-bit adder.

Designing a 1-bit Adder

0 + 0 = 00
0 + 1 = 01
1 + 0 = 01
1 + 1 = 10
  • Which Boolean function gives the low bit (sum)? XOR
  • Which Boolean function gives the high bit (carry)? AND

Remember Binary Addition?

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.

Designing a Full Adder

So we need to add three bits (a, b and the carry-in). The 2-bit result is the carry-out and the sum:

a + b + Cin = CoutSum
0 + 0 + 0 = 00
0 + 0 + 1 = 01
0 + 1 + 0 = 01
0 + 1 + 1 = 10
1 + 0 + 0 = 01
1 + 0 + 1 = 10
1 + 1 + 0 = 10
1 + 1 + 1 = 11

Turn it into an expression, simplify, build it from gates…

A 1-bit Full Adder

Sum = a ^ b ^ Cin    Cout = (a & b) | (Cin & (a ^ b))

Example: 4-bit Adder

Chain 4 full adders: each carry-out feeds the next adder’s carry-in (a ripple-carry adder).

Subtraction

  • How do we perform integer subtraction? Recall why 2’s complement is a good idea: no new hardware!

\[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: Adder/Subtractor

Overflow

  • Unsigned overflow: look at the final carry-out Cout (for addition, Cout = 1 means the result didn’t fit).
  • Signed overflow happens when:
    • adding two positives gives a negative, or
    • adding two negatives gives a positive.
  • Detect it at the most significant bit: overflow if carry-in ≠ carry-out, which is a single XOR gate!

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.

Add/Subtract With Overflow Detection

The ALU

ALU Slice

One bit of an Arithmetic Logic Unit: compute every operation in parallel, then use a mux (controlled by F) to pick the result.

The ALU

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).

Alternate ALU Design

  • The previous design did the ALU work per bit, then chained the slices.
  • We can also do each word-size operation (16-bit AND, 16-bit OR, …) and mux the resulting words.
  • Same result, different organization.

Abstraction: The ALU

  • General structure:
    • two operand inputs (n bits each)
    • control inputs (which operation)
    • result + status flags (zero?, overflow?, carry out)
  • We can also build circuits for multiplication and division. They’re just more complex.

Shifters

Another Operation We Might Want: Shift

  • Remember << and >>? How would we implement them?
  • Suppose we have an 8-bit number \(b_7 b_6 b_5 b_4 b_3 b_2 b_1 b_0\)…
  • …and want to shift it left by a 3-bit amount \(s_2 s_1 s_0\) (0–7 places).

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. 👇

Building a Bit Shifter: Shift by One

A simpler problem: a shift-by-one circuit. Eight 2-to-1 muxes, all controlled by the same bit s₀:

Building a Bit Shifter: Shift by Two

The same idea, but each mux’s “1” input comes from two rows below (controlled by s₁):

Building a Bit Shifter: Shift by Four

And from four rows below (controlled by s₂):

Now Shift by a 3-bit Number

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).

Summary

  • Boolean algebra and functions: truth tables, sum of products, simplification, De Morgan’s laws
  • Logic gates: AND, OR, NOT, XOR, NAND, NOR, XNOR, and how they’re built from transistors
  • Multiplexers: select one of several inputs
  • Adders: half adder → full adder → ripple-carry adder → adder/subtractor with overflow detection
  • Arithmetic Logic Unit (ALU): compute every operation, mux out the one you want
  • Bit shifting: a barrel shifter made of mux stages