Microprocessor Architecture
Learning Objectives
- Identify the internal building blocks of a microprocessor/CPU: ALU, control unit, registers, and buses
- Explain the fetch-decode-execute cycle step by step, including what changes in the program counter each cycle
- Distinguish between address bus, data bus, and control bus and state what travels on each
- Compare von Neumann and Harvard architectures and explain why most MCUs use Harvard-style memory
- Explain how pipelining improves throughput without changing instruction count
- Read and trace a short assembly program to predict register and memory changes
Quick Answer
A microprocessor's architecture is the internal organization that lets it fetch an instruction from memory, figure out what it means, and carry it out — repeated billions of times per second. The core pieces are the ALU (does math and logic), the control unit (sequences everything and decodes instructions), registers (tiny, extremely fast storage right inside the CPU), and three buses (address, data, control) that connect the CPU to memory and I/O. This matters because every optimization in modern computing — from a microcontroller ticking at 16 MHz to a laptop CPU doing billions of operations per second — is built on this same fetch-decode-execute foundation, just made faster through techniques like pipelining and superscalar execution.
The Fetch-Decode-Execute Cycle
Every microprocessor, no matter how simple or advanced, keeps doing the same three-step loop, forever, as long as it has power and a clock signal:
- Fetch — the control unit reads the memory address held in the Program Counter (PC) and pulls the instruction stored there into the Instruction Register (IR). The PC then increments to point at the next instruction.
- Decode — the control unit interprets the bit pattern in the IR to figure out which operation to perform and which registers/operands it needs.
- Execute — the ALU or another functional unit actually performs the operation (add two numbers, load a value from memory, write to a GPIO register, branch to a new address, etc.).
This is not an abstract diagram — it is literally what happens every clock cycle (or several cycles, on simpler CPUs) inside your MCU.
Example: Tracing a Real Instruction
Consider this line of embedded C:
count = count + 1;
On an AVR (8-bit) target, this typically compiles to something like:
LDS R16, count ; Fetch: load PC's target instruction; Execute: read variable 'count' from SRAM into register R16
INC R16 ; Fetch-decode-execute: increment R16 by 1 (ALU operation)
STS count, R16 ; Fetch-decode-execute: store R16 back into SRAM at 'count'
Each of those three assembly lines runs its own full fetch-decode-execute cycle. LDS and STS move data between the CPU's registers and SRAM over the internal data bus; INC uses the ALU. Notice this is exactly why a single line of C can take multiple clock cycles on real hardware — a fact that matters a lot when you're timing interrupt handlers.
Key Components of a Microprocessor
- Arithmetic Logic Unit (ALU) — performs addition, subtraction, and logic operations (AND, OR, NOT, XOR, shifts). Every "computation" in a program ultimately routes through the ALU.
- Control Unit (CU) — the "conductor." It doesn't do the math itself; it decodes instructions and generates the control signals that tell the ALU, registers, and memory what to do and when.
- Registers — the fastest storage in the entire system, physically inside the CPU. Examples: the Program Counter (PC), Accumulator, Instruction Register (IR), general-purpose registers (R0-R31 on AVR), and the Status Register/Flags (zero flag, carry flag, etc.) that record the outcome of the last ALU operation.
- Bus system — the "roads" connecting CPU, memory, and I/O:
- Address bus (unidirectional, CPU → memory): carries the memory address the CPU wants to read or write
- Data bus (bidirectional): carries the actual data being transferred
- Control bus (bidirectional): carries signals like read/write, clock, interrupt requests
- Clock circuitry — generates the timing pulse (e.g., 16 MHz crystal) that paces every stage of the fetch-decode-execute cycle. Doubling clock speed roughly doubles instruction throughput, at the cost of higher power draw.
Real-World Example
When you press a key on a computer keyboard, the keyboard controller raises an interrupt line (part of the control bus). The CPU finishes its current instruction, pushes its PC and status flags onto the stack, and jumps to the interrupt service routine's address. That address travels over the address bus; the actual keycode data travels over the data bus. This is the exact same mechanism an MCU uses when a button press triggers a pinChangeInterrupt — the CPU architecture doesn't care whether it's a desktop keyboard or a garage-door sensor.
Why It Matters
Understanding buses and registers explains why certain operations in embedded programming are fast and others are slow. Reading a value already in a CPU register is essentially free (1 clock cycle); reading from external memory over a bus takes multiple cycles because of bus arbitration and memory access latency. This is why performance-critical embedded code keeps hot variables in registers (the register keyword, or letting the compiler optimize) rather than repeatedly reading from RAM.
Von Neumann vs. Harvard Architecture
This distinction is one of the most exam-relevant ideas in this chapter, and it directly explains a design choice in almost every MCU you'll use.
- Von Neumann architecture: program instructions and data share the same memory space and the same bus. Simpler to design, but the CPU cannot fetch the next instruction and read/write data in the same cycle (a bottleneck called the "von Neumann bottleneck").
- Harvard architecture: program memory (flash) and data memory (SRAM) are physically separate, with separate buses. The CPU can fetch the next instruction while simultaneously reading or writing data — improving throughput.
Nearly all modern MCUs (AVR, PIC, ARM Cortex-M) use a modified Harvard architecture: separate flash and SRAM address spaces internally, but often a unified view exposed to the programmer. This is why, on an Arduino, you must explicitly use PROGMEM to store a constant array in flash instead of SRAM — the compiler needs to know which memory space (and therefore which bus and access method) to target.
Types of Microprocessors/Architectures
| Architecture family | Where it's used | Examples |
|---|---|---|
| x86 / x86-64 | Desktop and laptop PCs | Intel Core i7, AMD Ryzen 9 |
| ARM (Cortex-A, application class) | Smartphones, Raspberry Pi's SoC, tablets | Apple M-series, Qualcomm Snapdragon, Cortex-A72 |
| ARM (Cortex-M, microcontroller class) | Embedded MCUs | STM32, Nordic nRF52 |
| RISC-V | Emerging open-standard embedded and application processors | ESP32-C3, SiFive cores |
| AVR | Classic hobbyist microcontroller boards | Arduino Uno's ATmega328P |
The important exam distinction: Cortex-A cores (application processors, need an MMU and usually run Linux/Android) are microprocessor-class, while Cortex-M cores (microcontroller) are the ones embedded inside true MCUs like the STM32 family. Both are "ARM," but they serve very different roles.
Pipelining: Making the Cycle Faster Without Changing It
A non-pipelined CPU does fetch, then decode, then execute, one instruction fully finishing before the next one starts — like one customer completely finishing checkout before the next customer even walks up.
A pipelined CPU overlaps stages: while instruction 1 is executing, instruction 2 is being decoded, and instruction 3 is being fetched — like a checkout line where scanning, bagging, and payment for different customers happen in parallel stages.
Pipelining does not reduce the latency of a single instruction, but it dramatically increases throughput (instructions completed per second). ARM Cortex-M3, for example, uses a 3-stage pipeline. The tradeoff is complexity: branches (if/else, function calls) can force the pipeline to flush and restart, called a "pipeline hazard" or "branch misprediction penalty."
Common Misunderstanding
Students often think pipelining makes each individual instruction execute faster. It doesn't — it lets multiple instructions be in different stages simultaneously, improving overall throughput, not single-instruction latency.
Advanced Concepts (Brief Overview)
- Superscalar execution — issuing more than one instruction per clock cycle by having multiple execution units (multiple ALUs). Common in desktop/server CPUs, rare in MCUs due to cost and power.
- Out-of-order execution — reordering instructions to avoid stalls while the results are checked for correctness afterward. Found in high-performance CPUs, essentially never in MCUs (predictability matters more than raw speed for real-time control).
- Multi-core processors — multiple CPU cores on one chip for parallel execution. Some MCUs are now dual-core (e.g., RP2040 in the Raspberry Pi Pico) specifically to dedicate one core to time-critical I/O and another to application logic.
Key Terms
| Term | Definition |
|---|---|
| ALU (Arithmetic Logic Unit) | The CPU block that performs arithmetic and logic operations |
| Control Unit (CU) | The CPU block that decodes instructions and generates control signals |
| Register | Fast, small storage location physically inside the CPU (e.g., PC, accumulator, general-purpose registers) |
| Program Counter (PC) | A register holding the memory address of the next instruction to fetch |
| Instruction Register (IR) | Holds the currently fetched instruction while it is decoded and executed |
| Address bus | Carries memory addresses from CPU to memory/I/O (unidirectional) |
| Data bus | Carries the actual data being read or written (bidirectional) |
| Control bus | Carries control signals such as read/write and interrupt requests |
| Instruction Set Architecture (ISA) | The complete set of instructions a processor understands (e.g., ARMv7-M, AVR instruction set) |
| Pipelining | Overlapping the fetch/decode/execute stages of consecutive instructions to increase throughput |
| Von Neumann architecture | Design where program and data share one memory space and bus |
| Harvard architecture | Design where program memory and data memory have separate address spaces/buses |
Common Mistakes
-
Misconception: "The ALU executes the whole program." Why it's wrong: Students conflate "does the computing" with "runs the program." Correct explanation: The ALU only performs arithmetic/logic on data handed to it by the control unit; the control unit is what sequences instructions, decodes them, and directs data flow.
-
Misconception: "Pipelining makes each instruction complete faster." Why it's wrong: The word "faster" is ambiguous between latency and throughput. Correct explanation: A single instruction still takes the same number of pipeline stages to complete (same latency); pipelining increases the number of instructions completed per unit time (throughput) by overlapping stages of different instructions.
-
Misconception: "Von Neumann and Harvard architecture are old, irrelevant history." Why it's wrong: These terms sound academic, so students assume they don't apply to real chips they use. Correct explanation: Nearly every AVR, PIC, and ARM Cortex-M microcontroller in active use today is a modified Harvard architecture, with real, practical consequences (e.g., needing
PROGMEMin Arduino to place data in flash instead of SRAM).
Comparison and Connections
| Aspect | Von Neumann | Harvard (modified, used in most MCUs) |
|---|---|---|
| Program & data memory | Same memory space, same bus | Separate memory spaces, separate buses |
| Simultaneous fetch + data access | No (bottleneck) | Yes |
| Design complexity | Simpler | Slightly more complex |
| Used in | x86 desktop CPUs (conceptually) | AVR, PIC, ARM Cortex-M |
| Aspect | Microprocessor (this chapter) | Microcontroller (Chapter 1) |
|---|---|---|
| Focus | Internal CPU architecture: ALU, CU, buses, pipeline | Whole-chip integration: CPU + memory + peripherals |
| Contains memory/IO on-chip? | No (MPU) | Yes (MCU) |
| What you study here | How instructions actually execute | What a complete embedded chip looks like |
Practice Questions
Recall
- Name the three stages of the fetch-decode-execute cycle and briefly describe what happens in each. Answer guidance: Fetch — read instruction from memory using the PC; Decode — interpret the opcode/operands; Execute — the ALU or control unit performs the operation.
- List the three types of buses in a microprocessor system and what each carries. Answer guidance: Address bus (memory address, CPU to memory), data bus (actual data, bidirectional), control bus (read/write and interrupt signals, bidirectional).
Understanding 3. Explain why the Program Counter must be incremented during the fetch stage, before the instruction is even decoded. Answer guidance: So that when the current instruction finishes (unless it's a branch/jump that explicitly changes the PC), the CPU already knows the address of the next sequential instruction to fetch, keeping the pipeline moving without delay. 4. Explain, using the von Neumann bottleneck, why Harvard architecture improves performance in MCUs. Answer guidance: In von Neumann, fetching an instruction and reading/writing data compete for the same bus, so they can't happen simultaneously. Harvard's separate buses let instruction fetch and data access happen in the same cycle, increasing throughput.
Application
5. You're debugging embedded C code where a loop counter stored in a global variable increments unexpectedly slowly compared to a local variable kept in a register. Using what you know about registers vs. memory buses, explain the likely cause.
Answer guidance: The local variable can be kept in a CPU register (near-zero access time), while the global variable must be loaded from and stored to SRAM over the data bus each iteration, adding multiple clock cycles per access.
6. An embedded systems job posting requires "experience with Harvard architecture MCUs and PROGMEM." Explain in your own words what a candidate needs to understand to satisfy this requirement.
Answer guidance: Understanding that program memory (flash) and data memory (SRAM) are separate on AVR/Harvard-style MCUs, and that constant data placed in PROGMEM must be read with special instructions (e.g., pgm_read_byte) because it lives in a different address space than normal variables.
Analysis 7. Compare Cortex-A and Cortex-M ARM cores and explain why only one of them is considered "microcontroller-class." Answer guidance: Cortex-A cores are application processors with MMUs designed to run full OSes like Linux/Android (microprocessor-class, e.g., Raspberry Pi's SoC); Cortex-M cores are lightweight, deterministic, low-power cores designed to be embedded directly in single-chip MCUs like the STM32 family. 8. A CPU designer proposes removing the pipeline from a Cortex-M3-based product to "simplify the design." Analyze the tradeoffs of this decision. Answer guidance: Removing the pipeline would simplify timing analysis and eliminate pipeline hazards/branch penalties, but would substantially reduce instruction throughput since stages could no longer overlap — a poor tradeoff unless the application is extremely simple and power/cost-constrained.
FAQ
Q1: Is a "core" the same thing as a microprocessor? Roughly — a "core" is one instance of the fetch-decode-execute machinery (ALU, control unit, registers). A "multi-core" chip has several of these on one die, each capable of running instructions independently.
Q2: Why do MCUs rarely use out-of-order execution like desktop CPUs? Out-of-order execution adds complexity, power draw, and unpredictable timing — the opposite of what real-time embedded control needs. MCUs prioritize deterministic, predictable timing over raw throughput.
Q3: What does "32-bit" actually refer to in "32-bit microprocessor"? It typically refers to the width of the general-purpose registers and/or the data bus — how many bits of data the ALU processes and moves per operation. A 32-bit ARM Cortex-M can add two 32-bit numbers in one instruction; an 8-bit AVR needs multiple instructions to do the same 32-bit addition.
Q4: Why does my compiled C code produce more assembly instructions than I expect? Complex C expressions and operations not directly supported in hardware (like division on some 8-bit MCUs) get broken into multiple simpler machine instructions, each going through its own fetch-decode-execute cycle.
Q5: Do I need to learn assembly language to understand microprocessor architecture?
You don't need to write production assembly, but being able to read a short disassembly (which most IDEs and tools like avr-objdump or arm-none-eabi-objdump can generate) is extremely valuable for understanding timing, debugging hard faults, and optimizing critical code paths.
Quick Revision
- Every CPU repeats fetch → decode → execute, driven by the clock and the Program Counter
- ALU does the math/logic; Control Unit sequences and decodes; Registers are the fastest on-chip storage
- Three buses: address (where), data (what), control (how — read/write/interrupt signals)
- Von Neumann = shared program/data memory and bus (bottleneck); Harvard = separate buses, used in most MCUs
- Most real MCUs (AVR, PIC, ARM Cortex-M) use modified Harvard architecture
- Pipelining overlaps instruction stages to boost throughput, not single-instruction latency
- Cortex-A = microprocessor-class (runs OS); Cortex-M = microcontroller-class (embedded, deterministic)
- Superscalar and out-of-order execution boost desktop CPU performance but are rare in MCUs due to power/predictability tradeoffs
- Multi-core MCUs (e.g., RP2040) let one core handle timing-critical I/O while another runs application logic
- A single C statement often compiles into several assembly instructions, each its own fetch-decode-execute cycle
Related Topics
Prerequisites: Introduction to Microcontrollers, basic binary/hexadecimal number systems, basic digital logic
Related Topics: Digital Logic Design, Computer Organization, Instruction Set Architecture
Next Topics: Programming Microcontrollers, Microcontroller Peripherals