Livt packages
Livt.IO
Version 1.8.1
Memory, UART, I2C, SPI, and Ethernet input/output components for Livt hardware designs.
Published files (126)
- BufferedUartApiTest.lvt
- BufferedUartPermissionTest.lvt
- BufferedUartTest.lvt
- ConcurrentUartTest.lvt
- LoopbackUartTest.lvt
- RtsCtsBufferedUartSmokeTest.lvt
- RtsCtsBufferedUartTest.lvt
- UartBaudConfigurationTest.lvt
- UartCapacityTest.lvt
- UartFrameConfigurationTest.lvt
- UartReceiverTest.lvt
- UartSynthesisConfigurationTest.lvt
- UartTest.lvt
- UartTransmitterTest.lvt
tests/uart/BufferedUartTest.lvt
namespace Livt.IO.Tests
using Livt.IO
/**
* Exercises BufferedUart with a shared fixture instance. Each scenario establishes the
* inputs and state it needs.
*/
@Test
@Context(ClockFrequency = 100MHz)
component BufferedUartTest
{
// Independent default-baud timing tolerates scheduled serial-stimulus overhead.
const TICKS_PER_BIT: int = 868
// Shared fixture instances, signals, and observation state.
controller: BufferedUart<3, 3>
// Shared fixture instances, signals, and observation state.
loopback_uart: BufferedUart<3, 3>
// Shared fixture instances, signals, and observation state.
rx: logic = 0b1
// Shared fixture instances, signals, and observation state.
tx: logic
// Shared fixture instances, signals, and observation state.
loopback_rx: logic = 0b1
// Shared fixture instances, signals, and observation state.
loopback_tx: logic
/**
* Creates the shared fixture instances (BufferedUart). Tests initialize the state required
* by their scenario.
*/
new()
{
this.controller = new BufferedUart<3, 3>(this.rx, this.tx)
this.loopback_rx = this.loopback_tx
this.loopback_uart = new BufferedUart<3, 3>(this.loopback_rx, this.loopback_tx)
}
/**
* Checks the initial state case.
*/
@Test
fn TestInitialState()
{
// Verify initial state
assert this.controller.GetReceiveCount() == 0
assert this.controller.GetTransmitSpace() == 3
assert this.controller.GetReceiveCount() == 0
assert this.controller.IsTransmitting() == 0b0
}
/**
* Checks the transmit single byte case.
*/
@Test
fn TestTransmitSingleByte()
{
// Queue a byte for transmission
var result = this.controller.TryTransmit(0xAA)
assert result == true // Should succeed
// Wait for automatic transmission to start and complete
Simulation.Wait(TICKS_PER_BIT * 15)
// Check transmission occurred (tx line should be back to idle)
assert this.tx == 0b1
// Buffer should be empty again
Simulation.Wait(10)
assert this.controller.GetTransmitSpace() == 3
}
/**
* Checks the transmit multiple bytes case.
*/
@Test
fn TestTransmitMultipleBytes()
{
// Queue multiple bytes
assert this.controller.TryTransmit(0x12) == 0b1
assert this.controller.TryTransmit(0x34) == 0b1
assert this.controller.TryTransmit(0x56) == 0b1
// Check buffer usage
assert this.controller.GetTransmitSpace() > 0
// Wait for all transmissions to complete
// Each byte takes ~10 bit periods
Simulation.Wait(TICKS_PER_BIT * 35)
// All should be transmitted
assert this.tx == 0b1
Simulation.Wait(10)
assert this.controller.GetTransmitSpace() == 3
}
/**
* Checks the transmit buffer full case.
*/
@Test
fn TestTransmitBufferFull()
{
// Fill the buffer in a tight loop (faster than transmission)
for (var i = 0; i < 3 + 1; i++) {
var result = this.controller.TryTransmit(0x55)
assert result == 0b1
}
// Buffer should be full
assert this.controller.GetTransmitSpace() == 0
// Buffer should be full NOW (first byte still transmitting)
// Try immediately without waiting
var overflow_result = this.controller.TryTransmit(0xFF)
assert overflow_result == 0b0
// Wait for buffer to drain completely
Simulation.Wait(TICKS_PER_BIT * ((3 + 2) * 12))
assert this.controller.GetTransmitSpace() == 3
}
/**
* Checks the receive single byte case.
*/
@Test
fn TestReceiveSingleByte()
{
// Initially no data available
assert this.controller.GetReceiveCount() == 0
// Send a byte on RX line (0x55)
this.rx = 0b1
Simulation.Wait(100)
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
// Send 0x55 = 01010101, LSB first: 1,0,1,0,1,0,1,0
this.rx = 0b1 // Bit 0
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 1
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 2
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 3
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 4
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 5
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 6
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 7
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
// Data should be available
assert this.controller.GetReceiveCount() > 0
assert this.controller.GetReceiveCount() == 1
// Receive the byte
var data: byte
assert this.controller.TryReceive(data) == true
assert data == 0x55
// No more data available
assert this.controller.GetReceiveCount() == 0
assert this.controller.GetReceiveCount() == 0
// Return to idle
this.rx = 0b1
Simulation.Wait(10)
}
/**
* Checks the receive multiple bytes case.
*/
@Test
fn TestReceiveMultipleBytes()
{
// Send first byte (0xAA)
this.rx = 0b1
Simulation.Wait(100)
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
// 0xAA = 10101010, LSB first: 0,1,0,1,0,1,0,1
this.rx = 0b0 // Bit 0
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 1
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 2
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 3
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 4
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 5
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 6
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 7
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
// Send second byte (0x55)
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
// 0x55 = 01010101, LSB first: 1,0,1,0,1,0,1,0
this.rx = 0b1 // Bit 0
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 1
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 2
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 3
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 4
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 5
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 6
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 7
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
// Should have 2 bytes available
assert this.controller.GetReceiveCount() == 2
// Receive in order
var byte1: byte
assert this.controller.TryReceive(byte1) == true
assert byte1 == 0xAA
var byte2: byte
assert this.controller.TryReceive(byte2) == true
assert byte2 == 0x55
// Buffer should be empty
assert this.controller.GetReceiveCount() == 0
// Return to idle
this.rx = 0b1
Simulation.Wait(10)
}
/**
* Checks the receive buffer full case.
*/
@Test
fn TestReceiveBufferFull()
{
// Fill receive buffer by sending BUFFER_SIZE bytes
this.rx = 0b1
Simulation.Wait(100)
for (var i = 0; i < 3; i = i + 1) {
// Send a byte (value = i)
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
// Send 8 data bits (all zeros for simplicity)
for (var j = 0; j < 8; j = j + 1) {
this.rx = 0b0
Simulation.Wait(TICKS_PER_BIT)
}
this.rx = 0b1 // Stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
}
// Buffer should be full
assert this.controller.GetReceiveCount() == 3
// Send one more byte - should be dropped
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
for (var j = 0; j < 8; j = j + 1) {
this.rx = 0b1 // Send 0xFF
Simulation.Wait(TICKS_PER_BIT)
}
this.rx = 0b1 // Stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
// Still should have only BUFFER_SIZE bytes
assert this.controller.GetReceiveCount() == 3
// Return to idle
this.rx = 0b1
Simulation.Wait(10)
}
/**
* Checks the frame error does not queue data case.
*/
@Test
fn TestFrameErrorDoesNotQueueData()
{
this.controller.ClearReceiveBuffer()
this.controller.ClearErrors()
this.rx = 0b1
Simulation.Wait(100)
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
// Send 0xC3 = 11000011, LSB first: 1,1,0,0,0,0,1,1
this.rx = 0b1 // Bit 0
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 1
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 2
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 3
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 4
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 5
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 6
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 7
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Invalid stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
assert this.controller.GetReceiveCount() == 0
assert this.controller.GetFrameErrorCount() > 0
assert this.controller.GetFrameErrorCount() == 1
this.rx = 0b1
Simulation.Wait(TICKS_PER_BIT * 2)
// Send a valid frame to confirm recovery.
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
// Send 0x3C = 00111100, LSB first: 0,0,1,1,1,1,0,0
this.rx = 0b0 // Bit 0
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 1
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 2
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 3
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 4
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Bit 5
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 6
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b0 // Bit 7
Simulation.Wait(TICKS_PER_BIT)
this.rx = 0b1 // Stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
assert this.controller.GetReceiveCount() == 1
var receivedByte1: byte
assert this.controller.TryReceive(receivedByte1) == true
assert receivedByte1 == 0x3C
assert this.controller.GetFrameErrorCount() == 1
}
/**
* Checks the clear receive buffer case.
*/
@Test
fn TestClearReceiveBuffer()
{
this.controller.ClearReceiveBuffer()
// Send a byte
this.rx = 0b1
Simulation.Wait(100)
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
for (var i = 0; i < 8; i = i + 1) {
this.rx = 0b1
Simulation.Wait(TICKS_PER_BIT)
}
this.rx = 0b1 // Stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
// Should have data
assert this.controller.GetReceiveCount() == 1
// Clear buffer
this.controller.ClearReceiveBuffer()
// Should be empty
assert this.controller.GetReceiveCount() == 0
assert this.controller.GetReceiveCount() == 0
// Return to idle
this.rx = 0b1
Simulation.Wait(10)
}
/**
* Checks the clear transmit buffer case.
*/
@Test
fn TestClearTransmitBuffer()
{
// Queue some bytes
this.controller.TryTransmit(0x12)
this.controller.TryTransmit(0x34)
// Wait a tiny bit (not enough to transmit)
Simulation.Wait(10)
// Clear transmit buffer
this.controller.ClearTransmitBuffer()
// Buffer should be empty
assert this.controller.GetTransmitSpace() == 3
// Wait to ensure nothing transmits
Simulation.Wait(TICKS_PER_BIT * 25)
// Should still be idle
assert this.tx == 0b1
}
/**
* Checks the receive empty buffer case.
*/
@Test
fn TestReceiveEmptyBuffer()
{
this.controller.ClearReceiveBuffer()
// Try to receive from empty buffer
assert this.controller.GetReceiveCount() == 0
var data: byte
assert this.controller.TryReceive(data) == false
// Should return 0x00 when buffer is empty
assert data == 0x00
// Buffer should still be empty
assert this.controller.GetReceiveCount() == 0
}
/**
* Checks the clear frame errors case.
*/
@Test
fn TestClearFrameErrors()
{
this.controller.ClearErrors()
// Create a framing error.
this.rx = 0b1
Simulation.Wait(100)
this.rx = 0b0 // Start bit
Simulation.Wait(TICKS_PER_BIT)
for (var i = 0; i < 8; i = i + 1) {
this.rx = 0b0
Simulation.Wait(TICKS_PER_BIT)
}
this.rx = 0b0 // Invalid stop bit
Simulation.Wait(TICKS_PER_BIT * 2)
assert this.controller.GetFrameErrorCount() > 0
assert this.controller.GetFrameErrorCount() == 1
this.controller.ClearErrors()
assert this.controller.GetFrameErrorCount() == 0
assert this.controller.GetFrameErrorCount() == 0
this.rx = 0b1
Simulation.Wait(10)
}
/**
* Checks the loopback transmit receive case.
*/
@Test
fn TestLoopbackTransmitReceive()
{
this.loopback_uart.ClearReceiveBuffer()
this.loopback_uart.ClearTransmitBuffer()
// Transmit a byte
this.loopback_uart.TryTransmit(0x42)
// Wait for transmission to start
Simulation.Wait(TICKS_PER_BIT * 9)
// Wait a bit more for reception to complete
Simulation.Wait(TICKS_PER_BIT * 2)
// Should have received the byte
assert this.loopback_uart.GetReceiveCount() > 0
var received: byte
assert this.loopback_uart.TryReceive(received) == true
assert received == 0x42
}
}