设计|FSM有限状态机(三段式)-Verilog实现

一. 状态机理论基础 状态机基本概念: 状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。
以上是标准解释,其实状态机就是为了解决比如IIC协议这种状态多的模块,状态多意味着直接用使能来一一判断各功能触发与否会很复杂,那么此时用状态机就可以巧妙的将所有可能的状态“串”起来,简单根据实时情况实现功能的跳变;所有逻辑顺序和时序规律的事情都可以适合用状态机来描述。
设计|FSM有限状态机(三段式)-Verilog实现
文章图片

有限状态机类型: 第一类:若输出只和状态有关而与输入无关,则称为Moore状态机
第二类:输出不仅和状态有关而且和输入有关系,则称为Mealy状态机
两个状态机类型都常用,但一般Moore型状态机消耗的状态会比Mealy多
有限状态机的verilog三种具体实现方式: 分别有一、二、三段式状态机实现方式,这里推荐使用三段式状态机(大部分情况下,有时2段式会更好)
所谓一、二、三段粗暴理解就是可以分别使用一、二、三个always块去实现一有限个状态机
一段式:“状态变量变化,状态转移,输出” 三者全部放到一个always模块里面去实现,新手往往就会这样做,虽然这样似乎比较符合思 路,但这 样写出来的代码过于冗长,难以维护更新,还不符合时序逻辑和组合逻辑分开写的要点,因此不推荐。
二段式:将状态变量变化独立到一个always模块时序逻辑实现,状态转移和输出放到一个always模块里面组合逻辑实现,这样输出容易产生毛刺等不稳定因素。
三段式:在二的基础上,将输出独立时序逻辑输出,可以理解为独立到一个always块中用时钟沿触发,这样做层次分明,可读性强,维护简单,输出还稳定,时序逻辑可以有效“过滤输出”毛刺的问题,但是有些情况下二段式性能会更好,因为输出不用等拍,直接输出。
如何写一个高质量的状态机: 1、安全性:综合实现无毛刺异常扰动,状态机要完备,既不会进入死循环,哪怕偶然跑偏也能恢复到正常状态(三度段式+状态完备);
2、速度:速度要快,满足设计频率的要求;
3、面积:面积要小,满足设计的面积要求;
4、易懂易维护性:FSM设计要清晰易懂,易维护(采用三段式)。
2、3需要有较强的电路时序分析功底才能比较好的优化,要非常熟悉verilog综合(DC)出来的电路情况,要有一定的静态时序分析(STA)和优化的能力,初学者能做好1、4就很不错了。
二.Verilog实现状态机例子 2.1FSM实现实现11010110序列输出
状态机设计

module FSM_gener( inputclk, inputrst_n, output regdata_current ); //变量分配定义 reg [3:0] state_current; reg [3:0] state_next; regdata_next; localparam//使用格雷码,减少数据翻转,减小误码率和功耗 IDEL= 4'b0000, ONE= 4'b0001, TWO= 4'b0011, THREE = 4'b0010, FOUR= 4'b0110, FIVE= 4'b0111, SIX= 4'b0101, SEVEN = 4'b0100, EIGHT= 4'b1100; //第一段状态机,时序逻辑状态更新 always@( posedge clk or negedge rst_n ) begin if( !rst_n ) state_current <= IDEL; else state_current <= state_next; end //第二段状态机,组合逻辑状态判断跳转 always@( * ) begin case( state_current ) IDEL:begin state_next <= ONE; data_next <= 1'b0; end ONE:begin state_next <= TWO; data_next <= 1'b1; end TWO: begin state_next <= THREE; data_next <= 1'b1; end THREE:begin state_next <= FOUR; data_next <= 1'b0; end FOUR:begin state_next <= FIVE; data_next <= 1'b1; end FIVE:begin state_next <= SIX; data_next <= 1'b0; end SIX: begin state_next <= SEVEN; data_next <= 1'b1; end SEVEN:begin state_next <= EIGHT; data_next <= 1'b1; end EIGHT:begin state_next <= IDEL; data_next <= 1'b0; end default:begin state_next <= IDEL; data_next <= 1'b0; end endcase end //第三段状态机,时序逻辑数据输出 always@( posedge clk or negedge rst_n ) begin if( !rst_n ) data_current <= 1'b0; else data_current <= data_next; endendmodule

仿真验证
`timescale 1ns/1ns `define clock_period 20module FSM_gener_tb(); regclk; regrst_n; wiredata_current; FSM_gener FSM_gener0 ( .clk(clk), .rst_n(rst_n),.data_current(data_current) ); initial begin clk = 1'b1; end always#( `clock_period )clk = ~clk; initial begin rst_n = 0; #( `clock_period*10); rst_n = 1; #( `clock_period*10 + 1'b1 ); #( `clock_period*50 ); $stop; endendmodule

仿真结果如下所示,状态机循环输出11010110满足设计要求
设计|FSM有限状态机(三段式)-Verilog实现
文章图片

2.2 连续字符串"1101"检测
【设计|FSM有限状态机(三段式)-Verilog实现】点击此处访问链接https://blog.csdn.net/weixin_42455055/article/details/119832332

    推荐阅读