uart
UART with AXI4-Lite CSRs — TX/RX FIFOs, programmable framing and baud rate.
A UART with AXI4-Lite CSRs for FPGA and ASIC: TX/RX FIFOs, programmable
framing and baud rate, sticky error flags, a level interrupt, and a loopback
self-test. Plain synthesizable SystemVerilog verified by self-checking
Verilator testbenches plus SymbiYosys formal proofs; portable (the one
vendor-aware cell, the RX synchronizer, is isolated in rtl/tech/);
registers single-sourced from gen/regmap.py; packaged as vendor-neutral
IP-XACT 1685-2014. The CSR port drops onto any AXI4-Lite fabric.
Design spec: docs/spec.md · register map: docs/registers.md (generated).
Features
- 8 data bits, parity none/even/odd, 1–2 stop bits (TX; RX checks the first stop bit), programmable 24-bit divisor (min 8 cycles/bit)
- parameterizable TX/RX FIFOs (
FIFO_DEPTH, power of 2, default 16) - sticky W1C errors: overrun / frame / parity (errored frames still deliver their data byte)
- level interrupt
irq_o = |(IE & IP)over {rx_avail, tx_empty, err} - loopback self-test mode; RX start-glitch (runt) rejection
- RX line synchronized through
uart_tech_sync(generic/xilinx/intel/lattice,TECH=make knob)
Status
| Area | State |
|---|---|
| RTL | ✅ lint -Wall-clean across all four tech vendors |
| Loopback TB | ✅ UART P 0000 — config sweep, readback, IRQ truth table, TX-full drop, RX overrun + W1C |
| Line-level TB | ✅ UARTL P 0000 — independent encoder/decoder, ±2% divisor mismatch, parity/stop corruption, runt rejection |
| Coverage | ✅ 98.7% rtl/ (150/152; the 2 misses are unreachable defensive FSM defaults) |
| Formal | ✅ F_fifo proven (occupancy + complete shadow-memory data integrity, DEPTH 4/16, mutation-tested) + F_tx basic proven (idle-high, pop discipline) + F_tx shape bounded-checked (btormc, 350 cycles ≈ 2 max frames: exact (1+8+P+S)·DIV length, start/stop windows) |
| IP-XACT | ✅ schema-validated (ipxact/); ERR carries modifiedWriteValue=oneToClear, RXD carries readAction=modify |
| Integration | ✅ UARTX P 0000 — CSRs hosted behind ../xbar's crossbar incl. DECERR path (make sim-xbar) |
| OOC | ✅ timing closed on xc7a100t-1 (Vivado 2026.1): 370 LUT / 496 FF / 0 BRAM, WNS +2.75 ns @ 10 ns → Fmax ≈ 138 MHz |
| Board | ✅ 2000/2000 on the Arty A7-100T: arty_uart_echo (FSM AXI master → ../xbar crossbar → this UART on the physical USB-UART; make synth-echo prog echo-test) |
make lint # Verilator -Wall (TECH= picks the sync cell vendor)
make lint-tech # all four vendors
make sim # both TBs -> "UART P 0000", "UARTL P 0000"
make sim-xbar # behind the crossbar (needs ../xbar) -> "UARTX P 0000"
make coverage # merged line coverage, rtl/ only
make formal # F_fifo + F_tx (SymbiYosys, abc pdr)
make ipxact # vendor-neutral IEEE 1685-2014 package
make synth-ooc # Vivado out-of-context synth+impl, timing-gated
Layout
rtl/ core/{fifo,tx,rx}.sv, bus/axil_regs.sv, uart_axil.sv (top),
tech/{generic,xilinx,intel,lattice}/tech_sync.sv
tb/ tb_uart_loop.sv (CSR loopback), tb_uart_line.sv (line-level +
error injection), tb_uart_xbar.sv (integration), shared AXI tasks
formal/ uart_fifo.sby + uart_tx.sby (yosys-dialect harnesses; DUTs sv2v'd)
docs/ spec.md, registers.md (generated)
gen/ regmap.py (single source of truth), ipxact_gen.py
License
Apache-2.0 — see LICENSE. Copyright 2026 Hasan Kurşun.