1. 有限状态机:硬件控制的灵魂
第一次接触状态机是在大学实验室,当时看着LED灯按预设节奏流动闪烁,突然意识到这背后藏着硬件设计的精髓。有限状态机(FSM)就像交通信号灯的智能调度系统——它根据当前状态(红灯/绿灯)和触发条件(倒计时结束)决定下一个状态切换。在FPGA开发中,摩尔型状态机特别适合流水灯这类输出仅依赖当前状态的场景,比如当系统处于"LED1亮"状态时,无论外部是否有按键输入,都会持续输出0010信号。
实际项目中我常遇到初学者混淆状态机类型。简单来说,摩尔机的输出像固执的守旧派,只认当前状态;而米勒机更像精明的商人,输出取决于当前状态和输入条件。做流水灯选择摩尔机就对了,因为灯的状态切换完全由定时器触发,不需要实时响应外部输入信号。这里有个实用技巧:用参数定义状态编码时,建议采用独热码(one-hot)如4'b0001、4'b0010,虽然占用资源稍多,但能避免状态解码错误,特别适合初学者调试。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 流水灯的状态舞蹈编排
设计状态转移图就像编排舞蹈动作。我曾用白板画过这样一个案例:四个LED代表四个舞者,每个节拍(500ms)变换一次队形。状态转移图要明确三个要素——现态(当前队形)、转移条件(节拍器信号)和次态(下一个队形)。具体到代码实现,状态空间定义可以这样优化:
verilog复制parameter S_LED0 = 0, S_LED1 = 1, S_LED2 = 2, S_LED3 = 3;
reg [1:0] state; // 2位寄存器存储4种状态
定时器设计有个坑要注意:很多新手会直接在状态机里累加计数器,这会导致代码臃肿。更好的做法是独立设计定时器模块,通过标志位通知状态机。比如下面这个经过三次项目迭代的计数器方案:
verilog复制always @(posedge clk) begin
if(cnt >= 25_000_000) begin
time_pulse <= 1'b1;
cnt <= 0;
end else begin
cnt <= cnt + 1;
time_pulse <= 1'b0;
end
end
3. 三段式状态机的黄金法则
在Altera FPGA上调试
