I saw a code in section 3.2 interlude in generator-bootcamp:
val io = IO(new Bundle {
val in = Flipped(Decoupled(UInt(8.W)))
val out = Decoupled(UInt(8.W))
})
Is there anyone who know the functionality of "Flipped"?
I searched it in chisel3 doc, but it doesn't have this information.
https://chisel.eecs.berkeley.edu/api/#Chisel.package$$Flipped$
Thanks in advance
Decoupled defaults to being an output, that is its argument, in this case the UInt(8.W) will bring data into the module. Decoupled adds ready and valid handshaking signals to in.
The Flipped() changes the direction of all fields of it's argument. So out is suitable for communicating information out of the module.
The code here is equivalent to
val io = IO(new Bundle {
val in = new Bundle {
val valid = Input(Bool())
val ready = Output(Bool())
val bits = Input(UInt(8.W))
}
val out = new Bundle {
val valid = Output(Bool())
val ready = Input(Bool())
val bits = Output(UInt(8.W))
}
}
I will see that something gets added to chisel3 wiki.
Related
I'm using the suggestName API for IO(), for example
class TestModule extends MultiIOModule{
val AXI = IO(new AXIWriteIO(32,32,4)).suggestName("axi")
val S_AXI = IO(Flipped(new AXIWriteIO(32,32,4)))
AXI.AW.suggestName("aw")
AXI <> S_AXI
}
It works with the "axi" part, but not the "aw" part.
The suggestName also does not work inside the bundle definition class:
class AXIAddress(val addrWidthBits: Int, val idBits: Int) extends Bundle {
val id = UInt(idBits.W).suggestName("ID")
//...
}
Any idea?
chisel version is 3.2.0
I chisel3 it is not possible to use suggestName inside Bundles. The names emitted into FIRRTL is the chisel variable name. To get the correct naming of the external ports while still being able to use nested bundles internally to represent the AXI interface I have done something like this:
class AXIAddress extends Bundle {
val addr = UInt(32.W)
val size = UInt(4.W)
val len = UInt(2.W)
}
class AXIMasterIF extends Bundle {
val readAddr = Decoupled(new AXIAddress)
val writeAddr = Decoupled(new AXIAddress)
}
object AXIMasterIF {
def apply(): AXIMasterIF = {
val axi = Wire(new AXIMasterIF)
axi
}
}
class AXIExternalIF extends Bundle {
val AWADDR = Output(UInt(32.W))
val AWVALID = Output(Bool())
val AWREADY = Input(Bool())
val AWSIZE = Output(UInt(4.W))
val AWLEN = Output(UInt(2.W))
val ARADDR = Output(UInt(32.W))
val ARVALID = Output(Bool())
val ARREADY = Input(Bool())
val ARSIZE = Output(UInt(4.W))
val ARLEN = Output(UInt(2.W))
def connect(int: AXIMasterIF): Unit = {
this.AWADDR := int.writeAddr.bits.addr
this.AWVALID := int.writeAddr.valid
int.writeAddr.ready := this.AWREADY
this.AWSIZE := int.writeAddr.bits.size
this.AWLEN := int.writeAddr.bits.len
this.ARADDR := int.readAddr.bits.addr
this.ARVALID := int.readAddr.valid
int.readAddr.ready := this.ARREADY
this.ARSIZE := int.readAddr.bits.size
this.ARLEN := int.readAddr.bits.len
}
}
class TopWrapper extends MultiIOModule {
// First instantive the "internal", nested, representation of the AXI Slave interface
val axiInt = AXIMasterIF()
// Then instantiate the external, correctly named, AXI Slave interace that we can connect in Vivado
val axiExt = IO(new AXIExternalIF).suggestName("MM_AXI_0")
// Make connections
axiExt.connect(axiInt)
}
The AXIExternalIF is the one that is exposed to the rest of the system. It must be in the top level module of your design. AXIMasterIF which uses AXIAddres is connected to that interface and is used internally to connect things to the AXI interface.
If you wanna play around with it and look at the emitted verilog you can do that at Scastie
I'm having trouble to do partial bulk connection with <>.
I saw in the book Digital Design with Chisel (4.3 Bulk Connections).
It is allowed to connect two bundles with partially matched signals.
I'm currently working on chisel3.2. and it seems not working, and during elatorating it
reports
chisel3.internal.ChiselException: Connection between left (AnonymousBundle(IO io in Fetch)) and source (AnonymousBundle(IO io in Decode)) failed #.regB: Left Record missing field (regB).
Is this changed at some version?
If it is changed, how do we do partial connection now?
This is the testing code(don't mind the module, it is only to keep the signal from optimization):
class Fetch extends Module {
val io = IO(new Bundle {
val instr = Output(UInt(32.W))
val pc = Output(UInt(32.W))
})
val r = RegInit(0.U(32.W))
r := r + 1.U
io.pc := r
io.instr := r+1.U
}
class Decode extends Module {
val io = IO(new Bundle {
val instr = Input(UInt(32.W))
val pc = Input(UInt(32.W))
val aluOp = Output(UInt(5.W))
val regA = Output(UInt(32.W))
val regB = Output(UInt(32.W))
})
io.aluOp := io.pc
io.regA := io.instr
io.regB := io.instr
}
class Execute extends Module {
val io = IO(new Bundle {
val aluOp = Input(UInt(5.W))
val regA = Input(UInt(32.W))
val regB = Input(UInt(32.W))
val result = Output(UInt(32.W))
})
io.result := io.regA
when(io.aluOp > 10.U){
io.result := io.regB
}
}
object MAIN{
def main(args:Array[String]):Unit = {
Driver.execute(Array(""),()=>new Module{
val io = IO(new Bundle{
val result = Output(UInt(32.W))
})
val fetch = Module(new Fetch())
val decode = Module(new Decode())
val execute = Module(new Execute)
fetch.io <> decode.io
decode.io <> execute.io
io <> execute.io
})
}
}
Link:chisel3-vs-chisel2
In Unsupported constructs Chapter:
In Chisel2, bulk-connects <> with unconnected source components do not update connections from the unconnected components.
In Chisel3, bulk-connects strictly adhere to last connection semantics and unconnected OUTPUTs will be connected to INPUTs resulting in the assignment of random values to those inputs.
I'm sorry that I have not fully understanded how to use <> in Chisel3.In my opinion, you should avoid to use <> in Chisel3.
Here is an example that is avaiable in Chisel3.
Code is from here.
import Chisel.Queue
import chisel3._
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import chisel3.util.Decoupled
import layered.stage.ElkStage
class MyQueue extends Module {
// Example circuit using a Queue
val io = IO(new Bundle {
val in = Flipped(Decoupled(UInt(8.W)))
val out = Decoupled(UInt(8.W))
})
val queue = Queue(io.in, 2) // 2-element queue
io.out <> queue
}
object MyQueue extends App{
(new ChiselStage).emitVerilog(new MyQueue,Array("-td", "vout"))
// gengerate graph file and it can be viewed by using IDEA plugin named EasySocHDL
(new ElkStage).execute(
Array("-td", "vout", "--lowFir"),
Seq(ChiselGeneratorAnnotation(() => new MyQueue))
)
}
I tried to add some generation options to my bundle code:
class myIO (val bitwidth: Int,numOfInstances: Int = 1) extends Bundle {
val en = if (numOfInstances == 1) Bool(INPUT) else Vec(numOfInstances,Bool(INPUT))
val data = UInt(INPUT,bitwidth.W)
...
}
when I tried
val io = IO(new myIO(32)) // use default
I get compilation error "type missmatch" io.en is chisel3.core.Data but chisel3.Bool is required. Also when trying :
val io = IO(new myIO(32,1))
I got the same error
I have a Vec[Decoupled[UInt]] that I want to connect to a Vec of Vec[Decoupled[UInt]] based on a select signal. However, once it seems the directionality of the Decoupled is lost once it is nested two layers deep, so it won't let me initialize the ready signals or drive the output with the input.
For example, Chisel allows me to instantiate this:
class Example extends Module {
val io = IO(new Bundle {
val in = Vec(3, Flipped(Decoupled(UInt(3.W))))
val out = Vec(3, Decoupled(UInt(3.W)))
})
io.in.foreach(_.ready := false.B) // Only here for consistency
io.out <> io.in
}
But this yields an error:
class Example extends Module {
val io = IO(new Bundle {
val sel = Input(UInt(4.W))
val in = Vec(10, Vec(3, Flipped(Decoupled(UInt(3.W)))))
val out = Vec(3, Decoupled(UInt(3.W)))
})
io.in.foreach(_.foreach(_.ready := false.B))
io.out <> io.in(io.sel)
}
The latter gives errors that read
Sink is unwriteable by current module (line 7)
Both left and right are drivers (line 8)
Is this an error with Chisel or am I missing something? How can I work around this?
This is... weird. I haven't found the cause yet but I have confirmed the buggy behavior you are seeing. Fortunately, there is an easy workaround, put the Flipped outside the Vec.
class Example extends Module {
val io = IO(new Bundle {
val sel = Input(UInt(4.W))
val in = Flipped(Vec(10, Vec(3, Decoupled(UInt(3.W)))))
val out = Vec(3, Decoupled(UInt(3.W)))
})
io.in.foreach(_.foreach(_.ready := false.B))
io.out <> io.in(io.sel)
}
I've filed an issue on the Chisel repo to track this bug.
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.
The following compile error is reported by FIRRTL in Eclipse IDE on Windows without any Verilog source being generated by FIRRTL
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
}