1. 程式人生 > >Verilog_有限狀態機

Verilog_有限狀態機

名詞解釋

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

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

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

程式碼風格

一段式

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

二段式

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

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

三段式

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

 

自動售報機Verilog實現


設計說明

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

design code 

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

//用同步復位、時鐘正跳變沿觸發的狀態觸發器
[email protected]
(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