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. 功能代码
    • 将其余的代码补全,主要是状态机转移信号那个部分
相关推荐
zlinear数据采集卡2 小时前
D223的DDS信号发生器:10000点查找表与4通道16位DAC波形输出
arm开发·嵌入式硬件·fpga开发·开源
物质波波波17 小时前
WS-RPE:面向边缘物理AI实时特征值计算的硬件工作窃取调度器与冗余PE激活架构
人工智能·fpga开发·架构·系统架构·硬件架构
我爱C编程19 小时前
基于FPGA的DSB调制解调系统verilog开发
fpga开发·verilog·fpga·dsb
zlinear数据采集卡20 小时前
USB HS 480M高速传输与SRAM记录仪:DABM-D223数据存储系统全解析
arm开发·嵌入式硬件·fpga开发·开源
逻辑诗篇1 天前
基于 XCVU13P 的 4 路 100G 光纤 PCIe 处理板 PCIE727 硬件规格全解析
fpga开发
玩嵌入式谁会脱发呀1 天前
【FPGA】 verilog设计spi读写flash实现数据DMA搬运
fpga开发
LabVIEW开发2 天前
LabVIEW 如何把地下震源定位误差做到5米内
fpga开发·labview·labview知识·labview功能·labview程序
Dr.kangder2 天前
嵌入式处理器架构解析(十)——DSP+FPGA
fpga开发·架构·嵌入式
szxinmai主板定制专家3 天前
Zynq MPSoC实现半导体真空腔体状态监测|FPGA多传感器时序同步采集方案
fpga开发·zynq·控制器·mpsoc·半导体设备·fpga同步
学习FPGA的电气小兴兴3 天前
基于FPGA的DDS信号发生器设计,生成频率可调的正弦波、三角波、锯齿波和方波
fpga开发·数字信号处理·fpga·vivado·dsp·dds·diy