0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

状态机的一段式、二段式、三段式的区别

FPGA技术江湖 来源:FPGA技术江湖 2023-08-21 09:25 次阅读

本篇文章描述状态机的一段式、二段式、三段式区别

一、状态机

再次给出状态机的示意图:

1.1、摩尔型,输出只与状态寄存器的输出状态有关

1.2、米粒型,输出不仅与状态寄存器的输出状态有关,还与组合逻辑的输入有关

e9fe45a2-3ee7-11ee-ac96-dac502259ad0.png

二、一段式、二段式、三段式区别

根据状态机的结构,状态机描述方式 可分为:一段式、二段式、三段式

1.1、一段式

整个状态机写到一个 always 模块里面。在该模块中既描述状态转移,又描述状态的输入和输出。

1.2、二段式

用两个 always 模块来描述状态机。

1.2.1、其中一个 always 模块采用同步时序描述状态转移;

1.2.2、另一个 always模块采用组合逻辑判断状态转移条件,描述状态转移规律及其输出,注意组合逻辑输出要用阻塞赋值。

1.3、三段式

在两个 always 模块描述方法基础上,使用三个 always 模块。

1.3.1、 一个 always 模块采用同步时序描述状态转移;

1.3.2、一个 always 采用组合逻辑判断状态转移条件,描述状态转移规律,注意组合逻辑输出要用阻塞赋值;

1.3.3、另一个 always 模块描述状态输出(可以用组合电路输出,也可以时序电路输出),注意组合逻辑输出要用阻塞赋值。

1.4、综合

可以看出两段式有限状态机与一段式有限状态机的区别是将时序部分(状态转移)和组合部分(判断状态转移条件和产生输出)分开,写为两个always语句,即为两段式有限状态机。将组合部分中的判断状态转移条件和产生输出再分开写,则为三段式有限状态机。

三、自动售货机、一段式

module  auto_sell(
    input   clk,
    input       rst_n,
    input       coin_one,
    input       coin_half,
     
    output  reg     water,
    output  reg     coin_back
);
 
    parameter   ZERO        = 3'b000;
    parameter   HALF        = 3'b001;
    parameter   ONE         = 3'b010;
    parameter   ONE_HALF = 3'b011;
    parameter   TWO         = 3'b100;
     
    //一段式状态机
    reg [2:0]       status;
     
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                status   <= ZERO;
                water    <= 0;
                coin_back <= 0;
            end
        else
            case(status)
                ZERO :
                        begin  
                            water    <= 0;
                            coin_back <= 0;
                            if(coin_half)
                                status <= HALF;
                            else if(coin_one)
                                status <= ONE;
                            else
                                status <= status;
                        end
                HALF :
                        begin  
                            water    <= 0;
                            coin_back <= 0; 
                            if(coin_half)
                                status <= ONE;
                            else if(coin_one)
                                status <= ONE_HALF;
                            else
                                status <= status;   
                        end
                ONE :  
                        begin  
                            water    <= 0;
                            coin_back <= 0;
                            if(coin_half)
                                status <= ONE_HALF;
                            else if(coin_one)
                                status <= TWO;
                            else
                                status <= status;               
                        end
                ONE_HALF :
                            begin  
                                if(coin_half)
                                    begin
                                        status <= TWO;
                                        water    <= 1'b0;
                                        coin_back <= 1'b0;
                                    end
                                else if(coin_one)
                                    begin
                                        status <= ZERO;
                                        water    <= 1'b1;
                                        coin_back <= 1'b0;
                                    end
                                else
                                    begin
                                        status <= status;   
                                        water    <= 1'b0;
                                        coin_back <= 1'b0;                                      
                                    end
                            end
                TWO :  
                        begin  
                            if(coin_half)
                                    begin
                                        status <= ZERO;
                                        water    <= 1'b1;
                                        coin_back <= 1'b0;
                                    end
                            else if(coin_one)
                                    begin
                                        status <= ZERO;
                                        water    <= 1'b1;
                                        coin_back <= 1'b1;
                                    end
                            else
                                    begin
                                        status <= status;   
                                        water    <= 1'b0;
                                        coin_back <= 1'b0;                                      
                                    end    
                        end
                default:
                            begin
                                status <= ZERO; 
                                water    <= 1'b0;
                                coin_back <= 1'b0;                                      
                            end
            endcase        
    end
 
