1. 程式人生 > >FPGA 設計 Verilog 基礎(二)

FPGA 設計 Verilog 基礎(二)

1.1 狀態機設計

狀態機是許多數字系統的核心部件,是一類重要的時序邏輯電路。通常包括三個部分:一是下一個狀態的邏輯電路,二是儲存狀態機當前狀態的時序邏輯電路,三是輸出組合邏輯電路。通常,狀態機的狀態數量有限,成為有限狀態機(FSM)。由於狀態機的所有觸發器的時鐘由同一脈衝邊沿觸發,故也稱之位有限狀態機。

根據狀態機的輸出訊號是否與電路的輸入有關分為Mealy型狀態機和Moore型狀態機。電路的輸出訊號不僅與電路的當前狀態有關,還與電路的輸入有關,稱為Mealy型狀態機。相反,電路的輸出僅僅與各觸發器的狀態有關,不受電路輸入訊號的影響,稱為Moore型狀態機。其標準模型如下所示:

狀態機的狀態轉移圖,通常可以根據輸入和內部條件畫出。一般來說,狀態機的設計包括以下設計步驟:

  • 根據需求和設計原則,確定是Mealy型還是Moore型狀態機。
  • 分析狀態機的所有狀態,對每一狀態選擇合適的編碼方式,進行編碼。
  • 根據狀態轉移關係和輸出繪出狀態轉移圖。
  • 構建何使的狀態機結構,對狀態機進行硬體描述。

狀態機的描述通常由三種描述方法,稱為一段式狀態,二段式狀態機和三段式狀態機。狀態機的描述通常包括以下四個部分:

  • 利用引數定義語句parameter 描述狀態機的各個狀態名稱,即狀態編碼。狀態編碼通常有很多種方法,包括自然二進位制編碼、One-hot編碼、格雷編碼等。
  • 用時序的always 塊描述狀態觸發器實現狀態儲存。
  • 使用敏感表和case語句(也可採用if-else)描述狀態轉換邏輯。
  • 描述狀態機的輸出邏輯。

下面根據狀態機的三種方法,來比較各種方法的優劣。

1.2 一段式狀態機

`timescale 1ns / 1ps

module detect_1(
    input   clk_i,
    input   rst_n_i,
    output  out_o
    );
    reg out_r;
    //狀態宣告和狀態編碼
    reg [1:0] state;
    parameter [1:0] S0 = 2'b00;
    parameter [1:0] S1 = 2'b01;
    parameter [1:0] S2 = 2'b10;
    parameter [1:0] S3 = 2'b11;
    //一段式狀態機
    always @(posedge clk_i)
    begin
        if(!rst_n_i) begin
            state <= S0;
            out_r <= 1'b0;
        end 
        else
            case(state)
                S0:
                    begin
                        out_r <= 1'b0;
                        state <= S1;
                    end
                S1:
                    begin
                        out_r <= 1'b1;
                        state <= S2;
                    end  
                S2:
                    begin
                        out_r <= 1'b0;
                        state <= S3;
                    end     
                S3:
                    begin
                        out_r <=1'b1;
                        state <= S0;
                    end
             endcase
    end
    
assign out_o = out_r;
endmodule

1.3 兩段式狀態機 

`timescale 1ns / 1ps

//兩段式狀態機
module detect_2(
    input   clk_i,
    input   rst_n_i,
    output  out_o
    );
    
    reg out_r;
    //狀態宣告和狀態編碼
    reg [1:0] Current_state;
    reg [1:0] Next_state;
    parameter [1:0] S0 = 2'b00;
    parameter [1:0] S1 = 2'b01;
    parameter [1:0] S2 = 2'b10;
    parameter [1:0] S3 = 2'b11;
    //時序邏輯:描述狀態轉換
    always @(posedge clk_i)
    begin
        if(!rst_n_i) 
            Current_state <= 0;
        else
            Current_state <= Next_state;
    end
    
    always @(*)
    begin
        out_r =1'b0;
        case(Current_state)
            S0:
                begin
                    out_r = 1'b0;
                    Next_state = S1;
                end
            S1:
                begin
                    out_r = 1'b1;
                    Next_state = S2;
                end
            S2:
                begin
                    out_r =1'b0;
                    Next_state = S3;
                end
            S3:
                begin
                    out_r = 1'b0;
                    Next_state = Next_state;
                end
            default:
                begin
                    out_r =1'b0;
                    Next_state = S0;
                end
         endcase
    end
    
endmodule

1.4 三段式狀態機 

`timescale 1ns / 1ps


module detect_3(
    input   clk_i,
    input   rst_n_i,
    output  out_o
    );
    
    reg out_r;
    //狀態宣告和狀態編碼
    reg [1:0] Current_state;
    reg [1:0] Next_state;
    
    parameter [1:0] S0 = 2'b00;
    parameter [1:0] S1 = 2'b01;
    parameter [1:0] S2 = 2'b10;
    parameter [1:0] S3 = 2'b11;
    
    //時序邏輯:描述狀態轉換
    
    always @(posedge clk_i)
    begin
        if(!rst_n_i)
            Current_state <= 0 ;
        else
            Current_state <= Next_state;
    end
    
    //組合邏輯:描述下一狀態
    always @(*)
    begin
        case(Current_state)
            S0:
                begin
                    Next_state <= S1;
                end
            S1: 
                begin
                    Next_state <= S2;
                end
            S2:
                begin
                    Next_state <= S3;
                end
            S3:
                begin
                    Next_state <= Next_state;
                end
            default:
                Next_state  = S0;
        endcase
    end
    
    //輸出邏輯
    always @(posedge clk_i)
    begin
        if(!rst_n_i)
            out_r <= 1'b0;
        else
            begin
                case(Current_state)
                    S0,S2:
                        out_r <= 1'b0;
                    S1,S3:
                        out_r <= 1'b1;
                    default:
                        out_r <= out_r;
                 endcase
             end
    end
endmodule