基于FPGA的密码锁设计

题目要求:

密码锁共有12个键,0-9的数字键,*为取消键,#为确定键。
开锁时,需要输入4位正确密码后,按#号键确定,密码锁可以打开,注意这里只要最后按#键前4位正确即可,密码门打开后30秒回到初始态。
如果连续3次输错密码,密码门自动死锁3分钟。
密码门有一个六位超级密码230419,输入后可以用户重置并且设置四位开锁密码,用于设置新的开锁密码时,需要连续输入两次并按#确认,两次必须相同,否则设置失败。
无论是开锁还是设置密码可以按*号来取消。

具体功能:

使用两个状态机实现:
对于"输入密码——判定密码——开锁/死锁"部分功能,划分一个状态机S。

对于"输入超级密码——重设密码"功能,划分一个状态机T。

状态机S共有6个状态:
S0-S3:当前已输入了正确密码的前0/1/2/3位。
S4:已输入正确密码,等待确认。
Open:已开启,开启状态保持两个时钟。
Lock:已死锁,死锁状态保持两个时钟。

状态机T共有22个状态:

T0 - T11:检测12位序列230419230419已经正确输入到哪一位

T11 - T15:输入新密码第1/2/3/4

T16 - T19:重复新密码的第1/2/3/4

T20:等待确认。

OK:重设密码成功。

T0-T11的状态转移为常见的序列检测思路,T11-T15将输入的数字暂存在reg[3:0] newpasswd0/1/2/3中,T16-T19分别检测第二次输入的密码是否与寄存器中的密码相同,如果相同,进入T20等待按下确认键。

以上各状态中,超级密码出错/再次输出密码不一致/按下取消键都会回到T0状态。

T20时按下确认键进入OK状态,将newpasswd中的密码复制到passwd中,并重置连续输错次数wrong_count0

部分代码示例:

/***********************状态机S*************************//
always @(posedge clk or posedge clr)
begin 
if(clr)
begin
present_state_s <= S0;
unlock_ok <= 1'b0;
locking <= 1'b0;
wrong_count <= 0;
end
else
present_state_s <= next_state_s;
end
always @(*)
begin
case(present_state_s)
S0:begin
if(cancel)
next_state_s = S0;
else if(confirm)
begin
next_state_s = S0;
wrong_count = wrong_count + 1;
end
else if(din == passwd0)
next_state_s = S1;
else 
next_state_s = S0;
end
S1:begin
if(cancel)
next_state_s = S0;
else if(confirm)
begin
next_state_s = S0;
wrong_count = wrong_count + 1;
end
else if(din == passwd1)
next_state_s = S2;
else 
next_state_s = S0;
end
 
S2:begin
if(cancel)
next_state_s = S0;
else if(confirm)
begin
next_state_s = S0;
wrong_count = wrong_count + 1;
end
else if(din == passwd2)
next_state_s = S3;
else 
next_state_s = S0;
end
S3:begin
if(cancel)
next_state_s = S0;
else if(confirm)
begin
next_state_s = S0;
wrong_count = wrong_count + 1;
end
else if(din == passwd3)
next_state_s = S4;
else 
next_state_s = S0;
end
S4: begin 
if(confirm)
next_state_s = Open;
else
next_state_s = S0;
end
Open: begin
unlock_ok = 1'b1;
//open_time <= 3;// 设置为3个周期
if(open_time == 3)
begin
unlock_ok = 1'b0;
next_state_s = S0;
end
else
next_state_s = Open;
end	
Lock: begin
locking = 1'b1;
//lock_time <= 3;// 设置为3个周期
if(lock_time == 3)
begin
locking = 1'b0;
next_state_s = S0;
end
else
next_state_s = Lock;
end
default: 
begin
next_state_s = S0;
wrong_count = 0;
unlock_ok = 1'b0;
locking = 1'b0;
open_time = 0;
lock_time = 0;
end
endcase
 
