Frequently Asked Questions
- Where should I start if I want to learn Chisel?
- How do I ... in Chisel?
- What versions of the various projects work together?
- How can I contribute to Chisel?
- Why DecoupledIO instead of ReadyValidIO?
- Why do I have to wrap module instantiations in
Module(...)
? - Why Chisel?
- Does Chisel support X and Z logic values?
- I just want some Verilog; what do I do?
- I just want some FIRRTL; what do I do?
- Why doesn't Chisel tell me which wires aren't connected?
- What does
Reference ... is not fully initialized.
mean? - Can I specify behavior before and after generated initial blocks?
Where should I start if I want to learn Chisel?
We recommend the Chisel Bootcamp for getting started with Chisel.
How do I do ... (e.g. like that in Verilog) in Chisel?
See the cookbooks.
What versions of the various projects work together?
See Chisel Project Versioning.
How can I contribute to Chisel?
Check out the Contributor Documentation in the chisel3 repository.
Why DecoupledIO instead of ReadyValidIO?
There are multiple kinds of Ready/Valid interfaces that impose varying restrictions on the producers and consumers. Chisel currently provides the following:
- DecoupledIO - No guarantees
- IrrevocableIO - Producer promises to not change the value of 'bits' after a cycle where 'valid' is high and 'ready' is low. Additionally, once 'valid' is raised it will never be lowered until after 'ready' has also been raised.
Why do I have to wrap module instantiations in Module(...)
?
In short: Limitations of Scala
Chisel Modules are written by defining a Scala class and implementing its constructor. As elaboration runs, Chisel constructs a hardware AST from these Modules. The compiler needs hooks to run before and after the actual construction of the Module object. In Scala, superclasses are fully initialized before subclasses, so by extending Module, Chisel has the ability to run some initialization code before the user's Module is constructed. However, there is no such hook to run after the Module object is initialized. By wrapping Module instantiations in the Module object's apply method (ie. Module(...)
), Chisel is able to perform post-initialization actions. There is a proposed solution, so eventually this requirement will be lifted, but for now, wrap those Modules!
Why Chisel?
Please see Chisel Motivation
Does Chisel support X and Z logic values
Chisel does not directly support Verilog logic values x
unknown and z
high-impedance. There are a number of reasons to want to avoid these values. See:The Dangers of Living With An X and Malicious LUT: A stealthy FPGA Trojan injected and triggered by the design flow. Chisel has its own eco-system of unit and functional testers that limit the need for x
and z
and their omission simplify language implementation, design, and testing. The circuits created by chisel do not preclude developers from using x
and z
in downstream toolchains as they see fit.
Get me Verilog
I wrote a module and I want to see the Verilog; what do I do?
Here's a simple hello world module in a file HelloWorld.scala.
package intro
import chisel3._
class HelloWorld extends Module {
val io = IO(new Bundle{})
printf("hello world\n")
}
Add the following
import circt.stage.ChiselStage
object VerilogMain extends App {
ChiselStage.emitSystemVerilog(new HelloWorld)
}
Now you can get some Verilog. Start sbt:
bash> sbt
> run-main intro.VerilogMain
[info] Running intro.VerilogMain
[info] [0.004] Elaborating design...
[info] [0.100] Done elaborating.
[success] Total time: 1 s, completed Jan 12, 2017 6:24:03 PM
or as a one-liner:
bash> sbt 'runMain intro.VerilogMain'
After either of the above there will be a HelloWorld.v file in the current directory:
// Generated by CIRCT firtool-1.99.1
module HelloWorld( // faqs.md:11:7
input clock, // faqs.md:11:7
reset // faqs.md:11:7
);
endmodule
// ----- 8< ----- FILE "verification/cover/layers-HelloWorld-Verification-Cover.sv" ----- 8< -----
// Generated by CIRCT firtool-1.99.1
`include "verification/layers-HelloWorld-Verification.sv"
`ifndef layers_HelloWorld_Verification_Cover
`define layers_HelloWorld_Verification_Cover // <stdin>:6:5
`endif // layers_HelloWorld_Verification_Cover // <stdin>:6:5
// ----- 8< ----- FILE "verification/assume/layers-HelloWorld-Verification-Assume.sv" ----- 8< -----
// Generated by CIRCT firtool-1.99.1
`include "verification/layers-HelloWorld-Verification.sv"
`ifndef layers_HelloWorld_Verification_Assume
`define layers_HelloWorld_Verification_Assume // <stdin>:5:5
`endif // layers_HelloWorld_Verification_Assume // <stdin>:5:5
// ----- 8< ----- FILE "verification/assert/layers-HelloWorld-Verification-Assert.sv" ----- 8< -----
// Generated by CIRCT firtool-1.99.1
`include "verification/layers-HelloWorld-Verification.sv"
`ifndef layers_HelloWorld_Verification_Assert
`define layers_HelloWorld_Verification_Assert // <stdin>:4:5
`endif // layers_HelloWorld_Verification_Assert // <stdin>:4:5
// ----- 8< ----- FILE "verification/layers-HelloWorld-Verification.sv" ----- 8< -----
// Generated by CIRCT firtool-1.99.1
`ifndef layers_HelloWorld_Verification
`define layers_HelloWorld_Verification // <stdin>:3:3
bind HelloWorld HelloWorld_Verification verification (
.reset (reset),
.clock (clock)
);
`endif // layers_HelloWorld_Verification // <stdin>:3:3
// ----- 8< ----- FILE "verification/HelloWorld_Verification.sv" ----- 8< -----
// Generated by CIRCT firtool-1.99.1
// Users can define 'PRINTF_COND' to add an extra gate to prints.
`ifndef PRINTF_COND_
`ifdef PRINTF_COND
`define PRINTF_COND_ (`PRINTF_COND)
`else // PRINTF_COND
`define PRINTF_COND_ 1
`endif // PRINTF_COND
`endif // not def PRINTF_COND_
module HelloWorld_Verification( // faqs.md:13:9
input reset, // faqs.md:13:9
clock // faqs.md:13:9
);
`ifndef SYNTHESIS // faqs.md:13:9
always @(posedge clock) begin // faqs.md:13:9
if ((`PRINTF_COND_) & ~reset) // faqs.md:13:9
$fwrite(32'h80000002, "hello world\n"); // faqs.md:13:9
end // always @(posedge)
`endif // not def SYNTHESIS
endmodule
You can see additional options with
bash> sbt 'runMain intro.HelloWorld --help'
This will return a comprehensive usage line with available options.
For example to place the output in a directory name buildstuff use
bash> sbt 'runMain intro.HelloWorld --target-dir buildstuff --top-name HelloWorld'
Alternatively, you can also use the sbt console to invoke the Verilog driver:
$ sbt
> console
[info] Starting scala interpreter...
Welcome to Scala 2.12.13 (OpenJDK 64-Bit Server VM, Java 1.8.0_275).
Type in expressions for evaluation. Or try :help.
scala> (new circt.stage.ChiselStage).emitSystemVerilog(new HelloWorld())
chisel3.Driver.execute(Array[String](), () => new HelloWorld)
Elaborating design...
Done elaborating.
res1: String =
"module HelloWorld(
input clock,
input reset
);
...
As before, there should be a HelloWorld.v file in the current directory.
Note: Using the following, without the new
,
will ONLY return the string representation, and will not emit a .v
file:
ChiselStage.emitSystemVerilog(new HelloWorld())
Get me FIRRTL
If for some reason you don't want the Verilog (e.g. maybe you want to run some custom transformations before exporting to Verilog), then use something along these lines:
package intro
import chisel3._
import circt.stage.ChiselStage
class MyFirrtlModule extends Module {
val io = IO(new Bundle{})
}
object FirrtlMain extends App {
ChiselStage.emitCHIRRTL(new MyFirrtlModule)
}
Run it with:
sbt 'runMain intro.FirrtlMain'
FIRRTL version 4.1.0
circuit MyFirrtlModule :
layer Verification, bind, "verification" :
layer Assert, bind, "verification/assert" :
layer Assume, bind, "verification/assume" :
layer Cover, bind, "verification/cover" :
public module MyFirrtlModule : @[faqs.md 64:7]
input clock : Clock @[faqs.md 64:7]
input reset : UInt<1> @[faqs.md 64:7]
output io : { } @[faqs.md 65:14]
skip
Alternatively, you can also use the sbt console to invoke the FIRRTL driver directly (replace MyFirrtlModule with your module name):
$ sbt
> console
[info] Starting scala interpreter...
Welcome to Scala 2.12.13 (OpenJDK 64-Bit Server VM, Java 1.8.0_275).
Type in expressions for evaluation. Or try :help.
scala> circt.stage.ChiselStage.emitCHIRRTL(new MyFirrtlModule)
Elaborating design...
Done elaborating.
res3: String = ...
Why doesn't Chisel tell me which wires aren't connected?
As long as your code uses import chisel3._
(and not import Chisel._
), it does!
See Unconnected Wires for details.
What does Reference ... is not fully initialized.
mean?
It means that you have unconnected wires in your design which could be an indication of a design bug.
In Chisel2 compatibility mode (NotStrict
compile options), chisel generates firrtl code that disables firrtl's initialized wire checks.
In pure chisel3 (Strict
compile options), the generated firrtl code does not contain these disablers (is invalid
).
Output wires that are not driven (not connected) are reported by firrtl as not fully initialized
.
Read more at Unconnected Wires for details on solving the problem.
Can I specify behavior before and after generated initial blocks?
Users may define the following macros if they wish to specify behavior before or after emitted initial blocks.
BEFORE_INITIAL
, which is called before the emitted (non-empty) initial block if it is definedAFTER_INITIAL
, which is called after the emitted (non-empty) initial block if it is defined
These macros may be useful for turning coverage on and off.