This blog is an update to my older blog about the RTL design of UART Controller. I have updated and released the newer version of the IP: UART Controller v1.1, which now comes with additional features. Read to learn how this IP was designed from scratch.
UART – Getting a Grip of the Basics
UART aka Universal Asynchronous Receiver Transmitter is the simplest and one of the earliest serial communication protocols in use. The simple 2-wire interface (TX, RX) can be used to communicate between two devices serially; this includes micro-controllers, simple sensors, bluetooth modules, Wi-Fi modules etc. However, the communication is asynchronous i.e., there is no common clock used and there is no handshaking involved. This makes UART error-prone at higher data rate (also called baud rate). Popularly used baud rate ranges from 1200-115200. UART also has optional feature of adding even / odd parity in the data packet. A typical UART data packet looks like:
UART Packet format
Start bit indicates the start of packet; followed by Data bits (LSb to Msb) and optional Parity bit; finally 1 or 2 Stop bits indicates the end of packet.
Understanding the Requirements
UART Controller needs to receive parallel data from an external device and then convert it to serial data. Similarly, it has to receiver serial data from an external device and then convert it to parallel data. UART Controller has to support variety of baud rates. It would be handy if we can add an error detecting mechanism as well. Since UART is asynchronous, the receiver is going to be tricky; it has to be robust to deal with metastability and possible data corruption.
UART Controller v1.1 – Specifications
Based on the requirements, we reach at the following specifications for UART Controller v1.1:
- Full duplex communication, 8-bit data.
- Simple valid-ready handshaking at the data interface of Transmitter and Receiver for ease of integration with FIFOs.
- Configurable parity: odd, even, or no parity.
- Configurable baud rate.
- Built-in CDC synchronizer at receiver line.
Designing the IP Architecture
Design of UART Controller v1.1 can be demarcated into three modules: UART Transmitter, UART Receiver, Baud Generator.
UART Controller – Block Diagram
User can configure the IP through Control Interface. All parallel data inputs and outputs from/to User are at Data Interface. IP updates its status like communication errors (framing and parity errors) in Status flags. Please find all configuration/status options in the UART Controller v1.1 – IP User Guide attached at the end. TX and RX make up the serial interface.
UART Transmitter reads parallel data and converts it to serial data. The serial data is then sent out through TX. UART Receiver receives serial data via RX and converts it to parallel data. A multi-flop CDC synchronizer is also implemented in RX path to avoid the metastability of incoming serial data because RX is clocked by an unrelated external clock. If parity is configured, parity computation and validation are also performed by UART Transmitter and UART Receiver for each frame. The IP has a single system clock and reset.
Baud Generator is responsible for bit-synchronization needed for frame transmission and reception. It generates accurate baud pulses for UART Transmitter and UART Receiver to clock serial data. I said baud pulses, not baud clock. Yes, that’s important point here because generating a divided clock using flip-flops is not a good design practice in RTL, especially if targeting FPGAs (curious, why? read my blog on Clock Dividers in RTL). For e.g., if user configures the IP for 9600 bps baud rate, then baud pulse of 9600 Hz is required by UART Transmitter. UART Receiver uses oversampling technique and samples the serial data in the middle. It employs 8x sampling; hence needs a baud pulse of 9600 \times 8 = 76800 \text{ Hz}.
Sampling at RX at 8x rate
UART Receiver – Baud rate tolerance
Baud pulses in our IP have to be derived from the system clock at an accuracy not worse than \pm 5\% and also it is assumed that the incoming data baud rate is within the \pm 5\% range of error. The reason for this can be mathematically approximated.
The UART receiver detects the start bit to start the frame reception. Once the receiver detects the start bit, it keeps sampling until the middle of the stop bit. After that, the receiver waits to re-synchronize to the next start bit. To receive the frame correctly and re-synchronize to the next frame, we should be able to sample all data bits and the stop bit correctly. Since the sampling clock of the receiver is asynchronous to the clock of the external transmitter which generates the serial data, there will be slight deviation in the clock periods and hence the baud rates of the transmitter and the receiver.
For eg: If the incoming baud rate is 9600 \text{ bps}, the receiver should sample at 9600 \times 8 = 76800 \text{ Hz}. But what if the baud rate of the transmitter is slightly off, say 9570 \text{ bps}… The receiver should be able to tolerate these tiny differences in the baud rate for reliable operation. For the receiver that we designed, let’s calculate the tolerance.
Let the error accumulated every sampling cycle = \Delta
\Delta is the difference in the expected sampling period and the actual sampling period.
No. of sampling cycle required up to the sampling of the stop bit in the middle = (1 + 8 + 0.5) * 8 = 76
\therefore The error accumulated over the frame = 76\Delta
To sample the stop bit correctly and re-synchronize to the next start bit, the error accumulated should be kept within a half bit period, T/2, otherwise it will sample the wrong bit:
76\Delta < T/2
\implies \Delta < T/152
\Delta = (\frac{T}{8}-\frac{T'}{8}), where T' is the bit period corresponding to the sampling rate of the receiver.
\therefore \frac{(T-T')}{T} < 8 * \frac{1}{152} \implies \Delta < \pm5.3\%
Hence, the popular UART specification seen in all the receivers: The baud rate error maximum tolerance = \pm5\%.
Baud rate tolerance can be improved a little (\pm0.5\%) by switching to higher sampling rates, and the reliability of bit sampling can be improved by adding filters. But the overhead is the higher power, area utilization, and the limits the minimum baud rate supported.
There are intricacies associated with baud pulse generation and how to configure the baud rate for the IP, which have been described in detail in the IP User Guide.
On-board Testing
No simulation is more satisfactory than actually seeing the design working on board. We can test the IP by synthesising it on an FPGA (Synthesisable test bench available with the source codes) and then verify the functionality by interfacing the IP with any UART device.
In the video below, I have used Arduino to receive bytes from the IP: at 115200 bps, odd parity, 1 stop bit. And then loop the same bytes back to the IP. The IP was synthesised and implemented on Artix-7 on Basys-3 FPGA board.
Testing UART Controller on board
UART Controller v1.1 – Source Codes & User Guide
UART Controller v1.1 is a fully tested, portable, configurable and synthesisable soft IP core. All source codes and IP documentation of UART Controller v1.1 are open-source and can be downloaded for free from the links below.
Download the IP package and resources from the Chipmunk IP Catalog:
IP Solutions – uart_v1_1
Update
Feb-2024: UART Controller v1.2 has been released with upgraded features!
IP Solutions – uart_v1_2
Support
Leave a comment or visit support for any queries/feedback regarding the content of this blog.
If you liked Chipmunk , don’t forget to follow!:
Follow Chipmunk
Bonus
Tricky digital puzzle where you have to check whether a serially received number is divisible by some constant N. How to solve this? Find it here:
Like this:
Like Loading...
Related