Chisel学习7 有限状态机

文章介绍了有限状态机(FSM)在数字设计中的基本概念和实现方式,包括摩尔机和梅利机。FSM由状态寄存器、组合逻辑和输出逻辑组成,可用于描述复杂的系统行为。文中通过报警FSM和上升沿检测器的例子,展示了MooreFSM和MealyFSM的区别,MealyFSM因其响应速度和状态效率被认为更为优越。Chisel语言被用来实现这些FSM的编码。

有限状态机(FSM)是数字设计中的基本构建块。FSM可以被描述为一组状态和状态之间的条件(保护)状态转换。FSM具有初始状态,其在复位时被设置。FSM也称为同步时序电路。

FSM的实现由三部分组成:(1)保持当前状态的寄存器,(2)计算取决于当前状态和输入的下一状态的组合逻辑,以及(3)计算FSM的输出的组合逻辑。

原则上,包含用于存储状态的寄存器或其他存储器元件的每个数字电路可以被描述为单个FSM。但是,这可能并不实际,例如,尝试将您的笔记本电脑描述为单个FSM。在下一章中,我们将描述如何通过将较小的FSM组合成通信FSM来构建更大的系统。

基本有限状态机

图8.1显示了FSM的原理图。寄存器包含当前状态。下一状态逻辑根据当前状态和输入(in)计算下一状态值(nextState)。在下一个时钟周期,state变为nextState。输出逻辑计算输出(out)。由于输出仅取决于当前状态,因此该状态机被称为摩尔机。
在这里插入图片描述
在这里插入图片描述
状态图直观地描述了这种FSM的行为。在状态图中,各个状态被描绘为用状态名称标记的圆圈。状态转换用状态之间的箭头示出。采用此转换时的防护(或条件)将绘制为箭头的标签。

图8.2显示了一个简单的FSM示例的状态图。FSM有三种状态:绿色、橙色和红色,指示警报级别。FSM在绿色电平启动。当不良事件发生时,警报级别切换为橙色。在第二个不良事件时,报警级别切换为红色。在这种情况下,我们想敲响警钟;振铃是该FSM的唯一输出。我们将输出添加到红色状态。报警器可通过清除信号复位。

虽然状态图可能在视觉上令人愉悦并且FSM的功能可以被快速地掌握,但是状态表可能更快地被写下。表8.1显示了报警FSM的状态表。我们列出当前状态、输入值、结果下一个状态和当前状态的输出值。原则上,我们需要为所有可能的状态指定所有可能的输入。这个表有3×4 = 12行。我们简化了表,指出明确的输入是一个不关心当一个坏的事件发生。这意味着坏事件优先于清除事件。输出列有一些重复。如果我们有一个更大的FSM和/或更多的输出,我们可以将表分成两个,一个用于下一个状态逻辑,一个用于输出逻辑。
在这里插入图片描述
最后,在我们的警告级别FSM的所有设计之后,我们将在Chisel中对其进行编码。清单8.1显示了报警FSM的Chisel代码。注意,我们使用Chisel类型Bool作为FSM的输入和输出。要使用Enum和开关控制指令,我们需要导入chisel3.util。

  // The three states
  val green :: orange :: red :: Nil = Enum(3)

各个状态值被描述为一个列表,其中各个元素与::运算符; Nil表示列表的结尾。将枚举实例分配给状态列表。

使用Mealy状态机进行快速输出

在Moore FSM上,输出仅取决于当前状态。这意味着输入的改变可以被视为下一个时钟周期中最早的输出的改变。如果我们想观察到一个即时的变化,我们需要一个从输入到输出的组合路径…让我们考虑一个最小的例子,边缘检测电路。

