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. 功能代码
    • 将其余的代码补全,主要是状态机转移信号那个部分
相关推荐
颜子鱼3 小时前
FPGA-状态机
fpga开发
GateWorld6 小时前
FPGA设计中的“幽灵信号:一条走线,两种命运——浅析路径延迟导致的逻辑错误
fpga开发
云雾J视界10 小时前
RISC-V开源处理器实战:从Verilog RTL设计到FPGA原型验证
fpga开发·开源·verilog·risc-v·rtl·数字系统
我爱C编程16 小时前
【仿真测试】基于FPGA的完整BPSK通信链路实现,含频偏锁定,帧同步,定时点,Viterbi译码,信道,误码统计
fpga开发·bpsk·帧同步·viterbi译码·频偏锁定·定时点
tiger11918 小时前
FPGA在AI时代的定位?
人工智能·fpga开发
白杨树田20 小时前
【EDA软件】【文件合并烧录操作方法】
fpga开发
FPGA_小田老师20 小时前
FPGA基础知识(八):时序约束深度解析--从基础理论到工程实践
fpga开发·时钟约束·fpga基础·create clock·时序问题
秋风战士1 天前
通信算法之336 :3GPPMixed Mode Turbo Decoder
算法·matlab·fpga开发·信息与通信·基带工程
国科安芯1 天前
国产MCU芯片在船舶压力传感器中的应用探索与实践
网络·单片机·嵌入式硬件·fpga开发·车载系统