endmodule

四、自动售货机、二段式

1.1、二段式,写法一

module  auto_sell(
    input   clk,
    input       rst_n,
    input       coin_one,
    input       coin_half,
     
    output  reg     water,
    output  reg     coin_back
);
 
    parameter   ZERO        = 3'b000;
    parameter   HALF        = 3'b001;
    parameter   ONE         = 3'b010;
    parameter   ONE_HALF = 3'b011;
    parameter   TWO         = 3'b100;
 
//--------------------二段式 1  ok--------------------------
    //二段式状态机
    reg [2:0]   c_status;
    reg [2:0]   n_status;
     
    //状态转移
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            c_status <= ZERO;
        else
            c_status <= n_status;
    end
     
    //描述状态转移规律以及输出
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                n_status <= ZERO;
                water <= 1'b0;
                coin_back <= 1'b0;  
            end
        else
            case(c_status)
                ZERO :
                        begin  
                            water <= 1'b0;
                            coin_back <= 1'b0;                          
                            if(coin_half)
                                n_status <= HALF;
                            else if(coin_one)
                                n_status <= ONE;
                            else
                                n_status <= ZERO;
                        end
                HALF :
                        begin  
                            water <= 1'b0;
                            coin_back <= 1'b0;                          
                            if(coin_half)
                                n_status <= ONE;
                            else if(coin_one)
                                n_status <= ONE_HALF;
                            else
                                n_status <= HALF;   
                        end
                ONE :  
                        begin  
                            water <= 1'b0;
                            coin_back <= 1'b0;                          
                            if(coin_half)
                                n_status <= ONE_HALF;
                            else if(coin_one)
                                n_status <= TWO;
                            else
                                n_status <= ONE;            
                        end
                ONE_HALF :
                            begin  
                                water <= 1'b0;
                                coin_back <= 1'b0;                              
                                if(coin_half)
                                        n_status <= TWO;
                                else if(coin_one)
                                    begin
                                        n_status <= ZERO;
                                        water <= 1'b1;
                                        coin_back <= 1'b0;  
                                    end
                                else
                                        n_status <= ONE_HALF;   
                            end
                TWO :  
                        begin  
                            water <= 1'b0;
                            coin_back <= 1'b0;                          
                            if(coin_half)
                                begin
                                    n_status <= ZERO;
                                    water <= 1'b1;
                                    coin_back <= 1'b0;                                      
                                end
                            else if(coin_one)
                                begin
                                    n_status <= ZERO;
                                    water <= 1'b1;
                                    coin_back <= 1'b1;                                          
                                end
                            else
                                n_status <= TWO;                                        
                        end
                default:
                            n_status <= ZERO;                                   
            endcase
    end
     
 
endmodule

1.2、二段式,写法二

module  auto_sell(
    input   clk,
    input       rst_n,
    input       coin_one,
    input       coin_half,
     
    output  reg     water,
    output  reg     coin_back
);
 
    parameter   ZERO        = 3'b000;
    parameter   HALF        = 3'b001;
    parameter   ONE         = 3'b010;
    parameter   ONE_HALF = 3'b011;
    parameter   TWO         = 3'b100;
 
