有限状态机
建模步骤
跳转到“建模步骤”- 列出有限且互斥的状态。
- 为每个状态写清进入条件、退出条件和输出。
- 区分 Moore 输出(只依赖状态)和 Mealy 输出(依赖状态与输入)。
- 明确复位状态、超时、错误和非法状态恢复。
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; endend
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; endcaseend默认 next_state = state 表示没有触发条件时停留当前状态;输出先给默认值可避免锁存器。
两段式还是三段式
跳转到“两段式还是三段式”- 两段式:状态寄存器 + “下一状态和输出”组合块,代码紧凑。
- 三段式:状态寄存器 + 下一状态组合块 + 输出组合/时序块,适合输出复杂或需要寄存的设计。
选择应服从可读性、输出时序和团队规范,而不是把“三段式”当作固定答案。
审查要点
跳转到“审查要点”- 转移优先级是否明确,多个条件同时为真时会去哪里?
- 输出是否需要无毛刺;需要时将输出寄存。
- 输入是否来自其他时钟域;先完成 CDC 再进入状态机。
- 状态编码是否让工具自动选择即可;除非有可靠性或接口要求,不要过早手工编码。
- 仿真是否覆盖每条合法转移、复位、错误和非法状态恢复?