Boolean Algebra & Digital Logic
A Complete 10-Chapter Maths for Programmers Course
Table of Contents
- Why Boolean Algebra & Digital Logic Matters for Programmers
- Boolean Values, Operators & Truth Tables
- The Laws of Boolean Algebra
- Boolean Functions & Canonical Forms
- Simplifying Boolean Expressions
- Logic Gates & Combinational Circuits
- Building Blocks: Adders, Multiplexers & Decoders
- Sequential Logic: Latches, Flip-Flops & Memory
- Binary, Hexadecimal & Number Representation
- Capstone — Designing a Small Digital Circuit
Why Boolean Algebra & Digital Logic Matters for Programmers
Boolean Algebra & Digital Logic
Chapter 1 · Why Boolean Algebra & Digital Logic Matters for Programmers
Discrete Mathematics Fundamentals' own Chapter 2 already covered truth tables, AND/OR/NOT, and De Morgan's Laws — as propositional logic: statements that are true or false, connected by logical words. This course reintroduces the exact same truth tables, on purpose, as a genuinely different thing: an algebra — a system of values and operations you can manipulate with algebraic laws, the way ordinary arithmetic lets you manipulate numbers. That shift in framing is what turns "true/false sentences" into "the actual mathematics every logic gate, CPU, and bitwise operator in a running computer is built from."
Same Truth Table, Two Different Framings
Propositional logic asks: is this sentence true? Boolean algebra asks: what does this expression evaluate to? The underlying table never changes — only what the two columns are understood to mean.
| Propositional logic (Discrete Math Ch.2) | Boolean algebra (this course) |
|---|---|
P, Q — statements, each true or false | x, y — variables, each 1 or 0 |
P ∧ Q (P and Q) | x · y or xy (Boolean product) |
P ∨ Q (P or Q) | x + y (Boolean sum) |
¬P (not P) | x' or x̄ (complement) |
The · and + notation isn't decorative — writing Boolean operations as "multiplication" and "addition" is exactly what makes Chapter 3's algebraic laws (distributive, absorption, and the rest) feel like genuine algebra rather than a list of logic rules to memorize separately.
A Real Demonstration: Your Own Code Already Runs on These Laws
A permissions system — READ, WRITE, EXECUTE as individual bits, combined with | (OR) and tested with & (AND) — is Boolean algebra running directly in production code, not an analogy for it.
READ=0b100, WRITE=0b010. Granting both: READ | WRITE = 0b110. Idempotent law (x + x = x): perms | perms == perms — verified True. Absorption law (x + (x · y) = x): perms | (perms & y) == perms — verified True. De Morgan's Law, on real 3-bit values: ~(a & b) and (~a | ~b), both masked to 3 bits, computed to the identical result — verified directly, not assumed.
Five Concrete Connections to Real Code
| Boolean algebra topic | Where it actually shows up |
|---|---|
| Boolean operators (Ch.2-3) | Bitwise operators in every language — &, |, ^, ~, <<, >> |
| Boolean simplification (Ch.5) | Simplifying tangled if conditions and short-circuit logic in real code |
| Flags & bitmasks (Ch.2-3, Ch.9) | Permission systems, feature flags, CPU status registers, protocol header fields |
| Logic gates & circuits (Ch.6-8) | What a CPU's ALU, adders, and multiplexers are physically built from |
| Number representation (Ch.9) | Two's complement — why negative numbers behave the way they do in every language |
What This Course Won't Cover
Digital logic, taken to its full depth, becomes computer architecture and then chip engineering. This course deliberately stops well before that point:
- Computer architecture / CPU design — instruction sets, pipelining, cache hierarchies, and how gates assemble into an actual processor stay out of scope; that's its own substantial future topic
- VLSI / physical circuit engineering — transistor-level design, timing analysis, and fabrication are a genuinely different (and much deeper) discipline than the logical structure this course covers
- Formal digital design tools — HDLs like Verilog/VHDL, and real synthesis/simulation tooling, aren't covered; this course builds the mathematical foundation those tools are built on top of
Where This Course Is Headed
| Chapter | Topic |
|---|---|
| 2 | Boolean Values, Operators & Truth Tables |
| 3 | The Laws of Boolean Algebra |
| 4 | Boolean Functions & Canonical Forms |
| 5 | Simplifying Boolean Expressions |
| 6 | Logic Gates & Combinational Circuits |
| 7 | Building Blocks: Adders, Multiplexers & Decoders |
| 8 | Sequential Logic: Latches, Flip-Flops & Memory |
| 9 | Binary, Hexadecimal & Number Representation |
| 10 | Capstone — Designing a Small Digital Circuit |
Hands-On Exercises
Using this chapter's own translation table, rewrite the propositional-logic statement (P ∧ Q) ∨ ¬P in Boolean algebra notation (using ·, +, and ').
A feature-flag system uses DARK_MODE=0b1000, BETA=0b0100, ADMIN=0b0010, DEBUG=0b0001. A user has flags enabled = DARK_MODE | BETA. Verify directly (compute the actual bit values) that the idempotent law enabled | enabled == enabled holds for this specific value, and explain in one sentence why this law will always hold for any combination of flags, not just this one.
A colleague says "bitwise operators are just a performance trick — they don't have any real mathematical structure behind them." Using this chapter's own flags demonstration, explain specifically why that's wrong, naming at least one Boolean algebra law that real bitwise code already obeys.
📄 View solutionChapter 1 Quick Reference
- Boolean algebra is propositional logic's own truth tables, reframed as algebra:
·(AND),+(OR),'(NOT) instead of∧,∨,¬ - Real bitwise/flags code already obeys Boolean algebra's laws — verified directly on a permissions bitmask (idempotent, absorption, De Morgan's)
- Five direct connections: bitwise operators, condition simplification, flags/bitmasks, logic gates/circuits, number representation
- Deliberately out of scope: full computer architecture/CPU design, VLSI/physical circuit engineering, HDL tooling
- Next chapter: Boolean values, operators, and truth tables — formalized
Boolean Values, Operators & Truth Tables
Boolean Algebra & Digital Logic
Chapter 2 · Boolean Values, Operators & Truth Tables
A Boolean value is one of exactly two elements — 0 or 1 (equivalently False/True). A Boolean operator takes one or two Boolean values and produces another. This chapter defines the full working set — including two operators, XOR and NAND/NOR, that Discrete Mathematics Fundamentals' own propositional-logic chapter never needed but digital logic can't do without.
The Core Three: AND, OR, NOT
| x | y | x · y (AND) | x + y (OR) |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 1 |
AND is 1 only when both inputs are 1. OR is 1 when at least one input is 1. NOT (x') simply flips: 0' = 1, 1' = 0.
XOR — Exclusive Or
XOR (⊕) is 1 exactly when its two inputs differ — true when exactly one input is 1, unlike plain OR which also accepts both.
| x | y | x ⊕ y (XOR) |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
1⊕1=0, exactly like adding two 1-bits and dropping the carry), which is precisely why Chapter 7's half adder is built directly from it.
NAND & NOR — Derived, and Surprisingly Powerful
NAND (NOT AND) and NOR (NOT OR) are simply AND/OR immediately followed by NOT:
| x | y | NAND(x,y) | NOR(x,y) |
|---|---|---|---|
| 0 | 0 | 1 | 1 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 0 |
A Remarkable Verified Fact: NAND Alone Builds Everything
NAND is functionally complete — every other operator in this chapter, including NOT, AND, and OR themselves, can be built using only NAND, wired to itself and to its own inputs.
NOT(x) = NAND(x, x) — verified for both x=0 and x=1. AND(x,y) = NAND(NAND(x,y), NAND(x,y)) — verified for all 4 input pairs, matching real AND exactly. OR(x,y) = NAND(NOT(x), NOT(y)) — verified for all 4 input pairs, matching real OR exactly.
Real Relevance: Logical vs. Bitwise Operators — a Genuine Trap
Most languages give you two separate operator families for what looks like the same idea: logical operators (and/or/not in Python) working on whole truthy/falsy expressions with short-circuit evaluation, and bitwise operators (&/|/^/~) working on individual bits — this chapter's own AND/OR/NOT/XOR, applied per-bit to an entire number at once.
& binds tighter than comparison operators in Python — so temperature > 10 & temperature < 30 silently parses as temperature > (10 & temperature) < 30, not the intended range check. Verified directly: with temperature = 50 (clearly not between 10 and 30), the un-parenthesized version wrongly returns True, while (temperature > 10) & (temperature < 30) correctly returns False. Always parenthesize each side when mixing comparisons with bitwise operators.
~True evaluates to -2, not False — ~ is bitwise complement, not logical negation, and applying it to a boolean silently promotes it to an integer first. This is a genuinely recognized trap: recent Python versions emit a DeprecationWarning specifically for ~ on a bare bool, confirming this is a known real-world footgun, not an edge case invented for this lesson. Use not x for logical negation, ~ only when you deliberately mean bitwise complement.
Operators in Code
Hands-On Exercises
Write out the full truth table for NOR(x,y) derived entirely from AND, OR, and NOT — that is, show (x + y)' matches the NOR truth table for all 4 input combinations.
Using this chapter's own NOT(x) = NAND(x,x) and OR(x,y) = NAND(NOT(x), NOT(y)) identities, trace through the computation of OR(0,1) step by step using only NAND operations, and confirm the final result is 1.
A piece of code checks if score > 90 & score < 100: in Python (using bitwise & instead of and). For score = 95, compute what this condition actually evaluates to (showing the precedence-driven parse), and explain why it happens to look correct here even though the operator choice is a real bug. Then show a specific score value where the bug produces a genuinely wrong result.
Chapter 2 Quick Reference
- AND (·): 1 only if both inputs are 1. OR (+): 1 if at least one input is 1. NOT ('): flips the value
- XOR (⊕): 1 exactly when inputs differ — the basis of binary addition without carry (Chapter 7)
- NAND/NOR: AND/OR immediately followed by NOT
- NAND alone is functionally complete — verified to build NOT, AND, and OR for every input
- Logical operators (
and/or/not) and bitwise operators (&/|/^/~) are genuinely different — mixing them causes real, verified bugs (precedence,~True) - Next chapter: The laws of Boolean algebra
The Laws of Boolean Algebra
Boolean Algebra & Digital Logic
Chapter 3 · The Laws of Boolean Algebra
Chapter 1's own finding-box already showed three of these laws holding on a real permissions bitmask, without naming them formally. This chapter names every law properly, proves each one, and introduces the one proof method that's unique to Boolean algebra: since every variable only has two possible values, an identity in n variables can be proved completely just by checking all 2ⁿ input combinations — no infinite case to worry about, unlike ordinary algebra over the real numbers.
The Standard Laws
| Law | Statement |
|---|---|
| Commutative | x+y = y+x, xy = yx |
| Associative | (x+y)+z = x+(y+z), (xy)z = x(yz) |
| Distributive | x(y+z) = xy+xz |
| Identity | x+0 = x, x·1 = x |
| Domination | x+1 = 1, x·0 = 0 |
| Complement | x+x' = 1, x·x' = 0 |
| Idempotent | x+x = x, x·x = x |
| Absorption | x+(xy) = x, x(x+y) = x |
x: x+x'=1 and x·x'=0 in both cases. Absorption law, all 4 combinations of x,y: x+(x·y) equals x in every single case.
A Genuinely Surprising Law: The Second Distributive Law
Ordinary arithmetic distributes multiplication over addition (x(y+z)=xy+xz) — but never the reverse; addition does not distribute over multiplication for real numbers. Boolean algebra is different: OR genuinely does distribute over AND, a law with no counterpart in ordinary arithmetic at all.
x+(y·z) = (x+y)·(x+z) — checked exhaustively, every single one of the 8 possible (x,y,z) combinations matches on both sides.
x=2, y=3, z=4: x+(y×z) = 2+12 = 14, but (x+y)×(x+z) = 5×6 = 30 — not equal. This law is a genuine property of the two-valued Boolean system, not a fact that happens to carry over from regular arithmetic just because the +/· notation looks the same.
De Morgan's Laws, Proved Algebraically
Discrete Mathematics Fundamentals introduced these as a logical equivalence between statements. Here they're the same two identities, proved the same exhaustive way as every other law in this chapter:
(x+y)' = x'·y' — matches on every input pair. (x·y)' = x'+y' — matches on every input pair. Same theorem, same truth values, now derived as algebra rather than restated as a logic rule.
The Duality Principle
Notice the laws above come in matched pairs. That's not a coincidence: swap every + with ·, and every 0 with 1, and any true Boolean law becomes another true Boolean law — its dual. The two distributive laws are duals of each other; so are the two De Morgan's laws, the two identity laws, and the two domination laws. Once one half of a pair is proved, the other is guaranteed true for free.
Real Relevance: Negating Compound Conditions Correctly
De Morgan's Laws are the exact tool for correctly inverting a compound condition in real code — not (a and b) is not the same as (not a) and (not b), a mistake that's easy to make under pressure. The correct inversion, straight from this chapter's own proof, is (not a) or (not b). Chapter 5 builds on every law in this chapter directly to simplify tangled real conditions down to their shortest equivalent form.
Hands-On Exercises
Using a full truth table (all 4 combinations of x,y), prove the commutative law for AND: xy = yx.
Using this chapter's own duality principle, state the dual of the identity law x·1 = x without checking a truth table first — then verify your answer is actually true for both values of x.
A piece of code needs to negate the condition is_admin or is_owner to correctly express "neither an admin nor the owner." Using De Morgan's Law from this chapter, write the correct negated form, and explain specifically what would go wrong if someone incorrectly wrote not is_admin or not is_owner instead.
Chapter 3 Quick Reference
- Every Boolean law can be completely proved by checking all
2ⁿinput combinations — a finite, exhaustive proof unique to two-valued algebra - Commutative, associative, distributive, identity, domination, complement, idempotent, absorption — the full standard law set, each verified exhaustively
- The second distributive law (
x+(yz)=(x+y)(x+z)) has no counterpart in ordinary arithmetic — confirmed to fail for real numbers - De Morgan's Laws, re-proved algebraically — same theorem as Discrete Mathematics Fundamentals Chapter 2, now derived rather than restated
- Duality: swap
+↔·and0↔1in any true law to get another true law, for free - Next chapter: Boolean functions and canonical forms
Boolean Functions & Canonical Forms
Boolean Algebra & Digital Logic
Chapter 4 · Boolean Functions & Canonical Forms
Chapters 2-3 gave the vocabulary and the laws. This chapter gives the actual, mechanical procedure: given any truth table at all, how do you write down a Boolean expression that produces it? The answer works for every possible function, every time, with no cleverness required.
How Many Boolean Functions Even Exist?
A Boolean function of n variables has 2ⁿ rows in its truth table, and each row's output can independently be 0 or 1 — so there are exactly 2^(2ⁿ) possible functions of n variables.
2^(2²) = 16 possible functions (AND, OR, XOR, NAND, NOR, XNOR, and 10 others, including the two constant functions "always 0" and "always 1"). 3 variables: 2^(2³) = 256 possible functions.
Minterms: A Building Block for Exactly One Row
A minterm is an AND of every variable (each either plain or complemented) that evaluates to 1 for exactly one input combination and 0 everywhere else. For two variables x,y, the minterm for the row x=1,y=0 is xy' — it's only 1 when x=1 and y=0.
Sum-of-Products: Reconstructing Any Truth Table
1, write down that row's own minterm. OR all of them together. The result is guaranteed to reproduce the exact original truth table — this is the sum-of-products (SOP) form, and it works for any Boolean function, not just convenient ones.
Maxterms & Product-of-Sums: The Dual Construction
A maxterm is the dual idea — an OR of every variable that evaluates to 0 for exactly one input combination. Taking the maxterm for every row where the output is 0, and AND-ing them together, gives the product-of-sums (POS) form — the same truth table, built from the opposite direction.
A Real Worked Example: The Majority Function
majority(x,y,z) outputs 1 exactly when at least two of its three inputs are 1 — a genuinely useful function, not a toy: it's the core of triple modular redundancy (TMR), the real fault-tolerance technique used in spacecraft and other safety-critical computers, where three independent copies of a circuit vote and the majority result is trusted even if one copy has been corrupted (by a cosmic ray flipping a bit, for instance).
1 for exactly 4 rows: (0,1,1), (1,0,1), (1,1,0), (1,1,1). Output is 0 for the other 4: (0,0,0), (0,0,1), (0,1,0), (1,0,0).
x'yz + xy'z + xyz' + xyz (one minterm per 1-row). POS: (x+y+z)(x+y+z')(x+y'+z)(x'+y+z) (one maxterm per 0-row). Both expressions were evaluated against the actual majority() function for all 8 input combinations — every single one matches, both forms and the original function agree perfectly.
Real Relevance: Specifying Business Logic From Test Cases
Anywhere requirements arrive as a table of "given these flags, the system should do X" — SOP construction turns that table directly into a correct, complete Boolean condition, mechanically, without needing to guess a clever simplified form first. Chapter 5 picks up immediately from here: an SOP expression built this way is always correct, but rarely the shortest way to say it — simplification is the next problem.
Canonical Forms in Code
Hands-On Exercises
A 2-variable function f(x,y) is 1 only when x=0, y=1 or x=1, y=0 (this is XOR). Write out its SOP form using minterms, and verify it matches the actual XOR truth table for all 4 input combinations.
Using the same XOR function from Exercise 1, write out its POS form using maxterms (from the rows where the output is 0), and verify it also matches the actual XOR truth table for all 4 combinations.
📄 View solutionA requirements table says a discount applies (output 1) only when is_member=1, is_holiday=0 or when is_member=0, is_holiday=1 — and never applies in any other combination of the two flags. Using this chapter's own SOP procedure, write the exact Boolean expression this requirements table describes, and name which well-known 2-input function it turns out to be.
Chapter 4 Quick Reference
- A function of
nvariables has exactly2^(2ⁿ)possible truth tables — 16 for 2 variables, 256 for 3 - Minterm: an AND term that's 1 for exactly one row. Maxterm: an OR term that's 0 for exactly one row
- Sum-of-Products (SOP): OR together the minterms of every 1-row — reconstructs any truth table, mechanically
- Product-of-Sums (POS): AND together the maxterms of every 0-row — the dual construction, same guarantee
- Verified on a real, useful function (3-input majority, the core of triple modular redundancy) — both forms matched exactly
- SOP built this way is always correct, but rarely shortest — Chapter 5 covers simplification
- Next chapter: Simplifying Boolean expressions
Simplifying Boolean Expressions
Boolean Algebra & Digital Logic
Chapter 5 · Simplifying Boolean Expressions
Chapter 4 closed with an honest admission: the SOP form it built is always correct, but almost never the shortest way to say the same thing. This chapter delivers two genuinely different tools for shrinking an expression down — algebraic simplification using Chapter 3's own laws, and Karnaugh maps, a visual method that finds the same simplification by spotting patterns instead of manipulating symbols.
Algebraic Simplification: Shrinking Chapter 4's Own Majority Function
Chapter 4's SOP form for the majority function was x'yz + xy'z + xyz' + xyz — 4 terms, 12 literals total. Simplifying it directly:
A=A+A) allows duplicating the shared xyz term twice, giving x'yz + xy'z + xyz' + xyz + xyz + xyz — still exactly equal to the original, just written with two extra (redundant) copies. Regrouping: (x'yz+xyz) + (xy'z+xyz) + (xyz'+xyz). Factoring each pair (distributive law): yz(x'+x) + xz(y'+y) + xy(z'+z). Applying the complement law (x'+x=1) to each: yz(1) + xz(1) + xy(1). Applying the identity law (x·1=x): yz + xz + xy.
xy + xz + yz matches majority(x,y,z) exactly, for all 8 input combinations — down from 4 terms / 12 literals to 3 terms / 6 literals, exactly half the size, with zero loss of correctness.
Karnaugh Maps: The Same Simplification, Found Visually
A Karnaugh map (K-map) arranges a truth table in a grid where adjacent cells always differ in exactly one variable — achieved by ordering the column headers in Gray code (00, 01, 11, 10, not the "obvious" 00, 01, 10, 11) so a single-bit change always corresponds to a single step across the grid.
| x \ yz | 00 | 01 | 11 | 10 |
|---|---|---|---|---|
| 0 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 1 | 1 |
1-cells eliminates whichever variable changes between them, leaving only the variables that stay fixed across the group. Groups may overlap freely.
(x=1,yz=01) and (x=1,yz=11) are adjacent (only y changes) → group gives xz. Cells (x=1,yz=11) and (x=1,yz=10) are adjacent (only z changes) → group gives xy. Cells (x=0,yz=11) and (x=1,yz=11) are adjacent (only x changes) → group gives yz. Together: xz + xy + yz — the exact same result the algebraic method reached, found by pattern-spotting instead of symbol manipulation.
A Second, Simpler Example
A 2-variable function: f(x,y) = xy + xy'.
xy + xy' = x(y+y') = x(1) = x — an entire variable, y, disappears completely. Checked for all 4 inputs: f(x,y) equals plain x in every case. On a K-map, this is exactly a group spanning an entire row — the widest possible group, eliminating the one variable that changes across the whole row.
Real Relevance
Chapter 4's requirements-table-to-SOP procedure is guaranteed correct but routinely produces expressions far longer than necessary — exactly what happened with the majority function's own 12-literal starting point. Whether reached algebraically or visually, a simplified expression means fewer conditions to read in code, and — critically for Chapter 6 onward — fewer physical logic gates to build the same circuit from.
Hands-On Exercises
Simplify f(x,y) = xy + x'y algebraically, using Chapter 3's own laws, showing each step. Verify your simplified result against the original for all 4 input combinations.
Draw the K-map for the function f(x,y) = xy + x'y from Exercise 1 (a 2×2 grid, rows x=0/1, columns y=0/1), identify the group of adjacent 1s, and confirm it produces the same simplified expression you found algebraically.
A colleague simplifies xy + xz + yz (this chapter's own majority-function result) down to just xy + xz, claiming the yz term is redundant. Determine whether they're correct by checking all 8 input combinations, and explain your conclusion.
Chapter 5 Quick Reference
- Algebraic simplification: apply Chapter 3's own laws (idempotent to duplicate a shared term, distributive to factor, complement + identity to collapse) directly to an SOP expression
- Chapter 4's majority function shrank from 4 terms/12 literals to 3 terms/6 literals — verified against the original for all 8 inputs
- Karnaugh map: a grid with Gray-code-ordered headers so adjacent cells differ in exactly one variable; group adjacent 1s to eliminate the variable that changes across the group
- Both methods, applied to the same function, land on the exact same simplified result — verified directly
- A group spanning an entire row/column eliminates a whole variable (Exercise-worthy 2-variable example:
xy+xy'=x) - Next chapter: Logic gates and combinational circuits
Logic Gates & Combinational Circuits
Boolean Algebra & Digital Logic
Chapter 6 · Logic Gates & Combinational Circuits
Everything so far has been symbols on a page. This chapter makes it physical: a logic gate is a real electronic component that takes voltage levels standing in for 0 and 1, and produces an output voltage exactly matching one of Chapter 2's own truth tables. Wire gates together, and Chapter 5's simplified expressions become an actual working circuit.
Combinational Circuits: Output Depends Only on Right-Now Inputs
A combinational circuit is built purely from gates with no memory anywhere in it — its output at any instant depends only on its current inputs, never on what happened before. Every circuit in this chapter is combinational. Chapter 8 introduces the genuinely different case — circuits that do remember something — which is a different kind of building block entirely, not just "combinational logic with extra wires."
Building Chapter 5's Own Simplified Circuit
Chapter 5 simplified the majority function down to xy + xz + yz. Wired directly into gates, using only 2-input AND and OR gates:
A1 = AND(x=1, y=1) = 1. A2 = AND(x=1, z=0) = 0. A3 = AND(y=1, z=0) = 0. O1 = OR(A1=1, A2=0) = 1. Output = OR(O1=1, A3=0) = 1. Matches majority(1,1,0) = 1 exactly — and the full circuit was verified against majority() for all 8 possible inputs, not just this one trace.
Why Chapter 5's Simplification Mattered Physically
Chapter 4's own unsimplified SOP form (x'yz + xy'z + xyz' + xyz) needs real gates too — and Chapter 5's simplification isn't just a shorter formula, it's a genuinely smaller, cheaper, faster circuit.
| Version | NOT gates | AND gates | OR gates | Total |
|---|---|---|---|---|
| Chapter 4's unsimplified SOP | 3 | 4 (3-input each) | 3 (chained 2-input) | 10 |
| Chapter 5's simplified form | 0 | 3 (2-input each) | 2 (chained 2-input) | 5 |
Real Relevance
This is literally what happens inside an FPGA or ASIC design flow: a Boolean expression gets simplified, then mapped onto real gates, then measured by exactly the gate-count and propagation-delay metrics above. Chapter 2's own NAND-completeness proof is why many real fabrication processes build every gate type shown here — AND, OR, NOT included — out of nothing but wired-together NAND gates, for manufacturing consistency.
Gate Simulation in Code
Hands-On Exercises
Using this chapter's own majority circuit, trace the signal through every gate for x=0, y=1, z=1, showing each gate's output, and confirm the final result matches majority(0,1,1).
Chapter 5's Exercise 1 simplified xy + x'y down to just y. Draw (describe in words, gate by gate) the circuit for the unsimplified form xy + x'y, count its gates (including any NOT gates needed), and compare that count to the simplified circuit, which needs zero gates at all since the output is just y directly.
Explain, using this chapter's own combinational-circuit definition, why a circuit that computes output = A AND (output from one clock cycle ago) could not be a combinational circuit, even though it's built entirely from an AND gate.
Chapter 6 Quick Reference
- Logic gate: a physical component realizing one of Chapter 2's own truth tables in real voltage levels
- Combinational circuit: output depends only on current inputs — no memory anywhere (contrast: Chapter 8's sequential logic)
- Chapter 5's simplified majority circuit (
xy+xz+yz) traced and verified directly, gate by gate, for all 8 inputs - Simplification's real payoff: 10 gates down to 5, zero NOT gates needed — smaller, cheaper, and faster (less propagation delay)
- Fewer gates in a circuit is the exact same "fewer operations, less time" idea as Algorithms & Complexity, applied to hardware instead of code
- Next chapter: Building blocks — adders, multiplexers, and decoders
Building Blocks: Adders, Multiplexers & Decoders
Boolean Algebra & Digital Logic
Chapter 7 · Building Blocks: Adders, Multiplexers & Decoders
Chapter 6 built one specific circuit. This chapter builds three genuinely reusable ones — standard components wired into essentially every real digital system, including the exact logic a CPU uses to add numbers.
The Half Adder: Chapter 2's XOR Promise, Delivered
Chapter 2 called XOR "the basis of binary addition without carry." A half adder adds two single bits and produces exactly that: a SUM bit and a CARRY bit.
SUM = x ⊕ y. CARRY = x · y. Two gates, total.
1+1=2, i.e. binary 10: SUM=0, CARRY=1 — matches. 0+1=1, binary 01: SUM=1, CARRY=0 — matches. Every one of the 4 input combinations produces the exact CS (carry, sum) digits of the real binary sum.
The Full Adder — and a Genuine Reuse of Chapters 4-6
A half adder can't be chained — real multi-bit addition needs each column to also accept a carry in from the column before it. A full adder takes three inputs (x, y, cin) and produces SUM and COUT: SUM = x ⊕ y ⊕ cin, COUT = xy + cin(x⊕y).
(x,y,cin): COUT equals 1 in precisely the same cases as majority(x,y,cin) — because a carry genuinely does occur exactly when at least two of the three bits being added are 1. This isn't a coincidence worth noting in passing: the full adder's carry-out logic is Chapter 5-6's own simplified xy+xz+yz circuit, with the variables simply renamed. The exact 5-gate circuit already built and traced in Chapter 6 is a real full adder's carry logic, reused wholesale.
Chaining Full Adders: A Real Multi-Bit Adder
Wire the COUT of one full adder into the cin of the next, and multi-bit numbers add correctly, column by column, exactly like doing long addition by hand — this is a real ripple-carry adder, and it's genuinely how simple ALU addition works.
11₂ + 10₂ (3+2): first stage adds the low bits with cin=0, its carry feeds the second stage — result 101₂ (5). 10₂ + 10₂ (2+2): result 100₂ (4). 01₂ + 01₂ (1+1): result 010₂ (2). All three verified correct against real binary addition.
Multiplexers: A Selectable Wire
A multiplexer (MUX) routes exactly one of several data inputs through to a single output, chosen by a separate select input. A 2-to-1 MUX: output = sel'·in0 + sel·in1.
sel=0, the output always exactly matches in0, regardless of in1. With sel=1, the output always exactly matches in1, regardless of in0 — confirmed for every combination.
Decoders: Physically Wired Minterms
A decoder takes n select inputs and activates exactly one of 2ⁿ output lines. A 2-to-4 decoder's four outputs are literally Chapter 4's own four possible 2-variable minterms — a'b', a'b, ab', ab — each wired to its own physical output line.
ab=00 activates D0. ab=01 activates D1. ab=10 activates D2. ab=11 activates D3 — the active output number always equals the binary value of the select inputs, confirmed for all 4 combinations.
Real Relevance
Ripple-carry addition is the literal mechanism behind a CPU's own integer addition (real ALUs use faster carry-lookahead variants at scale, but the correctness principle is identical). Multiplexers select which data path is active on every clock cycle inside a real processor. Decoders turn a binary address into "activate exactly this one memory location" — the basic mechanism behind RAM addressing itself.
Building Blocks in Code
Hands-On Exercises
Using this chapter's own full adder, add the 2-bit binary numbers 10 and 11 (decimal 2 and 3) via a ripple-carry chain, showing each full adder's inputs and outputs, and confirm the result equals 101 (decimal 5).
Using this chapter's own MUX formula (sel'·in0 + sel·in1), trace the output for sel=1, in0=1, in1=0, and explain in one sentence why the value of in0 doesn't matter at all once sel=1 is fixed.
Explain, using this chapter's own finding about the full adder's carry-out logic, why a chip designer who already has a working, well-tested majority-function circuit could reuse it directly as the carry-out logic of a full adder — without redesigning anything from scratch.
📄 View solutionChapter 7 Quick Reference
- Half adder:
SUM=x⊕y,CARRY=xy— exactly Chapter 2's own XOR promise, delivered - Full adder: adds
x, y, cin;SUM=x⊕y⊕cin,COUT=majority(x,y,cin)— a genuine, verified reuse of Chapters 4-6's own circuit - Ripple-carry adder: chain full adders, COUT of one feeds cin of the next — verified on real 2-bit binary addition
- Multiplexer: routes exactly one of several inputs to the output based on a select line
- Decoder: activates exactly one of
2ⁿoutputs — physically wires Chapter 4's own minterms, one per output line - Next chapter: Sequential logic — latches, flip-flops, and memory
Sequential Logic: Latches, Flip-Flops & Memory
Boolean Algebra & Digital Logic
Chapter 8 · Sequential Logic: Latches, Flip-Flops & Memory
Chapter 6 defined a combinational circuit as one whose output depends only on its current inputs, and named this chapter as the exception. The mechanism behind that exception is simple to state and genuinely powerful: wire a gate's output back into its own input, and the circuit's behavior starts depending on its own history — which is exactly what memory is.
The SR Latch: Two Gates, Wired to Remember
The simplest memory element is two NOR gates, cross-coupled — each gate's output feeds into the other gate's input. It has two inputs, S (set) and R (reset), and two outputs, Q and its complement Q'.
Q = NOR(R, Q'), Q' = NOR(S, Q) — each output depends on the other gate's own current output, not just on S and R directly.
Q=0: S=1,R=0 (SET) → Q=1. Then S=0,R=0 (HOLD) → Q stays 1. Another S=0,R=0 → still 1. Then S=0,R=1 (RESET) → Q=0. Then two more S=0,R=0 steps → Q stays 0 both times. The exact same inputs (S=0,R=0) produced different Q values depending on what happened earlier — precisely the history-dependence that disqualifies this circuit from being combinational, now demonstrated with a real simulated gate network rather than asserted.
The Forbidden State
S=1, R=1 simultaneously drives both Q and Q' toward 0 — verified directly: both outputs land on 0, breaking the invariant that Q and Q' must always be complements of each other. Real SR latches genuinely forbid this input combination; it's not a corner case this chapter is glossing over, it's a real constraint every actual circuit using an SR latch has to respect.
The D Latch: A Structural Fix
A D latch adds a data input D and an enable line, deriving S and R automatically: S = D · enable, R = D' · enable.
D and enable: S and R are never both 1 at the same time — because D and D' can never both be 1, whatever gets AND-ed with enable inherits that same guarantee. The forbidden state isn't avoided by careful usage; it's ruled out by the wiring itself.
Level-Triggered vs. Edge-Triggered: Why Flip-Flops Exist
A D latch is level-triggered — while enable stays high, Q tracks D continuously, which can cause real problems when latches are chained (a change can "race" through several stages within a single enable pulse). A D flip-flop is edge-triggered — it only updates at the exact instant a clock signal transitions (e.g. low-to-high), holding steady the rest of the time. This is the real building block used in registers, counters, and pipeline stages, specifically because it makes multi-stage timing predictable.
Real Relevance: This Is What a Variable Actually Is
A CPU register, one bit of RAM, or the value behind an ordinary variable in running code — all the way down at the hardware level — genuinely is one of these feedback circuits. There's no separate "memory technology" beyond this trick, repeated billions of times: writing a variable sets a flip-flop; reading it later returns whatever that flip-flop has been holding since.
Sequential Logic in Code
Hands-On Exercises
Starting from Q=1, Q'=0, trace this chapter's own SR latch through the sequence (S=0,R=1), (S=0,R=0), (S=0,R=0), (S=1,R=0), showing Q after each step, and confirm Q genuinely holds its value during both (0,0) steps.
Using this chapter's own D latch equations (S=D·enable, R=D'·enable), compute S and R for D=1, enable=0, and explain what this means for Q — does the latch update, or hold its previous value? Connect your answer to what "enable" is actually doing.
A colleague argues "a D latch can never reach the SR latch's forbidden state, so it must be strictly better and the plain SR latch is obsolete." Using this chapter's own material, explain what's wrong with dismissing the SR latch entirely — specifically, is the SR latch's own S/R behavior ever still useful on its own terms, separate from the forbidden-state issue?
📄 View solutionChapter 8 Quick Reference
- Feedback (a gate's output wired back into its own input) is the mechanism that breaks Chapter 6's own combinational definition and creates memory
- SR latch: cross-coupled NOR gates — verified directly to genuinely hold its value across identical
S=0,R=0inputs, depending on prior history - Forbidden state:
S=1,R=1breaks theQ/Q'complement invariant — verified directly, a real constraint - D latch: derives S/R from D and enable so the forbidden state becomes structurally impossible — verified across all 4 combinations
- D flip-flop: edge-triggered, not level-triggered — the real building block for registers and multi-stage timing
- A variable's stored value, all the way down, genuinely is one of these feedback circuits
- Next chapter: Binary, hexadecimal, and number representation
Binary, Hexadecimal & Number Representation
Boolean Algebra & Digital Logic
Chapter 9 · Binary, Hexadecimal & Number Representation
Every chapter so far has quietly assumed numbers arrive as bits. This chapter asks the question directly — and answers a mystery Chapter 2 left open along the way: why ~True really does equal -2, not by accident, but by design.
Binary and Hexadecimal: The Same Number, Two Notations
Binary is positional notation base 2. Hexadecimal (base 16) exists because it aligns perfectly with binary in a way decimal never can: each hex digit represents exactly 4 bits, with no remainder.
173 in binary: 10101101. Split into 4-bit groups: 1010 and 1101 — decimal 10 and 13, i.e. hex A and D. Result: 0xAD, confirmed to equal 173 exactly.
Two's Complement: How Negative Numbers Actually Work
A naive "sign bit" scheme (flip the top bit to mean negative) has two real problems: it creates two representations of zero (+0 and -0), and ordinary addition breaks unless the hardware special-cases signs. Two's complement avoids both: to negate a number, invert every bit, then add 1.
+3 = 0011. Inverting gives 1100; adding 1 gives 1101 — the encoding of -3. +5 → -5 = 1011. There's exactly one encoding of zero (0000), and the 4-bit range is -8 to 7 — deliberately asymmetric, one more negative value than positive, since 0 itself uses up one of the 16 available patterns on the positive side.
The Real Payoff: Chapter 7's Own Adder Needs No Changes at All
This is the entire reason two's complement is universal: a ripple-carry adder built with zero awareness of signs correctly computes negative results, purely because of how the bit patterns are chosen.
0011 (+3) and 1101 (-3) through the exact same full-adder chain from Chapter 7: result bits 0000, with a discarded final carry-out of 1 — zero, exactly correct. Adding 0101 (+5) and 1011 (-5): same result, 0000. No special subtraction circuit, no sign-checking logic — the identical hardware from Chapter 7 handles both positive and negative numbers correctly, simply because the encoding was chosen to make that true.
Closing the Loop: Why ~True Really Is -2
Chapter 2 flagged ~True == -2 as a real, verified gotcha without explaining why. In two's complement, bitwise complement and negation are related by a clean identity:
~x = -x - 1, for every value checked: ~5=-6 (-5-1=-6), ~10=-11, ~100=-101, all matching exactly. Applied to Chapter 2's own case: True acts as 1, so ~True = -1-1 = -2 — not a quirk of Python's own boolean handling, but two's complement working exactly as designed, on a value that happened to be a boolean.
Arithmetic vs. Logical Right Shift
Right-shifting a negative number needs to decide what to fill the vacated high bits with. Python's >> is an arithmetic shift — it fills with the sign bit, preserving negativity and behaving like floor division by 2.
-8 >> 1 = -4. -7 >> 1 = -4 (floor of -3.5). -1 >> 1 = -1 — stays negative forever under repeated arithmetic shifting, never reaching 0 the way a logical (zero-filling) shift would. Some languages (Java's >>>, for instance) offer a separate logical shift operator specifically because arithmetic and logical shifts genuinely disagree on negative inputs.
Real Relevance
Bitwise operators (&, |, ^, ~, <<, >>) operate directly on these representations — Chapter 2's own flags/bitmasks are binary representation in action, and every value stored anywhere in a running program is, physically, one of the encodings this chapter just formalized.
Number Representation in Code
Hands-On Exercises
Convert 202 to binary, then group it into 4-bit nibbles and convert each nibble to hexadecimal, confirming your hex result equals 202 when checked directly.
Encode +6 and -6 in 4-bit two's complement (showing the invert-then-add-1 process for the negative value), then add the two 4-bit patterns using Chapter 7's own full-adder chain, showing each stage's SUM and COUT, and confirm the result is 0000 with the carry-out discarded.
Using this chapter's own ~x = -x-1 identity, predict the value of ~(-5) without computing it directly first, then verify your prediction. Explain in one sentence why applying ~ twice in a row (~~x) always returns the original value x.
Chapter 9 Quick Reference
- Hex aligns exactly with binary — each hex digit is 4 bits, no remainder
- Two's complement: invert all bits, add 1 — fixes sign-magnitude's double-zero and broken-addition problems
- 4-bit range is
-8to7— deliberately asymmetric, exactly one representation of zero - Verified directly: Chapter 7's own unmodified adder correctly computes
+x + (-x) = 0— no special subtraction circuitry needed - Closed the loop on Chapter 2:
~x = -x-1—~True=-2was two's complement working exactly as designed - Arithmetic right shift sign-extends negative numbers; logical shift zero-fills — genuinely different results, real cross-language relevance
- Next chapter: Capstone — designing a small digital circuit
Capstone — Designing a Small Digital Circuit
Boolean Algebra & Digital Logic
Chapter 10 · Capstone — Designing a Small Digital Circuit
One continuous project: a real 3-bit adder/subtractor with overflow detection — the exact same technique a genuine ALU uses to compute both A+B and A-B from a single piece of hardware, touching every chapter of this course in the order a real designer would actually reach for each idea.
| Step | Task | Chapter(s) used |
|---|---|---|
| 1 | The core trick: one mode signal, reusing addition to do subtraction | Ch.9 (two's complement) |
| 2 | Wire the mode-select logic | Ch.1-3 (operators, laws), Ch.6 (gates) |
| 3 | Build the full 3-bit circuit | Ch.7 (full adders, chained) |
| 4 | Trace and verify four real cases | Ch.7, Ch.9 |
| 5 | Derive overflow detection from first principles | Ch.4 (canonical form), Ch.5 (simplification) |
| 6 | Full gate-count accounting | Ch.6 |
Step 1 — The Core Trick
Chapter 9 proved that negating a number in two's complement is "invert every bit, then add 1." A single mode signal M can trigger exactly that, on demand: XOR every bit of B with M (inverting B when M=1, leaving it unchanged when M=0), and feed M itself in as the initial carry-in (supplying the "+1"). When M=0: ordinary addition, A+B. When M=1: A + B' + 1 = A + (-B) = A - B.
Step 2 — Wiring the Mode-Select Logic
Three XOR gates (one per bit of B), each with M as one input — the smallest possible piece of combinational logic (Chapter 6) doing real, load-bearing work.
Step 3 — The Full 3-Bit Circuit
Three full adders, chained exactly as in Chapter 7's own ripple-carry adder — LSB first, each stage's COUT feeding the next stage's cin — except the chain's very first cin is M instead of a hardwired 0, and each adder's own B input is the XOR-modified bit from Step 2, not the raw bit.
Step 4 — Four Real Cases, Fully Traced
full_adder(0,1,cin=0) → SUM=1, COUT=0. Middle: full_adder(1,0,cin=0) → SUM=1, COUT=0. Sign/MSB: full_adder(0,0,cin=0) → SUM=0, COUT=0. Result: 3. Correct.
B XOR M flips 1 (001) to 110. LSB: full_adder(1,0,cin=1) → SUM=0, COUT=1. Middle: full_adder(1,1,cin=1) → SUM=1, COUT=1. Sign/MSB: full_adder(0,1,cin=1) → SUM=0, COUT=1. Result: 2. Correct.
SUM=0, COUT=1. Middle: SUM=1, COUT=0. Sign/MSB: SUM=1, COUT=0. Result bits 110, decoded as two's complement: −2. Correct — the exact same unmodified circuitry handles a negative result with no special case.
SUM=0, COUT=0. Middle: SUM=0, COUT=1. Sign/MSB: SUM=1, COUT=0. Raw result bits 100 decode as −4 — 2+2 is not −4. This is a genuine overflow: 4 falls outside the 3-bit signed range (−4 to 3, per Chapter 9). The circuit doesn't know this on its own — Step 5 builds the logic that catches it.
Step 5 — Deriving Overflow Detection From First Principles
Overflow happens exactly when the carry into the sign bit's own full adder disagrees with the carry out of it — one more bit "wanted" to flow in than the sign position can correctly represent. Both signals already exist as real wires in the circuit built in Step 3, so this is genuinely just overflow = carry_in_sign ⊕ carry_out_sign — a single XOR gate, no new adder logic required.
2+1: carry-in-to-sign 0, carry-out-of-sign 0 → overflow 0. 3−1: 1 and 1 → overflow 0. 1−3: 0 and 0 → overflow 0. 2+2: 1 and 0 → overflow 1 — the exact case flagged as suspicious above, now caught mechanically rather than by manual inspection.
Step 6 — Full Gate-Count Accounting
Each full adder needs 2 XOR + 2 AND + 1 OR gates (5 total, per Chapter 7's own SUM=x⊕y⊕cin, COUT=xy+cin(x⊕y) formulas, reusing the shared x⊕y signal). Three full adders: 15 gates. Three mode-select XOR gates: 3 gates. One overflow XOR gate: 1 gate.
What This Course Doesn't Cover
As stated honestly back in Chapter 1: full computer architecture/CPU design, VLSI/physical circuit engineering, and formal HDL tooling were named as deliberately out of scope, and stayed out of scope through all ten chapters. This capstone's own adder/subtractor is a genuine, real ALU building block — but a real ALU is many such blocks, plus instruction decoding, registers, and control logic this course never claimed to cover.
Where This Course Connects
Algorithms & Complexity's own "fewer operations, less time" reasoning reappeared directly in Chapter 6's gate-count argument, now paying off again in this capstone's own 19-gate, three-function circuit. Discrete Mathematics Fundamentals' own propositional logic was this course's own starting point (Chapter 1), and its proof-technique toolkit underwrote Chapter 3's own exhaustive law proofs. Number Theory & Cryptographic Math's own binary/modular reasoning and this course's Chapter 9 cover genuinely adjacent ground — worth revisiting side by side.
Hands-On Exercises
Using this chapter's own circuit, trace −1 + 1 (M=0) through all three full-adder stages, showing each stage's SUM and COUT, and confirm the result is 0 with no overflow.
Using this chapter's own overflow formula, check whether −3 − 2 (M=1) overflows the 3-bit signed range. Trace the circuit fully, compute the carry-into-sign and carry-out-of-sign values, and state whether the result is trustworthy.
Explain, using this chapter's own gate-count accounting, why building two separate circuits — one dedicated adder and one dedicated subtractor — would very likely need more than 19 gates combined, even though each one individually might look simpler than the combined adder/subtractor.
📄 View solutionChapter 10 Quick Reference
- Full worked project: two's-complement negation via XOR+carry-in (Ch.9) → mode-select gates (Ch.1-3,6) → chained full adders (Ch.7) → four fully traced/verified cases including a caught overflow → overflow formula derived from first principles (Ch.4-5) → full gate count (Ch.6)
- The exact same unmodified circuitry correctly handles addition, subtraction, and negative results — verified directly, no special-casing anywhere
- Overflow = carry-into-sign XOR carry-out-of-sign — one extra gate, reusing wires the circuit already has
- 19 gates total: a real adder, subtractor, and overflow detector, sharing nearly all their hardware
- Out of scope: full CPU/ALU design, VLSI engineering, HDL tooling
- Course complete — Boolean Algebra & Digital Logic, 10 chapters, from truth tables to a working adder/subtractor