when ( myData === 3.U ) { // Some logic to run when myData equals 3. } .elsewhen ( myData === 1.U ) { // Some logic to run when myData equals 1. } .otherwise { // Some logic to run when myData is neither 3 nor 1. }
1 2 3 4 5 6 7 8 9
// Returns the current `when` condition when (a) { when (b) { when (c) { }.otherwise { when.cond // this is equal to: a && b && !c } } }
val input = IO(Flipped(Decoupled(newGcdInputBundle(width)))) val output = IO(Decoupled(newGcdOutputBundle(width)))
val xInitial = Reg(UInt()) val yInitial = Reg(UInt()) val x = Reg(UInt()) val y = Reg(UInt()) val busy = RegInit(false.B) val resultValid = RegInit(false.B)
Queue creates a FIFO (first-in, first-out) queue with
Decoupled interfaces on both sides, allowing backpressure. Both the data
type and number of elements are configurable.
1 2 3 4 5 6 7 8 9 10 11
classMyQueue(width: Int, len: Int) extendsModule{ val io = IO(newBundle { val in = Flipped(Decoupled(UInt(width.W))) val out = Decoupled(UInt(width.W)) }) val fifo = Queue(io.in, len) io.out <> fifo }
Arbiters routes data from nDecoupledIO sources
to one DecoupledIO sink, given a prioritization. There are
two types included in Chisel:
Arbiter: prioritizes lower-index producers
RRArbiter: runs in round-robin order
Note that Arbiter routing is implemented in combinational
logic.
1 2 3 4 5 6 7 8 9 10 11 12
classMyArbiter(InNum: Int, width: Int) extendsModule{ // Example circuit using a priority arbiter val io = IO(newBundle { val in = Flipped(Vec(InNum, Decoupled(UInt(width.W)))) val out = Decoupled(UInt(width.W)) }) // Arbiter doesn't have a convenience constructor, so it's built like any Module val arbiter = Module(newArbiter(UInt(width.W), InNum)) // 2 to 1 Priority Arbiter arbiter.io.in <> io.in io.out <> arbiter.io.out } println(getVerilog(newMyArbiter(2, 32)))
PopCount
PopCount returns the number of high (1) bits in the input as a
UInt.
计算 1 的个数。
1
io.out := PopCount(io.in)
Reverse
Reverse returns the bit-reversed input.
翻转。
1
io.out := Reverse(io.in)
OneHot encoding utilities
OneHot is an encoding of integers where there is one wire for each
value, and exactly one wire is high. This allows the efficient creation
of some functions, for example muxes. However, behavior may be undefined
if the one-wire-high condition is not held.
UInt to OneHot: UIntToOH
OneHot to UInt: OHToUInt
Muxes
These muxes take in a list of values with select signals, and output
the value associated with the lowest-index select signal.
These can either take a list of (select: Bool, value: Data) tuples,
or corresponding lists of selects and values as arguments. For
simplicity, the examples below only demonstrate the second form.
Priority Mux
A PriorityMux outputs the value associated with the
lowest-index asserted select signal.
OneHot Mux
An Mux1H provides an efficient implementation when it is
guaranteed that exactly one of the select signals will be high. Behavior
is undefined if the assumption is not true.
1 2 3 4 5 6 7 8 9 10
classMyPriorityMux(InNum: Int, width: Int) extendsModule{ // Example circuit using PriorityMux val io = IO(newBundle { val in_sels = Input(Vec(InNum, Bool())) val in_bits = Input(Vec(InNum, UInt(width.W))) val out = Output(UInt(width.W)) }) io.out := PriorityMux(io.in_sels, io.in_bits) } println(getVerilog(newMyPriorityMux(2, 32)))
counter
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classMyCounter(cnt: Int, width: Int) extendsModule{ // Example circuit using Mux1H val io = IO(newBundle { val count = Input(Bool()) val out = Output(UInt(width.W)) }) val counter = Counter(cnt) // 3-count Counter (outputs range [0...2]) when(io.count) { counter.inc() } io.out := counter.value }
println(getVerilog(newMyCounter(3, 2))) // 3-count Counter (outputs range [0...2])
Map
1 2 3 4 5 6 7 8 9 10 11 12 13
println(List(1, 2, 3, 4).map(x => x + 1)) // explicit argument list in function println(List(1, 2, 3, 4).map(_ + 1)) // equivalent to the above, but implicit arguments println(List(1, 2, 3, 4).map(_.toString + "a")) // the output element type can be different from the input element type
println(List((1, 5), (2, 6), (3, 7), (4, 8)).map { case (x, y) => x*y }) // this unpacks a tuple, note use of curly braces
// Related: Scala has a syntax for constructing lists of sequential numbers println(0 to 10) // to is inclusive , the end point is part of the result println(0 until 10) // until is exclusive at the end, the end point is not part of the result
// Those largely behave like lists, and can be useful for generating indices: val myList = List("a", "b", "c", "d") println((0 until 4).map(myList(_)))
println(List(1, 2, 3, 4).reduce((a, b) => a + b)) // returns the sum of all the elements println(List(1, 2, 3, 4).reduce(_ * _)) // returns the product of all the elements println(List(1, 2, 3, 4).map(_ + 1).reduce(_ + _)) // you can chain reduce onto the result of a map
1 2 3
10 24 14
Fold
类似 reduce,不过可以提供一个初值。
1 2 3
println(List(1, 2, 3, 4).fold(0)(_ + _)) // equivalent to the sum using reduce println(List(1, 2, 3, 4).fold(1)(_ + _)) // like above, but accumulation starts at 1 println(List().fold(1)(_ + _)) // unlike reduce, does not fail on an empty input
classMyRoutingArbiter(numChannels: Int) extendsModule{ val io = IO(newBundle { val in = Vec(numChannels, Flipped(Decoupled(UInt(8.W)))) val out = Decoupled(UInt(8.W)) } )