Livt packages
Livt.IO
Version 1.8.1
Memory, UART, I2C, SPI, and Ethernet input/output components for Livt hardware designs.
Published files (126)
tests/i2c/I2cMasterTest.lvt
namespace Livt.IO.Tests
using Livt.IO
/**
* Test bus adapter that exposes observed line levels and low-drive requests without
* physical board pins.
*/
component I2CMasterTestBus : I2CBus
{
// Shared fixture instances, signals, and observation state.
observed_scl: logic
observed_sda: logic
/**
* Initializes fixture state and constructor bindings. Test cases share the fixture
* instance rather than constructing a fresh subject for each method.
*/
new()
{
this.observed_scl = 0b1
this.observed_sda = 0b1
}
/**
* Publishes the fixture SCL/SDA levels in the test clock context.
*/
process ApplyObservedLines()
{
state {
this.scl = this.observed_scl
this.sda = this.observed_sda
}
}
/**
* Sets the SCL/SDA levels that the fixture will present to the component under test.
*/
public fn SetObservedLines(sclValue: logic, sdaValue: logic)
{
state {
this.observed_scl = sclValue
this.observed_sda = sdaValue
}
}
}
/**
* Exercises I2CMaster with a shared fixture instance. Each scenario establishes the inputs
* and state it needs.
*/
@Test
component I2CMasterTest
{
// Shared fixture instances, signals, and observation state.
bus: I2CMasterTestBus
master: I2CMaster
/**
* Creates the shared fixture instances (I2CMasterTestBus, I2CMaster). Tests initialize the
* state required by their scenario.
*/
new()
{
this.bus = new I2CMasterTestBus()
this.master = new I2CMaster(this.bus)
}
/**
* Waits until the master is no longer busy; the test runner timeout bounds a stalled
* command.
*/
fn WaitForCommand()
{
while (this.master.IsBusy()) {
state {
}
}
}
/**
* Checks the busy rejects second command case.
*/
@Test
fn TestBusyRejectsSecondCommand()
{
this.bus.SetObservedLines(0b1, 0b1)
var started: bool = this.master.BeginStart()
var rejected: bool = this.master.BeginStop()
assert started == true
assert rejected == false
assert this.master.IsBusy() == true
this.WaitForCommand()
assert this.master.IsBusy() == false
assert this.master.HasResult() == true
this.master.ClearResult()
assert this.master.HasResult() == false
}
/**
* Checks that a byte write without a responding target completes with NACK.
*/
@Test
fn TestWriteWithoutTargetReportsNack()
{
this.bus.SetObservedLines(0b1, 0b1)
var accepted: bool = this.master.BeginWriteByte(0x55)
assert accepted == true
this.WaitForCommand()
assert this.master.HasResult() == true
assert this.master.WasAckReceived() == false
assert this.master.WasNackReceived() == true
}
/**
* Checks that an external target ACK is retained after the byte write.
*/
@Test
fn TestWriteWithExternalAckReportsAck()
{
this.bus.SetObservedLines(0b1, 0b0)
var accepted: bool = this.master.BeginWriteByte(0x55)
assert accepted == true
this.WaitForCommand()
assert this.master.HasResult() == true
assert this.master.WasAckReceived() == true
assert this.master.WasNackReceived() == false
}
/**
* Checks that BeginWriteAddress sends shifted write address.
*/
@Test
fn TestBeginWriteAddressSendsShiftedWriteAddress()
{
this.bus.SetObservedLines(0b1, 0b0)
var accepted: bool = this.master.BeginWriteAddress(0x42)
assert accepted == true
this.WaitForCommand()
assert this.master.HasResult() == true
assert this.master.WasAckReceived() == true
}
/**
* Checks that BeginReadAddress sends shifted read address.
*/
@Test
fn TestBeginReadAddressSendsShiftedReadAddress()
{
this.bus.SetObservedLines(0b1, 0b0)
var accepted: bool = this.master.BeginReadAddress(0x42)
assert accepted == true
this.WaitForCommand()
assert this.master.HasResult() == true
assert this.master.WasAckReceived() == true
}
/**
* Checks the address helpers reject invalid seven bit address case.
*/
@Test
fn TestAddressHelpersRejectInvalidSevenBitAddress()
{
this.bus.SetObservedLines(0b1, 0b1)
this.master.ClearResult()
assert this.master.BeginWriteAddress(0x80) == false
assert this.master.BeginReadAddress(0x80) == false
assert this.master.IsBusy() == false
assert this.master.HasResult() == false
}
/**
* Checks that Read released line returns all ones.
*/
@Test
fn TestReadReleasedLineReturnsAllOnes()
{
this.bus.SetObservedLines(0b1, 0b1)
var accepted: bool = this.master.BeginReadByte(false)
assert accepted == true
this.WaitForCommand()
assert this.master.HasResult() == true
assert this.master.GetReadByte() == 0xFF
}
/**
* Checks the clock stretch keeps master busy until scl released case.
*/
@Test
fn TestClockStretchKeepsMasterBusyUntilSclReleased()
{
this.bus.SetObservedLines(0b0, 0b1)
var accepted: bool = this.master.BeginStop()
assert accepted == true
Simulation.Wait(this.master.HalfPeriodTicks() * 2)
assert this.master.IsBusy() == true
this.bus.SetObservedLines(0b1, 0b1)
this.WaitForCommand()
assert this.master.IsBusy() == false
assert this.master.HasResult() == true
}
}