|  | --- | 
|  | title: "UART HWIP Technical Specification" | 
|  | --- | 
|  |  | 
|  | # Overview | 
|  |  | 
|  | This document specifies UART hardware IP functionality. This module | 
|  | conforms to the | 
|  | [Comportable guideline for peripheral functionality.](/doc/rm/comportability_specification) | 
|  | See that document for integration overview within the broader | 
|  | top level system. | 
|  |  | 
|  |  | 
|  | ## Features | 
|  |  | 
|  | - 2-pin full duplex external interface | 
|  | - 8-bit data word, optional even or odd parity bit per byte | 
|  | - 1 stop bit | 
|  | - 32 x 8b RX buffer | 
|  | - 32 x 8b TX buffer | 
|  | - Programmable baud rate | 
|  | - Interrupt for transmit empty, receive overflow, frame error, parity error, break error, receive | 
|  | timeout | 
|  |  | 
|  | ## Description | 
|  |  | 
|  | The UART module is a serial-to-parallel receive (RX) and parallel-to-serial | 
|  | (TX) full duplex design intended to communicate to an outside device, typically | 
|  | for basic terminal-style communication. It is programmed to run at a particular | 
|  | baud rate and contains only a transmit and receive signal to the outside world, | 
|  | i.e. no synchronizing clock. The programmable baud rate guarantees to be met up | 
|  | to 1Mbps. | 
|  |  | 
|  | ## Compatibility | 
|  |  | 
|  | The OpenTitan UART is feature compatible to a specific implementation in [Chromium EC](https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/chip/g/uart.c). | 
|  | Additional features such as parity have been added. | 
|  |  | 
|  | # Theory of Operations | 
|  |  | 
|  | ## Block Diagram | 
|  |  | 
|  |  | 
|  |  | 
|  | ## Hardware Interfaces | 
|  |  | 
|  | {{< hwcfg "hw/ip/uart/data/uart.hjson" >}} | 
|  |  | 
|  | ## Design Details | 
|  |  | 
|  | ### Serial interface (both directions) | 
|  |  | 
|  | The TX/RX serial lines are high when idle. Data starts with a START bit (high | 
|  | idle state deasserts, **1**-->**0**) followed by 8 data bits. The least | 
|  | significant bit is sent first. If the parity feature is turned on then an odd or | 
|  | even parity bit follows after the data bits. Finally a STOP (**1**) bit | 
|  | completes one byte of data transfer. | 
|  |  | 
|  | {{< wavejson >}} | 
|  | { | 
|  | signal: [ | 
|  | { name: 'Baud Clock',     wave: 'p............'                                                        }, | 
|  | { name: 'tx',             wave: '10333333331..', data: [ "lsb", "", "", "", "", "", "", "msb" ]        }, | 
|  | { name: 'Baud Clock',     wave: 'p............'                                                        }, | 
|  | { name: 'tx (w/ parity)', wave: '103333333341.', data: [ "lsb", "", "", "", "", "", "", "msb", "par" ] }, | 
|  | ], | 
|  | head: { | 
|  | text: 'Serial Transmission Frame', | 
|  | }, | 
|  | foot: { | 
|  | text: 'start bit ("0") at cycle -1, stop bit ("1") at cycle 8, or after parity bit', | 
|  | tock: -2 | 
|  | }, | 
|  | foot: { | 
|  | text: [ | 
|  | 'tspan', | 
|  | ['tspan', 'start bit '], | 
|  | ['tspan', {class:'info h4'}, '0'], | 
|  | ['tspan', ' at cycle -1, stop bit '], | 
|  | ['tspan', {class:'info h4'}, '1'], | 
|  | ['tspan', ' at cycle 8, or at cycle 9 after parity bit'], | 
|  | ], | 
|  | tock: -2, | 
|  | } | 
|  | } | 
|  | {{< /wavejson >}} | 
|  |  | 
|  | ### Transmission | 
|  |  | 
|  | A write to {{< regref "WDATA" >}} enqueues a data byte into the 32 byte deep write FIFO, which | 
|  | triggers the transmit module to start UART TX serial data transfer. The TX | 
|  | module dequeues the byte from the FIFO and shifts it bit by bit out to the UART | 
|  | TX pin on positive edges of the baud clock. | 
|  |  | 
|  | If TX is not enabled, written DATA into FIFO will be stacked up and sent out | 
|  | when TX is enabled. | 
|  |  | 
|  | When the FIFO becomes empty as part of transmittion, a TX FIFO empty interrupt will be raised. | 
|  | This is separate from the TX FIFO water mark interrupt. | 
|  |  | 
|  |  | 
|  | ### Reception | 
|  |  | 
|  | The RX module oversamples the RX input pin at 16x the requested | 
|  | baud clock. When the input is detected low the receiver will check | 
|  | half a bit-time later (i.e. 8 cycles of the oversample clock) that the | 
|  | line is still low before detecting the START bit. If the line has | 
|  | returned high the glitch is ignored. After it detects the START bit, | 
|  | the RX module samples at the center of each bit-time and gathers | 
|  | incoming serial bits into a charcter buffer. If the STOP bit is | 
|  | detected as high and the optional partity bit is correct the data byte | 
|  | is pushed into a 32 byte deep RX FIFO. The data can be read out by | 
|  | reading {{< regref "RDATA" >}} register. | 
|  |  | 
|  | This behaviour of the receiver can be used to compute the approximate | 
|  | baud clock frequency error that can be tolerated between the | 
|  | transmitter at the other end of the cable and the receiver. The | 
|  | initial sample point is aligned with the center of the START bit. The | 
|  | receiver will then sample every 16 cycles of the 16 x baud clock, the | 
|  | diagram below shows the number of ticks after the centering that each | 
|  | bit is captured. Because of the frequency difference between the | 
|  | transmiter and receiver the actual sample point will drift compared to | 
|  | the ideal center of the bit. In order to correctly receive the STOP | 
|  | bit it must be sampled between the "early" and "late" points shown | 
|  | on the diagram, which are half a bit-time or 8 ticks of the 16x baud | 
|  | clock before or after the center. If the transmitter is considered | 
|  | "ideal" then the local clock must thus differ by no more than plus or | 
|  | minus 8 ticks in 144 or aproximately +/- 5.5%. If parity is enabled | 
|  | the stop bit will be a bit time later, so this becomes 8/160 or about | 
|  | +/- 5%. | 
|  |  | 
|  | {{< wavejson >}} | 
|  | { | 
|  | signal: [ | 
|  | { name: 'Sample', wave: '', node: '..P............', period: "2" }, | 
|  | {}, | 
|  | { name: 'rx', | 
|  | wave: '1.0.3.3.3.3.3.3.3.3.1.0.3', | 
|  | node: '...A................C.D..', | 
|  | cdata: [ "idle", "start", "+16", "+32", "+48", "+64", "+80", | 
|  | "+96", "+112", "+128", "+144", "next start" ] }, | 
|  | ], | 
|  | "edge"   : ["P-|>A center", "P-|>C early", "P-|>D late"], | 
|  | head: { | 
|  | text: 'Receiver sampling window', | 
|  | }, | 
|  | } | 
|  | {{< /wavejson >}} | 
|  |  | 
|  | In practice, the transmitter and receiver will both differ from the | 
|  | ideal baud rate. Since the worst case difference for reception is 5%, | 
|  | the uart can be expected to work if both sides are within +/- 2.5% of | 
|  | the ideal baud rate. | 
|  |  | 
|  | ### Setting the baud rate | 
|  |  | 
|  | The baud rate is set by writing to the {{< regref "CTRL.NCO" >}} register field. This should be | 
|  | set using the equation below, where `f_pclk` is the system clock frequency | 
|  | provided to the UART, and `f_baud` is the desired baud rate (in bits per second). | 
|  |  | 
|  | $$ NCO = 16 \times {{2^{$bits(NCO)} \times f\_{baud}} \over {f\_{pclk}}} $$ | 
|  |  | 
|  | The formula above depends on the NCO CSR width. | 
|  | The logic creates a x16 tick when the NCO counter overflows. | 
|  | So, the computed baud rate from NCO value is below. | 
|  |  | 
|  | $$ f\_{baud} = {{1 \over 16} \times {NCO \over {2^{$bits(NCO)}}} \times {f\_{pclk}}} $$ | 
|  |  | 
|  | Note that the NCO result from the above formula can be a fraction but | 
|  | the NCO register only accepts an integer value. This will create an | 
|  | error if the baud rate is not divisible by the fixed clock frequency. As | 
|  | discussed in the previous section the error rate between the receiver | 
|  | and remote transmitter should be lower than `8 / 144` to latch a | 
|  | correct character value when parity is not used and lower than `8 / | 
|  | 160` when parity is used. In the expectation that the device the other | 
|  | side of the line behaves similarly, this requires each side have a | 
|  | baud rate that is matched to within +/- 2.5% of the ideal baud | 
|  | rate. The contribution to this error if NCO is rounded down to an | 
|  | integer (which will make the actual baud rate always lower or equal to | 
|  | the requested rate) can be computed from: | 
|  |  | 
|  | $$ Error = {{(NCO - INT(NCO))} \over {NCO}} percent $$ | 
|  |  | 
|  | In this case if the resulting value of NCO is greater than $$ {1 \over | 
|  | 0.025} = 40 $$ then this will always be less than the 2.5% error | 
|  | target. | 
|  |  | 
|  | For NCO less than 40 the error in baud rate may or may not be | 
|  | acceptable and should be carefully checked and rounding to the nearest | 
|  | integer may achieve better results. If the computed value is close to | 
|  | an integer so that the error in the target range then the baud rate | 
|  | can be supported, however if it is too far off an integer then the | 
|  | baud rate cannot be supported. This check is needed when | 
|  |  | 
|  | $$ {{baud} < {{40 * f\_{pclk}} \over {2^{$bits(NCO)+4}}}} \qquad OR \qquad | 
|  | {{f\_{pclk}} > {{{2^{$bits(NCO)+4}} * {baud}} \over {40}}} $$ | 
|  |  | 
|  | Using rounded frequencies and common baud rates, this implies that | 
|  | care is needed for 9600 baud and below if the system clock is under | 
|  | 250MHz, with 4800 baud and below if the system clock is under 125MHz, | 
|  | 2400 baud and below if the system clock us under 63MHz, and 1200 baud | 
|  | and below if the system clock is under 32MHz. | 
|  |  | 
|  |  | 
|  | ### Interrupts | 
|  |  | 
|  | UART module has a few interrupts including general data flow interrupts | 
|  | and unexpected event interrupts. | 
|  |  | 
|  | #### tx_watermark / rx_watermark | 
|  | If the TX FIFO level becomes smaller than the TX water mark level (configurable via {{< regref "FIFO_CTRL.RXILVL" >}} and {{< regref "FIFO_CTRL.TXILVL" >}}), the `tx_watermark` interrupt is raised to inform SW. | 
|  | If the RX FIFO level becomes greater than or equal to RX water mark level (configurable via {{< regref "FIFO_CTRL.RXILVL" >}} and {{< regref "FIFO_CTRL.TXILVL" >}}), the `rx_watermark` interrupt is raised to inform SW. | 
|  |  | 
|  | Note that the watermark interrupts are edge triggered events. | 
|  | This means the interrupt only triggers when the condition transitions from untrue->true. | 
|  | This is especially important in the tx_watermark case. | 
|  | When the TX FIFO is empty, it by default satisifies all the watermark conditions. | 
|  | In order for the interrupt to trigger then, it is required that software initiates a write burst that is greater than the programmed watermark value. | 
|  |  | 
|  | For example, assume TX watermark is programmed to be less than 4 bytes, and software programs one byte at a time, waits for it to finish transmitting, before supplying the next byte. | 
|  | Under these conditions, the TX watermark interrupt will never trigger because the size of the FIFO never exceeds the watermark level. | 
|  |  | 
|  |  | 
|  | #### tx_empty | 
|  | If TX FIFO becomes empty as part of transmit, the interrupt `tx_empty` is asserted. | 
|  | The transmitted contents may be garbage at this point as old FIFO contents will likely be transmitted. | 
|  |  | 
|  | #### rx_overflow | 
|  | If RX FIFO receives an additional write request when its FIFO is full, | 
|  | the interrupt `rx_overflow` is asserted and the character is dropped. | 
|  |  | 
|  | #### rx_break_err | 
|  | The `rx_break_err` interrupt is triggered if a break condition has | 
|  | been detected. A break condition is defined as the RX pin being | 
|  | continuously low for more than a programmable number of | 
|  | character-times (via {{< regref "CTRL.RXBLVL" >}}, either 2, 4, 8, or 16). A | 
|  | character time is 10 bit-times if parity is disabled (START + 8 data + | 
|  | STOP) or 11 bit-times if parity is enabled (START + 8 data + parity + | 
|  | STOP). If the UART is connected to an external connector this would | 
|  | typically indicate the cable has been disconnected (or there is a | 
|  | break in the wire). If the UART is connected to another part on the | 
|  | same board it would typically indicate the other part has reset or | 
|  | rebooted. (If the open connector or resetting peer part causes the RX | 
|  | input to not be actively driven, then a pulldown resistor is needed to | 
|  | ensure a break and a pullup resistor will ensure the line looks idle | 
|  | and no break is generated.)  Note that only one interrupt is generated | 
|  | per break -- the line must return high for at least half a bit-time | 
|  | before an additional break interrupt is generated. The current break | 
|  | status can be read from the {{< regref "STATUS.BREAK" >}} bit. If STATUS.BREAK is set | 
|  | but {{< regref "INTR_STATE.BREAK" >}} is clear then the line break has already caused | 
|  | an interrupt that has been cleared but the line break is still going | 
|  | on. If {{< regref "STATUS.BREAK" >}} is clear but {{< regref "INTR_STATE.BREAK" >}} is set then | 
|  | there has been a line break for which software has not cleared the | 
|  | interrupt but the line is now back to normal. | 
|  |  | 
|  | #### rx_frame_err | 
|  | The `rx_frame_err` interrupt is triggered if the RX module receives the `START` | 
|  | bit (**0**) and a series of data bits but did not detect the `STOP` bit | 
|  | (**1**). This can happen because of noise affecting the line or if the | 
|  | transmitter clock is fast or slow compared to the receiver. In a real frame | 
|  | error the stop bit will be present just at an incorrect time so the line will | 
|  | continue to signal both high and low. The start of a line break (described | 
|  | above) matches a frame error with all data bits zero and one frame error | 
|  | interrupt will be raised. If the line stays zero until the break error occurs, | 
|  | the frame error will be set at every char-time. Frame errors will continue to | 
|  | be reported after a break error. | 
|  |  | 
|  | {{< wavejson >}} | 
|  | { | 
|  | signal: [ | 
|  | { name: 'Baud Clock',        wave: 'p............'                                                 }, | 
|  | { name: 'rx',                wave: '10333333330..', data: [ "lsb", "", "", "", "", "", "", "msb" ] }, | 
|  | {}, | 
|  | { name: 'intr_rx_frame_err', wave: '0..........1.'}, | 
|  | ], | 
|  | head: { | 
|  | text: 'Serial Receive with Framing Error', | 
|  | }, | 
|  | foot: { | 
|  | text: [ | 
|  | 'tspan', | 
|  | ['tspan', 'start bit '], | 
|  | ['tspan', {class:'info h4'}, '0'], | 
|  | ['tspan', ' at cycle -1, stop bit '], | 
|  | ['tspan', {class:'error h4'}, '1'], | 
|  | ['tspan', ' missing at cycle 8'], | 
|  | ], | 
|  | tock: -2, | 
|  | } | 
|  | } | 
|  | {{< /wavejson >}} | 
|  |  | 
|  | The effects of the line being low for certain periods are summarized | 
|  | in the table: | 
|  |  | 
|  | |Line low (bit-times) | Frame Err? | Break? | Comment | | 
|  | |---------------------|------------|--------|---------| | 
|  | |<10                  | If STOP=0  | No     | Normal operation | | 
|  | |10 (with parity)     | No         | No     | Normal zero data with STOP=1 | | 
|  | |10 (no parity)       | Yes        | No     | Frame error since STOP=0 | | 
|  | |11 - RXBLVL*char     | Yes        | No     | Break less than detect level | | 
|  | |\>RXBLVL*char        | Yes        | Once   | Frame error signalled at every char-time, break at RXBLVL char-times| | 
|  |  | 
|  | #### rx_timeout | 
|  | The `rx_timeout` interrupt is triggered when the RX FIFO has data sitting in it | 
|  | without software reading it for a programmable number of bit times (using the | 
|  | baud rate clock as reference, programmable via {{< regref "TIMEOUT_CTRL" >}}). This is used to | 
|  | alert software that it has data still waiting in the FIFO that has not been | 
|  | handled yet. The timeout counter is reset whenever the FIFO depth is changed or | 
|  | an `rx_timeout` event occurs. If the RX FIFO is full and new character is | 
|  | received, it won't reset the timeout value. The software is responsible for | 
|  | keeping the RX FIFO in the level below the watermark. The actual timeout time | 
|  | can vary based on the reset of the timeout timer and the start of the | 
|  | transaction. For instance, if the software resets the timeout timer by reading a | 
|  | character from the RX FIFO and right after it there is a baud clock tick and the | 
|  | start of a new RX transaction from the host, the timeout time is reduced by 1 | 
|  | and half baud clock periods. | 
|  |  | 
|  | #### rx_partity_err | 
|  | The `rx_parity_err` interrupt is triggered if parity is enabled and | 
|  | the RX parity bit does not match the expected polarity as programmed | 
|  | in {{< regref "CTRL.PARITY_ODD" >}}. | 
|  |  | 
|  | # Programmers Guide | 
|  |  | 
|  | ## Initialization | 
|  |  | 
|  | The following code snippet demonstrates initializing the UART to a programmable | 
|  | baud rate, clearing the RX and TX FIFO, setting up the FIFOs for interrupt | 
|  | levels, and enabling some interrupts. The NCO register controls the baud rate, | 
|  | and should be set using the equation below, where `f_pclk` is the fixed clock | 
|  | frequency and `f_baud` is the baud rate in bits per second. The UART uses the | 
|  | primary clock `clk_i` as a clock source. | 
|  |  | 
|  | $$ NCO = {{2^{20} * f\_{baud}} \over {f\_{pclk}}} $$ | 
|  |  | 
|  | Note that the NCO result from the above formula can be a fraction but | 
|  | the NCO register only accepts an integer value. See the the | 
|  | [Reception](#reception) and [Setting the baud | 
|  | rate](#setting-the-baud-rate) sections for more discussion of the | 
|  | baud rate error target and when care is needed. | 
|  |  | 
|  | Also note that because the baud rate is multiplied by 2^20 care is | 
|  | needed not to overflow 32-bit registers. Baud rates can easily be more | 
|  | than 12 bits. The code below is careful to force 64-bit | 
|  | arithmetic. (Even if the complier is pre-computing constants there can | 
|  | be unexpected overflow). | 
|  |  | 
|  | ```cpp | 
|  | #define CLK_FIXED_FREQ_HZ (50ULL * 1000 * 1000) | 
|  |  | 
|  | void uart_init(unsigned int baud) { | 
|  | // nco = 2^20 * baud / fclk. Assume NCO width is 16bit. | 
|  | uint64_t uart_ctrl_nco = ((uint64_t)baud << 20) / CLK_FIXED_FREQ_HZ; | 
|  | REG32(UART_CTRL(0)) = | 
|  | ((uart_ctrl_nco & UART_CTRL_NCO_MASK) << UART_CTRL_NCO_OFFSET) | | 
|  | (1 << UART_CTRL_TX) | | 
|  | (1 << UART_CTRL_RX); | 
|  |  | 
|  | // clear FIFOs and set up to interrupt on any RX, half-full TX | 
|  | *UART_FIFO_CTRL_REG = | 
|  | UART_FIFO_CTRL_RXRST                 | // clear both FIFOs | 
|  | UART_FIFO_CTRL_TXRST                 | | 
|  | (UART_FIFO_CTRL_RXILVL_RXFULL_1 <<3) | // intr on RX 1 character | 
|  | (UART_FIFO_CTRL_TXILVL_TXFULL_16<<5) ; // intr on TX 16 character | 
|  |  | 
|  | // enable only RX, overflow, and error interrupts | 
|  | *UART_INTR_ENABLE_REG = | 
|  | UART_INTR_ENABLE_RX_WATERMARK_MASK  | | 
|  | UART_INTR_ENABLE_TX_OVERFLOW_MASK   | | 
|  | UART_INTR_ENABLE_RX_OVERFLOW_MASK   | | 
|  | UART_INTR_ENABLE_RX_FRAME_ERR_MASK  | | 
|  | UART_INTR_ENABLE_RX_PARITY_ERR_MASK; | 
|  |  | 
|  | // at the processor level, the UART interrupts should also be enabled | 
|  | } | 
|  | ``` | 
|  |  | 
|  | ## Common Examples | 
|  |  | 
|  | The following code shows the steps to transmit a string of characters. | 
|  |  | 
|  | ```cpp | 
|  | int uart_tx_rdy() { | 
|  | return ((*UART_FIFO_STATUS_REG & UART_FIFO_STATUS_TXLVL_MASK) == 32) ? 0 : 1; | 
|  | } | 
|  |  | 
|  | void uart_send_char(char val) { | 
|  | while(!uart_tx_rdy()) {} | 
|  | *UART_WDATA_REG = val; | 
|  | } | 
|  |  | 
|  | void uart_send_str(char *str) { | 
|  | while(*str != '\0') { | 
|  | uart_send_char(*str++); | 
|  | } | 
|  | ``` | 
|  |  | 
|  | Do the following to receive a character, with -1 returned if RX is empty. | 
|  |  | 
|  | ```cpp | 
|  | int uart_rx_empty() { | 
|  | return ((*UART_FIFO_STATUS_REG & UART_FIFO_STATUS_RXLVL_MASK) == | 
|  | (0 << UART_FIFO_STATUS_RXLVL_LSB)) ? 1 : 0; | 
|  | } | 
|  |  | 
|  | int uart_rcv_char() { | 
|  | if(uart_rx_empty()) | 
|  | return -1; | 
|  | return *UART_RDATA_REG; | 
|  | } | 
|  | ``` | 
|  |  | 
|  | ## Interrupt Handling | 
|  |  | 
|  | The code below shows one example of how to handle all UART interrupts | 
|  | in one service routine. | 
|  |  | 
|  | ```cpp | 
|  | void uart_interrupt_routine() { | 
|  | volatile uint32 intr_state = *UART_INTR_STATE_REG; | 
|  | uint32 intr_state_mask = 0; | 
|  | char uart_ch; | 
|  | uint32 intr_enable_reg; | 
|  |  | 
|  | // Turn off Interrupt Enable | 
|  | intr_enable_reg = *UART_INTR_ENABLE_REG; | 
|  | *UART_INTR_ENABLE_REG = intr_enable_reg & 0xFFFFFF00; // Clr bits 7:0 | 
|  |  | 
|  | if (intr_state & UART_INTR_STATE_RX_PARITY_ERR_MASK) { | 
|  | // Do something ... | 
|  |  | 
|  | // Store Int mask | 
|  | intr_state_mask |= UART_INTR_STATE_RX_PARITY_ERR_MASK; | 
|  | } | 
|  |  | 
|  | if (intr_state & UART_INTR_STATE_RX_BREAK_ERR_MASK) { | 
|  | // Do something ... | 
|  |  | 
|  | // Store Int mask | 
|  | intr_state_mask |= UART_INTR_STATE_RX_BREAK_ERR_MASK; | 
|  | } | 
|  |  | 
|  | // .. Frame Error | 
|  |  | 
|  | // TX/RX Overflow Error | 
|  |  | 
|  | // RX Int | 
|  | if (intr_state & UART_INTR_STATE_RX_WATERMARK_MASK) { | 
|  | while(1) { | 
|  | uart_ch = uart_rcv_char(); | 
|  | if (uart_ch == 0xff) break; | 
|  | uart_buf.append(uart_ch); | 
|  | } | 
|  | // Store Int mask | 
|  | intr_state_mask |= UART_INTR_STATE_RX_WATERMARK_MASK; | 
|  | } | 
|  |  | 
|  | // Clear Interrupt State | 
|  | *UART_INTR_STATE_REG = intr_state_mask; | 
|  |  | 
|  | // Restore Interrupt Enable | 
|  | *UART_INTR_ENABLE_REG = intr_enable_reg; | 
|  | } | 
|  | ``` | 
|  |  | 
|  | One use of the `rx_timeout` interrupt is when the {{< regref "FIFO_CTRL.RXILVL" >}} | 
|  | is set greater than one, so an interrupt is only fired when the fifo | 
|  | is full to a certain level. If the remote device sends fewer than the | 
|  | watermark number of characters before stopping sending (for example it | 
|  | is waiting an acknowledgement) then the usual `rx_watermark` interrupt | 
|  | would not be raised. In this case an `rx_timeout` would generate an | 
|  | interrupt that allows the host to read these additional characters. The | 
|  | `rx_timeout` can be selected based on the worst latency experienced by a | 
|  | character. The worst case latency experienced by a character will happen | 
|  | if characters happen to arrive just slower than the timeout: the second | 
|  | character arrives just before the timeout for the first (resetting the | 
|  | timer), the third just before the timeout from the second etc. In this | 
|  | case the host will eventually get a watermark interrupt, this will happen | 
|  | `((RXILVL - 1)*timeout)` after the first character was received. | 
|  |  | 
|  | ## Device Interface Functions (DIFs) | 
|  |  | 
|  | {{< dif_listing "sw/device/lib/dif/dif_uart.h" >}} | 
|  |  | 
|  | ## Register Table | 
|  |  | 
|  | {{< registers "hw/ip/uart/data/uart.hjson" >}} |