Livt packages
Livt.IO
Version 1.8.1
Memory, UART, I2C, SPI, and Ethernet input/output components for Livt hardware designs.
Published files (126)
- phy
- EthernetCrc.lvt
- EthernetReceiver.lvt
- EthernetResult.lvt
- EthernetTransmitter.lvt
- IEthernetLinkStatus.lvt
- IEthernetMedia.lvt
- IEthernetReceiver.lvt
- IEthernetTransmitter.lvt
- IMdioController.lvt
- IMdioPins.lvt
- IMiiPins.lvt
- IRmiiPins.lvt
- MdioController.lvt
- MiiAdapter.lvt
- MiiClearEndpoint.lvt
- MiiClockBridge.lvt
- MiiCompletionReceiver.lvt
- MiiFifoStorage.lvt
- MiiReadBuffer.lvt
- MiiReceiver.lvt
- MiiTransmitter.lvt
- RmiiAdapter.lvt
src/ethernet/MiiReceiver.lvt
namespace Livt.IO
/**
* Captures low-nibble-first MII bytes in the PHY receive clock domain.
* Tokens contain data[7:0], start[8], end[9], error[10]. End is a separate
* token. Overflow discards the rest of the frame and eventually emits an error
* terminator; a partial frame can never silently join the following frame.
*/
component MiiReceiver
{
// First-byte token marker.
const FRAME_START: logic[11] = 0x100
// Separate frame-termination token marker.
const FRAME_END: logic[11] = 0x200
// Damaged-frame token marker.
const FRAME_ERROR: logic[11] = 0x400
// Borrowed PHY data/control and FIFO admission in the RX clock domain.
rxData: logic[4]
rxValid: logic
rxError: logic
ready: bool
// Partial-byte assembly and sticky frame/error tracking.
low: logic[4]
half: bool
active: bool
first: bool = true
bad: bool
ending: bool
// Token publication; a pending terminator remains valid until accepted.
public valid: out bool
public data: out logic[11]
/**
* Borrows physical RX pins and FIFO admission in the receive domain.
*/
new(domain: IContext, rxData: logic[4], rxValid: logic, rxError: logic, ready: bool)
{
this.context = domain
this.rxData = rxData
this.rxValid = rxValid
this.rxError = rxError
this.ready = ready
}
/**
* Publishes a byte on the high nibble edge, or a pending frame terminator.
*/
process Ports[]()
{
this.valid = ending || (rxValid == 0b1 && half && !bad)
var token = ((rxData as logic[11]) << 4) | (low as logic[11])
if (first) {
token = token | FRAME_START
}
if (ending) {
token = FRAME_END
}
if (bad || rxError == 0b1) {
token = token | FRAME_ERROR
}
this.data = token
}
/**
* Tracks framing and never resumes capture in the middle of a lost frame.
*/
process Capture()
{
state {
if (ending) {
if (ready) {
this.ending = false
this.active = false
this.first = true
this.half = false
this.bad = rxValid == 0b1
}
} elif (rxValid == 0b1) {
this.active = true
if (rxError == 0b1) {
this.bad = true
}
if (half) {
if (!ready) {
this.bad = true
}
this.first = false
} else {
this.low = rxData
}
this.half = !half
} elif (active) {
this.bad = bad || half
this.ending = true
} else {
this.bad = false
}
}
}
}