|
手写一个固定优先级仲裁器,将将源代码逐行注释说明(注释中逻辑值0,false,false.B都是一个意思,1,true,true.B也都是一个意思,不要追究语法了):
import chisel3._
import chisel3.util._
class JArbiterIO[T <: Data](private val gen:T,val n:Int) extends Bundle {
val enq = Flipped(Vec(n,Decoupled(gen)))
val deq = Decoupled(gen)
val chosen = Output(UInt(log2Ceil(n).W)) //enq是Vec集合类型,n个元素需要多少bit才能表示这个数
}
//选择哪个producer 最后一个producer没有包含在内(why?) 将返回Seq序号0始终设置为true.B
private object JAribiterCtrl {
def apply(requests:Seq[Bool]): Seq[Bool] = requests.length match {
case 0 => Seq()
case 1 => Seq(true.B)
case _ => true.B +: requests.tail.init.scanLeft(requests.head)(_ || _).map(!_) //+: 是中缀操作符,右边的操作数是调用方法的对象 true.B放在前面
//SeqLike类中有:+和+:,其中:+是普通操作方法,将右加到左的尾部,+:则将左加到右的前部
//总结:最开始添true.B,去掉last元素之后,只要某位置出现true.B,则从它开始包括它在内返回的Seq中都是false.B,
// 如果是最后一个元素不管是true.B还是false.B,则最终返回的Seq全部都是本总结前面所述结果(因为最后一个元素被tail.init丢弃了)
}
}
class JArbiter[T <: Data](gen:T,n:Int) extends Module {
val io = IO(new JArbiterIO(gen,n))
//先要赋默认值
io.deq.bits := io.enq(n-1).bits //最后一个enq的数据
io.chosen := (n-1).asUInt() //最大序号
for(i <- (n-2) to 0 by -1) { //n=3 n=2 n=1 n=0 (n=3时循环2次,n=2时循环1次,n=1或0时不循环) 也就是说(n-2) to 0 by -1也是将last enq去掉了
when(io.enq(i).valid) { //只要某个输入的valid有效
io.deq.bits := io.enq(i).bits //仲裁器的输出数据为它对应的数据 如果有多个valid,则根据语法,最后(序号小)一个的赋值将会是仲裁器数据输出
io.chosen := i.asUInt()
}
}
//如果只有一个in,则grant(0)=true.B
//如果只有二个in,grant(0)=true.B,grant(1)=io.enq(0).valid的值取反
//如果有三个in,grant(0)=true.B,grant(1)=io.enq(0).valid的值取反,grant(2)=io.enq(1).valid的值取反
val grant = JAribiterCtrl(io.enq.map(_.valid)) //所有enq的valid
for((enq,g) <- io.enq zip grant) { //Lit(1,2,3) zip (4,5)==>List((1,4),(2,5))
enq.ready := g && io.deq.ready //总结:某个producer发出了valid则小于它序号的所有producer的ready都将ready=1
//只要有io.deq.ready,那么第0序号的producer的ready肯定会true,如果还有其它序号producer的valid=true.B(多个producer时,先是取最小序号的producer,暂叫producerA),
//那么producerA对应序号之前grant成员会是true.B,包括本producerA以及本producerA序号之后都是false.B
//如果只有二个producer,当producer(1)valid=1而producer(0)valid=0时,grant(0)=true.B,grant(1)=其实就是producer(0)的valid值取反即=1
//如果有三个producer,当producer(2)valid=1时,grant(0)=true.B,grant(1)=true.B(其实就是producer(0)的valid值取反),grant(2)=true.B(其实就是producer(1)的valid值取反)
//如果只有二个producer,当producer(0)valid=1,grant(0)=true.B,grant(1)=false.B
//如果有三个producer,当producer(1)valid=1时,grant(0)=true.B,grant(1)=true.B,grant(2)=false.B
}
//最后一个producer的valid=1即io.enq.last.valid=1 不管grantlast如何取值,最终 io.deq.valid:=1,但分析分析并且分析对应的数据输出
// 如果grant.last=1,说明除了最后一个producer之外,其它所有producer的valid都是0,最终 io.deq.valid:=1,输出数据也是最后一个producer的数据
// 如果grant.last=0,说明倒数第二个或倒数第三/第四等producer的valid总有一个或多个=1,所以io.deq.valid=1,从逻辑角度来看下游收到valid也没有错,此时要分析上面数据是否对应(最小序号的producer的数据)
//最后一个producer的valid=0即io.enq.last.valid=0 则
// 如果grant.last=1,说明除了最后一个producer之外,其它所有producer的valid都是0,当然!grant.last=false,最终io.deq.valid=false
// 如果grant.last=0,说明倒数第二个或倒数第三/第四等producer的valid总有一个或多个=1,所以io.deq.valid=1,从逻辑角度来看下游收到valid也没有错,此时要分析上面数据是否对应(最小序号的producer的数据)
io.deq.valid := !grant.last || io.enq.last.valid
//总结:当有多个有效producer时,只有序号最小的producer的数据才能输出
}
|
|