当前位置:网站首页>吃透Chisel语言.29.Chisel进阶之通信状态机(一)——通信状态机:以闪光灯为例
吃透Chisel语言.29.Chisel进阶之通信状态机(一)——通信状态机:以闪光灯为例
2022-07-30 13:47:00 【github-3rr0r】
Chisel进阶之通信状态机(一)——通信状态机:以闪光灯为例
上一部分我们学习了单个有限状态机的Chisel描述方法,但是单个有限状态机通常很难描述稍微有点复杂的数字设计。在这种情况下,可以把问题划分为两个或更多的小的、简单的FSM。这个FSM之间使用信号进行通信,某个FSM的输出是另一个FSM的输入,这个FSM又观察另一个FSM的输出。把一个大的FSM分割成简单的小FSM的做法叫作分解FSM。通信FSM通常直接根据设计规格直接设计,因为如果用首先单个FSM实现设计的话就太大了。这一篇文章就一起来学习通信状态机的设计实现。
通信FSM——以闪光灯为例
为了讨论通信FSM,我们使用闪光灯的例子,这个闪光灯有一个输入start和一个输出light,该闪光灯的设计规格如下:
- 当
start在一个周期内为高电平时,闪烁开始; - 会闪烁三次;
- 一次闪烁中,
light为on持续6个周期,为off持续4个周期; - 序列之后,FSM会将
light置为off并等待下一个start;
直接用一个FSM实现这个闪光灯的话,该FSM会有27中状态:1个是等待输入的初始状态, 3 × 6 3\times 6 3×6个关于on状态的状态, 2 × 4 2\times 4 2×4个关于off状态的状态,共27中状态。我们这里就不写这种实现的代码了。
那我们可以把这个大FSM分解为两个小FSM:一个主FSM用于实现闪烁逻辑,一个定时器FSM用于实现等待,下图展示了这两个FSM之间的组合:

定时器FSM会倒数6个周期或4个周期,用于生成想要的时序,定时器的规格如下:
- 当
timerLoad被设置的时候,定时器加载一个值到倒数计数器,不依赖于状态; timerSelect会选择在加载5或3;timerDone会在计数器完成倒数的时候被设置并保持被设置状态;- 其他情况,定时器会进行倒数。
下面的代码就展示了该闪光灯的定时器FSM和主FSM实现:
val timerReg = RegInit(0.U)
// 计时器连接
val timerLoad = WireDefault(false.B) // 给load信号后启动定时器
val timerSelect = WireDefault(true.B) // 选择6周期循环或4周期循环
val timerDone = Wire(Bool())
timerDone := timerReg === 0.U
timerLoad := timerDone
// 定时器FSM(倒数计数器)
when(!timerDone) {
timerReg := timerReg - 1.U
}
when(timerLoad) {
when(timerSelect) {
timerReg := 5.U
} .otherwise {
timerReg := 3.U
}
}
val off :: flash1 :: space1 :: flash2 :: space2 :: flash3 :: Nil = Enum(6)
val stateReg = RegInit(off)
val light = WireDefault(false.B) // FSM的输出
// 主FSM
switch(stateReg) {
is(off) {
timerLoad := true.B
timerSelect := true.B
when (start) {
stateReg := flash1}
}
is (flash1) {
timerSelect := false.B
light := true.B
when (timerDone) {
stateReg := space1}
}
is (space1) {
when (timerDone) {
stateReg := flash2}
}
is (flash2) {
timerSelect := false.B
light := true.B
when (timerDone) {
stateReg := space2}
}
is (space2) {
when (timerDone) {
stateReg := flash3}
}
is (flash3) {
timerSelect := false.B
light := true.B
when (timerDone) {
stateReg := off}
}
}
代码就不解释了,就提示一点,switch语句里面没有赋值的wire都会赋默认值,所有space1和space2里面可以省略timerSelect和light的赋值,但建议最好别这么写。
不过这个解决方案在主FSM中还是有冗余代码,flash1、flash2和flash3状态的功能一致,space1和space2也是如此。我们可以把这几种flash状态分解到第二个计数器里面,那么主FSM就只有三个状态了off、flash和space。下图就展示了新的通信FSM设计:

