历史状态机

        我们知道状态机输出为当前状态和输入的函数,事实上还存在这样的状态机,它的输出不仅与当前状态和输入有关还与前一个(或者多个)状态有关。这类状态机通常被称为“扩展状态机”或“历史状态机”,相比常规状态机能够处理更加复杂的情况,因为它可以记住先前的状态信息,常规状态机的原理图见图一。

常规状态机的原理图
图一 常规状态机的原理图

        历史状态机主要特征在于,历史状态机通过记录在此之前的少数状态,能够立刻恢复到此前的某一状态,或者输出与此前状态有关的信号,图二中只展示了记录当前状态的前一状态历史状态机,不难推广到多个状态寄存器组记录前多个历史状态。

图二 历史状态机原理图
图二 历史状态机的原理图

        历史状态机能够保持对过去状态的记录,即它在状态转移后存储最近此前的状态信息,可以在必要时进行回溯或重新计算。历史状态机的这种属性能辅助系统进行进行决策,系统可以根据当前状态和历史状态(记录)进行决策和执行相应的行为,这使得历史状态机能够对系统的演变历史和先前的决策做出反应。

        比较图二和图一可见,如果从图二紫色虚线处隔断,历史状态机可以使用常规状态机加上当前状态的延迟逻辑等效表达,与常规状态机的次态判决只使用当前状态和输入不同的是,历史状态机的次态组合逻辑还额外使用了滞后一定周期的“历史态”,下面是基于Verilog语言描述的一个简单例子:

        下面的状态机代码中,添加了一个名为protocol_state_hist的历史状态寄存器,它记录上一个周期的状态供下一个周期的状态转移决策使用。在时钟的上升沿,当前态被保存到protocol_state_hist中成为历史状态,它可以被次态逻辑使用进行条件判断以决定次态protocol_state_next。

module CommunicationProtocol (
    input wire clk,                 // 时钟信号
    input wire reset,               // 复位信号
    input wire connect_request,     // 连接请求信号
    input wire data,                // 数据包信号
    input wire ack,                 // 确认消息信号
    output wire send_data,          // 发送数据信号
    output wire send_ack            // 发送确认消息信号
);

// 定义状态
reg[1:0] protocol_state;
parameter CONNECTING = 2'b00;
parameter SENDING    = 2'b01;
parameter RECEIVING  = 2'b10;

// 次态定义
reg[1:0] protocol_state_next;

// 定义状态寄存器(当前)
reg[1:0] protocol_state_reg;

// 定义历史状态寄存器
reg[1:0] protocol_state_hist;

// 定义状态转移规则
always @(posedge clk or posedge reset) begin
    if (reset) begin
        protocol_state_reg <= CONNECTING;
        protocol_state_hist <= CONNECTING;
    end
    else begin
        protocol_state_reg <= protocol_state_next;
        protocol_state_hist <= protocol_state_reg;
    end
end

// 定义状态逻辑
always @(*) begin
    case (protocol_state_hist)  /*也可能是protocol_state_reg,根据需要(这里就是上图中的“云”——求解次态的组合逻辑)*/
        CONNECTING:
            if (connect_request)
                protocol_state_next = SENDING;
            else
                protocol_state_next = CONNECTING;
        SENDING:
            if (data)
                protocol_state_next = RECEIVING;
            else
                protocol_state_next = SENDING;
        RECEIVING:
            if (ack)
                protocol_state_next = SENDING;
            else
                protocol_state_next = RECEIVING;
        default:
            protocol_state_next = CONNECTING;
    endcase
end

// 输出动作逻辑
assign send_data = (protocol_state_reg == SENDING);
assign send_ack = (protocol_state_reg == RECEIVING);

endmodule

   在数字逻辑设计中,历史状态机(Historical State Machine)可用于实现以下功能:

  1. 状态序列控制:历史状态机用于控制系统在不同状态之间的转移。通过记录历史状态和定义状态转移规则,可以确定系统在不同条件下应采取的行动,从而实现状态序列的控制。
  2. 错误检测和纠正:历史状态机可用于检测和纠正数字系统中的错误。通过在状态转移过程中检查输入和输出,可以捕捉和处理错误情况,例如错误的输入序列或未预期的状态转换。
  3. 协议处理:历史状态机常用于处理通信协议。通过定义协议的状态和状态转移规则,可以有效地处理协议消息的接收、解析、验证和响应。历史状态机能够跟踪通信过程中的状态和历史信息,确保协议的正确执行。
  4. 计数器和序列生成器:历史状态机可用于实现计数器和序列生成器。通过定义不同状态和状态转移规则,可以实现不同的计数模式和序列生成模式,例如二进制计数器、循环计数器、序列生成器等。
  5. 复杂逻辑控制:历史状态机可以实现复杂的逻辑控制功能。通过定义不同的状态和状态转移规则,可以根据输入信号和历史状态来决定系统的行为,实现复杂的逻辑运算和控制逻辑。

设计历史状态机时,需要考虑以下几个关键要素:

  • 状态集合:确定系统或程序的所有可能状态。状态应该能够清晰地描述系统的特定时刻的情况,并包括系统内部状态和外部环境的状态。
  • 状态转移规则:定义从一个状态转移到另一个状态的规则。这些规则可以基于输入信号、外部事件或内部条件来确定状态转移。状态转移规则决定了系统在给定条件下如何响应和变化。
  • 输入信号和外部事件:确定系统接收的输入信号和外部事件。这些信号和事件可以触发状态转移或影响系统的行为。输入信号和外部事件可以是来自外部环境的传感器信号、用户输入或其他系统的输出。
  • 输出动作:定义系统在特定状态下采取的操作或行为。输出动作可以是产生输出信号、控制外部设备、修改内部状态或执行其他操作。输出动作可以与状态转移规则和输入信号关联,以实现系统的预期行为。
  • 历史记录:确定是否需要记录历史状态。历史记录允许系统回溯到先前的状态,并根据历史状态做出决策或执行操作。历史记录可以通过寄存器或其他方式来实现。
  • 初始化状态:确定系统的初始状态。在系统启动或复位时,需要指定系统应处于的初始状态。初始状态应与系统的要求和预期行为相符。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值