Livt packages
Livt.Usb
Version 0.0.5
USB 2.0 low/full-speed PHY, host transfers, device discovery, HID keyboard, and read-only mass storage for Livt.
Published files (57)
src/io/Usb2Phy.lvt
namespace Livt.Usb.IO
using Livt.Usb
/**
* Low/full-speed USB PHY implemented in an inherited clock/reset context.
* Owns line sampling, encoding and pad direction; the link owns packet bytes,
* speed selection and bus-reset duration. Supports no high-speed negotiation.
* Board buffers connect separate input/output/enables and release on clock failure.
*/
component Usb2Phy : IUsb2Phy
{
// Rate validity also gates physical drive in builds that strip assertions.
const CLOCK_HZ: uint = this.context.TicksPer(1Hz)
const FULL_BIT_TICKS: uint = this.context.TicksPer(12MHz)
// Owned timing-critical paths and their combinational control bindings.
line: Usb2LineReceiver
receiver: Usb2PacketReceiver
transmitter: Usb2PacketTransmitter
receiveEnabled: bool
lineEnabled: bool
allowStart: bool
cancel: bool
// Board-facing single-ended pad controls; both output enables share ownership.
public dpOutput: out logic
public dmOutput: out logic
public dpEnable: out logic
public dmEnable: out logic
/**
* Binds raw input pins. The context must provide an integral number of samples
* per 12 MHz bit, at least eight. Change speed only while TX/RX are idle and
* bus reset is inactive.
*/
new(dpInput: logic, dmInput: logic)
{
line = new Usb2LineReceiver(dpInput, dmInput, this.speed, lineEnabled)
receiver = new Usb2PacketReceiver(this.speed, receiveEnabled, line.lineState,
line.bitTick, line.bitState, line.idle, line.se0, line.longSe0, line.invalid)
transmitter = new Usb2PacketTransmitter(this.speed, allowStart, cancel,
this.txValid, this.txData, this.keepAliveRequest)
}
/**
* Connects cycle-level streams, prioritizes bus reset and guards pad ownership.
*/
process Ports[]()
{
var clockValid = CLOCK_HZ % 12000000 == 0 && FULL_BIT_TICKS >= 8
var supported = clockValid && (speed == UsbSpeed.Low || speed == UsbSpeed.Full)
var resetting = this.context.rst == 0b1
cancel = resetting || busReset || !supported
lineEnabled = !cancel
receiveEnabled = !cancel && !transmitter.busy
allowStart = !cancel && !receiver.active && line.idle && line.modeReady
supportsLowSpeed = clockValid
supportsFullSpeed = clockValid
lineState = line.lineState
txReady = transmitter.ready
txBusy = transmitter.busy
keepAliveReady = transmitter.keepAliveReady
rxActive = receiver.active && receiveEnabled
rxValid = receiver.valid && receiveEnabled
rxData = receiver.data
rxError = receiver.error && !cancel
dpOutput = transmitter.output[1]
dmOutput = transmitter.output[0]
dpEnable = 0b0
dmEnable = 0b0
if (clockValid && !resetting && (busReset || transmitter.enable)) {
dpEnable = 0b1
dmEnable = 0b1
}
if (busReset) {
dpOutput = 0b0
dmOutput = 0b0
}
}
}