if (wrong_count >= 3)
begin
next_state_s = Lock;
wrong_count = 0;
end//判断错误逻辑
end
// 计时逻辑
always @(posedge clk or posedge clr) 
begin
if(clr)
begin
open_time <= 0;
lock_time <= 0;
end
else 
begin
if(present_state_s == Open && open_time < 3)
open_time <= open_time + 1;
else if(open_time == 3)
open_time <= 0;
if(present_state_s == Lock && lock_time < 3) 
lock_time <= lock_time + 1;
else if(lock_time == 3)
lock_time <= 0;
end
end
//****************************************************************//
//**********************状态机T***********************************//
reg [4:0] present_state_t, next_state_t;// 当前状态,下一状态
parameter  T0 = 5'b00000,T1 = 5'b00001,T2 = 5'b00010,T3 = 5'b00011,T4 = 5'b00100,
T5 = 5'b00101,T6 = 5'b00110,T7 = 5'b00111,T8 = 5'b01000,T9 = 5'b01001,
T10 = 5'b01010,T11 = 5'b01011,T12 = 5'b01100,T13 = 5'b01101,
T14 = 5'b01110,T15 = 5'b01111,T16 = 5'b10000,T17 = 5'b10001,
T18 = 5'b10010,T19 = 5'b10011,T20 = 5'b10100,OK = 5'b10101;
always @(posedge clk or posedge clr) 
begin
if(clr)
begin
reset_ok <= 1'b0;
 present_state_t <= T0;
end
else 
present_state_t <= next_state_t;
end
always @(*)
begin
case(present_state_t)
T0:
begin
reset_ok = 1'b0;
if(cancel) 
next_state_t = T0;
else if(din == superwd0)//2
next_state_t = T1;
else 
next_state_t = T0;
end
T1:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd1)//3
next_state_t = T2;
else 
next_state_t = T0;
end
T2:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd2) //0
next_state_t = T3;
else 
next_state_t = T0;
end
T3:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd3) //4
next_state_t = T4;
else 
next_state_t = T0;
end
T4:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd4) //1
next_state_t = T5;
else 
next_state_t = T0;
end
T5:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd5) //9
next_state_t = T6;
else 
next_state_t = T0;
end
T6:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd0)//2
next_state_t = T7;
else 
next_state_t = T0;
end
T7:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd1)//3
next_state_t = T8;
else 
next_state_t = T0;
end
T8:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd2)//0
next_state_t = T9;
else 
next_state_t = T0;
end
T9:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd3)//4
next_state_t = T10;
else 
next_state_t = T0;
end
T10:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd4)//1
next_state_t = T11;
else 
next_state_t = T0;
end
T11:
begin
if(cancel) 
next_state_t = T0;
else if(din == superwd5)//9
next_state_t = T12;
else 
next_state_t = T0;
end
T12:    //T12~T15将数字暂存在newpasswd中
begin
if(cancel) 
next_state_t = T0;
else 
begin
newpasswd0 = din;
next_state_t = T13;
end
end
T13:
begin
if(cancel) 
next_state_t = T0;
else 
begin
newpasswd1 = din;
next_state_t = T14;
end
end
T14:
begin
if(cancel) 
next_state_t = T0;
else 
begin
newpasswd2 = din;
next_state_t = T15;
end
end

T15:
begin
if(cancel) 
next_state_t = T0;
else 
begin
newpasswd3 = din;
next_state_t = T16;
end
end
T16:   //T16~T19用于检测第二次输入密码与寄存器密码是否相同
begin
if(cancel) 
next_state_t = T0;
else if(din == newpasswd0) 
next_state_t = T17;
else
next_state_t = T0;	 
end
T17:
begin
if(cancel) 
next_state_t = T0;
else if(din == newpasswd1) 
next_state_t = T18;
else
next_state_t = T0; 
end
 
T18:
begin
if(cancel) 
next_state_t = T0;
else if(din == newpasswd2) 
next_state_t = T19;
else
next_state_t = T0;	 
end
T19:
begin
if(cancel) 
next_state_t = T0;
else if(din == newpasswd3) 
next_state_t = T20;
else
next_state_t = T0;
end
 
T20:
begin
if(cancel)
next_state_t = T0;
else if(confirm)
next_state_t = OK;	
else
next_state_t = T20;
end
 
OK:
begin
passwd0 = newpasswd0;
passwd1 = newpasswd1;
passwd2 = newpasswd2;
passwd3 = newpasswd3;
reset_ok = 1'b1;
wrong_count = 0;
next_state_t = T0;
end
// default: 
// begin
// reset_ok = 1'b0; 
// wrong_count = 0;
 // unlock_ok = 1'b0;
 // locking = 1'b0;
// end
endcase 
end
//****************************************************************//
Endmodule

TB文件:

module tb_lock();
reg clk;
reg clr;
reg cancel;          //取消键*
reg [3:0] din;       //数字键
reg confirm;         //确定键#
wire unlock_ok;      // 成功开锁,输出 1
wire reset_ok;       //成功重设密码,输出 1
wire locking;        //输错密码锁定状态 输出 1



