不枉初心,砥砺前行

皮皮祥的博客

欢迎留言,评论

导航

三种状态机的区别?

状态机的写法可以分为以下几种:

一段式:最主要的特征是只有一个always块。在这个always块内既描述状态转移,又含有组合逻辑输入/输出,当前状态用寄存器输出;在这种状态机的写法中,组合逻辑电路和时序逻辑电路都在一起,没有分开;因此这种写法增加了代码的复杂度且不利于代码的维护和修改,同时也不利于后期约束;

两段式:最主要的特征是有两个always块,将组合逻辑和时序逻辑分开。其中一个always块采用同步时序描述状态转移,而另一个always块采用组合逻辑来判断状态转移的条件,描述状态转移规律及输出;在这种写法下,需要定义两个状态,分别是现态和次态,通过现态和次态的转换来实现状态转移;两段式状态机可以清晰完整的显示出状态机的结构,有利于代码的维护和后期修改,同时也降低编写复杂度;

三段式:最主要的特征是有三个always块。区别于两段式状态机的关键在于两段式状态机直接采用组合逻辑输出,而三段式状态机则通过在组合逻辑后再增加一级寄存器实现逻辑输出——即一个always块采用同步时序描述状态转移,一个always块采用组合逻辑判断转移条件、转移状态规律,最后一个always块采用同步时序描述状态的输出;这种三段式状态机的写法代码非常清晰,极大降低了编写维护代码的复杂度,最大程度清晰完整的显示出状态机的结构。同时可以有效地滤除两段式状态机组合逻辑输出可能产生的毛刺信号;另外对于总线形式的输出来说,容易使总线数据对齐,从而减小总线数据间的偏移,减小接收端数据采样出错的频率;但是代码量会长一些哦OvO

下面是以上介绍的三种状态机在下面这种状态转移图下的代码

module simple(
    input clk,
    input rst_n,
    input w,
    output reg[1:0] z
);

localparam A = 2'b00;
localparam B = 2'b01;
localparam C = 2'b10;

reg [1:0] state;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        state <= A;
        z <= 0;
    end
    else
    case (state)
        A:
        begin
            if (w) begin
                state <= B;
                z <= 2'd1;
            end
            else begin
                state <= A;
                z <= 2'd0;
            end
        end 
        B:
        begin
            if (w) begin
                state <= C;
                z <= 2'd2;
            end
            else begin
                state <= A;
                z <= 2'd1;
            end
        end
        C:
        begin
            if (w) begin
                state <= C;
                z <= 2'd2;
            end
            else begin
                state <= A;
                z <= 2'd0;
            end
        end
        default: 
        begin
            state <= A;
            z <= 2'd0;
        end
    endcase
end
endmodule

两段式状态机代码:

module simple(
    input clk,
    input rst_n,
    input w,
    output reg[1:0] z
);

localparam A = 2'b00;
localparam B = 2'b01;
localparam C = 2'b10;

reg [1:0] current_state;
reg [1:0] next_state;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        current_state <= A;
    end
    else 
        current_state <= next_state;
end

always @(*) begin
    case (current_state)
        A:
        begin
            if (w) begin
                next_state = B;
                z = 2'd1;
            end
            else begin
                next_state = A;
                z = 2'd0;
            end
        end 
        B:
        begin
            if (w) begin
                next_state = C;
                z = 2'd2;
            end
            else begin
                next_state <= A;
                z = 2'd1;
            end
        end
        C:
        begin
            if (w) begin
                next_state = C;
                z = 2'd2;
            end
            else begin
                next_state = A;
                z = 2'd0;
            end
        end
        default: 
        begin
            next_state = A;
            z = 2'd0;
        end
    endcase
end
endmodule

三段式状态机代码:

module simple(
    input clk,
    input rst_n,
    input w,
    output reg[1:0] z
);

localparam A = 2'b00;
localparam B = 2'b01;
localparam C = 2'b10;

reg [1:0] current_state;
reg [1:0] next_state;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        current_state <= A;
    end
    else 
        current_state <= next_state;
end

always @(*) begin
    case (current_state)
        A:
        begin
            if (w) begin
                next_state = B;
            end
            else begin
                next_state = A;
            end
        end 
        B:
        begin
            if (w) begin
                next_state = C;
            end
            else begin
                next_state <= A;
            end
        end
        C:
        begin
            if (w) begin
                next_state = C;
            end
            else begin
                next_state = A;
            end
        end
        default: 
        begin
            next_state = A;
        end
    endcase
end
always @(posedge clk or negedge rst_n) begin
    if (rst_n) begin
        z <= 2'd0;
    end
    else begin
        case (next_state)
            A: z <= 2'd0;
            B: z <= 2'd1;
            C: z <= 2'd2;
            default: z <= 2'd0;
        endcase
    end
end

endmodule

转自:https://zhuanlan.zhihu.com/p/431143109

posted on 2022-09-01 14:46  皮皮祥  阅读(702)  评论(0编辑  收藏  举报