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. 功能代码
    • 将其余的代码补全,主要是状态机转移信号那个部分
相关推荐
珞光电子USRP SDR软件无线电平台2 小时前
国产嵌入式SDR平台LW-E320-G详解:射频、FPGA、ARM架构与应用选型
arm开发·fpga开发·架构
FPGA小迷弟3 小时前
【硬核通俗】FPGA实现SDR软件无线电完整技术解析(原理+架构+实战)
fpga开发·dsp开发·sdr·无线电
Eloudy19 小时前
HSB FPGA 架构总体
fpga开发·架构
Terasic友晶科技20 小时前
【教程】Agilex 5 SOC FPGA的HPS端如何响应FPGA端中断(三)——设备树Overlay
fpga开发·设备树·agilex 5·设备树overlay
ARM|X86+FPGA工业主板厂家21 小时前
基于嵌入式 GPU 的智能服务机器人
linux·运维·arm开发·fpga开发·机器人
Freak嵌入式1 天前
Pico PIO 汇编语法深度详解:标识符、指令、伪指令全解析
汇编·stm32·单片机·嵌入式硬件·fpga开发·硬件架构
Riwuarua1 天前
从近似0基础开始FPGA开发 -- part.7 FPGA的网络通信设计
fpga开发
pingping_TEL1 天前
JESD204B_IP核使用教程
fpga开发
cmc10282 天前
292.三段式状态机第三段时序逻辑用state_c与_n的差异分析
fpga开发
智塑未来3 天前
FPGA开发板怎么选?先看资质、案例与研发底盘
fpga开发