完整版verilog实验之密码箱实验报告.docx
- 文档编号:27566772
- 上传时间:2023-07-02
- 格式:DOCX
- 页数:19
- 大小:641.93KB
完整版verilog实验之密码箱实验报告.docx
《完整版verilog实验之密码箱实验报告.docx》由会员分享,可在线阅读,更多相关《完整版verilog实验之密码箱实验报告.docx(19页珍藏版)》请在冰豆网上搜索。
完整版verilog实验之密码箱实验报告
Verilog实现密码箱
1.功能概述
小脚丫开发板的有4位拨码开关,可以表示数字0-9,有两个七段数码管,所以密码设为两位(00—99),初始密码00,利用四位拨码开关(sw)输入密码,,按下个位确认按键(low),在数码管上显示个位数字;再次输入密码,按下十位确认按键(high),在数码管上显示十位数字。
按下确认按键(enter),比较密码正误,若正确,实现开锁功能,用led8灯亮表示;错误,实现报错功能,用led1灯亮表示;连续错三次,实现警报功能,用8个灯全亮表示,此时只有重置(rst)才能重新输入密码。
初始密码为21。
为保证安全性,只有在开锁状态下,才可修改密码,修改拨码开关数值,按下个位确认按键(low),设置新密码个位,再次修改拨码开关数值,按下个位确认按键(high),设置新密码十位(实际上两个位密码修改与输入顺序不影响)。
再按下重置键(rst),即可重新输入密码。
同时在使用按键时,注意到了消抖。
2.效果展示
密码错误
密码正确
修改后密码正确
视频展示(双击播放)
3.代码分析
一、密码显示在数码管上
always@(*)
//数码管显示控制模块
begin
case(code_low)
4'd0:
seg_led1=9'b000111111;//数码管1显示0
4'd1:
seg_led1=9'b000000110;//1
4'd2:
seg_led1=9'b001011011;//2
4'd3:
seg_led1=9'b001001111;//3
4'd4:
seg_led1=9'b001100110;//4
4'd5:
seg_led1=9'b001101101;//5
4'd6:
seg_led1=9'b001111101;//6
4'd7:
seg_led1=9'b000000111;//7
4'd8:
seg_led1=9'b001111111;//8
4'd9:
seg_led1=9'b001101111;//9
default:
seg_led1=9'b100111111;//0
endcase
case(code_high)
4'd0:
seg_led2=9'b000111111;//数码管2显示0
4'd1:
seg_led2=9'b000000110;//1
4'd2:
seg_led2=9'b001011011;//2
4'd3:
seg_led2=9'b001001111;//3
4'd4:
seg_led2=9'b001100110;//4
4'd5:
seg_led2=9'b001101101;//5
4'd6:
seg_led2=9'b001111101;//6
4'd7:
seg_led2=9'b000000111;//7
4'd8:
seg_led2=9'b001111111;//8
4'd9:
seg_led2=9'b001101111;//9
default:
seg_led2=9'b100111111;//0
endcase
end
二、密码比对判断
always@(posedgeclk)//密码判断
begin
if(!
rst)
begin
wrong_cnt<=2'b00;//初始错误次数为0
code_low<=4'b0000;
code_high<=4'b0000;
led<=8'b11111111;
end
elseif(low_d)
begin
code_low<=sw;
end
elseif(high_d)
begin
code_high<=sw;
end
elseif(enter_d)
begin
if(wrong_cnt!
=2'd2)
begin
if((code_low==Y&&code_high==X)||(code_low==newcode_low&&code_high==newcode_high))
begin
led<=8'b01111111;//密码正确,led8亮
wrong_cnt<=2'd0;
end
else
begin
led<=8'b11111110;//密码错误,led1亮错误次数加一
wrong_cnt<=wrong_cnt+1;
end
end
else
led<=8'b00000000;//密码输错三次,报警
end
end
三、密码修改实现
//修改控制模块
always@(posedgeclk)
begin
if(!
rst)
change<=0;
elseif(led<=8'b01111111)
change<=1;
if(change==1&&high_d)
begin
newcode_high<=sw;
end
elseif(change==1&&low_d)
begin
newcode_low<=sw;
end
end
endmodule
四、按键消抖实现
//按键消抖模块
moduledebounce(clk,rst,key,key_pulse);
parameterN=2;//要消除的按键的数量
inputclk;
inputrst;
input[N-1:
0]key;//输入的按键
output[N-1:
0]key_pulse;//按键动作产生的脉冲
reg[N-1:
0]key_rst_pre;//定义一个寄存器型变量存储上一个触发时的按键值
reg[N-1:
0]key_rst;//定义一个寄存器变量储存储当前时刻触发的按键值
wire[N-1:
0]key_edge;//检测到按键由高到低变化是产生一个高脉冲
//利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中
always@(posedgeclkornegedgerst)
begin
if(!
rst)
begin
key_rst<={N{1'b1}};//初始化时给key_rst赋值全为1,{}中表示N个1
key_rst_pre<={N{1'b1}};
end
else
begin
key_rst<=key;//第一个时钟上升沿触发之后key的值赋给key_rst,同时key_rst的值赋给key_rst_pre
key_rst_pre<=key_rst;//非阻塞赋值。
相当于经过两个时钟触发,key_rst存储的是当前时刻key的值,key_rst_pre存储的是前一个时钟的key的值
end
end
assignkey_edge=key_rst_pre&(~key_rst);//脉冲边沿检测。
当key检测到下降沿时,key_edge产生一个时钟周期的高电平
reg[17:
0]cnt;//产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器
//产生20ms延时,当检测到key_edge有效是计数器清零开始计数
always@(posedgeclkornegedgerst)
begin
if(!
rst)
cnt<=18'h0;
elseif(key_edge)
cnt<=18'h0;
else
cnt<=cnt+1'h1;
end
reg[N-1:
0]key_sec_pre;//延时后检测电平寄存器变量
reg[N-1:
0]key_sec;
//延时后检测key,如果按键状态变低产生一个时钟的高脉冲。
如果按键状态是高的话说明按键无效
always@(posedgeclkornegedgerst)
begin
if(!
rst)
key_sec<={N{1'b1}};
elseif(cnt==18'h3ffff)
key_sec<=key;
end
always@(posedgeclkornegedgerst)
begin
if(!
rst)
key_sec_pre<={N{1'b1}};
else
key_sec_pre<=key_sec;
end
assignkey_pulse=key_sec_pre&(~key_sec);
endmodule
4.附录,源码图以及源码
//顶层模块
modulesafebox_plus(
inputclk,
input[3:
0]sw,//四位拨码开关,用作十进制密码
inputrst,//复位键
inputenter,//密码确认键
inputhigh,//十位输入键
inputlow,//个位输入键
outputreg[7:
0]led,//八位报警灯,led8为正确提示灯,led1为错误提示灯
outputreg[8:
0]seg_led1,//数码管1显示个位密码
outputreg[8:
0]seg_led2//数码管2显示十位密码
);
parameterX=4'd0;//用作初始密码
parameterY=4'd0;
wireenter_d;//key[3]确认密码输入
wirelow_d;//key[1]个位确认
wirehigh_d;//key[2]十位确认
reg[1:
0]wrong_cnt;//统计错误次数
reg[3:
0]code_low;//个位密码
reg[3:
0]code_high;//十位密码
regchange;//可修改密码状态
reg[3:
0]newcode_low;//更新密码个位
reg[3:
0]newcode_high;//更新密码十位
//例化调用消抖模块
debounce#(.N(3))u1
(
.clk(clk),
.rst(rst),
.key({enter,low,high}),
.key_pulse({enter_d,low_d,high_d})
);
always@(*)
//数码管显示控制模块
begin
case(code_low)
4'd0:
seg_led1=9'b000111111;//数码管1显示0
4'd1:
seg_led1=9'b000000110;//1
4'd2:
seg_led1=9'b001011011;//2
4'd3:
seg_led1=9'b001001111;//3
4'd4:
seg_led1=9'b001100110;//4
4'd5:
seg_led1=9'b001101101;//5
4'd6:
seg_led1=9'b001111101;//6
4'd7:
seg_led1=9'b000000111;//7
4'd8:
seg_led1=9'b001111111;//8
4'd9:
seg_led1=9'b001101111;//9
default:
seg_led1=9'b100111111;//0
endcase
case(code_high)
4'd0:
seg_led2=9'b000111111;//数码管2显示0
4'd1:
seg_led2=9'b000000110;//1
4'd2:
seg_led2=9'b001011011;//2
4'd3:
seg_led2=9'b001001111;//3
4'd4:
seg_led2=9'b001100110;//4
4'd5:
seg_led2=9'b001101101;//5
4'd6:
seg_led2=9'b001111101;//6
4'd7:
seg_led2=9'b000000111;//7
4'd8:
seg_led2=9'b001111111;//8
4'd9:
seg_led2=9'b001101111;//9
default:
seg_led2=9'b100111111;//0
endcase
end
always@(posedgeclk)//密码判断
begin
if(!
rst)
begin
wrong_cnt<=2'b00;//初始错误次数为0
code_low<=4'b0000;
code_high<=4'b0000;
led<=8'b11111111;
end
elseif(low_d)
begin
code_low<=sw;
end
elseif(high_d)
begin
code_high<=sw;
end
elseif(enter_d)
begin
if(wrong_cnt!
=2'd2)
begin
if((code_low==Y&&code_high==X)||(code_low==newcode_low&&code_high==newcode_high))
begin
led<=8'b01111111;
wrong_cnt<=2'd0;
end
else
begin
led<=8'b11111110;
wrong_cnt<=wrong_cnt+1;
end
end
else
led<=8'b00000000;
end
end
//修改控制模块
always@(posedgeclk)
begin
if(!
rst)
change<=0;
elseif(led<=8'b01111111)
change<=1;
if(change==1&&high_d)
begin
newcode_high<=sw;
end
elseif(change==1&&low_d)
begin
newcode_low<=sw;
end
end
endmodule
//按键消抖模块
moduledebounce(clk,rst,key,key_pulse);
parameterN=2;//要消除的按键的数量
inputclk;
inputrst;
input[N-1:
0]key;//输入的按键
output[N-1:
0]key_pulse;//按键动作产生的脉冲
reg[N-1:
0]key_rst_pre;//定义一个寄存器型变量存储上一个触发时的按键值
reg[N-1:
0]key_rst;//定义一个寄存器变量储存储当前时刻触发的按键值
wire[N-1:
0]key_edge;//检测到按键由高到低变化是产生一个高脉冲
//利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中
always@(posedgeclkornegedgerst)
begin
if(!
rst)
begin
key_rst<={N{1'b1}};//初始化时给key_rst赋值全为1,{}中表示N个1
key_rst_pre<={N{1'b1}};
end
else
begin
key_rst<=key;//第一个时钟上升沿触发之后key的值赋给key_rst,同时key_rst的值赋给key_rst_pre
key_rst_pre<=key_rst;//非阻塞赋值。
相当于经过两个时钟触发,key_rst存储的是当前时刻key的值,key_rst_pre存储的是前一个时钟的key的值
end
end
assignkey_edge=key_rst_pre&(~key_rst);//脉冲边沿检测。
当key检测到下降沿时,key_edge产生一个时钟周期的高电平
reg[17:
0]cnt;//产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器
//产生20ms延时,当检测到key_edge有效是计数器清零开始计数
always@(posedgeclkornegedgerst)
begin
if(!
rst)
cnt<=18'h0;
elseif(key_edge)
cnt<=18'h0;
else
cnt<=cnt+1'h1;
end
reg[N-1:
0]key_sec_pre;//延时后检测电平寄存器变量
reg[N-1:
0]key_sec;
//延时后检测key,如果按键状态变低产生一个时钟的高脉冲。
如果按键状态是高的话说明按键无效
always@(posedgeclkornegedgerst)
begin
if(!
rst)
key_sec<={N{1'b1}};
elseif(cnt==18'h3ffff)
key_sec<=key;
end
always@(posedgeclkornegedgerst)
begin
if(!
rst)
key_sec_pre<={N{1'b1}};
else
key_sec_pre<=key_sec;
end
assignkey_pulse=key_sec_pre&(~key_sec);
endmodule
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 完整版 verilog 实验 密码箱 报告