状态机(二):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块用于描述状态转移条件。虽然使用的硬件资源较多,但输出采用寄存器结构,无毛刺,而且代码更清晰易读,对于复杂的状态机来说逻辑清晰,是一种比较流行的状态机结构。

另外,对于更为复杂的状态机模型,并不限于以上结构,状态可能直接硬件多个电路,状态中包含子状态等,都会派生出更为复杂的写法。但一般来讲,小组合、大时序,状态跳转、状态转移条件判定,状态机输出分开描述,既可以做到逻辑清晰,也能控制电路的复杂度。

你可能感兴趣的:(数字逻辑设计,FPGA,数字逻辑,状态机,verilog)