跳转到内容
新建笔记

有限状态机

  1. 列出有限且互斥的状态。
  2. 为每个状态写清进入条件、退出条件和输出。
  3. 区分 Moore 输出(只依赖状态)和 Mealy 输出(依赖状态与输入)。
  4. 明确复位状态、超时、错误和非法状态恢复。
stateDiagram-v2
[*] --> IDLE
IDLE --> RUN: start
RUN --> DONE: last
RUN --> ERROR: fault
DONE --> IDLE: acknowledge
ERROR --> IDLE: clear
typedef enum logic [1:0] {
IDLE,
RUN,
DONE,
ERROR
} state_t;
state_t state, next_state;
always_ff @(posedge clk) begin
if (rst) begin
state <= IDLE;
end else begin
state <= next_state;
end
end
always_comb begin
next_state = state;
busy = 1'b0;
done = 1'b0;
unique case (state)
IDLE: begin
if (start) next_state = RUN;
end
RUN: begin
busy = 1'b1;
if (fault) next_state = ERROR;
else if (last) next_state = DONE;
end
DONE: begin
done = 1'b1;
if (acknowledge) next_state = IDLE;
end
ERROR: begin
if (clear) next_state = IDLE;
end
default: next_state = IDLE;
endcase
end

默认 next_state = state 表示没有触发条件时停留当前状态;输出先给默认值可避免锁存器。

  • 两段式:状态寄存器 + “下一状态和输出”组合块,代码紧凑。
  • 三段式:状态寄存器 + 下一状态组合块 + 输出组合/时序块,适合输出复杂或需要寄存的设计。

选择应服从可读性、输出时序和团队规范,而不是把“三段式”当作固定答案。

  • 转移优先级是否明确,多个条件同时为真时会去哪里?
  • 输出是否需要无毛刺;需要时将输出寄存。
  • 输入是否来自其他时钟域;先完成 CDC 再进入状态机。
  • 状态编码是否让工具自动选择即可;除非有可靠性或接口要求,不要过早手工编码。
  • 仿真是否覆盖每条合法转移、复位、错误和非法状态恢复?