图8.3显示了上升沿检测器的原理图。当当前输入为1且上一个时钟周期中的输入为0时,输出在一个时钟周期内变为1。状态寄存器只是一个D触发器,其中下一个状态只是输入。我们也可以将其视为一个时钟周期的延迟元件。输出逻辑将当前输入与当前状态进行比较。
在这里插入图片描述
当输出也取决于输入时,即,在FSM的输入和输出之间存在组合路径,这被称为Mealy状态机。

在这里插入图片描述

图8.4所示为Mealy型有限状态机的原理图。与Moore FSM类似,寄存器包含当前状态,下一状态逻辑根据当前状态和输入(in)计算下一状态值(nextState)。在下一个时钟周期,state变为nextState。输出逻辑根据当前状态和FSM的输入计算输出(out)。

图8.5显示了边缘检测器的Mealy FSM的状态图。由于状态寄存器仅由单个D触发器组成,因此只有两种状态是可能的,在该示例中我们将其命名为零和一。由于Mealy FSM的输出不仅依赖于状态,而且依赖于输入,因此我们不能将输出描述为状态循环的一部分。相反,状态之间的转换用输入值(条件)和输出(斜杠之后)标记。还请注意,我们绘制自转换,例如,在状态零中,当输入为0时,FSM保持在状态零,并且输出为0。上升沿FSM仅在从状态0转换到状态1时产生1输出。在状态1中,表示输入现在为1,输出为0。我们只希望输入的每个上升沿都有一个(周期)普尔斯。

  switch (stateReg) {
    is(zero) {
      when(io.din) {
        stateReg := one
        io.risingEdge := true.B
      }
    }
    is(one) {
      when(!io.din) {
        stateReg := zero
      }
    }
  }

上述代码显示了使用Mealy机进行上升沿检测的Chisel代码。与前面的示例一样,我们使用Chisel类型Bool作为单位输入和输出。输出逻辑现在是下一状态逻辑的一部分;在从0到1的转变时,输出被设置为真。否则,对输出的默认赋值(false.B)将被计入。

Moore Vs Mealy

为了显示Moore和Mealy FSM之间的差异,我们用Moore FSM重新进行边缘检测。
在这里插入图片描述
上图显示了Moore FSM的上升沿检测状态图。首先要注意的是,与Mealy版本中的两个状态相比,Moore FSM需要三个状态。需要状态puls来产生周期脉冲。FSM保持在仅脉冲一个时钟周期的状态,然后返回到起始状态零或一状态,等待输入再次变为0。我们在状态转换箭头上显示输入条件,并在表示状态的圆圈内显示FSM输出。

Moore版本的上升沿检测电路。它使用的D触发器数量是Mealy或直接编码版本的两倍。因此,所得到的下一状态逻辑也大于Mealy或直接编码的版本

Mealy FSM是更好的FSM,因为它们需要更少的状态,并且比Moore FSM反应更快。然而,Mealy机中的组合路径可能会在更大的设计中引起麻烦。

