Verilog 有限状态机

有限状态机(Finite-State MachineFSM),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。状态机不仅是一种电路的描述工具,而且也是一种思想方法,在电路设计的系统级和 RTL 级有着广泛的应用。

状态机类型

Verilog 中状态机主要用于同步时序逻辑的设计,能够在有限个状态之间按一定要求和规律切换时序电路的状态。状态的切换方向不但取决于各个输入值,还取决于当前所在状态。 状态机一般分为 2 类:Moore 状态机和 Mealy 状态机。

Moore 型状态机

Moore 型状态机的输出只与当前状态有关,与当前输入无关。

输出会在一个完整的时钟周期内保持稳定,即使此时输入信号有变化,输出也不会变化。输入对输出的影响要到下一个时钟周期才能反映出来。这也是 Moore 型状态机的一个重要特点:输入与输出是隔离开来的。

Mealy 型状态机

Mealy 型状态机的输出,不仅与当前状态有关,还取决于当前的输入信号。

Mealy 型状态机的输出是在输入信号变化以后立刻发生变化,且输入变化可能出现在任何状态的时钟周期内。因此,同种逻辑下,Mealy 型状态机输出对输入的响应会比 Moore 型状态机早一个时钟周期。

状态机设计流程

根据设计需求画出状态转移图,确定使用状态机类型,并标注出各种输入输出信号,更有助于编程。一般使用最多的是 Mealy 3 段式状态机,状态机的实现也分为两段式状态机和三段式状态机。

两段式状态机:

用两个always块来描述状态机,其中一个always模块采用同步时序来描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出。两段式状态机要定义现态与次态,通过现态和次态的转换来实现时序逻辑。两段式状态机示例模板如下:

//两段式状态机第一个always块,描述当前状态的状态寄存器,时序逻辑
always @(posedge sys_clk)
begin
    if(~sys_rst)
        current_state   <= S0;
    else
        current_state   <= next_state;
end
//两段式状态机第二个always块,组合逻辑判断状态转移条件,描述状态转移规律与输出
always @(*) 
begin
    next_state  = S0;
    case (current_state)
        S0: begin
            out <= xxx;
            if(...)
                next_state = xxx;
            else
                next_state = xxx;
        end
        S1: begin
            out <= xxx;
            if(...)
                next_state = xxx;
            else
                next_state = xxx;
        end
        ...
        default: ;
    endcase
end

总结:两段式状态机将同步时序与组合逻辑分别放到不同的always块中实现。这样做的好处不仅仅是便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,但使用组合逻辑则无可避免的会引入毛刺问题。

三段式状态机:

在两个always块描述方法的基础上,使用3个always块。一个always块采用同步时序描述状态转移,一个always块采用组合逻辑判断转移条件,描述状态转移规律,另一个always块描述状态输出(可以组合逻辑输出,也可以时序逻辑输出)。三段式状态机示例模板如下:

//三段式状态机第一个always块,描述当前状态的状态寄存器,时序逻辑
always @(posedge sys_clk)
begin
    if(~sys_rst)
        current_state   <= S0;
    else
        current_state   <= next_state;
end
//三段式状态机第二个always块,组合逻辑判断状态转移条件,描述状态转移规律
always @(*) 
begin
    next_state  = S0;
    case (current_state)
        S0: begin
            if(...)
                next_state = xxx;
            else
                next_state = xxx;
        end
        S1: begin
            if(...)
                next_state = xxx;
            else
                next_state = xxx;
        end
        ...
        default: ;
    endcase
end
//三段式状态机第三个always块,描述输出
always @(posedge sys_clk)
begin
    if(~sys_rst)
        out <= xxx;
    else
        case (next_state)
            S0: out <= xxx;
            S1: out <= xxx; 
            ...
            default: ;
        endcase
end

Moore状态机实现序列检测

对于Moore型状态机,序列检测1011的核心代码如下。

// Moore型三段式状态机第一个always块,同三段式实例模块
// Moore型三段式状态机第二个always块,描述下一状态的状态寄存器,总共有S0,S1,S2,S3,S4五个状态
always @(*) 
begin
    next_state  = S0;
    case (current_state)
        S0: begin
            if(data_in == 1'b1)
                next_state = S1;
            else
                next_state = S0;
        end
        S1: begin
            if(data_in == 1'b0)
                next_state = S2;
            else
                next_state = S1;
        end
        S2: begin
            if(data_in == 1'b1)
                next_state = S3;
            else
                next_state = S0;
        end
        S3: begin
            if(data_in == 1'b1)
                next_state = S4;
            else
                next_state = S0;
        end
        S4: begin
            if(data_in == 1'b0)
                next_state = S2;
            else
                next_state = S1;
        end
        default: next_state = S0;
    endcase
end
// Moore型三段式状态机第三个always块,描述输出,与输入信号无关
always @(posedge sys_clk)
begin
    if(~sys_rst)
        data_out <= 1'b0;
    else if(current_state == S4)
        data_out <= 1'b1;
    else
        data_out <= 1'b0;
end

//总结:三段式状态机的输出使用时序逻辑输出,避免了两段式状态机使用组合逻辑输出潜在的毛刺问题

Mealy状态机实现序列检测

对于Mealy型状态机,序列检测1011的核心代码如下。

// Mealy型三段式状态机第一个always块,同三段式实例模块
// Mealy型三段式状态机第二个always块,描述下一状态的状态寄存器,总共有S0,S1,S2,S3四个状态
always @(*) 
begin
    next_state  = S0;
    case (current_state)
        S0: begin
            if(data_in == 1'b1)
                next_state = S1;
            else
                next_state = S0;
        end
        S1: begin
            if(data_in == 1'b0)
                next_state = S2;
            else
                next_state = S1;
        end
        S2: begin
            if(data_in == 1'b1)
                next_state = S3;
            else
                next_state = S0;
        end
        S3: begin
            if(data_in == 1'b1)
                next_state = S1;
            else
                next_state = S0;
        end
        default: next_state = S0;
    endcase
end
// Mealy型三段式状态机第三个always块,描述输出,由现态和输入信号共同决定输出
always @(posedge sys_clk)
begin
    if(~sys_rst)
        data_out <= 1'b0;
    else if(current_state == S3 && data_in == 1'b1)
        data_out <= 1'b1;
    else
        data_out <= 1'b0;
end

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值