Scala Chisel Ripple Carry Adder Syntax - scala

im trying to design the following Ripple Carry Adder made of Fulladers. I tried a lot so far, but I'm struggling with Chisel Syntax. Could someone help me out and point out what I'm doing wrong? This is my Code below:
class RcaAdder(val n:Int) extends Module {
val io = IO(new Bundle {
val a = Input(UInt(n.W))
val b = Input(UInt(n.W))
val cin = Input(UInt(1.W))
val sum = Output(UInt(n.W))
val cout = Output(UInt(1.W))
})
//For loop
for(i <- 0 to n){
val fulladder = Module(new FullAdder())
fulladder.io.a := io.a(i)
fulladder.io.b := io.b(i)
if(i == 0){
fulladder.io.cin := io.cin
}else{
fulladder.io.cin := io.cout
}
io.cout := fulladder.io.cout
io.sum(i) := fulladder.io.sum
}
}
Which gets me the following error:
Exception in thread "main" chisel3.internal.ChiselException: Cannot reassign to read-only Bool(OpResult in RcaAdder)
I assume it has something to do with the " io.sum(i) := .. "
Please help me out! Thank you so much!

You are very close to getting it working. One problem you are having is that you cannot assign to a bit subset on the left hand side of :=. One way of getting around this is to create a Vec of UInt(1.W) and then use that as the RHS as a single as a single assignment. I think you have a problem with your ifs, I'd recommend using foldLeft instead of for because it provides a mechanism of accessing the previous elements. Put that all together and I think what you want is something like this.
class RcaAdder(n: Int) extends Module {
val io = IO(new Bundle {
val a = Input(UInt(n.W))
val b = Input(UInt(n.W))
val cin = Input(UInt(1.W))
val sum = Output(UInt(n.W))
val cout = Output(UInt(1.W))
})
val outBits = Wire(Vec(n, UInt(1.W)))
io.cout := (0 until n).foldLeft(io.cin) { case (carry, index) =>
val fullAdder = Module(new FullAdder)
fullAdder.io.a := io.a(index)
fullAdder.io.b := io.b(index)
fullAdder.io.cin := carry
outBits(index) := fullAdder.io.sum
fullAdder.io.cout. // This will be passed as carry to the next interation
}
io.sum := outBits.asUInt()
}
I've added a working test example here on scastie.
Good luck and welcome to Chisel

Related

Can Record class be used to create RegInit?

I am trying to use Record class to generate RegInit. This can help to dynamically create RegInit with other information in Module.
I am trying to use Record class to generate RegInit.
Here are my codes.
class MyReg(reg_info: List[(String, UInt)]) extends Record {
override def elements: ListMap[String, UInt] = ListMap(
reg_info.map(
x =>
x._1 -> x._2
):_*
)
override def cloneType: MyReg.this.type = new MyReg(reg_info).asInstanceOf[this.type]
}
class reg_test(reg_list: List[(String, String, List[(String, Int)])]) extends Module with RegSugar {
val io = IO(new Bundle() {
val a = Input(UInt(16.W))
val b = Input(UInt(16.W))
val d = Output(UInt(16.W))
val e = Output(UInt(16.W))
})
val myBundle = new Bundle() {
val a = UInt(16.W)
val b = UInt(16.W)
}
val reg_init_bundle = RegInit(myBundle, 0.U.asTypeOf(myBundle))
println(reg_init_bundle)
reg_init_bundle.a := io.a
reg_init_bundle.b := io.b
val list_b = List(("a", UInt(16.W)), ("b", UInt(16.W)))
val myRecord = new MyReg(list_b)
val reg_init = RegInit(myRecord, 0.U.asTypeOf(myRecord))
reg_init.elements("a") := io.a
reg_init.elements("b") := io.b
io.d := reg_init.elements("a") + reg_init.elements("b")
io.e := reg_init_bundle.a + reg_init_bundle.b
}
In my sight, Bundle extends Record and if these code work on Bundle, they should also work on Record.
However, the error is reported on the line:
val reg_init = RegInit(myRecord, 0.U.asTypeOf(myRecord))
Exception in thread "main" chisel3.package$RebindingException: Attempted reassignment of binding to reg_test.reg_init_?.a: Wire[UInt<16>], from: ChildBinding(reg_test.reg_init_?: Reg[MyReg])
at ... ()
at implicit_test.reg_test.$anonfun$reg_init$2(reg_test.scala:61)
at chisel3.internal.prefix$.apply(prefix.scala:48)
at implicit_test.reg_test.$anonfun$reg_init$1(reg_test.scala:61)
at chisel3.internal.plugin.package$.autoNameRecursively(package.scala:33)
at implicit_test.reg_test.<init>(reg_test.scala:61)
at implicit_test.reg_test$.$anonfun$verilogString$1(reg_test.scala:77)
at ... ()
at ... (Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace)
It seems that these codes can successfully generate RegInit with Bundle but failed to generate RegInit with Record.
Is that a way to generate RegInit with Record? or there is a compiler error?
https://github.com/chipsalliance/chisel3/issues/2998. Thanks, guys. Here is the explanation for this Question. Case closed.

