Why a dedicated I/O module is necessary, how external devices are classified, the five functions of an I/O module, I/O commands, and the two addressing schemes — memory-mapped and isolated I/O. The foundation for understanding the three I/O techniques in CA-09.
The third key element of a computer system — alongside CPU and memory — is the set of I/O modules. Each I/O module sits between the system bus and one or more external peripheral devices, acting as an intermediary that bridges the two worlds.
Why not connect peripherals directly to the system bus? Four compelling reasons make this impractical:
| # | Problem | Explanation |
|---|---|---|
| 1 | Variety of devices | There are hundreds of peripheral types with completely different operating principles. Incorporating control logic for all of them directly in the CPU would make it impossibly complex. |
| 2 | Speed mismatch | Peripherals are orders of magnitude slower than the CPU and system bus. A keyboard generates a byte every ~100 ms; a CPU executes ~10⁹ instructions per second. Tying the high-speed bus to a slow device would stall all other components. |
| 3 | Data format mismatch | Peripherals use different word lengths, encoding formats, and voltage levels than the computer. Serial devices (UART, USB, SPI) send one bit at a time while the CPU works with 32 or 64-bit words simultaneously. |
| 4 | Error and status management | Peripherals generate error conditions (paper jam, bad sector, CRC error, cable disconnected) that require detection and reporting. Without a dedicated module, the CPU would need to poll every device constantly. |
External devices (peripherals) are broadly classified into three categories based on their communication partner and purpose:
Three categories of external devices. Human-readable devices interact with users. Machine-readable devices interact with other hardware (storage, sensors, actuators). Communication devices exchange data with remote systems. Data rates span six orders of magnitude — from a keyboard (10 bytes/s) to a display frame buffer (30 GB/s).
Every external device, regardless of type, contains the same fundamental internal structure:
Internal structure of any external device. The Control Logic receives commands from the I/O module, reports device status, and manages the data buffer. The Transducer converts between the digital electrical signals inside the device and the physical phenomenon in the environment. The data buffer absorbs speed mismatches.
The I/O module sits permanently on the system bus, connecting the computer’s internal world (CPU and memory) to the external world (peripheral devices). It is not a passive connector — it contains active logic that manages communication in both directions.
System-level view. I/O Module 1 controls a printer and keyboard; I/O Module 2 controls a disk and network card. Each module contains Control, Status, and Data buffer registers visible to the CPU via the system bus. Each I/O module has a unique address on the bus so the CPU can target commands to specific devices.
An I/O module performs five major functions:
| # | Function | What it does | Why it matters |
|---|---|---|---|
| 1 | Control & Timing | Coordinates data flow between CPU/memory resources and peripheral devices. Arbitrates between competing requests. Manages the sequence of I/O operations. | CPU only issues high-level commands — the I/O module handles all the detailed timing and sequencing with the slow device. |
| 2 | CPU Communication | Responds to CPU commands (read, write, test). Reports status via BUSY/READY/ERROR signals. Recognises its own address on the address bus. | CPU can check device readiness or issue commands without needing to know the device’s internal workings. |
| 3 | Device Communication | Sends commands to the peripheral. Receives status information. Exchanges data using device-specific protocols (serial bit stream, parallel byte, SCSI commands, etc.). | CPU is completely isolated from device-specific protocols — it never handles serial-to-parallel conversion, SCSI commands, or analog signals. |
| 4 | Data Buffering | Temporarily stores data moving in both directions. Accepts fast bursts from memory and feeds them slowly to the printer; buffers slow trickles from keyboard and delivers them efficiently to memory. | Without buffering, either the fast device (memory bus) would stall waiting for the slow device, or data would be lost. |
| 5 | Error Detection | Detects mechanical failures (paper jam, bad disk sector, cable disconnect) and transmission errors (parity errors). Reports errors to CPU via status register. | Error handling is centralised in the I/O module — CPU does not need polling logic for every possible error condition on every device. |
I/O module internal registers. The Address Decoder recognises the module’s unique address on the bus. Status Register holds BUSY/READY/ERROR flags readable by CPU. Control Register holds the last command from CPU. Data Register holds the byte(s) being transferred. The Control Logic orchestrates all interactions and drives the IRQ line when the module needs CPU attention.
When the CPU communicates with an I/O module, it issues commands over the control bus. Four classes of commands exist:
| Command class | Purpose | Example |
|---|---|---|
| Control | Activates the peripheral and tells it to do something specific. Device-dependent. | Spin up disk, seek to track 42, rewind tape, reset printer, turn on motor |
| Test | Checks status of the I/O module and peripheral. CPU polls the status register. | Is device ready? Is there a paper jam? Is power on? Did a CRC error occur? |
| Read | Causes the I/O module to obtain a unit of data from the peripheral and place it in the data register for the CPU to collect. | Read one byte from keyboard, read a sector from disk, receive a byte from UART |
| Write | Causes the I/O module to take data from the data bus and transmit it to the peripheral. | Send a byte to UART, write a sector to disk, send a pixel to display controller |
There are two strategies for how I/O devices are addressed by the CPU:
Scenario: A CPU with a 32-bit address bus needs to communicate with 4 GB of DRAM and also control a UART, a display controller, and a GPIO bank.
Memory-Mapped I/O approach: Reserve part of the 32-bit address space (e.g. 0xF000_0000–0xFFFF_FFFF) for I/O registers. UART status at 0xF000_0000, UART data at 0xF000_0004, GPIO at 0xF001_0000. CPU uses normal LDR/STR instructions to access them — same as reading/writing a memory location. No special I/O instructions needed.
Isolated I/O approach: Separate I/O address space accessed only with special IN/OUT instructions (as in x86). UART port 0x3F8, keyboard port 0x60. I/O and memory have separate address spaces of (potentially) different widths.
Memory-mapped I/O (left): I/O registers and RAM share the same 32-bit address space. Normal load/store instructions access devices — no special I/O instructions needed. Isolated I/O (right): separate address spaces for memory and I/O ports. Special IN/OUT instructions switch to I/O space. x86 uses isolated I/O; modern ARM SoCs use memory-mapped I/O exclusively.
| Aspect | Memory-Mapped I/O | Isolated I/O |
|---|---|---|
| Address space | Shared with RAM — I/O uses part of memory map | Completely separate I/O port space |
| Instructions needed | Normal load/store (LDR, STR, MOV) | Special IN/OUT instructions |
| Protection/isolation | OS can protect I/O regions with MMU page permissions | Hardware-separate — no MMU needed to isolate I/O |
| Available memory space | Reduced — I/O registers consume part of 4 GB map | Full memory space available for RAM |
| Instruction richness | All memory instructions work on I/O (bit-set, compare, etc.) | Limited — only IN and OUT |
| Used by | ARM, RISC-V, MIPS, most RISC architectures | x86 (IN/OUT instructions, ports 0–0xFFFF) |
One of the central challenges of I/O design is the enormous range of data rates across different devices:
| Device | Behaviour | Typical data rate | Notes |
|---|---|---|---|
| Keyboard | Input | 0.01 KB/s | Human-limited — ~10 chars/sec max |
| Mouse | Input | 0.02 KB/s | Position updates at ~125 Hz |
| Voice input | Input | 0.02 KB/s | 8-bit audio at 8 kHz = 8 KB/s raw |
| Scanner | Input | 200 KB/s | Higher for professional scanners |
| Line printer | Output | 1 KB/s | ~100 chars/sec mechanical |
| Laser printer | Output | 100 KB/s | Page description language processing |
| Graphics display | Output | 30,000 KB/s | 4K at 60 Hz: ~3 GB/s to frame buffer |
| Network LAN | Input/Output | 200 KB/s | 10 Mbit/s Ethernet (legacy); Gigabit = 125 MB/s |
| Magnetic disk | Storage | 2,000 KB/s | Modern HDD: 100–200 MB/s; NVMe SSD: 3,500 MB/s |
Every ARM-based SoC uses memory-mapped I/O exclusively. When you open the Technical Reference Manual (TRM) or datasheet for any SoC (STM32, Raspberry Pi BCM2711, Qualcomm Snapdragon), you find a memory map table listing every peripheral register at its fixed address: UART0 at 0x02100000, SPI0 at 0x02101000, GPIO at 0x02200000, and so on. The five I/O module functions you learned here are all implemented in the peripheral’s register interface. When you write a device driver or verify a peripheral IP, you are programming the same conceptual register model described in this article.
In SoC RTL design, the I/O module is an IP block connected to the AMBA APB or AXI-Lite bus. Each peripheral IP — UART, SPI controller, I²C master, PWM, ADC controller — implements the I/O module concept in hardware: address decoder, control/status/data registers, interrupt generation, and a device-specific protocol state machine. The peripheral IP’s register interface is defined by a register map specification (often in IP-XACT format), which tools like IPGEN and Arm’s SoCDesigner use to auto-generate the APB interconnect fabric and documentation.
The wide range of I/O data rates directly influences hardware design decisions. The data buffer inside an I/O module is a FIFO — the same asynchronous FIFO studied in sequential logic design. For a UART at 115,200 baud (~11.5 KB/s) serviced by the CPU via interrupts every 1 ms, the FIFO needs to hold ~11.5 bytes between interrupts — a 16-byte FIFO is standard. For a PCIe NVMe SSD at 3.5 GB/s doing DMA transfers, the FIFO and DMA engine must be designed for burst sizes of 4 KB or more. Every I/O peripheral IP specification starts with the target data rate and derives FIFO depth, burst size, and DMA granularity from it.