FPGA 状态机赋值 —— 三段式结构
FPGA状态机赋值核心原则是时序逻辑用非阻塞赋值 (<=),组合逻辑用阻塞赋值 (=)。通常采用三段式结构:第一段时序逻辑负责状态寄存器更新,第二段组合逻辑负责状态跳转条件判断,第三段逻辑负责输出(建议时序输出以消除毛刺)。
1 详细赋值原则与结构
- 状态跳转(时序逻辑): 在 always @(posedge clk or negedge rst_n) 块中,使用非阻塞赋值更新当前状态:current_state <= next_state;。
- 状态控制(组合逻辑): 在 always @(*) 块中,使用阻塞赋值判断下一状态:next_state = …;。
- 状态输出(建议时序): 在 always @(posedge clk or negedge rst_n) 块中,使用非阻塞赋值更新输出,以避免组合逻辑的毛刺现象。
三段式状态机示例:
// 1. 时序逻辑,状态切换
always @(posedge clk or negedge rst_n) begin
if (!rst_n) current_state <= IDLE;
else current_state <= next_state; // <= 非阻塞
end
// 2. 组合逻辑,下一状态判断
always @(*) begin
case (current_state)
IDLE: if (start) next_state = WORK; // = 阻塞
else next_state = IDLE;
WORK: next_state = IDLE;
default: next_state = IDLE;
endcase
end
// 3. 时序逻辑,输出
always @(posedge clk or negedge rst_n) begin
if (!rst_n) out <= 1'b0;
else if (next_state == WORK) out <= 1'b1; // <= 非阻塞
else out <= 1'b0;
end
1.1 关键点总结:
- 禁止混合: 严禁在同一个 always 块中混合使用 = 和 <=。
- 阻塞与非阻塞: 组合逻辑用 =,为了立即更新;时序逻辑用 <=,为了并行操作。
- 安全性: 使用时序输出可有效消除状态机输出毛刺。
2 关于毛刺(Glitch)的预防
毛刺(Glitch)是指信号在达到稳定状态之前,由于内部路径延迟不同而产生的短暂、错误的尖峰脉冲。
2.1 毛刺的产生原因
毛刺的根本原因是信号通过不同逻辑门或走线的“速度”不一样(即传播延迟)。
假设状态机从状态 A (2'b01) 切换到状态 B (2'b10)。
- 在理想情况下,两个比特位应该同时翻转。
- 但在物理实现中,第 1 位变 0 稍微快了一点点,而第 0 位变 1 稍微慢了一点点。
- 那么在极短的瞬间(比如几个皮秒),逻辑电路看到的中间态就是
2'b00。
如果你的输出逻辑是 assign out = (state == 2'b00),那么这个 out 信号就会瞬间跳成高电平,然后立刻变回低电平。这个瞬间的高电平就是毛刺。
2.2 使用D触发器避免
always @(posedge clk) begin
base_pwr_allow <= (state == ST_ALLOW);
end
这种写法叫做寄存器输出。它的原理是:
- 滤除过程中的杂乱: 无论组合逻辑在时钟周期内怎么跳动(毛刺乱飞),D触发器(Register)都视而不见。
- 定点采样: 只有在时钟的上升沿那一刻,D触发器才会去抓取当时的稳定值。
- 干净输出: 一旦抓取完成,输出就在整个时钟周期内保持恒定,绝对不会有中间的抖动。
留下评论