Livt packages
Eccelerators.RiscV
Version 0.3.0
Composable RV32I and Zmmul processors, machine-mode support, and reusable FPGA system components written in Livt.
Published files (120)
src/Platform/RvUartDevice.lvt
namespace Eccelerators.RiscV.Platform
using Eccelerators.RiscV.Sequential
using Livt.IO
/**
* Load/store adapter borrowing a buffered UART in the same clock/reset domain.
* Registers are aligned words: TX at BASE, status at BASE+4, RX at BASE+8.
* Status bits are TX space (0), RX available (1), sticky receive error (2).
* TX writes use lane zero; other enabled lanes fault before effects. A zero
* mask is a no-op. RX reads consume at most one byte and return zero if empty.
* TX reads and writes to status/RX fault. Requests and responses remain stable
* until the caller releases request. A full TX FIFO backpressures a store.
* The owner may use the UART directly only while this adapter is quiescent.
*/
component RvUartDevice<BASE: uint = 0x40000000> : IRv32LoadStorePort
{
static assert (BASE & 3) == 0 && BASE <= 0xfffffff4, "UART window must be aligned and must not wrap"
// Borrowed scheduled transport; this adapter serializes all CPU side effects.
uart: IBufferedUart
/**
* Borrows an already constructed UART; pins and FIFO sizes remain its owner's choice.
*/
new(uart: IBufferedUart)
{
this.uart = uart
}
/**
* Accepts one stable request, performs its effect once, then holds completion.
*/
process Serve()
{
while (request == 0b0) {
state {
}
}
var location: uint = 0
var store: bool = false
var lanes: logic[4] = 0
var payload: byte = 0
state {
location = address as uint
store = write == 0b1
lanes = byteEnable
payload = writeData as byte
error = 0b0
readData = 0
}
if (location < BASE || location - BASE >= 12 || (location & 3) != 0) {
error = 0b1
} elif (store) {
if (location != BASE || (lanes & 0b1110) != 0) {
error = 0b1
} elif (lanes == 0b0001) {
while (!uart.TryTransmit(payload)) {
state {
}
}
}
} elif (location == BASE + 4) {
var status: uint = 0
if (uart.GetTransmitSpace() > 0) {
status = status | 1
}
if (uart.GetReceiveCount() > 0) {
status = status | 2
}
if (uart.GetFrameErrorCount() > 0 || uart.GetReceiveOverflowCount() > 0) {
status = status | 4
}
readData = status as logic[32]
} elif (location == BASE + 8) {
var received: byte = 0
uart.TryReceive(received)
readData = received as logic[32]
} else {
error = 0b1
}
state {
ready = 0b1
}
while (request == 0b1) {
state {
}
}
state {
ready = 0b0
error = 0b0
}
}
}