吃透Chisel语言.06.Chisel基础(三)——寄存器和计数器

Chisel基础(三)——寄存器和计数器

Chisel基础的上一部分我们介绍了Chisel中的运算符和组合逻辑,但是要构造复杂的数字逻辑电路,光有组合电路是不够的,因为组合电路是没有状态信息的。这一部分就介绍用于描述数字电路状态信息的基本组件,也就是大家耳熟能详的寄存器(Register)。介绍完寄存器和寄存器上的操作之后,我们将会用寄存器实现一个计数器。

寄存器

Chisel中提供了寄存器组件,本质是D-触发器(D flip-flops)的集合,D-触发器的概念属于数字逻辑电路的范畴,在此不展开讲述,我们将其抽象为寄存器即可。

Chisel中的寄存器隐式地连接到全局时钟,并在每个时钟的上升沿更新寄存器的值。

在寄存器声明时提供一个初始化值时,寄存器会使用连接到全局复位信号的同步复位信号。

寄存器中存放的值可以是能够表示为位的集合的任意Chisel类型,下面的代码就定义了一个位宽为8的寄存器,复位时会初始化为0:

val reg = RegInit(0.U(8.W))

输入使用更新操作符:=连接到寄存器,而寄存器的输出可以用寄存器名直接引用,用在表达式中:

reg := d
val q = reg

上面三行代码定义的寄存器电路如下图所示,包括一个隐式的时钟信号clock、一个初始化寄存器为0.U的隐式同步复位信号reset、输入信号d和输出信号q,全局信号globalreset都是隐式连接到每个寄存器的:

在这里插入图片描述

寄存器也可以用RegNext()来定义,参数分别为它的输入和一个作为初始值的常数:

val bothReg = RegNext(d, 0.U)

为了在写代码的时候区分组合逻辑和寄存器的信号,通常在命名的时候会给寄存器后面加上后缀Reg。另一种常见的方法,常用于Java和Scala,就是使用camelCase(驼峰命名法),用多个单词来作为标识符。在这种方式中,函数和变量都是小写开头,而类(类型),比如模块名,就使用大写开头。

Chisel中的命名相对自由,不过最好用好看又有描述性的命名。还有要注意的是,Scala和Chisel中的关键字不能作为命名。而关于Chisel的编码规范,后面会专门写一篇文章。

Chisel中用寄存器和Mux实现计数器

计数器是数字系统中很基础的组件,比如性能计数器、程序计数器等。我们可能会用寄存器记录事件发生的次数,但更多的情况是用于定义一个时间间隔。也就是计数器记录时钟周期数,在达到一定数目的时候(经过这个时间间隔时)触发一个操作。

简单的方法就是计数器计数到某个上限值就复位。要注意的是,计算机科学和数字设计里面,计数都是从0开始的,所以如果想计数到10,那就是从0数到9。

下面的代码就实现了一个计数器,最多计数到9,然后再重新从0计数到9:

val cntReg = RegInit(0.U(8.W))
cntReg := Mux(cntReg === 9.U, 0.U, cntReg + 1.U)

当然了,Chisel标准组件中是有计数器Counter的,这个我们后面再说!

虽然说Chisel会为信号和寄存器推断需要的位宽,但是最好还是在创建硬件对象的时候指定想要的位宽。在大多数场合,给寄存器一个已知的复位初始化值也是最好的:

val reg = RegInit(0.S(8.W))

如果不给定初始化值,让寄存器值在复位时是未定义的,可能会节省一条复位加载线网,但是在测试和验证的时候如果已知复位值会容易很多。

结语

关于寄存器的内容并不多,但寄存器是有状态信息的模块,还隐式引入了时钟,因此是时序电路的基础。那么组合电路有了,时序电路也有了,理论上就可以为所欲为实现任何我们想实现的数字电路了,实现一个处理器也自然不在话下。下一节我们会对Chisel中的BundleVec进行介绍,这是上节挖的坑,而这两个结构可以为我们编写代码带来超多的便利!

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值