1. 程式人生 > >狀態機(二):Verilog狀態機實現

狀態機(二):Verilog狀態機實現

本節主要談一談Verilog的狀態機實現模板,並淺析比較。

1 一段式狀態機 (單always塊結構):

always @(posedge clk or posedge rst) begin
    if(rst)
        FSM <= S0
    else begin
        case(FSM)
        S0:begin
            Out_0;          //輸出
            if(condition1)        FSM<= S1;//狀態轉移
            else if (condition2)  FSM<= S2;//狀態轉移
end S1:begin Out_1; //輸出 if(condition3) FSM<= S3;//狀態轉移 else if (condition4) FSM <=S4; … end …… default: begin Out_0; //輸出 if(condition0) FSM<= S0;//狀態轉移
end endcase end end

單always塊把組合邏輯和時序邏輯放在一個時序always塊描述。輸出時為暫存器輸出,所以無毛刺。但是這種方式會產生多餘的觸發器(因為把組合邏輯也放在時序邏輯中實現),而且程式碼難以修改除錯。對於那些簡單的狀態機,一段式方便理解。但是對於複雜狀態機,程式碼難於更改,條件複雜帶來電路開銷大,工作效能(電路最高頻率)亦受限,因此實際中這種結構很少使用。

2 兩段式狀態機 (雙always塊結構):

//時序邏輯,這段一般是不變的,描述從現態轉移到次態
always @ (posedge clk  or
posedge rst ) begin if(rst) current_state <= S0; else current_state<=next_state; end //組合邏輯,包括轉移條件以及輸出 always @ (current_state) begin case(current_state) S0:begin Out_0; //輸出 if(condition1) next_state <= S1;//狀態轉移 else if (condition2) next_state <= S2;//狀態轉移 else next_state <= S0; end S1:begin Out_1; //輸出 if(condition3) next_state <= S3;//狀態轉移 else if (condition4) next_state <=S4; … end …… default: begin Out_0; //輸出 if(condition0) next_state <= S0;//狀態轉移 end endcase end

二段式中,一個always塊採用同步時序描述狀態轉移;另一個採用組合邏輯判斷轉移條件,以及描述輸出。二段式便於閱讀,理解和維護,有利於綜合出更少的資源。但是由於採用的是組合邏輯輸出,容易產生毛刺,且不利於約束,也不利於佈局佈線。

3 三式狀態機 (三always塊結構):

//第一個always塊,時序邏輯,描述現態轉移到次態
always @ (posedge clk or negedge rst) begin
    if(rst_n) 
        current_state<=S0;
    else
        current_state<=next_state;
end

//第二個always塊,組合邏輯,描述狀態轉移的條件
always @ (current_state) begin
    case(current_state)
    S0:begin
        if(condition1)        next_state <= S1;//狀態轉移
        else if (condition2)  next_state <= S2;//狀態轉移
        else next_state <= S0;
        end
    S1:begin
        if(condition3)       next_state <= S3;//狀態轉移
        else if (condition4) next_state <=S4; 
        …
        end
    ……
    default: begin
            if(condition0)   next_state <= S0;//狀態轉移
           end
    endcase
end
//第三個always塊,時序邏輯,描述輸出
always @ (posedge clk or negedge rst) begin
if(rst)
    out0;
else
    case(current_state)
    S0: out0;
    S1: out1;
    ….
    default:Out0;
    endcase
end

三段式結構中,2個時序always塊分別用來描述狀態跳轉和輸出。組合always塊用於描述狀態轉移條件。雖然使用的硬體資源較多,但輸出採用暫存器結構,無毛刺,而且程式碼更清晰易讀,對於複雜的狀態機來說邏輯清晰,是一種比較流行的狀態機結構。

另外,對於更為複雜的狀態機模型,並不限於以上結構,狀態可能直接硬體多個電路,狀態中包含子狀態等,都會派生出更為複雜的寫法。但一般來講,小組合、大時序,狀態跳轉、狀態轉移條件判定,狀態機輸出分開描述,既可以做到邏輯清晰,也能控制電路的複雜度。