一段式、二段式以及三段式状态机(FSM)设计实例
状态机(FSM)分类
**分类:**摩尔型(Moore)有限状态机,输出只由当前状态确定。米利型(Mealy)有限状态机,输出不止于当前状态有关还与其输入有关。
状态转移的三种编码方式
独热码用的寄存器多,但译码简单;格雷码用于异步多时钟多bit的转换;二进制码用的寄存器少,但译码复杂。一般在CPLD中,由于能提供较多的逻辑资源推荐使用独热码,而在FPGA中提供较多的时序逻辑而推荐使用二进制码。
一段式、两段式状态机(FSM)区别
**一段式:**整个状态机写在一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出。
**两段式:**用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移,另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律及其输出。
**三段式:**在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以用时序电路输出)。
**注意事项:**①二段式状态机要在后面加一个触发器消除组合逻辑对输出产生的毛刺的影响。②编写状态机需要穷举所有状态,或者使用default,避免产生不必要的锁存器。③在设计中要有异步或者同步复位来确保状态机始终有个初始态。
vivado与modelsim联调显示状态机
需要先设置好vivado与modelsim的联调,具体参考其他博客,这段代码在打开modelsim后,再进行仿真时,需要删掉,否则会出现error。
设计实例
实现字符串“hello”的检测。
状态转移图
代码
代码在一个.v文件中编写,可分段调试。
定义代码段
`timescale 1ns / 1ns
module fsm_hello(
input sys_clk,
input reset_n,
input [7:0]data_in,
input data_in_valid,
output reg check_ok
);
localparam
CHECK_h = 5'b00_001,
CHECK_e = 5'b00_010,
CHECK_l1 = 5'b00_100,
CHECK_l2 = 5'b01_000,
CHECK_o = 5'b10_000;
reg [4:0]state;//一段式状态机
reg [4:0]pre_state;//两段式和三段式状态机
reg [4:0]next_state;
一段式状态机(FSM)
always@(posedge sys_clk or negedge reset_n)
if(!reset_n)begin
check_ok <= 1'b0;
state <= CHECK_h;
end
else begin
case(state)
CHECK_h:begin
check_ok <= 1'b0;
if(data_in_valid && data_in == "h")
state <= CHECK_e;
else
state <= CHECK_h;
end
CHECK_e:begin
check_ok <= 1'b0;
if(data_in_valid && data_in == "e")
state <= CHECK_l1;
else if(data_in_valid && data_in == "h")
state <