How to write a Muller C Element in Chisel Scala Language for async circuit?

When I wrote this :
class MullerC(val WIDTH: Int = 2) extends Module {
val io = IO(new Bundle {
val in = Input(Vec(WIDTH, Bool()))
val out = Output(Bool())
})
io.out := false.B
when (io.in.reduce(_ & _)) {
io.out := true.B
}.elsewhen (io.in.map(!_).reduce(_ & _)) {
io.out := false.B
}
}
I got Verilog like this :
module MullerC(
input clock,
input reset,
input io_in_0,
input io_in_1,
output io_out
);
assign io_out = io_in_0 & io_in_1;
endmodule
That is a simple and gate instead of a C gate.
But when I tried to add otherwise like this :
class MullerC(val WIDTH: Int = 2) extends Module {
val io = IO(new Bundle {
val in = Input(Vec(WIDTH, Bool()))
val out = Output(Bool())
})
io.out := false.B
when (io.in.reduce(_ & _)) {
io.out := true.B
}.elsewhen (io.in.map(!_).reduce(_ & _)) {
io.out := false.B
}.otherwise {
io.out := io.out
}
}
It could not be compiled any more:
Exception in thread "main" firrtl.transforms.CheckCombLoops$CombLoopException: : [module MullerC] Combinational loop detected:
MullerC.io_out
MullerC._GEN_0 #[----.scala 14:38 ----.scala 15:12 ----.scala 17:12]
MullerC._GEN_1 #[----.scala 12:30 ----.scala 13:12]
MullerC.io_out
How should I implement the Muller C in Chisel? Many thanks.
I found the answer via this link: Disable FIRRTL pass that checks for combinational loops
I should use otherwise and then add --no-check-comb-loops as a parameter to emit verilog code. Thanks.
By the way, I also tried this and it works as well.
class MullerC(val WIDTH: Int = 2) extends Module {
val io = IO(new Bundle {
val in = Input(Vec(WIDTH, Bool()))
val out = Output(Bool())
})
io.out := false.B
val allTrue = Wire(Bool())
val allFalse = Wire(Bool())
allTrue := io.in.reduce(_ & _);
allFalse := io.in.map(!_).reduce(_ & _)
io.out := Mux(allTrue | allFalse, Mux(allTrue, true.B, false.B), io.out)
}
This will generate more beautiful verilog code althought it does not matter.

I want to make adder tree with chisel 3

First of all, I implemented adder which is shown below.
class AdderSwitch(InputBandwidth: Int, OutputBandwidth: Int, NumberOfOutputBuffer: Int) extends Module {
val io = IO(new Bundle {
val InputLeft = Input(SInt(InputBandwidth.W))
val InputRight = Input(SInt(InputBandwidth.W))
val OutputLeft = Output(SInt(InputBandwidth.W))
val OutputSum = Output(SInt(OutputBandwidth.W))
val OutputRight = Output(SInt(InputBandwidth.W))
val PassingOrSum = Input(Bool())
val OutputLeftReady = Input(Bool())
val OutputSumReady = Input(Bool())
val OutputRightReady = Input(Bool())
})
val Demux0 = Module(new Demux(InputBandwidth = InputBandwidth))
Demux0.io.Sel := io.PassingOrSum
Demux0.io.DemuxInput := io.InputLeft
val Demux1 = Module(new Demux(InputBandwidth = InputBandwidth))
Demux1.io.Sel := io.PassingOrSum
Demux1.io.DemuxInput := io.InputRight
val OutputSumWire = Wire(SInt(OutputBandwidth.W))
OutputSumWire := Demux0.io.Output1 + Demux1.io.Output1// + Mux(io.ForwardingMux, io.ForwardRightInput, io.ForwardLeftInput)
val OutputLeftBuffer = Module (new Queue(SInt(), NumberOfOutputBuffer))
val OutputSumBuffer = Module (new Queue(SInt(), NumberOfOutputBuffer))
val OutputRightBuffer = Module (new Queue(SInt(), NumberOfOutputBuffer))
OutputLeftBuffer.io.enq.bits := Mux(io.PassingOrSum, OutputSumWire, Demux0.io.Output0)
OutputLeftBuffer.io.enq.valid := true.B
OutputSumBuffer.io.enq.bits := OutputSumWire
OutputSumBuffer.io.enq.valid := true.B
OutputRightBuffer.io.enq.bits := Mux(io.PassingOrSum, OutputSumWire, Demux1.io.Output0)
OutputRightBuffer.io.enq.valid := true.B
io.OutputLeft := OutputLeftBuffer.io.deq.bits
io.OutputSum := OutputSumBuffer.io.deq.bits
io.OutputRight := OutputRightBuffer.io.deq.bits
OutputLeftBuffer.io.deq.ready := io.OutputLeftReady
OutputSumBuffer.io.deq.ready := io.OutputSumReady
OutputRightBuffer.io.deq.ready := io.OutputRightReady
}
I checked my code works well when it is tested.
I want to make adder tree which looks like below with chisel 3.
I was trying to use my adder code as a node of this tree.
So, I decided to use scala library, scala.immutable.collection.
However, there are so many object and class. And, I am very new to this definition.
To implement scala tree data structure for my chisel code, what do I have to do first?