//---------------------二段式  2 ok--------------------------------------
 
    //二段式状态机
    reg [2:0]   status;
     
    //状态转移
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            status <= ZERO;
        else
            begin
                case(status)
                    ZERO :
                            begin                          
                                if(coin_half)
                                    status <= HALF;
                                else if(coin_one)
                                    status <= ONE;
                                else
                                    status <= ZERO;
                            end
                    HALF :
                            begin                          
                                if(coin_half)
                                    status <= ONE;
                                else if(coin_one)
                                    status <= ONE_HALF;
                                else
                                    status <= HALF; 
                            end
                    ONE :  
                            begin                      
                                if(coin_half)
                                    status <= ONE_HALF;
                                else if(coin_one)
                                    status <= TWO;
                                else
                                    status <= ONE;              
                            end
                    ONE_HALF :
                                begin                              
                                    if(coin_half)
                                            status <= TWO;
                                    else if(coin_one)
                                        begin
                                            status <= ZERO;
                                        end
                                    else
                                            status <= ONE_HALF; 
                                end
                    TWO :  
                            begin                          
                                if(coin_half)
                                    begin
                                        status <= ZERO;                                 
                                    end
                                else if(coin_one)
                                    begin
                                        status <= ZERO;                                     
                                    end
                                else
                                    status <= TWO;                                          
                            end
                    default:
                                status <= ZERO;                                 
                endcase        
            end
    end
 
 
    //输出 时序逻辑
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                water <= 1'b1;
                coin_back <= 1'b0;  
            end
        else
            case(status)
                ONE_HALF:
                            begin
                                if(coin_one)
                                    begin
                                        water <= 1'b1;
                                        coin_back <= 1'b0;
                                    end
                                else
                                    begin
                                        water <= 1'b0;
                                        coin_back <= 1'b0;                              
                                    end
                            end
                TWO:
                            begin
                                if(coin_half)
                                    begin
                                        water <= 1'b1;
                                        coin_back <= 1'b0;
                                    end
                                else if(coin_one)
                                    begin
                                        water <= 1'b1;
                                        coin_back <= 1'b1;                              
                                    end
                                else
                                    begin
                                        water <= 1'b0;
                                        coin_back <= 1'b0;                                  
                                    end
                            end
                default:
                            begin
                                water <= 1'b0;
                                coin_back <= 1'b0;                                  
                            end        
            endcase
    end
 
endmodule

五、自动售货机、三段式

module  auto_sell(
    input   clk,
    input       rst_n,
    input       coin_one,
    input       coin_half,
     
    output  reg     water,
    output  reg     coin_back
);
 
    parameter   ZERO        = 3'b000;
    parameter   HALF        = 3'b001;
    parameter   ONE         = 3'b010;
    parameter   ONE_HALF = 3'b011;
    parameter   TWO         = 3'b100;
 
    //三段式状态机
    reg [2:0]   c_status;
    reg [2:0]   n_status;
     
    //状态转移
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            c_status <= ZERO;
        else
            c_status <= n_status;
    end
     
    //状态转移规律及状态输出,组合逻辑输出只与输入有关
    //如果有n_status = n_status,电路会出错;
    always@(*)begin
        case(c_status)
            ZERO :
                    begin  
                        if(coin_half)
                            n_status = HALF;
                        else if(coin_one)
                            n_status = ONE;
                        else
                            n_status = ZERO;
                    end
            HALF :
                    begin  
                        if(coin_half)
                            n_status = ONE;
                        else if(coin_one)
                            n_status = ONE_HALF;
                        else
                            n_status = HALF;   
                    end
            ONE :  
                    begin  
                        if(coin_half)
                            n_status = ONE_HALF;
                        else if(coin_one)
                            n_status = TWO;
                        else
                            n_status = ONE;            
                    end
            ONE_HALF :
                        begin  
                            if(coin_half)
                                n_status = TWO;
                            else if(coin_one)
                                n_status = ZERO;
                            else
                                n_status = ONE_HALF;                                       
                        end
            TWO :  
                    begin  
                        if(coin_half)
                            n_status = ZERO;
                        else if(coin_one)
                            n_status = ZERO;
                        else
                            n_status = TWO;        
                    end
            default:
                        n_status = ZERO;                                   
        endcase        
    end
 
    always@(posedge clk,negedge rst_n)begin
        if(!rst_n)
            begin
                water = 1'b1;
                coin_back = 1'b0;  
            end
        else
            case(c_status)
                ONE_HALF:
                            begin
                                if(coin_one)
                                    begin
                                        water = 1'b1;
                                        coin_back = 1'b0;
                                    end
                                else
                                    begin
                                        water = 1'b0;
                                        coin_back = 1'b0;                              
                                    end
                            end
                TWO:
                            begin
                                if(coin_half)
                                    begin
                                        water = 1'b1;
                                        coin_back = 1'b0;
                                    end
                                else if(coin_one)
                                    begin
                                        water = 1'b1;
                                        coin_back = 1'b1;                              
                                    end
                                else
                                    begin
                                        water = 1'b0;
                                        coin_back = 1'b0;                                  
                                    end
                            end
                default:
                            begin
                                water = 1'b0;
                                coin_back = 1'b0;                                  
                            end        
            endcase
    end
     
