Add phase-by-phase tutorial notes

Add a Tutorial tree that mirrors the roadmap from Phase 0 through Linux bring-up.
Each phase and subphase gets a short learning note with consistent sections for
context, goals, new concepts, mental model, learning tasks, pitfalls, tooling,
testing, and references.

The tutorial material is intentionally explanatory rather than implementation
code. It gives a systems-oriented learner enough FPGA, SystemVerilog, RISC-V,
firmware, and Linux bring-up context to approach each roadmap phase without
turning the notes into copy-paste RTL.
This commit is contained in:
2026-04-28 12:11:23 +02:00
parent 8edfc86027
commit b008b37d49
43 changed files with 2110 additions and 0 deletions
@@ -0,0 +1,49 @@
# Phase 7.1 - UART TX Module
## Context
The TX module serializes bytes into start bit, data bits, and stop bit at a fixed baud
rate. It is a small timing-driven FSM.
## Goals
- Build a standalone transmitter.
- Learn baud-rate timing from the 50 MHz system clock.
- Verify busy/send behavior before CPU integration.
## New Concepts
- Baud rate: symbols per second on the serial line.
- Start bit: low bit marking beginning of a frame.
- Stop bit: high bit marking end of a frame.
- Bit timer: counter that holds each serial bit for the right number of clocks.
## How To Think About It
UART TX is a deterministic shift-and-timer machine. The hard part is not data structure;
it is exact timing and clean handoff from "send byte" to "busy."
## Learning Tasks
- Compute clocks per bit at 50 MHz and 115200 baud.
- Draw TX line waveform for one byte.
- Decide when `busy` asserts and deasserts.
## Pitfalls
- Off-by-one errors in the bit timer.
- Accepting a new byte before the previous frame has completed.
- Forgetting idle line is high.
## Tooling And Testing
- Simulate one byte and inspect the waveform.
- Test back-to-back bytes.
- On hardware, send a fixed message before involving the CPU.
## References
- Digilent Arty A7 reference: https://digilent.com/reference/programmable-logic/arty-a7/reference-manual
- UART framing overview: https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter
- Nandland UART tutorial: https://nandland.com/uart-serial-port-module/
@@ -0,0 +1,49 @@
# Phase 7.2 - UART RX Module
## Context
The RX module samples an asynchronous serial input and reconstructs bytes. It must handle
input synchronization and sampling near bit centers.
## Goals
- Build a standalone receiver.
- Learn oversampling and input synchronization.
- Produce a received byte plus valid indication.
## New Concepts
- Asynchronous input: signal not aligned to the FPGA clock.
- Synchronizer: flip-flop chain reducing metastability risk.
- Metastability: temporary uncertain state when sampling near an input transition.
- Oversampling: sampling multiple times per bit period to find stable centers.
## How To Think About It
RX is less forgiving than TX because the external signal is not clocked by your FPGA.
Respect clock-domain boundary hygiene even for a slow UART pin.
## Learning Tasks
- Draw how a start bit is detected.
- Decide the sample point for each data bit.
- Define what `valid` means and how it is cleared.
## Pitfalls
- Sampling the RX pin without synchronization.
- Sampling too close to bit transitions.
- Losing bytes because there is no buffering or clear valid/ready policy.
## Tooling And Testing
- Simulate with ideal frames and then slightly shifted frames.
- Test receiver behavior with back-to-back bytes.
- Add a FIFO later if software cannot poll fast enough.
## References
- Metastability overview: https://www.01signal.com/verilog-design/clockdomains/crossing-basics/
- Nandland UART receiver tutorial: https://nandland.com/uart-serial-port-module/
- Digilent Arty A7 reference: https://digilent.com/reference/programmable-logic/arty-a7/reference-manual
@@ -0,0 +1,49 @@
# Phase 7.3 - Bus Decoder + MMIO
## Context
The D-bus now routes requests to either RAM or UART registers. This is the first small
SoC-style memory map.
## Goals
- Decode address ranges for RAM and UART.
- Implement UART TX, RX, and status registers.
- Preserve the D-bus handshake contract.
## New Concepts
- Address map: assignment of address ranges to memory or devices.
- Register side effect: read or write that changes device state.
- Unmapped access: address with no valid target, later an access fault.
- Peripheral slave: bus endpoint that responds to device register accesses.
## How To Think About It
MMIO registers are a hardware/software ABI. Once firmware depends on them, changing
semantics becomes painful. Document behavior precisely.
## Learning Tasks
- Write a register table with access type and side effects.
- Decide read behavior for write-only registers and write behavior for read-only registers.
- Trace a store to UART TX through the D-bus decoder.
## Pitfalls
- Having two slaves respond to the same address.
- Letting no slave respond and hanging the bus forever.
- Making status bits unclear or inverted relative to software expectations.
## Tooling And Testing
- Unit-test the decoder separately from UART timing.
- Use ILA probes on selected slave, request, response, and UART status.
- Test unmapped access behavior once trap support exists.
## References
- OSDev MMIO overview: https://wiki.osdev.org/Memory_Mapped_Registers_in_C/C%2B%2B
- RISC-V privileged spec for access faults later: https://riscv.org/technical/specifications/
- Wishbone bus spec: https://cdn.opencores.org/downloads/wbspec_b4.pdf
@@ -0,0 +1,48 @@
# Phase 7.4 - Hello World
## Context
This is the first user-visible proof that software running on your CPU can communicate
with the outside world through MMIO.
## Goals
- Run a hand-written assembly program from instruction BRAM.
- Poll UART status and write bytes to TX data.
- Verify output in a terminal.
## New Concepts
- Polling: repeatedly reading status until a condition is true.
- Firmware: low-level software running directly on the hardware.
- Memory-mapped register access: using load/store instructions to control a device.
## How To Think About It
This milestone tests the full vertical slice: instruction fetch, decode, ALU, branches,
loads/stores, bus decode, UART, board pinout, and terminal settings.
## Learning Tasks
- Trace each instruction in the polling loop.
- Explain why the program waits for `tx_busy` to clear.
- Identify every hardware block involved in printing one character.
## Pitfalls
- Terminal configured for the wrong baud or line settings.
- Writing bytes without checking busy status.
- Debugging UART first when the actual bug is branch/load/store behavior.
## Tooling And Testing
- First verify UART standalone.
- In hardware, probe UART status and D-bus writes if the terminal is silent.
- Keep the program tiny and deterministic.
## References
- RISC-V assembly manual: https://github.com/riscv-non-isa/riscv-asm-manual
- Digilent Arty A7 reference: https://digilent.com/reference/programmable-logic/arty-a7/reference-manual
- UART overview: https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter
+49
View File
@@ -0,0 +1,49 @@
# 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
- OSDev MMIO overview: https://wiki.osdev.org/Memory_Mapped_Registers_in_C/C%2B%2B