Livt packages
Livt.Bus
Version 2.0.1
Configurable Avalon, AXI4-Lite, and Wishbone memory-mapped masters, interfaces, bridges, and test components.
Published files (67)
src/bridges/AvalonToAxi4LiteBridge32.lvt
namespace Livt.Bus.Bridges
using Livt.Bus.Avalon
using Livt.Bus.Axi4Lite
/**
* Converts non-pipelined Avalon-MM transactions into AXI4-Lite transactions.
* The bridge supports one transaction at a time and preserves byte addresses,
* write byte enables, read data, and two-bit response values.
*/
component AvalonToAxi4LiteBridge32 : IAxi4Lite32Master
{
// Response returned to Avalon when a downstream AXI handshake times out.
public const RESPONSE_SLVERR: Logic[2] = 0b10
// Avalon-MM source connected to the upstream side of this bridge.
upstream: IAvalon32Master
// Maximum ticks to wait for each downstream AXI handshake stage.
timeoutTicks: uint
// True only when the most recent downstream transaction timed out.
lastTimedOut: bool
// True while a timed-out AXI transaction is being completed and discarded.
recovering: bool
/**
* Connects an Avalon-MM source and initializes the AXI4-Lite master outputs.
* The default timeout for each AXI handshake stage is 1 ms.
*/
new(upstream: flip IAvalon32Master)
{
this.upstream = upstream
this.upstream.readdata = 0x00000000
this.upstream.waitrequest = 0b1
this.upstream.response = 0b00
this.awaddr = 0x00000000
this.awprot = 0b000
this.awvalid = 0b0
this.wdata = 0x00000000
this.wstrb = 0b0000
this.wvalid = 0b0
this.bready = 0b0
this.araddr = 0x00000000
this.arprot = 0b000
this.arvalid = 0b0
this.rready = 0b0
this.timeoutTicks = this.context.TicksFor(1ms)
this.lastTimedOut = false
this.recovering = false
}
/**
* Sets the maximum ticks to wait for each downstream AXI handshake stage.
* The count is exact; zero times out on the first stalled evaluation.
* A timeout completes the Avalon request with RESPONSE_SLVERR.
*/
public fn SetTimeoutTicks(timeoutTicks: uint)
{
this.timeoutTicks = timeoutTicks
}
/**
* Returns the maximum ticks allowed for each downstream AXI handshake stage.
*/
public fn GetTimeoutTicks() uint
{
return timeoutTicks
}
/**
* Returns true when the most recent downstream AXI transaction timed out.
*/
public fn LastTimedOut() bool
{
return lastTimedOut
}
/**
* Returns true while the bridge drains a timed-out AXI transaction.
* New Avalon requests remain stalled until recovery completes.
*/
public fn IsRecovering() bool
{
return recovering
}
/**
* Captures Avalon requests and sequences the corresponding AXI channels.
* Write address and data handshakes are tracked independently.
*/
process Run()
{
var addressAccepted: bool = false
var dataAccepted: bool = false
var elapsed: uint = 0
state Idle {
recovering = false
this.upstream.waitrequest = 0b1
this.awvalid = 0b0
this.wvalid = 0b0
this.bready = 0b0
this.arvalid = 0b0
this.rready = 0b0
if (this.upstream.write == 0b1) {
lastTimedOut = false
this.awaddr = this.upstream.address
this.awprot = 0b000
this.awvalid = 0b1
this.wdata = this.upstream.writedata
this.wstrb = this.upstream.byteenable
this.wvalid = 0b1
addressAccepted = false
dataAccepted = false
elapsed = 0
goto WriteTransfer
} elif (this.upstream.read == 0b1) {
lastTimedOut = false
this.araddr = this.upstream.address
this.arprot = 0b000
this.arvalid = 0b1
elapsed = 0
goto ReadAddress
} else {
goto Idle
}
}
state WriteTransfer {
if (this.awready == 0b1) {
addressAccepted = true
this.awvalid = 0b0
}
if (this.wready == 0b1) {
dataAccepted = true
this.wvalid = 0b0
}
if (addressAccepted && dataAccepted) {
this.bready = 0b1
elapsed = 0
goto WriteResponse
} elif ((elapsed + 1) >= timeoutTicks) {
lastTimedOut = true
recovering = true
this.upstream.readdata = 0x00000000
this.upstream.response = RESPONSE_SLVERR
this.upstream.waitrequest = 0b0
goto RecoverWriteTransfer
} else {
elapsed = elapsed + 1
goto WriteTransfer
}
}
state WriteResponse {
if (this.bvalid == 0b1) {
this.bready = 0b0
this.upstream.response = this.bresp
this.upstream.waitrequest = 0b0
goto Accepted
} elif ((elapsed + 1) >= timeoutTicks) {
lastTimedOut = true
recovering = true
this.upstream.readdata = 0x00000000
this.upstream.response = RESPONSE_SLVERR
this.upstream.waitrequest = 0b0
goto RecoverWriteResponse
} else {
elapsed = elapsed + 1
goto WriteResponse
}
}
state ReadAddress {
if (this.arready == 0b1) {
this.arvalid = 0b0
this.rready = 0b1
elapsed = 0
goto ReadData
} elif ((elapsed + 1) >= timeoutTicks) {
lastTimedOut = true
recovering = true
this.upstream.readdata = 0x00000000
this.upstream.response = RESPONSE_SLVERR
this.upstream.waitrequest = 0b0
goto RecoverReadAddress
} else {
elapsed = elapsed + 1
goto ReadAddress
}
}
state ReadData {
if (this.rvalid == 0b1) {
this.rready = 0b0
this.upstream.readdata = this.rdata
this.upstream.response = this.rresp
this.upstream.waitrequest = 0b0
goto Accepted
} elif ((elapsed + 1) >= timeoutTicks) {
lastTimedOut = true
recovering = true
this.upstream.readdata = 0x00000000
this.upstream.response = RESPONSE_SLVERR
this.upstream.waitrequest = 0b0
goto RecoverReadData
} else {
elapsed = elapsed + 1
goto ReadData
}
}
state RecoverWriteTransfer {
this.upstream.waitrequest = 0b1
if (this.awready == 0b1) {
addressAccepted = true
this.awvalid = 0b0
}
if (this.wready == 0b1) {
dataAccepted = true
this.wvalid = 0b0
}
if (addressAccepted && dataAccepted) {
this.bready = 0b1
goto RecoverWriteResponse
} else {
goto RecoverWriteTransfer
}
}
state RecoverWriteResponse {
this.upstream.waitrequest = 0b1
if (this.bvalid == 0b1) {
this.bready = 0b0
goto Recovered
} else {
goto RecoverWriteResponse
}
}
state RecoverReadAddress {
this.upstream.waitrequest = 0b1
if (this.arready == 0b1) {
this.arvalid = 0b0
this.rready = 0b1
goto RecoverReadData
} else {
goto RecoverReadAddress
}
}
state RecoverReadData {
this.upstream.waitrequest = 0b1
if (this.rvalid == 0b1) {
this.rready = 0b0
goto Recovered
} else {
goto RecoverReadData
}
}
state Recovered {
if (this.upstream.write == 0b0 && this.upstream.read == 0b0) {
recovering = false
goto Idle
} else {
goto Recovered
}
}
state Accepted {
this.upstream.waitrequest = 0b1
if (this.upstream.write == 0b0 && this.upstream.read == 0b0) {
goto Idle
} else {
goto Accepted
}
}
}
}