SystemC/TLM2 model of the NS16550A UART controller with full register compatibility, interrupt subsystem, and FIFO management. Designed for embedded system simulation and educational purposes.
Note: This is a hobby project developed for learning SystemC and UART internals.
The image above shows the UART running its self-test followed by interactive echo loopback mode. The SystemC simulation creates a virtual PTY that can be connected to external terminal applications like picocom, enabling real-time bidirectional communication with the simulated UART hardware.
Core Module: UartCore - Transaction-level model implementing tlm_fw_transport_if
Interface: TLM2 blocking transport with memory-mapped register access
Clock Domain: Single clock domain with configurable frequency (default: 100MHz)
Data Width: 8-bit register interface, 16-deep FIFO buffers
- Full NS16550A register set with DLAB multiplexing
- Transmit/Receive 16-byte FIFO with programmable trigger levels
- Complete interrupt priority scheme (Line Status, RX Timeout, RX Data Available, TX Empty, Modem Status)
- Hardware flow control (CTS/RTS) with auto-flow capability
- All parity modes: None, Odd, Even, Stick (Mark/Space)
- Data formats: 5-8 bits, 1-2 stop bits
- Loopback mode for internal testing
- Baud rate generation with 16-bit divisor
- Modem control signals (DTR, DSR, DCD, RI, OUT1, OUT2)
- Character timeout interrupt with 4-character threshold
- Enhanced Feature Register (EFR) for 16650 compatibility
- PTY interface for host terminal connectivity
- Interactive terminal mode with xterm-picocom integration
- Comprehensive VCD tracing for signal-level debug
- No DMA controller integration
- No multi-drop or 9-bit protocols
- Serial interface timing simplified (no bit-level timing)
- Single UART instance per module
#include "modules/uart/uart_core.h"
UartCore uart("uart", 100e6, debug_flag, pty_enable);
uart.clk(clock_signal);
uart.rst(reset_signal);
uart.irq(interrupt_signal);
uart.socket.bind(cpu_socket); // TLM2 bindingOffset | DLAB=0 | DLAB=1 | Access
-------|---------|--------|--------
0x00 | RHR/THR | DLL | RW
0x01 | IER | DLM | RW
0x02 | IIR/FCR | - | R/W
0x03 | LCR | LCR | RW
0x04 | MCR | MCR | RW
0x05 | LSR | LSR | R
0x06 | MSR | MSR | R
0x07 | SCR | SCR | RW
- SystemC 3.0+ (C++17 required)
- TLM2.0 library
- GCC/Clang with C++17 support
- Linux PTY support (optional)
make all # Build application and tests
make app # Build UART application only
make test # Build and run verification suite
make clean # Clean build artifacts./build/uart -debug # Enable VCD tracing and verbose loggingThe UART creates a virtual PTY that can be connected to external terminal applications:
./build/uart # Start UART (displays PTY path)
# In another terminal:
picocom --baud 115200 --flow n --noinit /dev/pts/X
# Or use the built-in xterm launcher:
uart.launch_terminal() # From SystemC codeThis enables real-time interaction with the simulated UART through a proper terminal interface, making it ideal for testing embedded software that expects serial console I/O.
Demo Sequence: The application first runs a comprehensive self-test transmitting "Lorem ipsum..." text through loopback mode, then switches to interactive echo mode where typed characters are immediately echoed back, demonstrating full bidirectional UART functionality.
- Throughput: ~150KB/s average (115200 baud simulation)
- Test Coverage: 65 verification tests, 100% pass rate
- VCD Output: ~70MB for full functional test (all signals traced)
- Simulation Speed: Real-time at 100MHz+ SystemC clock
Comprehensive test suite validates:
- Register access patterns and bit-field behavior
- FIFO overflow/underflow conditions
- Interrupt generation and clearing sequences
- Loopback data integrity across all configurations
- Baudrate accuracy and timing constraints
- Flow control assertion/deassertion logic
- Parity generation and error detection
- Timeout interrupt timing requirements
include/modules/uart/ # UartCore class definition
src/modules/uart/ # Implementation
src/applications/ # Standalone UART application
src/testbenches/ # Verification test suite
build/ # Compilation artifacts
This model provides a memory-mapped peripheral interface suitable for SystemC testbenches. Interrupt output should be connected to your system's interrupt handling logic. The PTY functionality enables host-based terminal testing - disable it for pure simulation workflows by setting the constructor parameter to false.
Clock frequency parameter affects baud rate accuracy - ensure sufficient resolution for target communication rates. Default 100MHz provides sub-1% error for standard baud rates up to 115200.
MIT License - see individual source files for copyright notices.
This implementation aims to be the a comprehensive, open-source NS16550A SystemC model with interactive terminal capability. While developed as a learning project, goal is still accuracy and completeness in UART functionality.