状态机也是常用电路,但是Chisel没有直接构建状态机的原语。不过,chisel3.util包里定义了一个Enum特质及其伴生对象。伴生对象里的apply方法定义如下:
def apply(n: Int): List[UInt]
它会根据参数n返回对应元素数的List[UInt],每个元素都是不同的,所以可以作为枚举值来使用。
最好把枚举状态的变量名也组成一个列表,然后用列表的模式匹配来进行赋值。有了枚举值后,可以通过“switch…is…is”
语句来使用。其中,switch里是相应的状态寄存器,而每个is分支的后面则是枚举值及相应的定义。例如检测持续时间超过两个时钟周期的高电平:
// fsm.scala
package test
import chisel3._
import chisel3.util._
class DetectTwoOnes extends Module {
val io = IO(new Bundle {
val in = Input(Bool())
val out = Output(Bool())
})
val sNone :: sOne1 :: sTwo1s :: Nil = Enum(3)
val state = RegInit(sNone)
io.out := (state === sTwo1s)
switch (state) {
is (sNone) {
when (io.in) {
state := sOne1
}
}
is (sOne1) {
when (io.in) {
state := sTwo1s
} .otherwise {
state := sNone
}
}
is (sTwo1s) {
when (!io.in) {
state := sNone
}
}
}
}
重点注意这句代码即可:
//列表模式匹配的另类用法
val sNone :: sOne1 :: sTwo1s :: Nil = Enum(3)
枚举状态名的首字母要小写,这样Scala的编译器才能识别成变量模式匹配。它生成的Verilog为:
// DetectTwoOnes.v
module DetectTwoOnes(
input clock,
input reset,
input io_in,
output io_out
);
reg [1:0] state;
wire _T_1;
wire _T_2;
wire _T_3;
wire _T_4;
assign _T_1 = 2'h0 == state;
assign _T_2 = 2'h1 == state;
assign _T_3 = 2'h2 == state;
assign _T_4 = io_in == 1'h0;
assign io_out = state == 2'h2;
always @(posedge clock) begin
if (reset) begin
state
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?