Carry Select Adder Scala Chisel

I'm trying to implement a Carry Select Adder using Chisel in Scala. However after various efforts i keep getting errors. The ripple carry adder and multiplexers are tested and working. This is my current Version. Any Input is greatly appreciated!
class CarrySelectAdder(val n:Int, val m:Int) extends Module {
val io = IO(new Bundle {
val a = Input(UInt(n.W))
val b = Input(UInt(n.W))
val cin = Input(UInt(1.W))
val sum = Output(UInt((n+1).W))
})
object carryselecthelper{ //not used atm
def n_sum_idx(stage:UInt) : UInt = {
return stage * (stage + 1.U) / 2.U;
}
}
//val test = math.ceil(n/m)
val rcas = Array.fill(2 * (n/m)){Module(new RcaAdder(m)).io} //2*math.ceil(n/m)
val muxs = Array.fill(n/m){Module(new Multiplexer(m+1)).io} //math.ceil(n/m)
val Sum = Wire(Vec(n, Bool()))
for (i <- 0 until n) {
rcas(i*2).a := io.a.apply(i*m+m,i*m)
rcas(i*2).b := io.b.apply(i*m+m,i*m)
rcas(i*2).cin := 0.asUInt
rcas(2*i+1).a := io.a.apply(i*m+m,i*m)
rcas(2*i+1).b := io.b.apply(i*m+m,i*m)
rcas(2*i+1).cin := 1.asUInt
muxs(i).a := rcas(i*2).sum
muxs(i).b := rcas(2*i+1).sum
if(i > 0){
muxs(i).sel := io.cin
}
if(i > 0){
if(muxs(i).sel == 0){
muxs(i).sel := rcas(2*i).cout
}else{
muxs(i).sel := rcas(2*i+1).cout
}
}
Sum(i) := muxs(i).out
}
io.sum := Sum.asUInt
}
Currently I'm getting an Exception in "ChiselGeneratorAnnotation":
l3.internal.ChiselException: Exception thrown when elaborating ChiselGeneratorAnnotation
at chisel3.stage.ChiselGeneratorAnnotation.elaborate(ChiselAnnotations.scala:55)
ChiselAnnotations.scala:55
at chisel3.stage.phases.Elaborate.$anonfun$transform$1(Elaborate.scala:19)
Elaborate.scala:19
at scala.collection.TraversableLike.$anonfun$flatMap$1(TraversableLike.scala:245)
TraversableLike.scala:245
at scala.collection.immutable.List.foreach(List.scala:392)
List.scala:392
at scala.collection.TraversableLike.flatMap(TraversableLike.scala:245)
TraversableLike.scala:245
at scala.collection.TraversableLike.flatMap$(TraversableLike.scala:242)
TraversableLike.scala:242
at scala.collection.immutable.List.flatMap(List.scala:355)
List.scala:355
at chisel3.stage.phases.Elaborate.transform(Elaborate.scala:18)
Elaborate.scala:18
at chisel3.iotesters.setupTreadleBackend$.apply(TreadleBackend.scala:143)
TreadleBackend.scala:143
at chisel3.iotesters.Driver$.$anonfun$execute$2(Driver.scala:53)
Driver.scala:53
at scala.runtime.java8.JFunction0$mcZ$sp.apply(JFunction0$mcZ$sp.java:23)
at logger.Logger$.$anonfun$makeScope$2(Logger.scala:168)
Logger.scala:168
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:62)
DynamicVariable.scala:62
at logger.Logger$.makeScope(Logger.scala:166)
Logger.scala:166
at logger.Logger$.makeScope(Logger.scala:127)
Logger.scala:127
at chisel3.iotesters.Driver$.$anonfun$execute$1(Driver.scala:38)
Driver.scala:38
at scala.runtime.java8.JFunction0$mcZ$sp.apply(JFunction0$mcZ$sp.java:23)
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:62)
DynamicVariable.scala:62
at chisel3.iotesters.Driver$.execute(Driver.scala:38)
Driver.scala:38
Upon request I added the Multiplexer and RCA class, they should work fine, since they ran all tests without issues. Thanks!
class Multiplexer(val n:Int) extends Module {
val io = IO(new Bundle {
val a = Input(UInt(n.W))
val b = Input(UInt(n.W))
val sel = Input(UInt(n.W))
val out = Output(UInt(n.W))
})
io.out := (io.sel & io.a) | (~io.sel & io.b)
}
class RcaAdder(val n:Int) extends Module {
val io = IO(new Bundle {
val a = Input(UInt(n.W))
val b = Input(UInt(n.W))
val cin = Input(UInt(1.W))
val sum = Output(UInt(n.W))
val cout = Output(UInt(1.W))
})
val FAs = Array.fill(n){Module(new FullAdder()).io}
val carry = Wire(Vec(n+1, UInt(1.W)))
val sum = Wire(Vec(n, Bool()))
carry(0) := io.cin
for (i <- 0 until n) {
FAs(i).a := io.a(i)
FAs(i).b := io.b(i)
FAs(i).cin := carry(i)
carry(i+1) := FAs(i).cout
sum(i) := FAs(i).sum.asBool
}
io.sum := sum.asUInt
io.cout := carry(n)
}
(This is what is used to test the code.)
class CarrySelectAdderTester(dut: CarrySelectAdder, n: Int) extends PeekPokeTester(dut) {
val max=scala.math.pow(2,n).toInt-1
for(i <- 0 to max){
for (j <- 0 to max){
for (k <- 0 to 1){
poke(dut.io.a,i)
poke(dut.io.b,j)
poke(dut.io.cin,k)
step(100)
expect(dut.io.sum,(i+j+k))
}
}
}
}
object CarrySelectAdderTester extends App{
val bitWidth=6
val bitsperblock=3
println("Testing the Carry Select Adder")
iotesters.Driver.execute(Array[String](), () => new CarrySelectAdder(bitWidth, bitsperblock)){
c => new CarrySelectAdderTester(c,bitWidth)
}
}

