状态机
意义:硬件设计中讲究并行设计,verilog描述的电路大多也都是并行的,但在实际的工程应用中,我们往往需要让硬件实现一定顺序的工作。这就需要用到状态机。
状态机:Finite State Machine 有限状态机,简称FSM
状态机使用场景:简单的顺序执行,如计时等功能,用计数器即可,如果控制流程复杂,且每个状态的跳转是乱序的,使用状态机有利于设计出高可靠性的系统。
状态机四要素:现态、次态、输入、输出(意思请顾名思义)
状态机模型:1)摩尔型:输出仅依赖于当前状态
2)米莉型:输出依赖于当前状态和当前状态下的输入
注意:状态机的输出最好先寄存在寄存器中再输出,因为大多数FPGA都会有全局复位信号GSR,芯片上电或复位后对所有寄存器、ram等复位。
状态机编码方法:推荐独热码,其余的就不说了(fpga啥都不多,就是寄存器多,独热码除了对比于其他的编码方式多消耗了一点触发器,其他全是优点,而且自己看的时候也清晰)
例:
这就叫独热码
localparam IDLE = 4'b0001;//初始状态
localparam DOWN = 4'b0010;//按键按下抖动
localparam HOLD = 4'b0100;//按键按下后稳定
localparam UP = 4'b1000;//按键上升抖动
状态机模型:
如图有三个状态,跳转就是箭头方向
最后,推荐三段式状态机,层级分明,逻辑清晰,修改简单。
按键消抖
如图,以按键低电平有效为例,每次按下,在电平变低和变高的时候,电平都会有一段时间的抖动,一般时间在20ms内。
我们需要做的就是在按键按下后,在合适的时间取到稳定的电平值作为实际的按键输出。
实现
将按键动作分4个状态,在什么时候取按键输入的电平看个人喜好,一般在保持态到来就认为按键电平稳定,可以取值,为保险起见,我这里是取得上升沿到来时的按键电平值,即按键电平第一次上升沿到来之前一个周期的电平值。
一次完整的按键动作一般认为是按键按下到上升沿计数完20ms。
module fsm_key_debounce # (parameter KEY_W = 3,TIME_20MS = 1_000_000)(
input clk ,
input rst_n ,
input [KEY_W - 1:0] key_in ,
output [KEY_W - 1:0] key_out
)