news 2026/6/9 22:06:42

基于Vivado与Verilog的智能密码锁设计及EGO1开发板实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Vivado与Verilog的智能密码锁设计及EGO1开发板实现

1. 智能密码锁设计概述

用FPGA开发板实现密码锁听起来很高大上?其实没那么复杂。我去年用EGO1开发板做过一个完整的密码锁项目,实测下来效果很稳。这个设计核心就是用Verilog在Vivado里写状态机,控制按键输入、密码比对和显示逻辑。相比单片机方案,FPGA的并行处理特性让响应速度直接起飞,按下按键的瞬间就能得到反馈。

先说说整体架构。这个密码锁需要实现几个核心功能:4位密码输入(支持修改密码)、10秒倒计时、数码管状态显示、LED开锁指示。我在EGO1上实际测试时,发现最关键的三个技术点:状态机设计要够健壮(防止死锁)、按键消抖必须做好(机械按键的物理特性你懂的)、数码管动态扫描要流畅(不然会有闪烁感)。下面我会结合代码详细拆解每个模块的实现技巧。

2. 硬件平台与开发环境

2.1 EGO1开发板配置

EGO1这块板子对初学者特别友好,板载资源完全够用:Artix-7 FPGA芯片(XC7A35T-1CPG236C)、8个拨码开关、5个按钮、8位数码管、LED指示灯。我实测用到的资源包括:

  • 4个拨码开关模拟密码输入(实际项目可以用矩阵键盘)
  • 3个独立按钮(确认、修改、上锁)
  • 2个LED(F1开锁指示、F2关锁指示)
  • 4位数码管显示倒计时和状态

开发环境用Vivado 2020.1版本,新建工程时注意两点:器件型号选xc7a35tcsg324-1(EGO1的FPGA型号),语言选Verilog。有个坑要注意:EGO1的时钟是100MHz,但数码管扫描频率建议降到1kHz左右,否则会有残影。

2.2 管脚分配技巧

在xdc约束文件里,我是这样定义管脚的(关键部分):

set_property PACKAGE_PIN T17 [get_ports clk] # 100MHz时钟 set_property PACKAGE_PIN M17 [get_ports key_0] # 数字键0 set_property PACKAGE_PIN M18 [get_ports key_1] # 数字键1 ... set_property PACKAGE_PIN U16 [get_ports led_open] # F1开锁灯

建议先用板子的原理图核对引脚编号,我一开始把LED极性搞反了,调试时发现灯是反着亮的。输出信号记得加Pullup,防止初始状态不确定:

set_property PULLUP true [get_ports {led_open}]

3. 核心模块实现

3.1 状态机设计

密码锁的灵魂就是状态机。我设计了6个状态(用parameter定义):

parameter S_LOCK = 0; // 锁定状态 parameter S_INPUT = 1; // 输入密码 parameter S_COMPARE = 2; // 密码比对 parameter S_OPEN = 3; // 开锁状态 parameter S_MODIFY = 4; // 修改密码 parameter S_ERROR = 5; // 密码错误

状态转移逻辑用always块实现,注意非阻塞赋值(用<=):

always@(posedge clk) begin case(current_state) S_LOCK: if(key_pressed) begin next_state <= S_INPUT; timer <= 10; // 启动10秒倒计时 end S_INPUT: if(confirm_pressed) next_state <= S_COMPARE; else if(timer == 0) next_state <= S_LOCK; // 超时复位 // 其他状态转移... endcase end

实测发现状态机要加异步复位,否则上电时会卡在未知状态。我在工程里专门加了复位按钮:

always@(posedge clk or posedge reset) if(reset) current_state <= S_LOCK; else current_state <= next_state;

3.2 按键消抖模块

机械按键的抖动问题必须解决,否则会误触发。我的消抖方案是20ms延迟检测

module debounce( input clk, input button_in, output reg button_out ); reg [19:0] counter; always@(posedge clk) begin if(button_in != button_out) counter <= counter + 1; else counter <= 0; if(&counter) button_out <= button_in; // 计数器满时更新 end endmodule

