Skip to content

eccelerators/livt-uart

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

UART Components for Livt

This package provides a layered UART implementation in Livt, from low-level RX/TX blocks up to a buffered controller and a simple convenience wrapper for application code.

For background on the design approach and why this repository is structured as a stack from signal-level components up to application-facing APIs, see DESIGN_NOTE.md.

📋 Overview

The current package is organized around these main components:

  • UartReceiver receives bytes from a serial RX line.
  • UartTransmitter sends bytes on a serial TX line.
  • UartBase combines the receiver and transmitter into one component with explicit control signals.
  • BufferedUart adds 16-byte transmit and receive FIFOs on top of UartBase.
  • Uart wraps BufferedUart with a small application-friendly API, including an all-or-nothing Send(data: byte[]) helper.
  • LoopbackUart connects TX back to RX internally for testing and verification.

The UART framing is currently fixed to:

  • 8 data bits
  • 1 start bit
  • 1 stop bit
  • no parity

Both the receiver and transmitter default to TICKS_PER_BIT = 868, which corresponds to 115200 baud on a 100 MHz clock.

📁 Project Structure

.
├── src/
│   ├── UartReceiver.lvt
│   ├── UartTransmitter.lvt
│   ├── UartBase.lvt
│   ├── BufferedUart.lvt
│   ├── Uart.lvt
│   └── LoopbackUart.lvt
├── tests/
│   ├── UartReceiverTest.lvt
│   ├── UartTransmitterTest.lvt
│   ├── UartBaseTest.lvt
│   ├── BufferedUartTest.lvt
│   ├── UartTest.lvt
│   └── LoopbackUartTest.lvt
└── livt.toml

🔨 Building

Build the package with:

livt build

The package configuration is defined in livt.toml. The current project name there is Uart.

🧪 Running Tests

Run the full test suite with:

livt test

Configured test components:

  • UartReceiverTest
  • UartTransmitterTest
  • UartBaseTest
  • BufferedUartTest
  • UartTest
  • LoopbackUartTest

📚 Component Guide

UartReceiver

Low-level UART receiver.

  • Input: rx
  • Outputs: rx_dv, rx_byte, rx_frame_error
  • Helpers: IsDataValid(), GetData(), IsFrameError()

The receiver double-registers the input line before sampling, pulses rx_dv for one cycle when a byte is complete, and pulses rx_frame_error when a frame is rejected because of an invalid stop bit.

UartTransmitter

Low-level UART transmitter.

  • Inputs: tx_dv, tx_byte
  • Outputs: tx, tx_active, tx_done

Pulse tx_dv high to begin transmitting tx_byte. tx_active stays high while transmission is in progress, and tx_done pulses for one cycle at completion.

UartBase

Thin composition layer that instantiates UartReceiver and UartTransmitter together.

Use this component when you want direct control over the UART handshake and status signals.

BufferedUart

Higher-level controller built on top of UartBase.

Features:

  • 16-byte transmit FIFO
  • 16-byte receive FIFO
  • queued transmit API with backpressure
  • receive polling API
  • buffer management helpers

Public methods:

  • Transmit(data: logic[8]) bool
  • Receive() logic[8]
  • IsDataAvailable() bool
  • IsBusy() bool
  • GetAvailableBytes() int
  • GetTransmitSpace() int
  • HasFrameError() bool
  • GetFrameErrorCount() int
  • ClearReceiveBuffer()
  • ClearTransmitBuffer()
  • ClearFrameErrors()

Transmit() returns false when the transmit FIFO is full. Incoming received bytes are dropped if the receive FIFO is full.

Uart

Small convenience wrapper around BufferedUart in the Livt.IO namespace.

Public methods:

  • IsDataAvailable() bool
  • Receive() logic[8]
  • Transmit(data: logic[8]) bool
  • GetTransmitSpace() int
  • HasFrameError() bool
  • GetFrameErrorCount() int
  • ClearFrameErrors()
  • Send(data: byte[]) bool

Send() is all-or-nothing: it returns false without queueing any bytes if there is not enough transmit space for the full message.

LoopbackUart

Test-oriented wrapper around BufferedUart that internally connects TX back to RX.

Public methods:

  • Transmit(data: logic[8]) bool
  • Receive() logic[8]
  • IsDataAvailable() bool
  • GetAvailableBytes() int
  • GetTransmitSpace() int
  • IsBusy() bool
  • HasFrameError() bool
  • GetFrameErrorCount() int
  • ClearReceiveBuffer()
  • ClearTransmitBuffer()
  • ClearFrameErrors()

LoopbackUart is intended for simulation, verification, and self-test scenarios where transmitted bytes should immediately flow back through the receive path.

💡 Example

using Livt.IO

component MyComponent
{
	uart: Uart

	new(rx: in logic, tx: out logic)
	{
		this.uart = new Uart(rx, tx)
	}

	public fn SendHello()
	{
		var helloWorld = "Hello, World!".Encode()
		
		this.uart.Send(helloWorld)
	}
}

🔧 Configuration

To target a different clock or baud rate, update TICKS_PER_BIT in both:

Formula:

TICKS_PER_BIT = Clock Frequency / Baud Rate

For example, at 100 MHz and 115200 baud:

100000000 / 115200 = 868

📝 Notes

  • LoopbackUart is intended for simulation and verification, not for external serial IO.
  • The top-level Uart component currently delegates to BufferedUart, so transmit operations are queue-based rather than single-cycle direct sends.
  • This package no longer includes the older AXI4-Lite, Avalon, or Wishbone wrapper components described in the previous README.

🤝 Contributing

Contributions are welcome. Areas that would be natural extensions for this package include:

  • parity bit support
  • configurable stop bits
  • configurable buffer sizes
  • overflow reporting for dropped received bytes
  • configurable baud-rate settings without editing source constants

📄 License

This project is licensed under the MIT License.

About

A layered UART implementation in Livt, from low-level RX/TX blocks up to a buffered controller and a simple convenience wrapper for application code.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors