I was trying to create control logic for a circuit in chisel when I received multiple errors related to the switch statements I was using. I decided to run the switch statement sample code provided on pages 9 and 10 of the official chisel tutorial to isolate the problem.
Scala code:
package Testbed
import Chisel._
class Testbed extends Module {
val io = new Bundle {
val nickel = Bool(dir = INPUT)
val dime = Bool(dir = INPUT)
val rdy = Bool(dir = OUTPUT) }
val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UFix(), 5)
val state = Reg(init = s_idle)
switch (state) {
is (s_idle) {
when (io.nickel) { state := s_5 }
when (io.dime) { state := s_10 }
} is (s_5) {
when (io.nickel) { state := s_10 }
when (io.dime) { state := s_15 }
} is (s_10) {
when (io.nickel) { state := s_15 }
when (io.dime) { state := s_ok }
} is (s_15) {
when (io.nickel) { state := s_ok }
when (io.dime) { state := s_ok }
} is (s_ok) {
state := s_idle
}
}
io.rdy := (state === s_ok)
}
class TestbedTests(c: Testbed) extends Tester(c) {
}
object Testbed {
def main(args: Array[String]): Unit = {
val tutArgs = args.slice(1, args.length)
chiselMainTest(tutArgs, () => Module(new Testbed())) {
c => new TestbedTests(c) }
}
}
But I get errors related to UFix:
[error] /home/chisel-tutorial/test/Testbed.scala:12: not found: value UFix
[error] val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UFix(), 5)
[error] ^
[error] /home/chisel-tutorial/test/Testbed.scala:13: inferred type arguments [Any] do not conform to method apply's type parameter bounds [T <: Chisel.Data]
[error] val state = Reg(init = s_idle)
[error] ^
[error] /home/chisel-tutorial/test/Testbed.scala:16: overloaded method value apply with alternatives:
[error] (v: Iterable[Chisel.Bits])(block: => Unit)Unit <and>
[error] (v: Chisel.Bits,vr: Chisel.Bits*)(block: => Unit)Unit <and>
[error] (v: Chisel.Bits)(block: => Unit)Unit
[error] cannot be applied to (Any)
[error] is (s_idle) {
[error] ^
[error] three errors found
[error] (compile:compile) Compilation failed
The tutorial actually had it written as UFIx with a capital I but I tried it both ways to no avail. I assumed this is just an old type and so I replaced UFix with UInt but left everything else the same. Then I get the following errors:
[error] /home/chisel-tutorial/test/Testbed.scala:19: value is is not a member of Unit
[error] possible cause: maybe a semicolon is missing before `value is'?
[error] } is (s_5) {
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
Heeding the error message, I attempted to resolve the error by adding semicolons prior to every "is" statement except for the first:
package Testbed
import Chisel._
class Testbed extends Module {
val io = new Bundle {
val nickel = Bool(dir = INPUT)
val dime = Bool(dir = INPUT)
val rdy = Bool(dir = OUTPUT) }
val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UInt(), 5)
val state = Reg(init = s_idle)
switch (state) {
is (s_idle) {
when (io.nickel) { state := s_5 }
when (io.dime) { state := s_10 }
}; is (s_5) {
when (io.nickel) { state := s_10 }
when (io.dime) { state := s_15 }
}; is (s_10) {
when (io.nickel) { state := s_15 }
when (io.dime) { state := s_ok }
}; is (s_15) {
when (io.nickel) { state := s_ok }
when (io.dime) { state := s_ok }
}; is (s_ok) {
state := s_idle
}
}
io.rdy := (state === s_ok)
}
class TestbedTests(c: Testbed) extends Tester(c) {
}
object Testbed {
def main(args: Array[String]): Unit = {
val tutArgs = args.slice(1, args.length)
chiselMainTest(tutArgs, () => Module(new Testbed())) {
c => new TestbedTests(c) }
}
}
and the resulting code was finally successful in generating verilog. Then I also tried removing the semicolon but putting the closing curly bracket from the previous switch statement in the line above which also worked:
package Testbed
import Chisel._
class Testbed extends Module {
val io = new Bundle {
val nickel = Bool(dir = INPUT)
val dime = Bool(dir = INPUT)
val rdy = Bool(dir = OUTPUT) }
val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UInt(), 5)
val state = Reg(init = s_idle)
switch (state) {
is (s_idle) {
when (io.nickel) { state := s_5 }
when (io.dime) { state := s_10 }}
is (s_5) {
when (io.nickel) { state := s_10 }
when (io.dime) { state := s_15 }}
is (s_10) {
when (io.nickel) { state := s_15 }
when (io.dime) { state := s_ok }}
is (s_15) {
when (io.nickel) { state := s_ok }
when (io.dime) { state := s_ok }}
is (s_ok) {
state := s_idle
}
}
io.rdy := (state === s_ok)
}
class TestbedTests(c: Testbed) extends Tester(c) {
}
object Testbed {
def main(args: Array[String]): Unit = {
val tutArgs = args.slice(1, args.length)
chiselMainTest(tutArgs, () => Module(new Testbed())) {
c => new TestbedTests(c) }
}
}
My concern now is whether the version of the switch statement as presented in the chisel tutorial works for other people, and if it does, does anyone know why I have to be careful to format my switch statements in a very particular way in order for them to work properly? If that is the case, what can I do to fix it?