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/Axi4LiteToAvalonBridge32.lvt
namespace Livt.Bus.Bridges
using Livt.Bus.Avalon
using Livt.Bus.Axi4Lite
/**
* Converts AXI4-Lite transactions into non-pipelined Avalon-MM transactions.
* The bridge accepts AXI write address and data independently and supports one
* downstream transaction at a time.
*/
component Axi4LiteToAvalonBridge32 : IAvalon32Master
{
// Response returned to AXI after normal Avalon request acceptance.
public const RESPONSE_OKAY: Logic[2] = 0b00
// Response returned to AXI when Avalon request acceptance times out.
public const RESPONSE_SLVERR: Logic[2] = 0b10
// AXI4-Lite source connected to the upstream side of this bridge.
upstream: IAxi4Lite32Master
// Maximum ticks to wait while downstream Avalon holds waitrequest high.
timeoutTicks: uint
// True only when the most recent downstream request timed out.
lastTimedOut: bool
// True while a timed-out Avalon request remains asserted for acceptance.
recovering: bool
/**
* Connects an AXI4-Lite source and initializes the Avalon-MM master outputs.
* The default Avalon acceptance timeout is 1 ms.
*/
new(upstream: flip IAxi4Lite32Master)
{
this.upstream = upstream
this.upstream.awready = 0b0
this.upstream.wready = 0b0
this.upstream.bresp = RESPONSE_OKAY
this.upstream.bvalid = 0b0
this.upstream.arready = 0b0
this.upstream.rdata = 0x00000000
this.upstream.rresp = RESPONSE_OKAY
this.upstream.rvalid = 0b0
this.address = 0x00000000
this.byteenable = 0b0000
this.write = 0b0
this.writedata = 0x00000000
this.read = 0b0
this.timeoutTicks = this.context.TicksFor(1ms)
this.lastTimedOut = false
this.recovering = false
}
/**
* Sets the maximum ticks to wait for downstream Avalon request acceptance.
* The count is exact; zero times out on the first stalled evaluation.
* A timeout returns RESPONSE_SLVERR on the matching AXI response channel.
*/
public fn SetTimeoutTicks(timeoutTicks: uint)
{
this.timeoutTicks = timeoutTicks
}
/**
* Returns the maximum ticks allowed for Avalon request acceptance.
*/
public fn GetTimeoutTicks() uint
{
return timeoutTicks
}
/**
* Returns true when the most recent downstream Avalon request timed out.
*/
public fn LastTimedOut() bool
{
return lastTimedOut
}
/**
* Returns true while the bridge completes a timed-out Avalon request.
* New AXI requests remain stalled until recovery completes.
*/
public fn IsRecovering() bool
{
return recovering
}
/**
* Captures AXI channels and sequences one corresponding Avalon request.
*/
process Run()
{
var writeAddress: Logic[32] = 0x00000000
var writeValue: Logic[32] = 0x00000000
var writeEnable: Logic[4] = 0b0000
var addressAccepted: bool = false
var dataAccepted: bool = false
var downstreamAccepted: bool = false
var responseAccepted: bool = false
var elapsed: uint = 0
state Idle {
this.upstream.awready = 0b0
this.upstream.wready = 0b0
this.upstream.arready = 0b0
this.upstream.bvalid = 0b0
this.upstream.rvalid = 0b0
this.write = 0b0
this.read = 0b0
this.byteenable = 0b0000
addressAccepted = false
dataAccepted = false
if (this.upstream.awvalid == 0b1 || this.upstream.wvalid == 0b1) {
lastTimedOut = false
recovering = false
this.upstream.awready = 0b1
this.upstream.wready = 0b1
goto CaptureWrite
} elif (this.upstream.arvalid == 0b1) {
lastTimedOut = false
recovering = false
this.upstream.arready = 0b1
goto CaptureRead
} else {
goto Idle
}
}
state CaptureWrite {
if (addressAccepted == false && this.upstream.awvalid == 0b1) {
writeAddress = this.upstream.awaddr
addressAccepted = true
this.upstream.awready = 0b0
}
if (dataAccepted == false && this.upstream.wvalid == 0b1) {
writeValue = this.upstream.wdata
writeEnable = this.upstream.wstrb
dataAccepted = true
this.upstream.wready = 0b0
}
if (addressAccepted && dataAccepted) {
this.address = writeAddress
this.writedata = writeValue
this.byteenable = writeEnable
this.write = 0b1
elapsed = 0
goto AvalonWrite
} else {
goto CaptureWrite
}
}
state AvalonWrite {
if (this.waitrequest == 0b0) {
this.write = 0b0
this.byteenable = 0b0000
this.upstream.bresp = this.response
this.upstream.bvalid = 0b1
goto WriteResponse
} elif ((elapsed + 1) >= timeoutTicks) {
lastTimedOut = true
recovering = true
downstreamAccepted = false
responseAccepted = false
this.upstream.bresp = RESPONSE_SLVERR
this.upstream.bvalid = 0b1
goto RecoverAvalonWrite
} else {
elapsed = elapsed + 1
goto AvalonWrite
}
}
state WriteResponse {
if (this.upstream.bready == 0b1) {
this.upstream.bvalid = 0b0
goto Idle
} else {
goto WriteResponse
}
}
state CaptureRead {
if (this.upstream.arvalid == 0b1) {
this.address = this.upstream.araddr
this.byteenable = 0b1111
this.read = 0b1
this.upstream.arready = 0b0
elapsed = 0
goto AvalonRead
} else {
goto CaptureRead
}
}
state AvalonRead {
if (this.waitrequest == 0b0) {
this.read = 0b0
this.byteenable = 0b0000
this.upstream.rdata = this.readdata
this.upstream.rresp = this.response
this.upstream.rvalid = 0b1
goto ReadResponse
} elif ((elapsed + 1) >= timeoutTicks) {
lastTimedOut = true
recovering = true
downstreamAccepted = false
responseAccepted = false
this.upstream.rdata = 0x00000000
this.upstream.rresp = RESPONSE_SLVERR
this.upstream.rvalid = 0b1
goto RecoverAvalonRead
} else {
elapsed = elapsed + 1
goto AvalonRead
}
}
state ReadResponse {
if (this.upstream.rready == 0b1) {
this.upstream.rvalid = 0b0
goto Idle
} else {
goto ReadResponse
}
}
state RecoverAvalonWrite {
if (downstreamAccepted == false && this.waitrequest == 0b0) {
this.write = 0b0
this.byteenable = 0b0000
downstreamAccepted = true
}
if (responseAccepted == false && this.upstream.bready == 0b1) {
this.upstream.bvalid = 0b0
responseAccepted = true
}
if (downstreamAccepted && responseAccepted) {
recovering = false
goto Idle
} else {
goto RecoverAvalonWrite
}
}
state RecoverAvalonRead {
if (downstreamAccepted == false && this.waitrequest == 0b0) {
this.read = 0b0
this.byteenable = 0b0000
downstreamAccepted = true
}
if (responseAccepted == false && this.upstream.rready == 0b1) {
this.upstream.rvalid = 0b0
responseAccepted = true
}
if (downstreamAccepted && responseAccepted) {
recovering = false
goto Idle
} else {
goto RecoverAvalonRead
}
}
}
}