在仿真时发现,如果直接用系统时钟(100MHz),计数器会很大。我做了个分频器,先降到1MHz再计数,这样counter计到20,000就够20ms。实际测试时,这个方案能稳定过滤掉按键抖动。

3.3 数码管动态显示

EGO1的8位数码管是共阳极的,需要动态扫描。我的方案是:

  1. 段选信号(dig_led)控制显示内容
  2. 位选信号(wei_led)轮流激活数码管

关键代码如下:

reg [2:0] scan_cnt; // 扫描计数器 always@(posedge clk_div) begin scan_cnt <= scan_cnt + 1; case(scan_cnt) 0: begin wei_led <= 8'b11111110; dig_led = seg_data[0]; end 1: begin wei_led <= 8'b11111101; dig_led = seg_data[1]; end // ...其他位 endcase end

刷新率要控制在1kHz左右(每位数码管显示时间约1ms)。我实测发现,如果直接用100MHz时钟扫描会有明显闪烁,后来用分频器生成1kHz时钟就流畅了。显示内容编码用查表法:

case(num) 0: seg = 8'b11000000; // 0 1: seg = 8'b11111001; // 1 // ... 'hA: seg = 8'b10001000; // A(显示OP中的O) 'hB: seg = 8'b10000011; // P endcase

4. 功能优化与调试

4.1 密码存储安全

初始密码我存在寄存器里:

reg [15:0] password_reg = 16'h3210; // 默认密码3210

但这样会有安全隐患——断电就恢复默认。后来我改用FPGA的Block RAM存储密码,并加了写保护逻辑:

always@(posedge clk) begin if(modify_mode && confirm_pressed) password_reg <= new_password; end

在EGO1上测试时,发现修改密码功能正常,但断电还是会丢失。如果要做产品级设计,建议外接EEPROM。

4.2 倒计时精度问题

10秒倒计时最初用系统时钟直接计数:

if(timer_en) counter <= counter + 1; if(counter == 100_000_000) begin // 100MHz时钟 timer <= timer - 1; counter <= 0; end

实测发现有两个问题:精度误差大(实际用了10.3秒)、占用资源多。优化方案是先用分频器产生1Hz时钟:

// 1Hz分频 always@(posedge clk) begin if(cnt_1hz == 50_000_000) begin clk_1hz <= ~clk_1hz; cnt_1hz <= 0; end else cnt_1hz <= cnt_1hz + 1; end // 倒计时逻辑 always@(posedge clk_1hz) if(timer > 0) timer <= timer - 1;

4.3 仿真测试技巧

在Vivado里做仿真时,我建了专门的testbench:

initial begin reset = 1; #100; reset = 0; // 复位 key_in = 4'b0011; #20; // 输入3 confirm = 1; #20; confirm = 0; // ... $finish; end

重点测试了三个场景:

  1. 正常开锁流程:输入正确密码->LED亮
  2. 密码错误流程:输入错误密码->数码管显示LC
  3. 修改密码流程:进入修改模式->设置新密码->用新密码开锁

仿真波形里要特别注意状态机跳转时机倒计时信号。有个bug我调试了很久:修改密码后状态机没返回开锁状态,后来发现是confirm信号消抖没做好。

5. 完整代码结构

顶层模块这样组织:

