Verilog实现1010密码锁FSM模块无PASS/FAIL输出问题排查
数字密码锁FSM代码故障修复
核心错误点
- 多驱动冲突:寄存器
present_state被两个独立的always块同时驱动,属于Verilog语法错误,无法正常综合运行 - 时序逻辑实现缺失:时钟触发的状态更新块仅定义了复位逻辑,未实现时钟沿下的状态跳转逻辑
- 按键处理不规范:直接将异步按键作为时钟触发状态更新,易产生亚稳态,且未实现「仅单按键按下时才更新状态」的互斥判断
- 编码规范错误:时序逻辑中使用阻塞赋值
=,应使用非阻塞赋值<= - 终态跳转逻辑缺失:正确状态S4、错误状态E4未添加保持逻辑,会出现后续按键触发异常跳转的问题
修复后完整代码
module lock_FSM( input B0, input B1, input Reset, input Clk, output reg PASS, output reg FAIL ); reg [3:0] present_state, next_state; parameter S0 = 4'b0000, S1 = 4'b0001, S2 = 4'b0010, S3 = 4'b0011, S4 = 4'b0100; parameter E1 = 4'b0101, E2 = 4'b0110, E3 = 4'b0111, E4 = 4'b1000; // 按键边沿检测、同步、互斥判断 reg B0_dly, B1_dly; wire B0_pos, B1_pos, key_valid; always @(posedge Clk or posedge Reset) begin if(Reset) begin B0_dly <= 1'b0; B1_dly <= 1'b0; end else begin B0_dly <= B0; B1_dly <= B1; end end assign B0_pos = B0 & ~B0_dly; assign B1_pos = B1 & ~B1_dly; assign key_valid = B0_pos ^ B1_pos; // 仅单按键按下时有效,互斥 // 状态寄存器(合并为单一时钟驱动,消除多驱动) always @(posedge Clk or posedge Reset) begin if(Reset == 1) begin present_state <= S0; end else if(key_valid) begin present_state <= next_state; end end // 次态组合逻辑 always @(*) begin next_state = present_state; if(key_valid) begin case (present_state) S0 : next_state = B1_pos ? S1 : E1; S1 : next_state = B0_pos ? S2 : E2; S2 : next_state = B1_pos ? S3 : E3; S3 : next_state = B0_pos ? S4 : E4; S4 : next_state = S4; // 正确终态保持 E4 : next_state = E4; // 错误终态保持 E1 : next_state = E2; E2 : next_state = E3; E3 : next_state = E4; default : next_state = S0; endcase end end // 输出逻辑 always @(*) begin case(present_state) S4: begin PASS = 1; FAIL = 0; end E4: begin PASS = 0; FAIL = 1; end default : begin PASS = 0; FAIL = 0; end endcase end endmodule
功能验证说明
修复后的代码符合设计要求:
- 仅当单个按键按下时才触发状态跳转,双按键同时按下无响应
- 输入满4位密码后才输出PASS/FAIL状态,状态保持到复位触发
- 所有输入经过系统时钟同步,避免亚稳态问题,符合FPGA时序设计规范
内容的提问来源于stack exchange,提问作者SETU P PATEL
相关产品推荐
相关产品推荐

