CA-05: Interrupts & the Instruction Cycle β€” VLSI Trainers
VLSI Trainers CA Series Β· 5 / 12
Computer Architecture Β· Article 5 of 12

CA-05: Interrupts & the Instruction Cycle

How the CPU executes instructions one at a time, what an interrupt is and why it dramatically improves efficiency, instruction cycle state diagrams with and without interrupts, and how multiple interrupts are handled through sequential and nested schemes.

πŸ”„The Basic Instruction Cycle

A CPU executes programs by repeating one elementary operation over and over, billions of times per second. That operation is called the instruction cycle β€” the complete sequence of steps required to fetch one instruction from memory and execute it.

In its simplest form, the instruction cycle has exactly two steps:

β‘  FETCH CYCLE

The CPU reads the next instruction from the memory location pointed to by the Program Counter (PC). The instruction is loaded into the Instruction Register (IR). PC is incremented to point to the following instruction.

β‘‘ EXECUTE CYCLE

The CPU interprets the instruction in IR and performs the required operation β€” an arithmetic calculation, a memory read/write, a branch, or an I/O command. This may itself involve multiple sub-steps.

This two-step loop repeats continuously until the machine is turned off, a halt instruction is encountered, or an unrecoverable error occurs.

The fetch cycle is identical for every instruction. It always reads from the address in PC, loads into IR, and increments PC. Only the execute cycle differs β€” it depends on the specific instruction being executed (ADD vs LOAD vs JUMP vs OUT).

πŸ“₯Fetch Cycle in Detail

The fetch cycle involves a precise sequence of register transfers. At the micro-architecture level, these are the steps:

  1. MAR ← PC   (copy Program Counter to Memory Address Register β€” puts the instruction address on the address bus)
  2. MBR ← Memory[MAR]   (read the instruction from memory into the Memory Buffer Register)
  3. PC ← PC + 1   (increment PC to point to the next instruction β€” unless this instruction is a branch)
  4. IR ← MBR   (copy instruction from MBR into the Instruction Register, ready for decode)
RegisterNameRole in fetch cycle
PCProgram CounterHolds the address of the next instruction. Updated after every fetch.
MARMemory Address RegisterHolds the address sent out on the address bus. Loaded from PC at start of fetch.
MBRMemory Buffer RegisterReceives the instruction word returned from memory on the data bus.
IRInstruction RegisterHolds the current instruction being decoded and executed. Loaded from MBR.
Instruction prefetching: Modern CPUs don’t wait for the execute cycle to finish before fetching the next instruction. During execution of instruction N, the pipeline fetches instruction N+1 and even decodes N+2. This is instruction-level parallelism β€” the basis of pipelined CPU design covered in CA-10.

βš™οΈExecute Cycle in Detail

The execute cycle’s behaviour depends entirely on which instruction is in IR. The four broad categories of operations:

Execute cycle categoryWhat happensExample instruction
Processor–MemoryData transferred between CPU and main memory. MAR carries the address; MBR carries the data.LOAD R1, [0x100] β€” read memory address 0x100 into register R1
Processor–I/OData transferred between CPU and an I/O module. Address identifies the I/O port; data moves via MBR.OUT 0x3F8, R2 β€” write R2 to UART port 0x3F8
Data ProcessingArithmetic or logical operation on register values. ALU performs the operation; result and flags updated.ADD R1, R2, R3 β€” R1 ← R2 + R3; update N, Z, C, V flags
ControlAlters the sequential flow of execution by writing a new value to PC.JMP 0x200 β€” PC ← 0x200, next fetch comes from 0x200

πŸ“ŠInstruction Cycle State Diagram β€” Without Interrupts

Figure 1 β€” Instruction cycle state diagram (no interrupts)
START Fetch IR ← Memory[PC]; PC++ Decode CU interprets IR opcode Execute ALU op / mem access / branch Halt HLT instruction or error always not HALT HLT next loop vlsitrainers.com