<think>嗯,用户想了解关于Chisel电路学习的每日一练。首先,我需要确认用户对Chisel的熟悉程度。可能他们刚开始学习,或者已经有一定基础,想通过每日练习来巩固知识。Chisel是构建在Scala上的硬件构造语言,所以可能需要结合Scala的基础知识。用户可能希望得到结构化的学习计划,包含每日的小练习,逐步深入。 接下来,我应该考虑如何组织内容。每日一练通常需要从简单到复杂,覆盖Chisel的核心概念,比如组合逻辑、时序电路、模块化设计、测试等。每天一个主题,配合代码示例和练习题目,这样用户可以动手实践。同时,要确保符合用户的要求,使用正确的中文和LaTeX格式,行内公式用$...$,独立公式用$$...$$。 另外,用户可能需要实际例子来理解概念,比如如何用Chisel实现一个加法器或状态机。测试部分也很重要,因为ChiselTest是常用的测试框架,应该包含如何编写测试用例。最后,高级主题如参数化设计、生成Verilog代码、性能优化可能适合后续的练习。 需要检查是否有遗漏的部分,比如安装配置环境,或者参考资料推荐。但用户可能已经具备基本环境,所以重点放在每日练习内容上。同时,结构要清晰,分点说明,每个练习日包含目标、示例代码和练习任务,让用户逐步完成。</think>以下是为Chisel硬件设计语言学习者设计的"每日一练"渐进式学习方案,采用问题导向型结构,结合关键知识点和代码示例: 🌟 **Day 1:基础逻辑门实现** ```scala class ANDgate extends Module { val io = IO(new Bundle { val a = Input(Bool()) val b = Input(Bool()) val out = Output(Bool()) }) io.out := io.a & io.b // 实现与门逻辑 } ``` 练习:扩展实现OR/XOR/NAND门电路 🔢 **Day 2:组合逻辑设计** 实现4位全加器: ```scala class FullAdder extends Module { val io = IO(new Bundle { val a = Input(UInt(1.W)) val b = Input(UInt(1.W)) val cin = Input(UInt(1.W)) val sum = Output(UInt(1.W)) val cout = Output(UInt(1.W)) }) io.sum := io.a ^ io.b ^ io.cin io.cout := (io.a & io.b) | (io.a & io.cin) | (io.b & io.cin) } ``` 练习:构建级联的4位行波进位加法器 ⏳ **Day 3:时序电路设计** 实现带异步复位的D触发器: ```scala class DFFAsyncReset extends Module { val io = IO(new Bundle { val d = Input(Bool()) val rst = Input(Bool()) val q = Output(Bool()) }) io.q := withReset(io.rst)(RegNext(io.d, false.B)) } ``` 练习:设计4位循环移位寄存器 📦 **Day 4:模块化设计** 构建计数器模块: ```scala class Counter(mod: Int) extends Module { val io = IO(new Bundle { val en = Input(Bool()) val out = Output(UInt(log2Ceil(mod).W)) }) val count = RegInit(0.U(log2Ceil(mod).W)) when(io.en) { count := Mux(count === (mod-1).U, 0.U, count + 1.U) } io.out := count } ``` 练习:实现可配置位宽的计数器 📊 **Day 5:总线接口设计** 定义APB总线接口: ```scala class APBBundle extends Bundle { val paddr = Output(UInt(32.W)) val psel = Output(Bool()) val penable = Output(Bool()) val pwrite = Output(Bool()) val pwdata = Output(UInt(32.W)) val prdata = Input(UInt(32.W)) val pready = Input(Bool()) } ``` 练习:实现APB总线转接器 🔍 **Day 6:测试验证** 使用ChiselTest进行模块验证: ```scala test(new ANDgate).withAnnotations(Seq(WriteVcdAnnotation)) { c => c.io.a.poke(false.B) c.io.b.poke(true.B) c.io.out.expect(false.B) c.clock.step() } ``` 练习:为计数器模块编写完整测试用例 💡 **高阶练习建议**: 1. 参数化FIR滤波器设计 2. RISC-V核心流水线实现 3. AXI4总线协议转换器 4. 动态时钟门控电路 5. 异步FIFO缓冲设计 📚 **学习资源推荐**: 1. 官方文档:https://www.chisel-lang.org/ 2. 数字设计实践工具链安装: ```bash brew install verilator # macOS sudo apt install verilator gtkwave # Ubuntu ``` 3. 在线实验平台:https://www.myhdl.org/chisel-edu/ 每日练习建议流程: 1. 理解当日设计目标 2. 编写Chisel代码 3. 生成Verilog:`sbt run` 4. 使用Verilator进行仿真验证 5. 记录设计参数和时序分析 通过持续练习,您将逐步掌握: - 硬件描述语言的抽象建模能力 - 数字系统架构设计方法 - 可重用IP核开发技巧 - 硬件/软件协同验证流程 建议每天投入1-2小时实践,遇到问题可通过Chisel社区(https://github.com/chipsalliance/chisel/discussions)交流讨论。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值