FPGA-状态机架构

状态机架构

状态机的适用场景

计数器结构适用与,状态只会按顺序执行的情况,如1->2->3->4这种情况。当出现1->3->1->4这状态跳转顺序不固定,要处理的输出信号复杂时的情况,就需要使用状态机了。

状态机规则

  1. 使用四段式写法,明德扬其所谓四段式,只是在moore摩尔型(输出与输入无关的类型)三段式的基础上加上了,一段规定状态转移信号的模板。
    具体模板如下,
verilog 复制代码
//以下是FSM的状态机模板

module FSM (

  

    input clk,

  

    input rst_n,

  

    input [3:0] data_in,

  

    output reg [3:0] data_out,

  

    output reg [3:0] data_out_2

  

);

  
  

//------------<状态机参数定义>------------------------------------------

//这里使用独热码编码节省组合逻辑资源

//此外还可以使用格雷码 、二进制码

localparam  IDLE  = 4'b0001,

            s1   = 4'b0010,

            s2   = 4'b0100,

            DONE = 4'b1000;

  

    reg [3:0] cur_state;  // 当前状态

    reg [3:0] next_state; // 下一状态

  
  

    // 第一段,状态的转移,时序逻辑

    always @(posedge clk or negedge rst_n) begin

        if (!rst_n)

            cur_state <= IDLE;

        else

            cur_state <= next_state;

    end

  
  
  

    // 第二段,新状态的生成,组合逻辑

    always @(*) begin

        case (cur_state)

            IDLE: begin

                if(IDLE2s1_start)

                    next_state = s1;

                else

                    next_state = cur_state;

            end

  

            s1: begin

                if (s12s2_start)

                    next_state = s2;

                else

                    next_state = cur_state;

            end

  

            s2: begin

                if (s22DONE_start)

                    next_state = DONE;

                else

                    next_state = cur_state;

            end

  

            DONE:begin

                if(DONE2IDLE_start)

                    next_state = IDLE;

                else

                    next_state = cur_state;

            end

  

            default:

                next_state = IDLE;                

        endcase

    end

  

    //第三段,状态机转移信号的赋值,组合逻辑

    //模板:

    //assign 状态机转移信号 = (cur_state == 当前状态) && (data_in == 当前状态的输入条件);

    assign IDLE2s1_start = (cur_state == IDLE) && (data_in == 4'b0001);

    assign s12s2_start = (cur_state == s1) && (data_in == 4'b0010);

    assign s22DONE_start = (cur_state == s2) && (data_in == 4'b0100);

    assign DONE2IDLE_start = (cur_state == DONE) && (data_in == 4'b1000);

  
  

    // 第四段,各状态的输出逻辑,组合逻辑

    // 对初学者,最好将所有输出分成单独的always块写,这样可以更清楚的看到各个状态的输出

    always @(posedge clk or negedge rst_n) begin

        case (cur_state)

            IDLE:

                data_out = 0;

  

            s1:

                data_out = data_in;

            s2:

                data_out = data_in;

  

            DONE:

                data_out = 0;

  

        endcase

    end

  

    always @(posedge clk or negedge rst_n) begin

        case (cur_state)

            IDLE:

                data_out_2 = 0;

  

            s1:

                data_out_2 = data_in;

  

            s2:

                data_out_2 = data_in;

  

            DONE:

                data_out_2 = 0;

        endcase

    end

  

//对于复杂工程,熟练工程师也可以将所有输出信号写到一个always块中,这样可以更清晰的看到各个状态的输出

//模板:

//always @(*) begin

  

always @(posedge clk or negedge rst_n) begin

    case (cur_state)

        IDLE: begin

            data_out = 0;

            data_out_2 = data_in;

        end

        s1: begin

            data_out = data_in;

            data_out_2 = data_in;

        end

        s2: begin

            data_out = data_in;

            data_out_2 = data_in;

        end

        DONE: begin

            data_out = 0;

            data_out_2 = data_in;

        end

    endcase

end

endmodule
  1. 状态转移信号的命名规则:
verilog 复制代码
(上一个状态名)2(下一个状态名)_start
  1. 用assign赋值状态转移条件时,必须与上当前状态。(跟计数器赋值结束条件时,必须与上+1条件类似)
  2. 状态不变时,要用next_state = cur_state。不要用具体的状态名如next_state=IDLE这种

状态机八步法

  1. 明确功能

    • 分析并明确功能
    • 每个状态机都应该写成一个单独的模块,便于复用和维护
    • 画出该模块框图,明确有哪些输入输出信号
    • 写出该模块的输入输出信号列表,其包括方向,位宽,功能。
  2. 输出分析

    • 明德扬认为应该对状态机的各输出信号,进行逐个的状态分析。即以输出信号为分析基础,这种做法跟普遍的以状态作为分析基础不同。
    • 将不同信号,在不同状态下的输出画图列出
  3. 状态合并

    • 原来的单个输出信号的状态分析,现在将所有的输出信号合并分析,状态能合在一起的就合在一起。
  4. 状态转移

    • 写出状态合并后,各状态的转移信号
  5. 转移条件

    • 将状态转移的条件用明确的信号表示

其表示也可以用更高的抽象级表示如下图,可以方便后续代码的编写。

  1. 完整性检查
    • 将所有的信号进行分析考虑(前面几步,主要分析了状态机信号,除状态机的信号的没有仔细考虑)
  2. 状态机代码
    • 套前面的状态机四段式
  3. 功能代码
    • 将其余的代码补全,主要是状态机转移信号那个部分
相关推荐
szxinmai主板定制专家10 小时前
基于 PC 的控制技术+ethercat+linux实时系统,助力追踪标签规模化生产,支持国产化
arm开发·人工智能·嵌入式硬件·yolo·fpga开发
博览鸿蒙21 小时前
如何为春招的金三银四做好准备
fpga开发
FPGA小迷弟1 天前
FPGA处理图像需要用到的主流接口详解
学习·fpga开发·verilog·fpga·modelsim
LeoZY_1 天前
CH347 USB转JTAG功能使用笔记:CH347根据SVF文件实现任意FPGA下载
笔记·stm32·嵌入式硬件·fpga开发·硬件架构·硬件工程
博览鸿蒙1 天前
FPGA在高性能计算中的应用:数据流加速与优化
fpga开发
maverick_1111 天前
【数字图像处理与FPGA实现】00 绪,建立“算法思维“与“硬件思维“的桥梁
图像处理·fpga开发
乌恩大侠2 天前
【OAI】 USRP 在conf文件中的配置,RU选项
fpga开发
qq_小单车3 天前
xilinx-DNA
fpga开发·xilinx
Flamingˢ3 天前
FPGA中的嵌入式块存储器RAM:从原理到实现的完整指南
fpga开发
Flamingˢ3 天前
FPGA中的存储器模型:从IP核到ROM的深度解析与应用实例
网络协议·tcp/ip·fpga开发