在 SpinalHDL 中,您可以通过使用枚举和 switch/case 语句来定义您的状态机,就像在 VHDL/Verilog 中一样。但在 SpinalHDL 中,您也可以使用专用语法。
下面的状态机在以下示例中实现:
风格一:
import spinal.lib.fsm._
class TopLevel extends Component {
val io = new Bundle {
val result = out Bool()
}
val fsm = new StateMachine {
val counter = Reg(UInt(8 bits)) init (0)
io.result := False
val stateA : State = new State with EntryPoint {
whenIsActive(goto(stateB))
}
val stateB : State = new State {
onEntry(counter := 0)
whenIsActive {
counter := counter + 1
when(counter === 4) {
goto(stateC)
}
}
onExit(io.result := True)
}
val stateC : State = new State {
whenIsActive(goto(stateA))
}
}
}
风格二:
import spinal.lib.fsm._
class TopLevel extends Component {
val io = new Bundle {
val result = out Bool()
}
val fsm = new StateMachine{
val stateA = new State with EntryPoint
val stateB = new State
val stateC = new State
val counter = Reg(UInt(8 bits)) init (0)
io.result := False
stateA
.whenIsActive(goto(stateB))
stateB
.onEntry(counter := 0)
.whenIsActive {
counter := counter + 1
when(counter === 4) {
goto(stateC)
}
}
.onExit(io.result := True)
stateC
.whenIsActive(goto(stateA))
}
}
StateMachine
是基类。它管理 FSM 的逻辑。
val myFsm = new StateMachine {
// Definition of states
}
StateMachine
还提供了一些访问器:
姓名 | 返回 | 描述 |
---|---|---|
isActive(state) | Bool | True 当状态机处于给定状态时返回 |
isEntering(state) | Bool | True 当状态机进入给定状态时返回 |
通过扩展 EntryPoint trait,可以将状态定义为状态机的入口点:
val stateA = new State with EntryPoint
或通过使用setEntry(state)
:
val stateA = new State
setEntry(stateA)
goto(nextState)
,它将状态机安排nextState
在下一个周期。exit()
安排状态机在下一个周期处于启动状态(或者,在 中StateFsm
,退出当前嵌套状态机)。这两个函数可以在状态定义中使用(见下文)或 using ,它始终适用,优先于状态。always { yourStatements }``yourStatements
可以使用多种状态:
State
(基地之一)StateDelay
StateFsm
StateParallelFsm
它们中的每一个都提供了以下函数来定义与它们关联的逻辑:
姓名 | 描述 |
---|---|
state.onEntry {```你的声明```} | yourStatements 状态机不在时应用state ,将state 在下一个周期 |
state.onExit {```你的声明```} | yourStatements 在状态机处于状态时应用,state 并将在下一个周期处于另一个状态 |
state.whenIsActive {```你的声明```} | yourStatements 当状态机处于state |
state.whenIsNext {```你的声明```} | yourStatements 当状态机将state 进入下一个周期时执行(即使它已经在其中) |
state.
隐含在块中:new State
val stateB : State = new State {
onEntry(counter := 0)
whenIsActive {
counter := counter + 1
when(counter === 4) {
goto(stateC)
}
}
onExit(io.result := True)
}
StateDelay
允许创建一个状态,该状态在执行语句之前等待固定数量的周期。使用它的首选方法是:whenCompleted {...}
val stateG : State = new StateDelay(cyclesCount=40) {
whenCompleted {
goto(stateH)
}
}
也可以写成一行:
val stateG : State = new StateDelay(40) { whenCompleted(goto(stateH)) }
StateFsm
允许描述包含嵌套状态机的状态。当嵌套状态机完成(退出)时,执行中的语句。whenCompleted { ... }
有一个 StateFsm 定义的例子:
// internalFsm is a function defined below
val stateC = new StateFsm(fsm=internalFsm()) {
whenCompleted {
goto(stateD)
}
}
def internalFsm() = new StateMachine {
val counter = Reg(UInt(8 bits)) init (0)
val stateA : State = new State with EntryPoint {
whenIsActive {
goto(stateB)
}
}
val stateB : State = new State {
onEntry (counter := 0)
whenIsActive {
when(counter === 4) {
exit()
}
counter := counter + 1
}
}
}
在上面的示例中,exit()
使状态机跳转到启动状态(内部隐藏状态)。这通知StateFsm
了内部状态机的完成。
StateParallelFsm
允许处理多个嵌套状态机。当所有嵌套状态机都完成后,执行中的语句。whenCompleted { ... }
例子:
val stateD = new StateParallelFsm (internalFsmA(), internalFsmB()) {
whenCompleted{
goto(stateE)
}
}
上面定义的进入状态的方式使得在复位和第一次时钟采样之间,状态机处于启动状态。只有在第一次时钟采样之后,定义的进入状态才会激活。这允许正确进入入口状态(在 中应用语句onEntry
),并允许嵌套状态机。
虽然它很有用,但也可以绕过该功能并直接让状态机引导到用户状态。
为此,请使用makeInstantEntry()而不是定义。该函数返回开机状态,复位后直接激活。new State