plenn08
plenn08

Reputation: 163

Chisel3: False Combinational Loop in Fixed Priority Arbiter

The following code implements a n N-bit fixed priority arbiter.

import chisel3._
import chisel3.util._

class fixedPriorityArbiter(val n_reqs:Int = 4) extends Module {
    val NO_OF_REQS = n_reqs
    val io = IO(new Bundle {
        val req     = Input(UInt(NO_OF_REQS.W))
        val grant   = Output(UInt(NO_OF_REQS.W))
    })
    val higherPriReq   = Wire(UInt(NO_OF_REQS.W))

    higherPriReq := Cat((higherPriReq(NO_OF_REQS-2, 0) | io.req(NO_OF_REQS-2, 0)), UInt(0,1.W))
    io.grant := io.req & ~higherPriReq
}


object main_obj extends App {
  val DUT = () => new fixedPriorityArbiter()
  val margs = Array("--compiler", "verilog")

  chisel3.Driver.execute(args= margs, dut= DUT)
}

Inexistent combinatorial loops are reported for this code. The chisel source mirrors a Verilog implementation of the circuit below which doesn't report any combinatorial loops when synthesized in Synopsys Synplify. enter image description here

The following compile error is reported by FIRRTL in Eclipse IDE on Windows without any Verilog source being generated by FIRRTL enter image description here

Upvotes: 2

Views: 440

Answers (1)

Jack Koenig
Jack Koenig

Reputation: 6064

FIRRTL does not support subword analysis so by using a UInt here you are creating what appears to be a combinational loop even though it actually isn't. To get around this, you can use aggregate types like Vecs to make it explicit to Firrtl that you are doing work on the individual bits. Here's an equivalent implementation using a Vec:

class FixedPriorityArbiter(val n_reqs: Int = 4) extends Module {
    val NO_OF_REQS = n_reqs
    val io = IO(new Bundle {
        val req     = Input(UInt(NO_OF_REQS.W))
        val grant   = Output(UInt(NO_OF_REQS.W))
    })
    val higherPriReq   = Wire(Vec(NO_OF_REQS, Bool()))

    // Vec implements scala.collection.Seq so you can use such operations as slice and map
    val upperOr = higherPriReq.slice(0, NO_OF_REQS-1).zip(io.req(NO_OF_REQS-2, 0).toBools)
                                                     .map { case (l, r) => l | r } 
    higherPriReq := false.B +: upperOr
    io.grant := io.req & ~higherPriReq.asUInt
}

Upvotes: 3

Related Questions