endmodule

六、仿真脚本

`timescale 1ns/1ps
 
module auto_sell_tb;
 
    reg     clk;
    reg rst_n;
    reg coin_one;
    reg coin_half;
     
    wire    water;
    wire    coin_back;
     
     
     
    initial begin
        clk = 0;
        rst_n = 0;
        coin_one = 0;
        coin_half = 0;
        #20;
        rst_n = 1;
        //延时200us
        #10000
         
        //投2.5元
        coin_half = 1;
        #20;
        coin_half = 0;
        #20;
         
        coin_one = 1;
        #20;   
        coin_one = 0;  
        #20;
                 
        coin_half = 1;
        #20;
        coin_half = 0;
        #20;
                 
        coin_half = 1;
        #20;
        coin_half = 0; 
        #20;
                 
        //延时200us
        #10000
         
        //投3元
        coin_half = 1;
        #20;
        coin_half = 0;
        #20;
                 
        coin_one = 1;
        #20;   
        coin_one = 0;  
        #20;
                 
        coin_half = 1;
        #20;
        coin_half = 0;
        #20;
                 
        coin_one = 1;
        #20;   
        coin_one = 0;
        #20;
                 
        //延时200us
        #10000 
        $stop;
    end
     
    auto_sell auto_sell_inst(
        .clk            (clk),
        .rst_n      (rst_n),
        .coin_one   (coin_one),
        .coin_half  (coin_half),
     
        .water      (water),
        .coin_back  (coin_back)
    );
     
    always #10 clk = ~clk;
 
endmodule

七、仿真结果

eaa5221e-3ee7-11ee-ac96-dac502259ad0.png

eac8262e-3ee7-11ee-ac96-dac502259ad0.png

eaea7bc0-3ee7-11ee-ac96-dac502259ad0.png

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    30

    文章

    5028

    浏览量

    117719
  • 仿真
    +关注

    关注

    50

    文章

    3872

    浏览量

    132158
  • 时序电路
    +关注

    关注

    1

    文章

    113

    浏览量

    21586
  • 状态机
    +关注

    关注

    2

    文章

    486

    浏览量

    27165

原文标题:笔记连载精选 |【状态机:一段式、二段式、三段式】 【原理及verilog仿真】篇

文章出处:【微信号:HXSLH1010101010,微信公众号:FPGA技术江湖】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    LTC4020三段式充电,转不到浮充电压怎么解决?

    LTC4020三段式充电,使用电子负载器对量产板测试充电曲线,发觉有些板恒压充转不了浮充,电流已降至0,就是转不到浮充电压
    发表于 01-05 14:20

    【labview毕业论文】基于labview的三段式距离保护研究

    ` 本帖最后由 zhihuizhou 于 2011-12-31 15:46 编辑 本文的研究对象是基于虚拟仪器的三段式距离保护。首先,介绍了距离保护的作用原理,阻抗继电器和它的接线方式,重点研究
    发表于 12-31 10:32

    不同形式的状态机占用资源问题

    最近在CPLD里面做了个4通道的模块,每个模块内都有状态机,开始我是用的一段式状态机写发,资源不够,然后我将
    发表于 01-21 14:07

    【Z-turn Board试用体验】有限状态机三段式描述方法(转载)

    ;(2)二段式:用两个always模块来描述状态机,其中个always模块采用同步时序描述状态转移;另个模块采用组合逻辑判断
    发表于 05-25 20:33

    彻底搞懂状态机一段式、两段式三段式)!个实例,种方法对比看!!!(程序)

    该模块中既描述状态转移,又描述状态的输入和输出;(2)二段式:用两个always模块来描述状态机,其中个always模块采用同步时序描述
    发表于 06-27 22:13

    IIC三段式状态机

    我是参考的网上的一段式的例子自己改成的,基本全部改掉了,时序也改掉了,有点自己没能明白,就是`define SCL_LOW(cnt==3'd3)这句,明明已经变为0了,但是ADD1:if(`SCL_LOW)beginnum
    发表于 09-04 15:22

    关于三段式状态机的疑惑,希望有人来为我解答。(新手求罩)

    本人在学习verilog 与状态机时发现有如下疑惑,希望有人能为我解答。如下,是部分三段式状态机的代码:always@(posedge clk or negedge rst_n)be
    发表于 11-21 10:57

    【FPGA开源教程连载】第七章 状态机设计实例

    两个always语句,即为两段式有限状态机。将组合部分中的判断状态转移条件和产生输入再分开写,则为三段式有限状态机。这样就使得
    发表于 12-26 00:17

    三段式过电流保护的模型

    我通过SIMULINK建立三段式过电流保护的模型,如下所示,但是仿真难结果不对,请大神指点下哪里错了。
    发表于 06-30 17:23

    请问在SVPWM算法里,7段式SVPWM和5段式SVPWM在编程方面有什么区别

    本帖最后由 只耳朵怪 于 2018-6-13 16:16 编辑 请问高手,在SVPWM算法里,7段式SVPWM和5段式SVPWM在编程方面有什么区别?谢谢!
    发表于 06-13 02:34

    Verilog三段式状态机描述及模版

    个always完成。三段式建模描述FSM的状态机输出时,只需指定case敏感表为次态寄存器, 然后直接在每个次态的case分支中描述该状态
    发表于 07-03 10:13

    Verilog三段式状态机描述及模版

    个always完成。三段式建模描述FSM的状态机输出时,只需指定case敏感表为次态寄存器, 然后直接在每个次态的case分支中描述该状态
    发表于 07-09 01:55

    三段式和四段式耳机的引脚定义

      耳机插座在我们日常生活中是比较常见的种电子元件,其耳机插座的类型规格也区分有四段式耳机插座、三段式耳机插座等。三段式和四段式耳机的引脚
    发表于 12-25 15:26

    FPGA状态机一段式简介

    (41)FPGA状态机一段式1.1 目录1)目录2)FPGA简介3)Verilog HDL简介4)FPGA状态机一段式5)结语1.2 FPGA简介FPGA(Field Programm
    发表于 02-23 06:45

    三段式状态机编写问题及三段式状态机各部分功能分析

    在 Verilog的江湖里,流传着一段,两段,三段式状态机的传说。它们各有优劣,本文就书写三段式状态机的错误原因进行探寻。
    的头像 发表于 06-20 10:35 2221次阅读
    <b class='flag-5'>三段式</b><b class='flag-5'>状态机</b>编写问题及<b class='flag-5'>三段式</b><b class='flag-5'>状态机</b>各部分功能分析