UART
PROTOCOL
PREPARED BY:
AHMED YASSER
Table of
Contents
Introduction 03
Protocol Explanation 04
Baud Rate 05
FIFO Buffers 06
Transmitter FSM Description 07
Receiver FSM Description 08
RTL Design 09
Testbench 16
Do File 18
Waveform 19
QuestaLint 23
Constraints File 24
Vivado 25
Introduction
The Universal Asynchronous Receiver/Transmitter (UART) is one of the oldest and most
widely used methods of serial communication. It has been a standard interface in
computers, embedded systems, and communication equipment for decades, thanks to
its simplicity and reliability. Unlike parallel communication, where multiple data lines are
used simultaneously, UART transmits data serially — one bit at a time — which reduces
wiring complexity and makes it ideal for low-pin-count devices.
What sets UART apart from synchronous protocols such as SPI and I²C is that it operates
asynchronously. This means there is no dedicated clock line shared between the
transmitter and the receiver. Instead, both devices must agree on a baud rate, which
defines the number of bits transmitted per second. Common baud rates include 9600,
19200, and 115200 bps.
UART is used in a wide range of applications, including:
Microcontroller-to-PC communication (for programming and debugging).
FPGA-based designs (for testing and data transfer).
Peripheral devices such as GPS modules, Bluetooth modules, and sensors.
Embedded systems for console output, data logging, and inter-device
communication.
rx rx dout w_data
rd_data rd_data
clk rx_tick_count wr
S_tick full rd rd_en
tick empty rx_empty
Receiver FIFO
Baud
Rate
generator
tx tx din rd_data
tx_tick_count rd w_data wr_data
S_tick tx_start empty wr wr_en
full tx_full
Transmitter FIFO
Protocol Explanation
The UART protocol defines how digital data is transmitted and received serially between
two devices without a shared clock signal. Data is sent frame by frame, with each frame
containing clearly defined control and data fields that allow synchronization and error
checking.
Frame Format
A UART frame is made up of the following elements:
[Link] State: When no data is being transmitted, the line is held HIGH
[Link] Bit (1 bit): A transition from HIGH to LOW signals the beginning of a new frame.
[Link] Bits (5–9 bits): The payload, transmitted least significant bit (LSB) first. In most systems,
8 data bits are used.
[Link] Parity Bit (1 bit): Provides simple error detection using either even or odd parity.
[Link] Bit(s) (1 or 2 bits): One or more HIGH bits mark the end of the frame and give the receiver
time to prepare for the next transmission.
Operation
The transmitter converts parallel data into serial form and sends it bit by bit over the
TX line.
The receiver monitors the RX line, detects the start bit, and then samples each
subsequent bit at the correct intervals to reconstruct the data.
Since the protocol is asynchronous, both transmitter and receiver must operate with
the same configuration (frame format and baud rate).
Error Handling
Parity Error: When the parity check fails (if enabled).
Framing Error: When the stop bit is missing or invalid.
Baud Rate
The baud rate defines the speed of communication in a UART system. It is the number of
signal changes (symbols) transmitted per second, and in UART, each symbol corresponds
to one bit. Therefore, baud rate = bits per second (bps).
Why Baud Rate is important
Both the transmitter and receiver must operate at the same baud rate to correctly
interpret the data.
A mismatch between baud rates causes incorrect sampling at the receiver, leading to
corrupted data.
Common baud rates include 9600, 19200, 115200 bps, depending on application
requirements.
Baud Rate and Oversampling
UART communication is asynchronous, meaning there is no dedicated clock line. To
ensure reliable reception, the receiver uses oversampling (commonly 16×) to detect the
start bit transition and correctly sample each data bit at its center.
Baud Rate Calculation
The baud rate is derived from the system clock using a frequency divider. The formula is:
System Clock Frequency
Baud Rate =
Divider x Oversampling Rate
Where:
System Clock Frequency = clock driving the UART module (e.g., 50 MHz).
Oversampling Rate = typically 16.
Divider = value set in the baud rate generator.
Example:
If the system clock is 50 MHz and the target baud rate is 9600 bps, with 16× oversampling:
50, 000, 000
Divider = ≈ 325
9600 x 16
So, the baud rate generator divides the 50 MHz clock by 325 to produce the correct
sampling signal.
FIFO Buffers
A First-In First-Out (FIFO) buffer is a memory queue that temporarily stores data to
balance speed differences between the transmitter/receiver and the CPU or external
device.
Why FIFOs are important in UART
Smooth Data Flow: Prevents data loss when the CPU cannot read or write at the
exact baud rate speed.
Interrupt Reduction: With a FIFO, the CPU handles multiple bytes per interrupt
instead of one byte at a time.
Error Handling: Helps avoid overflow (when writing too much data) and underflow
(when reading empty data).
Operation of FIFO in UART
Transmit FIFO (TX FIFO):
Stores outgoing data from the CPU before sending it serially.
The UART transmitter shifts out data byte by byte at the defined baud rate.
Receive FIFO (RX FIFO):
Stores incoming serial data until the CPU reads it.
Prevents data loss if the CPU cannot respond immediately.
Typical FIFO Depths
Early UARTs had only a 1-byte buffer.
Modern UARTs typically use 16-byte or 64-byte FIFOs, with some advanced designs
supporting even deeper buffers.
Transmitter FSM
The UART transmitter is implemented as a finite state machine (FSM) with four states:
IDLE, START, SHIFT, and STOP. The FSM ensures that data is serialized and transmitted
according to the UART protocol.
IDLE State (Default State):
The transmitter line (tx) remains high (logic 1) when idle.
When a transmission request (tx_start) is received, the input data is formatted into a complete
frame consisting of: {Stop Bit,Parity Bit,Data Bits,Start Bit}
Once the frame is loaded, the FSM transitions to the START state.
START State:
Sends the start bit (0) to indicate the beginning of transmission.
The bit is held on the line for one full bit duration (16 ticks of the oversampling clock
S_tick).
After one bit time, the FSM transitions to the SHIFT state.
SHIFT State:
Serially transmits the data bits (LSB first), followed by the parity bit.
A counter keeps track of both the oversampling ticks (for bit timing) and the number
of bits transmitted.
Once all data bits and the parity bit have been sent, the FSM moves to the STOP
state.
STOP State:
Sends the stop bit (1) to mark the end of the frame.
After the stop bit is held for one full bit duration, the signal tx_done_tick is asserted to
indicate transmission completion.
The FSM then returns to the IDLE state, ready for the next transmission.
RESET
tx_start && load_frame
START
IDLE START
S_tick && tick_count = 15
S_tick && tick_count = 15
STOP SHIFT
S_tick && tick_count = 15 && bit_count = N_BIT
Receiver FSM
The UART receiver is designed as a finite state machine (FSM) with four states: IDLE,
START, SHIFT, and STOP. Its job is to detect incoming serial data, sample it correctly
using the oversampling clock (S_tick), and convert it into parallel output while performing
error checks.
IDLE State (Default State):
The line (rx) is normally high (logic 1) when idle.
The FSM waits until it detects a falling edge (rx = 0), which indicates the beginning of
the start bit.
When the start bit is detected, the FSM transitions to START.
START State:
The receiver waits for half a bit period (8 ticks when oversampling at 16×) to sample
the middle of the start bit.
This ensures that any small timing mismatches do not cause incorrect detection.
After confirming a valid start bit, the FSM moves to the SHIFT state.
SHIFT State:
In this state, the receiver samples and shifts in the data bits and the parity bit, one by
one.
Each bit is sampled at the end of its bit duration (after 16 ticks of S_tick).
A counter keeps track of how many bits have been received.
Once all bits are collected, the FSM transitions to the STOP state.
STOP State:
Samples the stop bit (should be logic 1).
Performs parity check (compare received vs. computed parity).
Detects frame error if start/stop bits are invalid.
If everything is valid, asserts rx_done_tick and outputs the received data.
RESET
rx = 0
START
IDLE START
S_tick && tick_count = 15
S_tick && tick_count = 7
STOP SHIFT
S_tick && tick_count = 15 && bit_count = N_BIT
RTL Design
Baud Rate Generator
FIFO Module
Transmitter Module
Transmitter Top Module
Receiver Module
Receiver Top Module
UART Wrapper
Testbench
Do File
Waveform
Sending and Receiving Start Bit
Sending and Receiving From 1st to 8th Bit
Sending and Receiving Parity Bit
Sending and Receiving Stop Bit
Data Loaded into Receiver FIFO_A
Data Loaded into Receiver FIFO_B
Data Read From FIFO_A
Data Read From FIFO_B
Full Wave
QuestaLint
Constraints File
Vivado
Elaborated Design
Synthesis
Schematic
FSM Encoding Styles
Transmitter: gray - Receiver: gray
Transmitter: one_hot - Receiver: one_hot
Transmitter: one_hot - Receiver: sequential
Transmitter: sequential - Receiver: one_hot
Transmitter: sequential - Receiver: sequential
Implementation
FSM Encoding Styles
Transmitter: gray - Receiver: gray
Transmitter: one_hot - Receiver: one_hot
Transmitter: one_hot - Receiver: sequential
Transmitter: sequential - Receiver: one_hot
Transmitter: sequential - Receiver: sequential
Based on the Timing Summary Reports
for different FSM encoding styles, the
sequential - one_hot encoding provided
the best results.
Generate Bitstream