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

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

    关注

    31

    文章

    5305

    浏览量

    119921
  • 仿真
    +关注

    关注

    50

    文章

    4031

    浏览量

    133372
  • 时序电路
    +关注

    关注

    1

    文章

    114

    浏览量

    21677
  • 状态机
    +关注

    关注

    2

    文章

    492

    浏览量

    27465

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

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

收藏 人收藏

    评论

    相关推荐

    普通三段式充电原理

    普通三段式充电原理   普通三段式铅酸蓄电池充电器,充电过程如下: ① 恒流充电阶段,充电器充电电流保持恒定,充入
    发表于 11-16 14:24 2.8w次阅读

    三段式”过电流保护含意

    过流即过电流保护。三段式电流保护指的是电流速断保护(第一段)、限时电流速断保护(第二段)、定时限过电流保护(第三段),相互配合构成的套过电
    的头像 发表于 02-27 09:17 6271次阅读

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

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

    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三段式状态机描述(转载)

    时序电路的状态状态变量集合,这些状态变量在任意时刻的值都包含了为确定电路的未来行为而必需考虑的所有历史信息。 状态机采用Verilog
    发表于 02-09 09:42 1117次阅读

    双电源自动转换开关基础知识(工作原理、工作步骤、选型、二段式三段式区别

    本文主要介绍了双电源自动转换开关基础知识(工作原理、工作步骤、选型、二段式三段式区别)。它是种可以在常用电源和备用电源之间进行自动转换的开关。它是由
    发表于 03-23 11:54 5.2w次阅读
    双电源自动转换开关基础知识(工作原理、工作步骤、选型、<b class='flag-5'>二段式</b>和<b class='flag-5'>三段式</b>的<b class='flag-5'>区别</b>)

    浅谈FPGA 四段式状态机

    段式不是指个always代码,而是四程序。使用四段式的写法,可参照明德扬GVIM特色指令Ztj产生的状态机模板。
    发表于 05-28 10:50 2779次阅读

    关于使用FPGA三段式状态机点好处,你有什么看法?

    三段式描述状态机的好处,国内外各位大牛都已经说的很多了,大致可归为以下点:
    发表于 08-17 11:43 1.6w次阅读
    关于使用FPGA<b class='flag-5'>三段式</b><b class='flag-5'>状态机</b>的<b class='flag-5'>三</b>点好处,你有什么看法?

    FPGA三段式描述状态机的好处

    先谈谈第点关于思维习惯。我发现有些人会有这样种习惯,先用一段式状态机实现功能,仿真ok后,再将其转成三段式,他们对这种开发方式的解释是
    发表于 07-14 14:59 1428次阅读

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

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

    三段式距离保护和三段式电流保护原理是相同的,它们有哪些区别

    上也有着相似之处。但是它们在实际应用中存在些差异,下面我们将逐分析它们的区别、基本原理: 1. 三段式距离保护
    的头像 发表于 09-18 09:57 5174次阅读

    随着电流的增大,三段式过流保护的一段二段保护动作时限变小?

    为什么随着电流的增大,三段式过流保护的一段二段保护动作时限变小? 随着电流的增大,三段式过流保护的一段
    的头像 发表于 09-18 09:57 1064次阅读