Instruction cycle without interrupts. The CPU loops continuously: Fetch β†’ Decode β†’ Execute β†’ Fetch β†’ … until a HLT instruction or unrecoverable error occurs. At 3 GHz with average CPI=1, this loop runs 3 billion times per second.

πŸ’‘Why Interrupts Exist

Consider what happens without interrupts when the CPU needs to print a string to a printer:

  1. CPU sends one character to the printer controller (WRITE to I/O port)
  2. CPU must wait for the printer to finish β€” a mechanical printer takes ~1 ms per character
  3. At 1 GHz, 1 ms = 1,000,000 clock cycles wasted doing nothing
  4. CPU sends next character. Waits again. And again.

This approach β€” polling (or programmed I/O) β€” wastes the CPU. For every useful instruction executed to set up the print, a million instruction cycles are consumed in an idle loop checking whether the printer is ready.

The interrupt solution: Instead of polling, the CPU starts the I/O operation and then continues executing other useful work. When the I/O device finishes and is ready for more data, it sends an interrupt request (IRQ) signal to the CPU. The CPU then briefly pauses its current work, services the device (sends the next character), and resumes where it left off. The printer’s 1 ms wait is filled with 1 million useful instructions instead of 1 million idle poll loops.
Figure 2 β€” CPU time utilisation: polling vs interrupt-driven I/O
Without interrupts (polling) β€” CPU mostly idle user IO polling / idle β€” CPU wasted (1 million cycles) polling / idle again polling / idle again With interrupts β€” CPU executes useful work during I/O wait CPU I/O IRQ user IO continues executing user program β†’ ISR resumes user program β†’ ISR I/O device busy printing char 1 I/O device busy printing char 2 IRQ IRQ vlsitrainers.com

Without interrupts (top): the CPU polls and wastes millions of cycles between each I/O operation. With interrupts (bottom): the CPU initiates I/O, then continues executing useful work. When the I/O device asserts IRQ, the CPU briefly runs the ISR (purple), then resumes. I/O and CPU activity now overlap.

πŸ“‹Classes of Interrupts

Interrupts arise from different sources, classified into four main categories:

ClassSourceExamplesTypical handling
ProgramCPU executing an instructionArithmetic overflow, division by zero, illegal instruction, memory protection violationOS exception handler β€” may terminate the process or deliver a signal (e.g. SIGFPE)
TimerHardware timer inside the CPU or on the boardOS scheduler tick (every 1–10 ms), watchdog timer expiry, real-time clockOS scheduler β€” preempts current thread, runs next in queue (enables multitasking)
I/OI/O controller (printer, disk, network, keyboard)Printer ready for next character, disk sector read complete, keyboard key pressed, Ethernet packet arrivedDevice ISR β€” reads/writes data, may wake a blocked process, acknowledges the device
Hardware FailureSystem hardware detecting a faultPower failure (NMI), memory parity error, bus error, temperature warningEmergency handler β€” save state to stable storage, attempt graceful shutdown or recovery
Non-Maskable Interrupt (NMI): Hardware failure interrupts are typically non-maskable β€” they cannot be disabled by software. Even if the CPU has interrupts globally disabled (to protect a critical section), an NMI still fires. Power failure is the classic NMI: the CPU has nanoseconds to save critical state before voltage collapses.

πŸ”ƒInterrupt Cycle β€” How It Works

When an interrupt request arrives, the CPU handles it by executing an additional interrupt cycle at the end of the current execute cycle. The steps are:

  1. Check for interrupt: At the end of each execute cycle, the CPU checks the interrupt request line.
  2. Acknowledge: If an interrupt is pending and interrupts are enabled, the CPU asserts an interrupt acknowledge signal.
  3. Save context: The CPU saves the current PC (return address) and key registers (PSW β€” Program Status Word) onto the stack or into dedicated save registers.
  4. Load ISR address: PC is loaded with the starting address of the appropriate Interrupt Service Routine (ISR). This address comes from an interrupt vector table.
  5. Execute ISR: The ISR runs as a normal program β€” it services the device, clears the interrupt flag, and returns.
  6. Restore context: At the end of the ISR, a return-from-interrupt instruction (RTI or IRET) restores the saved PC and registers.
  7. Resume: Execution of the interrupted program continues from exactly where it was suspended β€” as if nothing happened.