现在图里面有两个计数FSM了,一个用于计数on和off间隔的时钟周期数,另一个用于计数剩下的flash次数。下面的代码就是向下计数FSM部分:
val cntReg = RegInit(0.U)
cntDone := cntReg === 0.U
// 向下计数FSM
when(cntLoad) {
cntReg := 2.U}
when(cntDecr) {
cntReg := cntReg - 1.U}
注意计数器加载了2以闪烁三次,因为它会倒数剩下的闪烁次数,并在定时器完成是递减到space状态。下面的代码展示了完整的新的闪光灯FSM实现:
import chisel3._
import chisel3.util._
class SimpleFsm extends Module {
val io = IO(new Bundle {
val start = Input(Bool())
val light = Output(Bool())
val state = Output(UInt()) // 用于调试
})
val light = WireDefault(false.B)
val timerLoad = WireDefault(false.B)
val timerSelect = WireDefault(true.B)
val timerDone = Wire(Bool())
val timerReg = RegInit(0.U)
timerDone := timerReg === 0.U
timerLoad := timerDone
when(!timerDone) {
timerReg := timerReg - 1.U
}
when(timerLoad) {
when(timerSelect) {
timerReg := 5.U
}.otherwise {
timerReg := 3.U
}
}
val cntLoad = WireDefault(false.B)
val cntDecr = WireDefault(true.B)
val cntDone = Wire(Bool())
val cntReg = RegInit(0.U)
cntDone := cntReg === 0.U
when(cntLoad) {
cntReg := 2.U }
when(cntDecr) {
cntReg := cntReg - 1.U }
val off :: flash :: space :: Nil = Enum(3)
val stateReg = RegInit(off)
switch(stateReg) {
is(off) {
timerLoad := true.B
timerSelect := true.B
cntLoad := true.B
when(io.start) {
stateReg := flash }
}
is(flash) {
cntLoad := false.B
timerSelect := false.B
light := true.B
when(timerDone & !cntDone) {
stateReg := space }
when(timerDone & cntDone) {
stateReg := off }
}
is(space) {
cntDecr := timerDone
when(timerDone) {
stateReg := flash }
}
}
io.light := light
io.state := stateReg
}
object MyModule extends App {
println(getVerilogString(new SimpleFsm()))
}
除了将主FSM的状态减少为3中以外,我们新的配置也更加可配置了。没有任何一个FSM会需要在我们想改变on、off时长的时候被修改。
测试代码如下:
import chisel3._
import chiseltest._
import org.scalatest.flatspec.AnyFlatSpec
class SimpleTestExpect extends AnyFlatSpec with ChiselScalatestTester {
"DUT" should "pass" in {
test(new SimpleFsm) {
dut =>
dut.clock.step()
println(dut.io.state.peekInt(), dut.io.light.peekBoolean())
dut.io.start.poke(true.B)
for (a <- 0 until 50) {
dut.clock.step()
dut.io.start.poke(false.B)
println(a, dut.io.state.peekInt(), dut.io.light.peekBoolean())
}
}
}
}
观察测试的输出,可知测试通过。
结语
这一篇文章我们以闪光灯电路为例,探索了通信电路,尤其是通信FSM的写法,FSM之间仅交换了控制信号。不过电路之间还可以交换数据,对于数据的协调交换,我们需要使用握手信号,这一部分的最后一篇文章我们就会一起学习用于单向数据交换的控制流的ready-valid接口。下一篇文章,我们将会学习带数据通路的状态机,从手动指定ready-valid信号开始。
边栏推荐
- The path to uniting the programmer: "titles bucket" to the highest state of pragmatic
- #第九章 子查询课后习题
- The main content of terrain analysis (the special effect level of the wandering earth)
- OFDM Sixteen Lectures 3- OFDM Waveforms
- 地形分析的主要内容(流浪地球的特效水平)
- [VMware virtual machine installation mysql5.7 tutorial]
- [论文翻译] Unpaired Image-To-Image Translation Using Cycle-Consistent Adversarial Networks
- 2022年,目前大环境下还适合转行软件测试吗?
- LoRaWAN网关源码分析(V1.0.2)
- 代码杂谈:从一道面试题看学会Rust的难度
猜你喜欢

ECCV 2022 | 通往数据高效的Transformer目标检测器

Conversion between pytorch and keras (the code takes LeNet-5 as an example)

LeetCode二叉树系列——199二叉树的右视图

43.【list的简单属性】

Flask Framework - Flask-Mail Mail

【ROS进阶篇】第十一讲 基于Gazebo和Rviz的机器人联合仿真(运动控制与传感器)

Classic test interview questions set - logical reasoning questions

LeetCode二叉树系列——107.二叉树的层序遍历II

权威推荐!腾讯安全DDoS边缘安全产品获国际研究机构Omdia认可

Jenkins自动化部署项目
随机推荐
为什么做软件测试一定要学自动化?谈谈我眼中自动化测试的价值
自动化测试之数据驱动DDT详细篇
AT4108 [ARC094D] Normalization
无代码开发平台全部应用设置入门教程
无代码开发平台应用可见权限设置入门教程
The way of programmers' cultivation: do one's own responsibilities, be clear in reality - lead to the highest realm of pragmatism
Jenkins自动化部署项目
【VMware虚拟机安装mysql5.7教程】
The truth of the industry: I will only test those that have no future, and I panic...
[论文翻译] Unpaired Image-To-Image Translation Using Cycle-Consistent Adversarial Networks
戴墨镜的卡通太阳SVG动画js特效
(HR面试)最常见的面试问题和技巧性答复
The path to uniting the programmer: "titles bucket" to the highest state of pragmatic
网站添加能换装可互动的live 2d看板娘
手把手教你写让人眼前一亮的软件测试简历,收不到面试邀请算我输
桌面软件开发框架大赏
There is a risk of water ingress in the battery pack tray and there is a potential safety hazard. 52,928 Tang DMs are urgently recalled
What is defect analysis?An article takes you to understand the necessary skills of test engineers
Eight years of testing experience, why was the leader criticized: the test documents you wrote are not as good as those of fresh graduates
Androd 跳转到google应用市场