1.6 KiB
1.6 KiB
Phase 7 - Memory-Mapped UART
Context
This phase connects software-visible memory addresses to a peripheral. UART becomes the first external communication path driven by CPU instructions.
Goals
- Build standalone TX and RX UART blocks.
- Map UART registers into the D-bus address space.
- Print a message from software running on the CPU.
New Concepts
- MMIO: memory-mapped I/O; device registers accessed with normal loads/stores.
- Address decoder: logic routing addresses to selected slaves.
- Status register: read-only register exposing peripheral state.
- FIFO: queue buffering bytes between producer and consumer.
How To Think About It
The CPU should not know about UART internals. It issues stores and loads; the bus decoder and peripheral register file translate those into device behavior.
Learning Tasks
- Draw the UART register map.
- Decide what happens if software writes while TX is busy.
- Decide when RX data is consumed and status changes.
Pitfalls
- Making register side effects ambiguous.
- Forgetting software must poll status before writes.
- Combining peripheral timing with CPU timing too tightly.
Tooling And Testing
- Verify UART standalone before MMIO integration.
- Use a terminal for end-to-end tests and ILA for bus/peripheral mismatches.
- Keep register behavior documented for firmware authors.
References
- Digilent Arty A7 USB-UART notes: https://digilent.com/reference/programmable-logic/arty-a7/reference-manual
- RISC-V platform-level interrupt spec for later context: https://github.com/riscv/riscv-plic-spec
- Memory-mapped I/O overview: https://en.wikipedia.org/wiki/Memory-mapped_I/O