initial 
 begin
     clk <= 0;
     confirm <= 0;
     din <= 0;
     cancel <= 0;
     clr <= 1;
#30  clr <= 0;


//依次输入 1 2 3 4 确认 成功开锁
     din <= 1;
#20  din <= 2;
#20  din <= 3;
#20  din <= 4;
#20  din <= 0;
     confirm <= 1;
#20  confirm <= 0;
#20
#20
#20
#20


//依次输入 1 2 3 5 确认 无法
     din <= 1;
#20  din <= 2;
#20  din <= 3;
#20  din <= 5;
#20  din <= 0;

     confirm <= 1;
#20  confirm <= 0;
     din <= 1;
#20  din <= 0;
#20
#20
#20
#20
 

//依次输入 230419 230419 6789 6789 确认
//密码从默认的 1234 修改为 6789


din <= 2; #20
din <= 3; #20
din <= 0; #20
din <= 4; #20
din <= 1; #20
din <= 9; #20

din <= 2; #20
din <= 3; #20
din <= 0; #20
din <= 4; #20
din <= 1; #20
din <= 9; #20

din <= 6; #20
din <= 7; #20
din <= 8; #20
din <= 9; #20

din <= 6; #20
din <= 7; #20
din <= 8; #20
din <= 9; #20
confirm <= 1; #20
confirm <= 0; din <= 0; #20



//连续输入 3 次错误密码:
//1234 # 1234 # 1234 #
 din <= 1; confirm <= 0; #20
 din <= 2; #20
 din <= 3; # 20
 din <= 4; #20
 din <= 0; confirm <= 1; #20
 din <= 1; confirm <= 0; #20
 din <= 2; #20
 din <= 3; #20
 din <= 4; #20
 din <= 0; confirm <= 1; #20
 din <= 1; confirm <= 0; #20
 din <= 2; #20
 din <= 3; #20
 din <= 4; #20
 din <= 0; confirm <= 1; #20
           
//连续输错三次后,进入 lock 状态




#20   din <= 6; confirm <= 0; 
#20   din <= 7; 
#20   din <= 8; 
#20   din <= 9; 
#20   din <= 0; confirm <= 1; 
#20   confirm <= 0; 


#20
#20
#20
#20
      din <= 6; 
#20   din <= 7; 
#20   din <= 8; 
#20   cancel <= 1; din <= 0; 
#20   din <= 9; cancel <= 0; 
#20   din <= 0; confirm <= 1; 
#20   confirm <= 0;

end


always #10 clk = ~clk; //晶振周期 20ns


lock test_lock(
   .clk(clk),
   .clr(clr),
   .din(din),
   .confirm(confirm),
   .cancel(cancel),
   .unlock_ok(unlock_ok),
   .reset_ok(reset_ok),
   .locking(locking)
);
endmodule

运行演示:

end

在电子技术飞速发展的今天,具有防盗报警等功能的电子密码锁代替弹子锁和密码量少,安全性差的机械式密码锁已是必然趋势。随着电子技术的发展,电子密码锁设计也在不断地发展,有传统的PCB板设计、用PLC设计或者用单片机设计等。其中,使用较多的是基于单片机技术的设计。以单片机为主要器件, 其编码器与解码器的生成为软件方式。在实际应用中, 由于程序容易跑飞, 系统的可靠性能较差。而用VHDL可以更加快速、灵活地设计出符合各种要求的密码锁,优于其他设计方法。 本文介绍的是一种基于现场可编程门阵列FPGA 器件的电子密码锁设计方法。本文采用EDA技术,利用Quartus II工作平台和硬件描述语言,设计了一种电子密码锁,并通过一片FPGA芯片实现。 设计充分利用了FPGA的资源可编程特性,可高效率的对系统进行升级与改进.用FPGA 器件构造系统, 所有算法完全由硬件电路来实现, 使得系统的工作可靠性大为提高。由于FPGA具有IsP功能,当设计需要更改时, 只需更改FPGA 中的控制和接口电路, 利用EDA 工具将更新后的设计下载到FPGA 中即可, 无需更改外部电路的设计, 大大提高了设计的效率。 另外,在本文设计的系统中充分考虑了实际生活的需要,加入了键盘防抖、数码显示控制、自动报警的功能使得设计人性化、实用化,真正起到了为现实生化服务的目的。因此,该密码锁具有较高的推广价值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值