module password_lock( input clk, input [3:0] key_in, // 4位密码输入 input confirm, // 确认键 input modify, // 修改键 output led_open, // 开锁LED output [7:0] dig_led, // 数码管段选 output [7:0] wei_led // 数码管位选 ); // 实例化各子模块 debounce deb_confirm(.clk(clk), .button_in(confirm), ...); state_machine fsm(.clk(clk), .key_in(key_debounced), ...); display disp(.clk(clk), .value(display_data), ...); endmodule

关键信号连接关系:

  • 按键输入 -> 消抖模块 -> 状态机
  • 状态机 -> 密码比对逻辑 -> LED控制
  • 倒计时器 -> 数码管显示模块

在EGO1上验证时,下载bitstream文件后要注意:

  1. 先按复位键初始化系统
  2. 用拨码开关输入密码(比如0011对应数字3)
  3. 按确认键触发比对
  4. 成功时F1灯亮,数码管显示"OP"

6. 常见问题解决

问题1:数码管显示模糊

  • 检查位选信号频率(建议1kHz)
  • 确认段选信号驱动能力足够(可加74HC245缓冲)

问题2:按键反应迟钝

  • 调整消抖时间(20ms-50ms)
  • 确保时钟分频正确

问题3:状态机卡死

  • 添加看门狗定时器
  • 检查所有状态转移条件是否完备

有个坑我踩过:修改密码功能测试时,发现新密码不生效。原因是状态机在修改模式没有正确更新密码寄存器。通过仿真发现是confirm信号在修改状态下被意外触发。建议关键信号都加边沿检测

reg confirm_dly; always@(posedge clk) confirm_dly <= confirm; wire confirm_pulse = ~confirm_dly & confirm;

7. 扩展功能建议

如果想进一步提升项目,可以考虑:

  1. 增加错误次数限制:连续错误3次锁定1分钟
  2. 添加蜂鸣器提示:密码正确/错误时发声
  3. 改用矩阵键盘:节省IO口(需要扫描逻辑)
  4. 无线开锁功能:通过蓝牙模块控制

我在原型阶段试过用PMOD接口接蓝牙模块,用手机APP发送密码。实测发现需要解决串口通信同步问题,后来加了起始位/停止位校验。如果大家有兴趣,我可以另开一篇讲无线集成。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 13:12:05

从零构建ESP32-C3蓝牙气象站:MicroPython与uBluetooth的实战指南

从零构建ESP32-C3蓝牙气象站&#xff1a;MicroPython与uBluetooth的实战指南 1. 项目概述与硬件准备 在物联网和智能硬件快速发展的今天&#xff0c;ESP32-C3凭借其出色的性能和丰富的功能&#xff0c;成为创客和开发者的热门选择。这款基于RISC-V架构的微控制器不仅支持Wi-F…

作者头像 李华
网站建设 2026/6/5 4:54:13

ChatGPT升级实战:从模型微调到生产环境部署的最佳实践

背景痛点&#xff1a;升级后的“甜蜜负担” ChatGPT 从 3.5 到 4o 的迭代速度堪比高铁&#xff0c;但开发者上车后才发现&#xff1a; 官方基座模型越来越“通用”&#xff0c;垂直场景想出彩必须微调&#xff0c;可官方 Fine-tune 接口最低也要 1k 条高质量样本&#xff0c;…

作者头像 李华
网站建设 2026/6/4 9:54:29

服务器机架单位 1U、2U、4U 到 42U,这些常见规格有什么区别?

今天给大家分享一个基础却极其重要的知识点——服务器的“U”单位,特别是1U、2U、4U和42U这些常见规格。 很多新同事在采购或上架设备时会问:“1U和2U到底差在哪儿?”“为什么机柜都是42U?”“高密度部署用1U好,还是2U更稳?”今天这篇帖子,就把这些问题一次性讲透。读完…

作者头像 李华
网站建设 2026/6/5 5:09:41

AI辅助开发实战:基于Python的用户画像电影推荐系统从0到1构建指南

AI辅助开发实战&#xff1a;基于Python的用户画像电影推荐系统从0到1构建指南 摘要&#xff1a;毕业设计中&#xff0c;许多学生在实现“基于Python的用户画像电影推荐系统”时面临数据稀疏、特征工程复杂、模型集成困难等问题。本文结合AI辅助开发工具&#xff08;如GitHub Co…

作者头像 李华
网站建设 2026/6/7 11:06:33

Dify国产化部署避坑清单:3大硬件兼容雷区、5类中间件配置失效场景及72小时压测数据实录

第一章&#xff1a;Dify国产化部署避坑清单总览在信创环境下部署 Dify 时&#xff0c;常因操作系统适配、中间件版本冲突、国产芯片指令集差异及安全策略限制导致服务启动失败、模型加载异常或 Web 控制台无法访问。本章聚焦常见“隐性陷阱”&#xff0c;提供可立即验证的检查项…

作者头像 李华