The user program sees nothing: From the perspective of the user program, the interrupt is completely transparent. The program did not call the ISR and does not know it ran. Context save/restore ensures the program’s registers and flags are unchanged when it resumes.
πŸ” Worked Example β€” Interrupt context save/restore

Scenario: User program is executing at PC=0x1050, R1=42, R2=17, FLAGS=0x04. An IRQ from the UART controller fires.

CPU interrupt cycle actions:

PUSH PC β†’ stack: saves 0x1050
PUSH PSW β†’ stack: saves FLAGS=0x04 (and mode bits)
PC ← IRQ_vector[UART] = 0x2000 (loaded from interrupt vector table)
[interrupts may be auto-disabled during ISR execution]

ISR at 0x2000 runs: reads UART data register, stores byte, clears interrupt flag in UART controller.

At ISR end β€” RTI instruction:

POP PSW β†’ FLAGS restored to 0x04
POP PC β†’ PC restored to 0x1050
[interrupts re-enabled]

Result: User program resumes at 0x1050 with R1=42, R2=17, FLAGS=0x04 β€” exactly as if no interrupt had occurred.

πŸ“ŠInstruction Cycle State Diagram β€” With Interrupts

Figure 3 β€” Instruction cycle state diagram with interrupt cycle added
START Fetch IR ← Mem[PC]; PC++ Decode CU interprets opcode Execute ALU / mem / branch IRQ ? Interrupt Save ctx; run ISR; restore Halt HLT / error not HLT HLT No IRQ β†’ fetch next IRQ! RTI β€” restore context, resume at saved PC Interrupts disabled? β†’ skip check vlsitrainers.com

Instruction cycle with interrupt cycle. After every Execute state, the CPU checks for pending interrupt requests (IRQ? diamond). If none, it loops back to Fetch as before. If an IRQ is pending and interrupts are enabled, the CPU enters the Interrupt state β€” saves context, runs the ISR, restores context β€” then returns to Fetch.

↗️Transfer of Control via Interrupts

Figure 4 β€” Transfer of control: user program β†’ ISR β†’ user program resume
User Program I/O Operation ISR (Interrupt Handler) t0 t↓ A1: compute R1 = R2 + R3 A2: WRITE β†’ printer (start I/O) I/O device busy printing character (~1 ms = millions of CPU cycles) ↓ done β†’ IRQ! A3: store R4, [0x200] A4: branch to L1 A5: cmp R5, #0 IRQ fires β€” CPU enters interrupt cycle after completing current instruction ← user program suspended (context saved) ISR: read status reg ISR: send next char RTI β€” restore context A6: add R6, R7, R8 (resumes) vlsitrainers.com

Transfer of control timeline. While the user program runs instructions A3–A5, the I/O device operates concurrently. When the device asserts IRQ, the CPU completes its current instruction then enters the interrupt cycle. The ISR runs, services the device, and RTI restores context. The user program resumes at A6 with no awareness of the interruption.

🎚️Multiple Interrupts

What happens when a second interrupt arrives while the CPU is already handling a first interrupt? There are two approaches:

SEQUENTIAL (Disable-on-entry)
  • CPU disables interrupts upon entering any ISR
  • New IRQs remain pending in hardware
  • After ISR returns and re-enables interrupts, pending IRQ is processed
  • Simple β€” no nesting, no re-entrancy issues
  • Problem: high-priority IRQ waits behind lower-priority ISR
NESTED (Priority-based)
  • Each interrupt has a priority level
  • A higher-priority IRQ can interrupt a lower-priority ISR
  • Context is saved nested on the stack (stack frames)
  • Higher-priority ISR completes first, then lower-priority ISR resumes
  • Used in real-time systems where critical events cannot wait
