chisel 语法

本文详细介绍了Chisel编程语言中的关键概念,如信号处理(resetSignal,frequ,Reg,Wire,Mux),状态机(FSM,Enum,stateReg,ledReg),以及Bundle和DirectionalBundle的使用,同时涵盖了Verilog风格的模块设计和Chisel特有的Valid/DecoupledIO处理。
摘要由CSDN通过智能技术生成

请添加图片描述


// 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 tick
  when(tick.io.tick === 1.U) {

    // State change one tick earlier
    when(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

//reg的各种写法
val r = Reg(UInt(4.W))
val r =  Reg(init = 0.U(32.W) )
val r = Reg(init = UInt(0, width = 1))

val pcReg = Reg(next= pcNext, init= 0.U(32.W))
val r = RegNext(io.in)
val reg = RegInit(0.U)
val reg = RegInit(0.U(max.getwidth.W))

Example 1.1.3

val r = Reg(UInt(4.W))
r := io.in
io.out := r

对应生成的Verilog代码是:

reg [3:0] r;
always @(posedge clock) begin
  r <= 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)
val reg =Reg(next = in)
另外,如果想在reset时初始化一个register,可以使用 RegInit:

val r = RegInit(0.U(4.W))
r := io.in

对应的Verilog代码如下:

reg [3:0] r;
always @(posedge clock) begin
  if (reset) begin
    r <= 4'h0;
  end else begin
    r <= io_in;
  end
end

reg + next + init
val pcReg = Reg(next= pcNext, init= 0.U(32.W))

上升沿检测器

def risingedge(x:Bool) = x && !Reg(next = x) 

计数器


def counter(max: UInt) = {
val x = Reg(init = 0.U(max.getWidth.W))
x := Mux(x === max, 0.U, x + 1.U)
x
}

// 下边是自己写的
def counter(max:UInt) {
	val reg = RegInit(0.UInt(max.getwidth.W))
	when(reg===max){
	reg := 0.U
}.otherwise{
	reg := reg + 1.U
}

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。

运算符

在这里插入图片描述

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值