<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
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

    文章

    5141

    瀏覽量

    118050
  • 仿真
    +關注

    關注

    50

    文章

    3884

    瀏覽量

    132369
  • 時序電路
    +關注

    關注

    1

    文章

    114

    瀏覽量

    21615
  • 狀態機
    +關注

    關注

    2

    文章

    486

    瀏覽量

    27239

原文標題:筆記連載精選 |【狀態機:一段式、二段式、三段式】 【原理及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

    徹底搞懂狀態機一段式、兩段式、三段式)!個實例,種方法對比看?。。。ǔ绦颍?/a>

    該模塊中既描述狀態轉移,又描述狀態的輸入和輸出;(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

    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

    FPGA三段式描述狀態機的好處

    先談談第二點關于思維習慣。我發現有些人會有這樣一種習慣,先用一段式狀態機實現功能,仿真ok后,再將其轉成三段式,他們對這種開發方式的解釋是一段式更直觀,可以更便捷的構建功能框架,但是大
    發表于 07-14 14:59 ?1278次閱讀

    三段式狀態機編寫問題及三段式狀態機各部分功能分析

    在 Verilog的江湖里,流傳著一段,兩段,三段式狀態機的傳說。它們各有優劣,本文就書寫三段式狀態機的錯誤原因進行探尋。
    的頭像 發表于 06-20 10:35 ?2557次閱讀
    <b class='flag-5'>三段式</b><b class='flag-5'>狀態機</b>編寫問題及<b class='flag-5'>三段式</b><b class='flag-5'>狀態機</b>各部分功能分析
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>