Figure 5 β€” Sequential vs nested interrupt handling: time sequence
Sequential: interrupts disabled during ISR β€” lower priority waits User program IRQ X ISR X (int disabled) IRQ Y (pending) Y waits ISR Y (now runs) User program resumes Sequential order: X then Y Nested: high-priority interrupt preempts lower-priority ISR User prog IRQ X (low) ISR X begins IRQ Y (HIGH) ISR Y (high pri) β€” nested ISR X resumes User program resumes Y serviced first, X then User Stack frames during nested interrupts User program context (PC, R0–R15) ISR X context (PC, R0–R15) ISR Y running ← stack top ← SP (stack pointer) Stack grows down β†’ vlsitrainers.com

Sequential interrupts (top): IRQ Y arrives during ISR X but must wait until ISR X completes and re-enables interrupts. Nested interrupts (bottom): IRQ Y (high priority) immediately preempts ISR X. ISR Y runs, returns, then ISR X resumes. The stack holds nested context frames β€” this is why the processor stack is critical hardware infrastructure, not just a software abstraction.

Priority levels and interrupt controllers: Real systems use a dedicated Interrupt Controller (e.g. Intel 8259A PIC, ARM GIC β€” Generic Interrupt Controller) to manage multiple IRQ lines, assign priorities, mask individual sources, and present one vectored request to the CPU. The GIC in ARM-based SoCs supports up to 1020 interrupt sources with configurable priorities, edge vs level triggering, and per-CPU routing.

πŸ”¬VLSI Connections

πŸ”¬ ARM GIC β€” Generic Interrupt Controller in every SoC

Every ARM-based SoC (Cortex-A smartphone processor, Cortex-M microcontroller, server CPU) implements the Generic Interrupt Controller (GIC) specification. The GICv3/v4 supports up to 1020 shared peripheral interrupts (SPIs), 16 software-generated interrupts (SGIs) per CPU core, and per-core private peripheral interrupts (PPIs). Each interrupt has a configurable priority (0–255), edge or level trigger type, and a target CPU affinity mask. When you work on SoC integration or verification, you configure the GIC register map, verify that each peripheral’s IRQ line reaches the correct GIC SPI input, and write testcases that fire interrupts and confirm the correct ISR vector is invoked.

πŸ”¬ The instruction cycle β†’ CPU pipeline stages

The Fetch–Decode–Execute cycle maps directly to pipeline stages in a modern CPU. A 5-stage pipeline (Fetch, Decode, Execute, Memory, Writeback) runs five instructions simultaneously β€” one in each stage. Interrupts in a pipelined CPU must flush in-flight instructions from the pipeline before entering the ISR β€” the pipeline drain is the hardware equivalent of completing the current instruction before taking an interrupt, which is exactly what the state diagram shows.

πŸ”¬ Interrupt-driven I/O β†’ DMA β†’ the path to CA-09

This article introduced interrupt-driven I/O as an improvement over polling. But even interrupt-driven I/O requires the CPU to execute ISR code for every chunk of data transferred. The next step, covered in CA-09, is DMA (Direct Memory Access): a dedicated DMA controller takes over the data transfer entirely, moving data from I/O device to memory without CPU involvement. The CPU only receives a single interrupt when the entire transfer is complete.

Summary β€” CA-05 key points: The instruction cycle has two steps: Fetch (IR ← Mem[PC]; PC++) and Execute (varies by instruction type: processor-memory, processor-I/O, data processing, or control). Without interrupts the CPU wastes millions of cycles polling slow I/O devices. Interrupts allow the CPU to perform useful work while I/O proceeds concurrently. The interrupt cycle saves context (PC, PSW), loads the ISR address from the interrupt vector table, runs the ISR, then restores context and resumes the original program transparently. Four interrupt classes: program, timer, I/O, hardware failure (NMI). Multiple interrupts handled sequentially (disable-on-entry) or nested (priority-based preemption).
System Bus & Bus Design ☰ CA Series Index Internal Memory
Scroll to Top