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/WishboneToAvalonBridge32.lvt
namespace Livt.Bus.Bridges
using Livt.Bus.Avalon
using Livt.Bus.Wishbone
/**
* Converts Wishbone Classic cycles into non-pipelined Avalon-MM transactions.
* The ACK-only Wishbone profile cannot carry Avalon error responses, so the
* most recent downstream status remains available through LastResponse().
*/
component WishboneToAvalonBridge32 : IAvalon32Master
{
// Response recorded before a transaction or when Avalon completes normally.
public const RESPONSE_OKAY: Logic[2] = 0b00
// Response recorded when downstream Avalon acceptance times out.
public const RESPONSE_SLVERR: Logic[2] = 0b10
// Wishbone source connected to the upstream side of this bridge.
upstream: IWishbone32Master
// Maximum ticks to wait while downstream Avalon holds waitrequest high.
timeoutTicks: uint
// Most recent Avalon response, or RESPONSE_SLVERR after a timeout.
lastResponse: Logic[2]
// True only when the most recent downstream transaction timed out.
lastTimedOut: bool
// True while a timed-out Avalon request remains asserted for acceptance.
recovering: bool
/**
* Connects a Wishbone source and initializes the Avalon-MM master outputs.
* The default Avalon acceptance timeout is 1 ms.
*/
new(upstream: flip IWishbone32Master)
{
this.upstream = upstream
this.upstream.datout = 0x00000000
this.upstream.ack = 0b0
this.address = 0x00000000
this.byteenable = 0b0000
this.write = 0b0
this.writedata = 0x00000000
this.read = 0b0
this.timeoutTicks = this.context.TicksFor(1ms)
this.lastResponse = RESPONSE_OKAY
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.
* On timeout the bridge withholds ack so the Wishbone source can time out.
*/
public fn SetTimeoutTicks(timeoutTicks: uint)
{
this.timeoutTicks = timeoutTicks
}
/**
* Returns the maximum ticks allowed for Avalon request acceptance.
*/
public fn GetTimeoutTicks() uint
{
return timeoutTicks
}
/**
* Returns the most recent Avalon response.
* A downstream timeout is reported as RESPONSE_SLVERR.
*/
public fn LastResponse() Logic[2]
{
return lastResponse
}
/**
* 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 Wishbone cycles are ignored until recovery completes.
*/
public fn IsRecovering() bool
{
return recovering
}
/**
* Converts each Wishbone cycle into one Avalon request and returns ack only
* after downstream completion.
*/
process Run()
{
var elapsed: uint = 0
var downstreamAccepted: bool = false
var sourceReleased: bool = false
state Idle {
recovering = false
this.upstream.ack = 0b0
this.write = 0b0
this.read = 0b0
this.byteenable = 0b0000
if (this.upstream.cyc == 0b1 && this.upstream.stb == 0b1) {
lastResponse = RESPONSE_OKAY
lastTimedOut = false
this.address = this.upstream.adr
this.byteenable = this.upstream.sel
this.writedata = this.upstream.datin
elapsed = 0
if (this.upstream.we == 0b1) {
this.write = 0b1
} else {
this.read = 0b1
}
goto Transfer
} else {
goto Idle
}
}
state Transfer {
if (this.waitrequest == 0b0) {
lastResponse = this.response
if (this.upstream.we == 0b0) {
this.upstream.datout = this.readdata
}
this.write = 0b0
this.read = 0b0
this.byteenable = 0b0000
this.upstream.ack = 0b1
goto Acknowledge
} elif ((elapsed + 1) >= timeoutTicks) {
lastResponse = RESPONSE_SLVERR
lastTimedOut = true
recovering = true
downstreamAccepted = false
sourceReleased = false
goto RecoverTransfer
} else {
elapsed = elapsed + 1
goto Transfer
}
}
state Acknowledge {
if (this.upstream.cyc == 0b0 || this.upstream.stb == 0b0) {
this.upstream.ack = 0b0
goto Idle
} else {
goto Acknowledge
}
}
state RecoverTransfer {
if (downstreamAccepted == false && this.waitrequest == 0b0) {
this.write = 0b0
this.read = 0b0
this.byteenable = 0b0000
downstreamAccepted = true
}
if (this.upstream.cyc == 0b0 || this.upstream.stb == 0b0) {
sourceReleased = true
}
if (downstreamAccepted && sourceReleased) {
recovering = false
goto Idle
} else {
goto RecoverTransfer
}
}
}
}