Day 11: UART TX — Your First Communication Interface¶
Course: Accelerated HDL for Digital System Design¶
Week 3, Session 11 of 16¶
Student Learning Objectives¶
- SLO 11.1: Explain the UART protocol: start bit, 8 data bits, stop bit, baud rate, and framing.
- SLO 11.2: Derive baud rate timing from the 25 MHz Go Board clock and implement a baud rate generator.
- SLO 11.3: Implement a UART TX module using FSM + PISO shift register + baud generator architecture.
- SLO 11.4: Integrate UART TX into a top module that transmits data from the Go Board to a PC terminal.
- SLO 11.5: Verify UART TX behavior in simulation before programming hardware.
Pre-Class Video (~50 min)¶
| # | Segment | Duration | File |
|---|---|---|---|
| 1 | UART protocol: start bit, 8 data bits, stop bit, baud rate | 14 min | video/day11_seg1_uart_protocol.mp4 |
| 2 | Baud rate generation: deriving precise timing from a fast clock | 10 min | video/day11_seg2_baud_rate.mp4 |
| 3 | TX architecture: FSM + PISO shift register + baud generator | 16 min | video/day11_seg3_tx_architecture.mp4 |
| 4 | Connecting to a PC: USB-to-serial, terminal emulator setup | 10 min | video/day11_seg4_pc_connection.mp4 |
Session Timeline¶
| Time | Activity | Duration |
|---|---|---|
| 0:00 | Warm-up: UART protocol quiz, pre-class questions | 5 min |
| 0:05 | Mini-lecture: UART as FSM+datapath, baud math, live build | 30 min |
| 0:35 | Lab Exercise 1: UART TX implementation | 40 min |
| 1:15 | Break | 5 min |
| 1:20 | Lab Exercise 2: Single character on button press | 20 min |
| 1:40 | Lab Exercise 3: Transmit "HELLO" | 25 min |
| 2:05 | Lab Exercise 4 (Stretch): Hex-to-ASCII | 15 min |
| 2:20 | Wrap-up and Day 12 preview | 10 min |
In-Class Mini-Lecture (30 min)¶
UART as an FSM + Datapath Design Exercise (10 min)¶
- Everything from Weeks 1–2 comes together: FSMs, counters, shift registers, testbenches
- Block diagram: baud generator (counter), bit counter, shift register, FSM controller, TX output
- The FSM states: IDLE (TX high), START (TX low for 1 bit period), DATA (shift out 8 bits LSB first), STOP (TX high for 1 bit period)
Baud Rate Math (10 min)¶
- 25 MHz / 115200 = 217.01... ≈ 217 clocks per bit
- Rounding considerations: 217 gives actual baud = 115,207 Hz, error = 0.006% — well within tolerance
- Other baud rates: 9600 → 2604 clocks; 19200 → 1302 clocks
- Design decision: Parameterize
CLKS_PER_BITso the module works at any baud rate
Live Build (10 min)¶
- Walk through the UART TX code structure together
- Highlight the critical details: LSB first, start bit = 0, stop bit = 1, idle = 1
- Show the provided architecture diagram (distributed as a handout or on screen)
- Terminal setup: 115200 baud, 8N1, no flow control
Lab Exercises¶
Exercise 1: UART TX Implementation (40 min)¶
Objective (SLO 11.1, 11.2, 11.3, 11.5): Build a working UART transmitter from the architecture diagram.
Tasks:
1. Implement the UART TX module with:
- parameter CLKS_PER_BIT = 217 (115200 baud at 25 MHz)
- Inputs: clk, rst, tx_start, tx_data[7:0]
- Outputs: tx_out, tx_busy
- FSM: IDLE → START → DATA (8 bits) → STOP → IDLE
- Baud rate counter for bit-period timing
- Bit counter (0–7) for tracking which data bit to send
2. Simulate first: Write a testbench that:
- Sends the byte 8'h41 (ASCII 'A')
- Verifies the TX line goes: IDLE(1) → START(0) → D0 D1 D2 D3 D4 D5 D6 D7 → STOP(1)
- Verify tx_busy is asserted during transmission
- Use a short CLKS_PER_BIT value (e.g., 4) for fast simulation
3. View waveforms in GTKWave. Verify the bit timing.
Checkpoint: Simulation shows correct UART TX waveform for 'A' (0x41).
Exercise 2: Single Character on Button Press (20 min)¶
Objective (SLO 11.4): Get the first character from the Go Board to the PC.
Tasks:
1. Create a top module that:
- Debounces a button (reuse Day 5 module)
- On button press, loads ASCII 'A' (or any character) and asserts tx_start
- Connects tx_out to the UART TX pin via .pcf
2. Synthesize and program.
3. Open a terminal emulator (e.g., screen, minicom, picocom, or PuTTY) at 115200 8N1.
4. Press the button — see 'A' appear on your PC terminal.
Checkpoint: Character appears on the PC terminal on button press.
Exercise 3: Transmit "HELLO" (25 min)¶
Objective (SLO 11.3, 11.4): Build a multi-byte transmitter using a ROM + sequencer.
Tasks:
1. Store the string "HELLO\r\n" in a ROM (7 bytes).
2. Build a sequencer FSM that:
- On trigger (button press or reset), starts at ROM address 0
- Sends each byte via UART TX, waiting for tx_busy to deassert before advancing
- Stops after the last byte
3. Synthesize and program. Verify "HELLO" appears on the terminal, followed by a newline.
Checkpoint: "HELLO" prints on the PC terminal from the Go Board.
Exercise 4 (Stretch): Hex-to-ASCII Converter (15 min)¶
Objective (SLO 11.4): Transmit human-readable data.
Tasks: 1. Implement a module that converts a 4-bit value to its ASCII hex character ('0'–'9', 'A'–'F'). 2. Use it to transmit the counter value as readable hex text: e.g., "0A\r\n", "0B\r\n", ... 3. Transmit a new value every ~1 second.
Deliverable¶
"HELLO" appearing on the PC terminal from the Go Board, with a simulation waveform showing correct UART TX framing.
Assessment Mapping¶
| Exercise | SLOs Assessed | Weight |
|---|---|---|
| 1 — UART TX implementation | 11.1, 11.2, 11.3, 11.5 | Core |
| 2 — Single character TX | 11.4 | Core |
| 3 — "HELLO" string TX | 11.3, 11.4 | Core |
| 4 — Hex-to-ASCII | 11.4 | Stretch (bonus) |
⚠️ Common Pitfalls & FAQ¶
Day 11 is your first communication interface. UART is unforgiving about timing — one wrong clock count and every byte is garbled.
- Characters show as garbage in the terminal? The most common cause is a baud rate mismatch. Double-check your
CLKS_PER_BITcalculation: for 115200 baud at 25 MHz, it should be25000000 / 115200 = 217. Also verify your terminal emulator is set to 115200 baud, 8N1. - UART sends LSB first. This catches everyone at least once. Bit 0 of your data byte goes out on the wire first, then bit 1, etc. If you're seeing characters that are "almost right but wrong," check your bit ordering.
- Sending multiple bytes and getting corruption? You must wait for
o_busyto go low (oro_doneto pulse) before sending the next byte. The "HELLO" sequencer in Exercise 3 forces you to handle this — don't shortcut it. - Terminal emulator won't connect? Common causes: wrong COM port (try them all), hardware flow control enabled (disable it), or another program has the port open. On Linux, check
ls /dev/ttyUSB*; on macOS,ls /dev/cu.*. - Which pin is TX on the Go Board? Check
go_board.pcffor the UART TX pin. It must match the pin connected to the USB-to-serial chip on the board. If you get this wrong, the terminal will show nothing at all.
Preview: Day 12¶
UART RX completes the communication loop — type on your PC, see it on the Go Board. You'll also build an SPI master and get hands-on with AI-generated protocol testbenches, learning to prompt for timing-aware verification.