// TODO: find out the new way to have a reset signal
class KnightRider(resetSignal: Bool = null, frequ: Int)//extends Module(_reset = resetSignal) {extends Module {val io = IO(new Bundle {val led = Output(Bits(6.W))})//定义了一个枚举类型,包含两个状态goLeft和goRight,用于控制FSM。val goLeft :: goRight :: Nil = Enum(2) //定义枚举类型val stateReg = RegInit(goLeft)val ledReg = RegInit(1.U(6.W))val tick = Module(new Tick(frequ))// Update FSM state and registers only with low frequency tickwhen(tick.io.tick === 1.U) {// State change one tick earlierwhen(ledReg(4) === 1.U) {stateReg := goRight}.elsewhen(ledReg(1) === 1.U) {stateReg := goLeft}when(stateReg === goLeft) {ledReg := ledReg << 1}.otherwise {ledReg := ledReg >> 1}}io.led := ledReg
}
=
和 :=
的区别。大体来讲,=
用来定义一个val,:=
用来连线。
reg
接下来,我们来定义寄存器register
Example 1.1.3
val r = Reg(UInt(4.W))
r := io.in
io.out := r
对应生成的Verilog代码是:
reg [3:0] r;
always @(posedge clock) beginr <= io_in;
end
assign io_out = r;
Example 1.1.3 的前两行可以简化为一行:
val r = RegNext(io.in)
这里 RegNext 表示一个寄存器,其参数为该寄存器的输入。r 会被推断为一个4-bit unsigned register,因为io.in是一个4-bit unsigned input。
更进一步,example 1.1.3可以压缩为一行代码:
io.out := RegNext(io.in)
另外,如果想在reset时初始化一个register,可以使用 RegInit:
val r = RegInit(0.U(4.W))
r := io.in
对应的Verilog代码如下:
reg [3:0] r;
always @(posedge clock) beginif (reset) beginr <= 4'h0;end else beginr <= io_in;end
end
Chisel新手教程(2)
wire reg
val data = Wire(UInt(10.W)) // This is a 10-bit wire
val dataR = Reg(UInt(10.W)) // This is a 10-bit register
val cnt = RegInit(0.U(8.W))
cnt := cnt + 1.U // increases by 1 each clock cycle
uint
你可以对 UInt 进行比特提取操作。假设 a 是一个8bit数据,你可提取 a 的 bit1 至 bit3 生成一个新的信号。
val a = "b10010110".U
val b = a(3, 1) // b is "b011".U
bool
Bool 表示布尔值,共有两个状态: true.B 或 false.B
val a = Wire(Bool())
a := true.B
Bool 可以被赋予 UInt 中的某一个比特
val data = Reg(UInt(7.W))
val bit0 = data(0) // Bool
val bit2 = data(2) // Bool
Note: 对于 UInt 信号的某一比特进行赋值是不支持的。下面的代码会导致编译报错: chisel3.internal.ChiselException: Cannot reassign to read-only …
val data = Wire(UInt(7.W))
data(2) := false.B // Error !! Not supported.
一种可行的替换方案是用 Vector of Bools.
val b = Wire(Vec(7, Bool()))
b(2) := someBool
data := b.asUInt
===
等于and =/=
如需比较两个信号值是否相同或不同,用 === 和 =/=
假设 data0 和 data1 是 UInt 类型,如果 data0 等于 data1,下面的代码会设置 eq 的值为 true.B
val eq = data0 === data1 // eq is inferred as type Bool
val ne = data0 =/= data1 // ne is inferred as type Bool
Note: == is for Scala type, === is for Chisel hardware type.
Cat
Cat 可以将多个 UInt 或者 Bool 值拼成(catenate)一个新的 UInt.
val a = Wire(UInt(3.W))
val b = Wire(Bool())
a := 2.U
b := true.B
val c = Cat(4.U(3.W), b, a) // c = "b1001010".U
Note: “b1001010”.U can also be written as “b100_1_010”.U to make it more readable. The underscore is ignored.
Chisel新手教程(3)
mux
Mux(condition, x, y)
when
when (condA) {r := x
}.elsewhen (condB) {r := y
}.otherwise {r := z
}
和 Verilog 类似,如果不定义 otherwise 的话,会认为 otherwise 为保持不变。因此要注意如果上例中 r 为 Wire 类型,不写 otherwise 的话则会生成 latch,这种情况一定要避免。
r := y
when (condA) { r := x }
Mux1H
在 chisel3.util 的package里提供了 one-hot 选择器 Mux1H。当我想实现一个 one-hot 的选择器时,我会选择用 Mux1H。
Chisel新手教程(4)
Bundle
Bundle 用来表示一组信号,例如下例中 x, y, z 三个信号组成一个 Bundle 信号 A
Example 1.0
class A extends Bundle {val x = Bool()val y = UInt(2.W)val z = UInt(4.W)
}
Directional Bundle
输入输出 Bundle 信号是有方向的,下例中 IO 接口包含一个 Input 和 Output Bundle 信号。
class Example extends Module {val io = IO(new Bundle() {val in = Input(new A)val out = Output(new A)})io.out := io.in
}
Valid & Decoupled IO
在实际工作中,我们经常会遇到数据信号携带一个 valid 指示,或者握手信号 valid/ready。Chisel 提供了 Valid 和 Decoupled 方法来给信号加入valid 或 valid/ready 信号。
例如对于开头 Example 1.0 里的 Bundle 信号 A,使用 Valid 方法可以得到 output valid 和 output A 。需要注意的是,要用 bits 来表示数据部分,也就是本例中的 A.
val outWithValid = Valid(new A)
...
val out_valid = outWithValid.valid
val out_A = outWithValid.bits // Bundle A
val out_A_x = outWithValid.bits.x // x of Bundle A
如果需要 Input 形式的 Valid IO,可以用 Flipped 或 Input
val inWithValid = Flipped(Valid(new A))
val inWithValid = Input(Valid(new A))
Decoupled 方法可以再提供一个 input 的 ready。如下例所示:
val in = Decoupled(new A)
val out_valid = in.valid
val out_A = in.bits
in.ready := in_ready
同样,可以用 Flipped 进行方向取反操作,得到 output 的 ready 和 input 的 valid/bits
另外,Decoupled 信号还定义了一个 fire 信号。in.fire 等价于 in.valid && in.ready。