1. 项目概述:FPGA密码锁的设计初衷与核心功能
这个基于Verilog HDL开发的FPGA密码锁项目,是我在嵌入式安全领域的一次实践探索。它的核心功能是通过4x4矩阵键盘实现用户交互,支持密码输入、验证和修改等基础功能。具体来说:
- 初始密码存储在FPGA片内存储器中
- 用户通过矩阵键盘输入6位密码进行验证
- 特殊组合键"12"触发密码修改模式
- 系统通过LED或数码管显示操作状态
选择FPGA作为实现平台主要考虑到其并行处理能力和可重构特性。与单片机方案相比,FPGA能够实现真正的并行密码校验,且没有软件层面的安全漏洞。我在Xilinx Artix-7开发板上实现了这个设计,时钟频率设置为50MHz。
实际开发中发现:矩阵键盘的防抖处理对系统稳定性影响很大,必须在前端硬件和Verilog代码中双重保障
2. 硬件架构设计解析
2.1 核心模块划分
整个系统采用模块化设计,主要包含以下功能单元:
| 模块名称 | 功能描述 | 关键信号 |
|---|---|---|
| 键盘扫描模块 | 检测矩阵键盘输入 | row[3:0], col[3:0] |
| 密码存储模块 | 存储当前有效密码 | mem[23:0] |
| 状态控制模块 | 管理系统工作状态 | state[2:0] |
| 显示驱动模块 | 控制LED/数码管输出 | seg[7:0], an[3:0] |
| 时钟分频模块 | 生成各模块所需时钟 | clk_1k, clk_10 |
2.2 矩阵键盘接口设计
4x4矩阵键盘采用典型的行列扫描方式:
verilog复制always @(posedge clk_1k) begin
case(scan_cnt)
2'b00: row <= 4'b0111;
2'b01: row <= 4'b1011;
2'b10: row <= 4'b1101;
2'b11: row <= 4'b1110;
endcase
scan_cnt <= scan_cnt + 1;
end
列信号通过电阻上拉,当某行被激活时,检测列线电平变化即可确定按键位置。实际测试中发现,机械按键的抖动时间通常在5-20ms之间,因此需要:
- 硬件层面:每个按键并联0.1μF电容
- 软件层面:检测到按键后延时20ms再确认状态
3. Verilog核心代码实现
3.1 密码存储与验证逻辑
密码存储采用24位寄存器,每组密码4位(0-9),共6位密码:
verilog复制reg [23:0] password_reg = 24'h123456; // 默认密码
always @(posedge clk) begin
if (modify_en) begin
case(input_cnt)
3'd0: password_reg[23:20] <= key_value;
3'd1: password_reg[19:16] <= key_value;
// ...其他位类似
endcase
end
end
密码验证采用逐位比较方式:
verilog复制always @(*) begin
case(input_cnt)
3'd0: check = (input_buffer[23:20] == password_reg[23:20]);
3'd1: check = check & (input_buffer[19:16] == password_reg[19:16]);
// ...后续位类似
endcase
end
3.2 状态机设计
系统采用有限状态机(FSM)控制流程,主要状态包括:
- IDLE:等待输入状态
- INPUT:密码输入中
- CHECK:密码验证
- MODIFY:密码修改模式
- SUCCESS:验证成功
- FAILED:验证失败
状态转移图关键部分实现:
verilog复制always @(posedge clk or posedge rst) begin
if (rst) begin
state <= IDLE;
end else begin
case(state)
IDLE: if (key_pressed) state <= INPUT;
INPUT: if (input_cnt == 6) state <= CHECK;
CHECK: if (check_ok) state <= SUCCESS; else state <= FAILED;
// ...其他状态转移
endcase
end
end
4. 关键问题与解决方案
4.1 按键冲突处理
当多个按键同时按下时,传统扫描方式会产生误判。解决方案:
- 增加按键有效性检测:只有单个列线为低电平时才视为有效输入
- 设置按键锁存:检测到第一个有效按键后,屏蔽后续输入直到释放
verilog复制// 在键盘扫描模块中添加冲突检测
wire valid_press = (col == 4'b1110) || (col == 4'b1101) ||
(col == 4'b1011) || (col == 4'b0111);
4.2 密码安全机制
为防止暴力破解,实现以下保护措施:
- 输入错误3次后锁定系统1分钟
- 密码修改需要先验证旧密码
- 所有密码在存储时进行简单异或加密
verilog复制// 错误计数器逻辑
always @(posedge clk) begin
if (state == FAILED) begin
err_cnt <= err_cnt + 1;
if (err_cnt == 2) lock_timer <= 60_000_000; // 50MHz时钟下计数1分钟
end
else if (lock_timer > 0) lock_timer <= lock_timer - 1;
end
5. 系统优化与扩展方向
5.1 性能优化实践
-
时序优化:对关键路径添加流水线
- 密码比较操作拆分为两个时钟周期
- 键盘扫描频率从1kHz提升到2kHz
-
资源优化:
- 共用显示译码器
- 状态编码采用One-Hot方式
5.2 功能扩展建议
- 增加密码复杂度检测:修改密码时检查是否过于简单
- 添加管理密码:区分用户密码和管理员密码
- 实现掉电保护:使用FPGA的Flash存储密码
- 增加通信接口:通过UART连接上位机记录操作日志
实际测试数据显示,当前设计在Xilinx Artix-7 XC7A35T芯片上的资源占用情况:
| 资源类型 | 使用量 | 总量 | 利用率 |
|---|---|---|---|
| LUT | 623 | 20800 | 3% |
| 寄存器 | 412 | 41600 | 1% |
| 块RAM | 1 | 50 | 2% |
这个密码锁工程从构思到实现大约花费了两周时间,期间最大的收获是对FPGA并行处理优势有了更深刻的理解。特别是在密码验证环节,传统MCU需要顺序比较各位密码,而FPGA可以并行比较所有位,显著提高了响应速度