Currying in hardware

I'm trying to implement a simple Address Decoder with a curried function inside. The code below won't compile, could anybody help me with this?
class AddrDecoder[T<:UInt] (dType:T, n:Int) extends Module {
val io = IO (new Bundle {
//val range = (Vec(Seq.fill(n){(dType,dType)})) // This won't compile, how to fix ?
val range = (List.fill(n){(dType,dType)})
val addr = Input (dType)
val en = Input (Bool())
val sel = Output(Bool())
})
def inside (range:(T,T))(addr:T):Bool = {
addr >= range._1 && addr < range._1 + range._2
}
when (io.en) {
io.sel := io.range map (inside(_)(io.addr))
}
}
[error] found : List[chisel3.Bool]
[error] (which expands to) List[chisel3.core.Bool]
[error] required: chisel3.core.Data
[error] io.sel := io.range map (inside(_)(io.addr))
#jkoenig provided an excellent solution. Posting it here for other's benefit
class AddrDecoder[T<:Data with Num[T]] (dType:T, n:Int) extends Module {
val io = IO (new Bundle {
val range0 = Input (Vec(n,dType))
val range1 = Input (Vec(n,dType))
val addr = Input (dType)
val en = Input (Bool())
val sel = Output(Vec(n,Bool()))
})
// Curried function which accepts a tuple and an input addr
// Use map to apply it to inputs
def inside (range:(T,T))(addr:T):Bool = {
addr >= range._1 && addr < range._1 + range._2
}
// MUX output
for (i <- 0 until n) {
io.sel(i) := false.B
}
when (io.en) {
io.sel := io.range0 zip io.range1 map (inside(_)(io.addr))
}
// $onehot0 output encoding check
assert (PopCount(io.sel) <= 1.U, "Invalid addr decoding")
}