有限狀態機FSM(自動售報機Verilog實現)


有限狀態機FSM(自動售報機Verilog實現)

FSM

  • 狀態機就是一種能夠描述具有邏輯順序和時序順序事件的方法。

狀態機有兩大類:Mealy型和Moore型。
Moore型狀態機的輸出只與當前狀態有關,而Mealy型狀態機的輸出不僅取決於當前狀態,還受到輸入的直接控制,並且可能與狀態無關。

當使用Verilog來描述一個簡單狀態機的設計時,應將狀態寄存器的控制器的控制和狀態機狀態里的組合邏輯分開。

  • 分離功能使得在邏輯部分的代碼中可以使用阻塞賦值語句

狀態更新邏輯包含狀態寄存器,不能被外設讀取。組合邏輯使用輸入和當前狀態值來對輸出賦值,並改變狀態機的下一狀態。


同步時序電路的設計方法

  • 邏輯抽象,得出電路的狀態轉換圖或者狀態轉換表
  • 狀態化簡
  • 狀態分配(狀態編碼:Binary,Gray,One-Hot)
  • Verilog根據最簡狀態轉換圖編程,檢查設計的電路能否自啟動

四個要素

  • 當前輸入
  • 當前狀態
  • 下一狀態
  • 當前輸出值

代碼風格

一段式

當前狀態、下一狀態、當前輸出值都寫在一個always塊中

二段式

當前狀態、下一狀態、當前輸出值寫在兩個always塊中

  • 注意:這樣三種組合方式,及有三種方式寫這兩個always塊。

三段式

當前狀態、下一狀態、當前輸出值分別寫在各自的always塊中,這樣需要3個always塊。


自動售報機Verilog實現


設計說明

設計一個簡單的數字電路用於電子的報紙售賣機的投幣器。

  • 假設報紙的價格為15分。
  • 投幣器只能接受5分和1角的硬幣。
  • 必須提供適當的數目的零錢,投幣器不找零。
  • 合法的硬幣組合包括1個5分的硬幣和1個一角的硬幣,3個5分的硬幣,1個1角的硬幣和1個5分的硬幣。2個1角的硬幣是合法的,但是投幣器不找零。

電路說明

  • 當投入硬幣時,一個兩位的信號coin[1:0]被傳送到數字電路。該信號在全局clock信號的下一個下降沿取值,並且准確地保持一個始終周期。
  • 數字電路的輸出是一位的。每次當投入硬幣總數為15分或者超過15分時,輸出信號newspaper變為高電平,並且保持一個時鍾周期。售賣機的門也被打開。
  • 可以用一個reset信號復位有限狀態機。假設為同步復位。

有限狀態機FSM

可以用有限狀態機表示該數字電路的功能。

  • 輸入:2位,coin[1:0]。沒有硬幣時,x0 = 2'b00;有一個5分的硬幣時,x5 = 2'b01;有一個1角的硬幣時,x10 = 2'b10。
  • 輸出:1位,newspaper。當newspaper = 1'b1時,打開門。
  • 狀態:4個狀態。s0 = 0分,s5 = 5分,s10 = 10分,s15 = 15分。

狀態機轉換圖

狀態 錢數 輸入 硬幣[1:0]
s0 0分 x0 2'b00
s5 5分 x5 2'b01
s10 10分 x10 2'b10
s15 15分 - 無關


verilog描述


design code

module vend(
            input    [1:0]   coin,
            input            clock,
            input            reset,
            output           newspaper
            );

//聲明有限狀態機的內部狀態
wire    [1:0]   NEXT_STATE;
reg     [1:0]   PRES_STATE;

//狀態編碼
parameter     s0  = 2'b00;
parameter     s5  = 2'b01;
parameter     s10 = 2'b10;
parameter     s15 = 2'b11;

//用同步復位、時鍾正跳變沿觸發的狀態觸發器
always@(posedge clock)
begin
    if(reset == 1'b1)
        PRES_STATE <= s0;
    else
        PRES_STATE <= NEXT_STATE;
end

//組合邏輯
function [2:0] fsm;  //狀態變化及輸出組合邏輯
    input  [1:0]  fsm_coin;
    input  [1:0]  fsm_PRES_STATE;

    reg           fsm_newspaper;
    reg    [1:0]  fsm_NEXT_STATE;

    begin
        case(fsm_PRES_STATE)
            s0:     //狀態為s0
               begin
                   if(fsm_coin == 2'b10)
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s10;
                   end
                   else if(fsm_coin == 2'b01)
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s5;
                   end
                   else
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s0;
                   end
               end
            s5:     //狀態為s5
               begin
                   if(fsm_coin == 2'b10)
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s15;
                   end
                   else if(fsm_coin == 2'b01)
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s10;
                   end
                   else
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s5;
                   end
               end
            s10:     //狀態為s10
               begin
                   if(fsm_coin == 2'b10)
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s15;
                   end
                   else if(fsm_coin == 2'b01)
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s15;
                   end
                   else
                   begin
                       fsm_newspaper   = 1'b0;
                       fsm_NEXT_STATE  = s10;
                   end
               end
            s15:     //狀態為s15
               begin
                   fsm_newspaper   = 1'b1;
                   fsm_NEXT_STATE  = s0;
               end
           endcase

           fsm = {fsm_newspaper,fsm_NEXT_STATE};
    end
endfunction

//每當硬幣放入或當前狀態改變時,組合邏輯動作
assign  {newspaper,NEXT_STATE} = fsm(coin,PRES_STATE);

endmodule

testbench

module vend_tb;

reg           clock;
reg           reset;
reg   [1:0]   coin;
wire          newspaper;

always #20 clock = ~clock;

initial
begin
    clock = 0;
    reset = 1;
    #100;
    reset = 0;

    @(posedge clock) coin[1:0] = 2'b00;
    @(posedge clock);
    @(posedge clock) coin[1:0] = 2'b01;
    @(posedge clock);
    @(posedge clock) coin[1:0] = 2'b10;
    @(posedge clock);

    @(posedge clock) coin[1:0] = 2'b10;
    @(posedge clock);
    @(posedge clock) coin[1:0] = 2'b10;
    @(posedge clock);
    
    @(posedge clock) coin[1:0] = 2'b00;
    @(posedge clock);
    @(posedge clock) coin[1:0] = 2'b01;
    @(posedge clock);
    @(posedge clock) coin[1:0] = 2'b01;
    @(posedge clock);
    @(posedge clock) coin[1:0] = 2'b01;

    #200 $finish;
end

initial begin
  $fsdbDumpfile("test.fsdb");
  $fsdbDumpvars();
end

vend u_vend( 
            .coin(coin),
            .clock(clock),
            .reset(reset),
            .newspaper(newspaper)
             );

endmodule

仿真結果



參考資料

[1]. Verilog HDL數字設計與綜合(第二版) [美]Simir Palnitkar 著 夏宇聞 等譯
[2]. Verilog 數字VLSI設計教程 [美] John Willianms 著 李林 等譯
[3]. 有限狀態機 FSM 設計
[4]. 有限狀態機FSM coding style整理 (SOC) (Verilog)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM