object AXI4Arbiter
{
def apply[T <: Data](policy: TLArbiter.Policy)(sink: IrrevocableIO[T], sources: IrrevocableIO[T]*): Unit = {
if (sources.isEmpty) {
sink.valid := false.B
} else {
returnWinner(policy)(sink, sources:_*)
}
}
def returnWinner[T <: Data](policy: TLArbiter.Policy)(sink: IrrevocableIO[T], sources: IrrevocableIO[T]*) = {
require (!sources.isEmpty)
// The arbiter is irrevocable; when !idle, repeat last request
val idle = RegInit(true.B)
// Who wants access to the sink?
val valids = sources.map(_.valid)
val anyValid = valids.reduce(_ || _)
// Arbitrate amongst the requests
val readys = VecInit(policy(valids.size, Cat(valids.reverse), idle).asBools)
// Which request wins arbitration?
val winner = VecInit((readys zip valids) map { case (r,v) => r&&v })
// Confirm the policy works properly
require (readys.size == valids.size)
// Never two winners
val prefixOR = winner.scanLeft(false.B)(||).init
assert((prefixOR zip winner) map { case (p,w) => !p || !w } reduce {_ && _})
// If there was any request, there is a winner
assert (!anyValid || winner.reduce(||))
// The one-hot source granted access in the previous cycle
val state = RegInit(VecInit.fill(sources.size)(false.B))
val muxState = Mux(idle, winner, state)
state := muxState
// Determine when we go idle
when (anyValid) { idle := false.B }
when (sink.fire) { idle := true.B }
if (sources.size > 1) {
val allowed = Mux(idle, readys, state)
(sources zip allowed) foreach { case (s, r) =>
s.ready := sink.ready && r
}
} else {
sources(0).ready := sink.ready
}
sink.valid := Mux(idle, anyValid, Mux1H(state, valids))
sink.bits :<= Mux1H(muxState, sources.map(_.bits))
muxState
}
}