UART, or universal asynchronous receiver-transmitter, is one of the most used device-to-device communication protocols. A UART enables two devices to exchange data serially without sharing the clock in a frame oriented way. The frame consists of a start bit, a number of data bits (typically one byte), a parity bit (optional) and 1-2 stop bits. EF_UART is a Soft IP with the following features:
- A configurable frame format
- Data bits could vary from 5 to 9 bits
- Even, odd, stick, or no-parity bit generation/detection
- One or Two stop bit generation
- Line-break detection
- Configurable receiver timeout
- Loopback capability for testing/debugging
- Glitch Filter on RX enable
- Matching received data detection
- 16-byte TX and RX FIFOs with programmable thresholds
- 16-bit prescaler (PR) for programmable baud rate generation
- Ten Interrupt Sources:
- RX FIFO is full
- TX FIFO is empty
- RX FIFO level is above the set threshold
- TX FIFO level is below the set threshold
- Line break detection
- Receiver data match
- Frame Error
- Parity Error
- Overrun
- Receiver timeout
APB, AHBL, and Wishbone wrappers, generated by the BusWrap bus_wrap.py
utility, are provided. All wrappers provide the same programmer's interface as outlined in the following sections.
Based on your use case, use one of the provided wrappers or create a wrapper for your system bus type. For an example of how to integrate the APB wrapper:
EF_UART_APB INST (
`TB_APB_SLAVE_CONN,
.rx(rx),
.tx(tx)
);
NOTE: `TB_APB_SLAVE_CONN is a convenient macro provided by BusWrap.
The following table is the result for implementing the EF_UART IP with different wrappers using Sky130 PDK and OpenLane2 flow.
Module | Number of cells | Max. freq |
---|---|---|
EF_UART | 1590 | 277 |
EF_UART_APB | 1943 | 208 |
EF_UART_AHBL | 1973 | 250 |
EF_UART_WB | 2170 | 83 |
Name | Offset | Reset Value | Access Mode | Description |
---|---|---|---|---|
RXDATA | 0000 | 0x00000000 | r | RX Data register; the interface to the Receive FIFO. |
TXDATA | 0004 | 0x00000000 | w | TX Data register; ; the interface to the Receive FIFO. |
PR | 0008 | 0x00000000 | w | The Prescaler register; used to determine the baud rate. |
CTRL | 000c | 0x00000000 | w | UART Control Register |
CFG | 0010 | 0x00003F08 | w | UART Configuration Register |
MATCH | 001c | 0x00000000 | w | Match Register |
RX_FIFO_LEVEL | fe00 | 0x00000000 | r | RX_FIFO Level Register |
RX_FIFO_THRESHOLD | fe04 | 0x00000000 | w | RX_FIFO Level Threshold Register |
RX_FIFO_FLUSH | fe08 | 0x00000000 | w | RX_FIFO Flush Register |
TX_FIFO_LEVEL | fe10 | 0x00000000 | r | TX_FIFO Level Register |
TX_FIFO_THRESHOLD | fe14 | 0x00000000 | w | TX_FIFO Level Threshold Register |
TX_FIFO_FLUSH | fe18 | 0x00000000 | w | TX_FIFO Flush Register |
IM | ff00 | 0x00000000 | w | Interrupt Mask Register; write 1/0 to enable/disable interrupts; check the interrupt flags table for more details |
RIS | ff08 | 0x00000000 | w | Raw Interrupt Status; reflects the current interrupts status;check the interrupt flags table for more details |
MIS | ff04 | 0x00000000 | w | Masked Interrupt Status; On a read, this register gives the current masked status value of the corresponding interrupt. A write has no effect; check the interrupt flags table for more details |
IC | ff0c | 0x00000000 | w | Interrupt Clear Register; On a write of 1, the corresponding interrupt (both raw interrupt and masked interrupt, if enabled) is cleared; check the interrupt flags table for more details |
RX Data register; the interface to the Receive FIFO.
TX Data register; ; the interface to the Receive FIFO.
The Prescaler register; used to determine the baud rate.
bit | field name | width | description |
---|---|---|---|
0 | en | 1 | UART enable |
1 | txen | 1 | UART Transmitter enable |
2 | rxen | 1 | UART Receiver enable |
3 | lpen | 1 | Loopback (connect RX and TX pins together) enable |
4 | gfen | 1 | UART Glitch Filer on RX enable |
bit | field name | width | description |
---|---|---|---|
0 | wlen | 4 | Data word length: 5-9 bits |
4 | stp2 | 1 | Two Stop Bits Select |
5 | parity | 3 | Parity Type: 000: None, 001: odd, 010: even, 100: Sticky 0, 101: Sticky 1 |
8 | timeout | 6 | Receiver Timeout measured in number of bits |
bit | field name | width | description |
---|---|---|---|
0 | level | 4 | FIFO data level |
RX_FIFO Level Threshold Register
bit | field name | width | description |
---|---|---|---|
0 | threshold | 4 | FIFO level threshold value |
bit | field name | width | description |
---|---|---|---|
0 | flush | 1 | FIFO flush |
bit | field name | width | description |
---|---|---|---|
0 | level | 4 | FIFO data level |
TX_FIFO Level Threshold Register
bit | field name | width | description |
---|---|---|---|
0 | threshold | 4 | FIFO level threshold value |
bit | field name | width | description |
---|---|---|---|
0 | flush | 1 | FIFO flush |
The wrapped IP provides four registers to deal with interrupts: IM, RIS, MIS and IC. These registers exist for all wrapper types generated by the BusWrap bus_wrap.py
utility.
Each register has a group of bits for the interrupt sources/flags.
-
IM
: is used to enable/disable interrupt sources. -
RIS
: has the current interrupt status (interrupt flags) whether they are enabled or disabled. -
MIS
: is the result of masking (ANDing) RIS by IM. -
IC
: is used to clear an interrupt flag.
The following are the bit definitions for the interrupt registers:
Bit | Flag | Width | Description |
---|---|---|---|
0 | TXE | 1 | Transmit FIFO is Empty. |
1 | RXF | 1 | Receive FIFO is Full. |
2 | TXB | 1 | Transmit FIFO level is Below Threshold. |
3 | RXA | 1 | Receive FIFO level is Above Threshold. |
4 | BRK | 1 | Line Break; 13 consecutive 0's have been detected on the line. |
5 | MATCH | 1 | Match; the received data matches the MATCH register. |
6 | FE | 1 | Framing Error; the receiver does not see a "stop" bit at the expected "stop" bit time. |
7 | PRE | 1 | Parity Error; the receiver calculated parity does not match the received one. |
8 | OR | 1 | Overrun; data has been received but the RX FIFO is full. |
9 | RTO | 1 | Receiver Timeout; no data has been received for the time of a specified number of bits. |
Parameter | Description | Default Value |
---|---|---|
SC | Number of samples per bit/baud | 8 |
MDW | Max data size/width | 9 |
GFLEN | Length (number of stages) of the glitch filter | 8 |
FAW | FIFO Address width; Depth=2^AW | 4 |
Port | Direction | Width | Description |
---|---|---|---|
rx | input | 1 | RX connected to the external interface |
tx | output | 1 | TX connected to external interface |
prescaler | input | 16 | Prescaler used to determine the baud rate. |
en | input | 1 | Enable for UART |
tx_en | input | 1 | Enable for UART transmission |
rx_en | input | 1 | Enable for UART receiving |
wdata | input | MDW | Transmission data |
timeout_bits | input | 6 | Receiver Timeout measured in number of bits. |
loopback_en | input | 1 | Loopback enable; connect tx to the rx |
glitch_filter_en | input | 1 | UART Glitch Filter on RX enable |
tx_level | output | FAW | The current level of TX FIFO |
rx_level | output | FAW | The current level of RX FIFO |
rd | input | 1 | Read from RX FIFO signal |
wr | input | 1 | Write to TX FIFO signal |
data_size | input | 4 | Number of data bits in the frame |
stop_bits_count | input | 1 | Number of stop bits in the frame (could be 1 or 2) |
parity_type | input | 3 | Type of Parity in the frame |
txfifotr | input | FAW | TX FIFO Threshold |
rxfifotr | input | FAW | RX FIFO Threshold |
match_data | input | MDW | Match data (match flag would be raised if it matches what is received) |
tx_empty | output | 1 | TX empty flag |
tx_full | output | 1 | TX full flag |
tx_level_below | output | 1 | TX level below flag |
rdata | output | MDW | Received Data |
rx_empty | output | 1 | RX empty flag |
rx_full | output | 1 | RX full flag |
rx_level_above | output | 1 | RX level above flag |
break_flag | output | 1 | Break flag |
match_flag | output | 1 | Match flag |
frame_error_flag | output | 1 | Frame error flag |
parity_error_flag | output | 1 | Parity error flag |
overrun_flag | output | 1 | Overrun flag |
timeout_flag | output | 1 | Timeout flag |
- Set the prescaler according to the required transmission and receiving baud rate where:
$Baud\ rate = Bus\ Clock\ Freq/((Prescaler+1)\times16)$ . Setting the prescaler is done through writing toPR
register - Configure the frame format by :
- Choosing the number of data bits which could vary from 5 to 9. This is done by setting the
wlen
field in theCFG
register - Choosing whether the stop bits are one or two by setting the
stb2
bit inCFG
register where ‘0’ means one bit and ‘1’ means two bits - Choosing the parity type by setting
parity
field inCFG
register where 000: None, 001: odd, 010: even, 100: Sticky 0, 101: Sticky 1
- Choosing the number of data bits which could vary from 5 to 9. This is done by setting the
- Set the receiver timeout value which fires the
RTO
interrupt after a certain amount of bits are received. This would be useful when the message received is not a multiple of the FIFO’s width.Timeout can be set by writing to thetimeout
field in theCFG
register - Set the FIFO thresholds by writing to the
RXLT
andTXLT
fields inFIFOCTRL
register. This would fireRXA
andTXB
interrupts when the RX FIFO level is above the threshold and TX FIFO level is below the threshold. - Enable the UART as well as RX or TX or both by setting
en
,txen
, andrxen
bits to ones in theCTRL
register - To optionally connect the RX signal to the TX signal so the UART transmits whatever it receives then enable loopback by setting the
loopback
bit to one in theCTRL
register. - To optionally enable the glitch filter on RX , set the
gfen
bit to one in theCTRL
register. - To read what was received , you can read
RXDATA
register. Note: you should check that there is something in the FIFO before reading using the interrupts registers. - To optionally check if the data received matches a certain value by writing to the
MATCH
register. This would fire theMATCH
interrupt if the received data matches the match value. - To transmit, write to the
TXDATA
register. Note: you should check that the FIFO is not full before adding something to it using the interrupts register to avoid losing data.
You can either clone repo or use IPM which is an open-source IPs Package Manager
- To clone repo:
git clone https://https://github.com/efabless/EF_UART.git
- To download via IPM , follow installation guides here then run
ipm install EF_UART
- Clone IP_Utilities repo in the same directory as the IP
- In the directory
EF_UART/verify/utb/
runmake APB-RTL
to run testbench for APB ormake AHBL-RTL
to run testbench for AHBL
In IP directory run:
cd verify/uvm-python/
To run all tests:
make run_all_tests BUS_TYPE=APB
To run a certain test:
make run_<test_name> BUS_TYPE=APB
To run all tests with a tag:
make run_all_tests TAG=<new_tag> BUS_TYPE=APB
To run all tests:
make run_all_tests BUS_TYPE=AHB
To run a certain test:
make run_<test_name> BUS_TYPE=AHB
To run all tests with a tag:
make run_all_tests TAG=<new_tag> BUS_TYPE=AHB