十二、数字密码锁设计
本文由山东大学研友袁卓贡献,特此感谢
实验目的
实现数字密码锁设计,要求矩阵按键输出且数码管显示输入密码,密码输入正确与否均会有相应标志信号产生。
实验平台
芯航线FPGA核心板、数码管_VGA_PS2模块、矩阵按键模块
实验原理
随着生活质量的提高,当代人们也认识到了安全的重要性,已经不再满足于老式的机械钥匙。近年来越来越多的技术开始在安全领域应用,例如普通的按键输入、指纹输入或者虹膜输入等。
本节设计一款按键输入式密码锁,用矩阵键盘输入密码,输入完成后进行密码比对,如密码输入正确则输出开门信号以及灯光指示,如密码输入错误则蜂鸣器进行报警以及灯光指示。
综合以上要求可以看出此处系统框图如图1所示。
图1 系统框图
其中各模块功能描述如表1所示。
表1 各模块功能描述
矩阵按键模块
现在分开介绍,矩阵按键输入控制模块的框图及其接口列表如下所示,详细内容可以参考芯航线关于矩阵按键的教程,此处不再详述。
图2 矩阵按键模块框图
表2 矩阵按键模块接口列表
密码比较模块:
现介绍密码检测模块,其主要功能即比较输入与预设的密码是否一致,
图2 密码检测模块框图
表2 密码检测模块列表
这里先将密码设置为4位十进制数1234,如下所示
parameter PASSWORD = 'b0001_0010_0011_0100;
通过计数矩阵按键按下标志信号,依次将数据暂存到寄存器mima_r中。
always@(posedge Clk or negedge Rst_n) begin
if(!Rst_n)
key_cnt <= 'b0;
else if(key_flag) begin
if(key_cnt == 'd3)
key_cnt <= 'b0;
else
key_cnt <= key_cnt + 'b1;
end
else
key_cnt <= key_cnt;
end always@(posedge Clk or negedge Rst_n) begin
if(!Rst_n)
mima_r <= 'b0;
else if(key_flag)
case(key_cnt)
'd0: mima_r[15:12] <= key_value[3:0];
'd1: mima_r[11:8] <= key_value[3:0];
'd2: mima_r[7:4] <= key_value[3:0];
'd3: mima_r[3:0] <= key_value[3:0];
default: mima_r <= ;
endcase
else
mima_r <= mima_r;
end
这里通过一个独立按键来控制比较信号,用到了按键消抖模块,详细内容可以参考芯航线有关章节。
wire key_startbj_flag;wire key_startbj_state; key_filter key_filter_start(
.Clk(Clk),
.Rst_n(Rst_n),
.key_in(start_bj),
.key_flag(key_startbj_flag),
.key_state(key_startbj_state)
);
当开始比较后,根据实际情况判断后输出正确与否。
always@(posedge Clk or negedge Rst_n)begin
if(!Rst_n) begin
error <= 'b0;
right <= 'b0;
end
else if(key_startbj_flag && !key_startbj_state)begin
if(mima_r == PASSWORD) begin
right <= 'b1;
error <= 'b0;
end
else begin
right <= 'b0;
error <= 'b1;
end
end
else begin
error <= 'b0;
right <= 'b0;
end
end
控制模块:
现在介绍模块的控制单元。本模块主要功能是根据密码检测模块的输出确定,开关门信号以及声光信号。其模块接口列表及功能描述如下所示。
图3 控制模块框图
表3 控制模块接口列表
在这里使用三段式状态机进行描述。
parameter IDLE = 'b001,
PASS = 'b010,
ALARM = 'b100;
第一个always块:
always@(posedge Clk or negedge Rst_n) begin
if(!Rst_n)
current_state <= IDLE;
else
current_state <= next_state;
end
第二个always块:
always@(current_state or error or right or cnt_2s) begin
case(current_state)
IDLE: begin
if(right)
next_state = PASS;
else if(error)
next_state = ALARM;
else
next_state = IDLE;
end
PASS: begin
if(cnt_2s) //door_close
next_state = IDLE;
else
next_state = PASS;
end
ALARM: begin
if(cnt_2s)
next_state = IDLE;
else
next_state = ALARM;
end
default: next_state = IDLE;
endcase
end
第三个always块:
always@(posedge Clk or negedge Rst_n) begin
if(!Rst_n) begin
door_open_r <= 'b0; led_alarm_r <= 1'b0;
led_right_r <= 'b0; beep_En <= 1'b0;
end
else begin
case(next_state)
IDLE: begin
door_open_r <= 'b0; led_alarm_r <= 1'b0;
led_right_r <= 'b0; beep_En <= 1'b0;
end
PASS: begin
if(cnt_2s)begin
door_open_r <= 'b0; led_alarm_r <= 1'b0;
beep_En <= 'b0; led_right_r <= 1'b0;
end
else begin
door_open_r = 'b1;led_right_r = 1'b1;
end
end
ALARM: begin
if(cnt_2s) begin
led_alarm_r = 'b0; beep_En = 1'b0;
end
else begin
led_alarm_r = 'b1; beep_En = 1'b1;
end
end
default: begin
door_open_r <= door_open_r; led_alarm_r <= led_alarm_r;
beep_En <= beep_En;
led_right_r <= led_right_r;
end
endcase
end
end
数码管显示模块:
Hex8为数码管显示模块,其框图以及其接口列表如下所示,具体功能介绍可参见芯航线相关内容。
图4 数码管显示模块框图
表4 数码管显示模块接口列表
顶层设计:
最后在顶层例化各模块即可,分配引脚后全编译无误后即可下载到芯航线开发板中观测到对应现象。
图5 顶层文件RTL Viewer
如有更多问题,欢迎加入芯航线 FPGA 技术支持群交流学习:472607506
小梅哥
芯航线电子工作室
关于学习资料,小梅哥系列所有能够开放的资料和更新(包括视频教程,程序代码,教程文档,工具软件,开发板资料)都会发布在我的云分享。(记得订阅)链接:http://yun.baidu.com/share/home?uk=402885837&view=share#category/type=0
赠送芯航线AC6102型开发板配套资料预览版下载链接:链接:http://pan.baidu.com/s/1slW2Ojj 密码:9fn3
赠送SOPC公开课链接和FPGA进阶视频教程。链接:http://pan.baidu.com/s/1bEzaFW 密码:rsyh