📄 passed_lock.v
字号:
module passed_lock(
clk,
resetb,
cmd,
alarmed,
passed,
password,
main_state,
try_count
);
input clk; //输入时钟信号
input resetb; //输入复位信号
input [4:0] cmd; //输入命令信号0
output alarmed; //输出警报信号led
output passed; //输出通过信号led
output [2:0] main_state;//lcd
output [1:0] try_count;
output [15:0] password;
wire clk;
wire resetb;
wire [4:0] cmd;
reg alarmed;
reg passed;
//输入与输出的声明部分,其中,clk为输入的时钟信号,resetb为密码舒服的输入信号,cmd为输入命令,需注意的时,cmd并不是总在表示密码,也表示密码的间隔,如当输入4位密码后需要一个确认“enter”信号,当密码输入错误时,需要取消“cancel”信号,这些信号之间在设计中通过有限状态转换机实现。
parameter PASSWORD=16'd1234;//盛放密码的参数
reg [15:0] password;//输入数值盛放寄存器
//输入的数字编码 0~9,enter,cancel
reg one=5'b10001,
two=5'b10010,
three=5'b10011,
four=5'b10100,
five=5'b10101,
six=5'b10110,
seven=5'b10111,
eight=5'b11000,
nine=5'b11001,
zero=5'b10000,
enter=5'b11010,
cancel=5'b11011;
reg cmd_t;//检验是否有按键按下
reg [2:0] main_state;//主状态
reg [2:0] next_state;//下一个状态
//主有限状态转换机的三个状态:waits、pass、alarm
parameter waits=3'b001,
pass=3'b010,
alarm=3'b100;
reg [2:0] sub_state;
reg [2:0] next_sub_state;
//主有限状态转换机的三个状态:first、second、third、fourth、finish。
parameter first=3'b000,
second=3'b001,
third=3'b010,
fourth=3'b011,
finish=3'b100;
//通过计时寄存器
reg [7:0] pass_count;
//警报计时寄存器
reg [10:0] alarm_count;
//尝试次数寄存器
reg [1:0] try_count;
//输入状态寄存器:error和correct
reg error;
reg correct;
//以上为中间状态的一些寄存器和一些所用到的参数
//主机状态机部分
always@(main_state or correct or error)
begin
case(main_state)
waits:
if(correct==1) //由waits转换到pass的条件
next_state=pass;
else if(error==1&&try_count==2)
next_state=alarm; //由waits转换到alarm的条件
else
next_state=waits;
pass:
if(pass_count[7]==1)//由pass转换到waits的条件
next_state=waits;
else
next_state=pass;
alarm:
if(alarm_count[10]==1)// 由alarm转换到waits的条件
next_state=waits;
else
next_state=alarm;
default://默认状态:waits
next_state=waits;
endcase
end
//状态转换
always@(posedge clk or negedge resetb)
begin
if(!resetb)
main_state<=waits;
else
main_state<=next_state;
end
//输出控制部分
always@(posedge clk or negedge resetb)
begin
if(!resetb)//复位时,开锁输出与警报输出都为零
begin
passed<=0;
alarmed<=0;
end
else if(main_state==pass)//当主机状态为pass时,开锁
begin
passed<=1;
alarmed<=0;
end
else if(main_state==alarm)//当主机状态为alarm时,警报
begin
passed<=0;
alarmed<=1;
end
else//其它状态复位
begin
passed<=0;
alarmed<=0;
end
end
//alarm一段时间后,自动进入waits状态
//alarm定时器
always@(posedge clk or negedge resetb)
begin
if(!resetb)
alarm_count<=0;
else if(main_state==alarm)//alarm状态计时器alarm定时器加1
alarm_count<=alarm_count+1;
else
alarm_count<=0;
end
//锁pass以后计数开始,当规定的时间到达后自动上锁,并进入waits状态
//pass定时器
always@(posedge clk or negedge resetb)
begin
if(!resetb)
pass_count<=0;
else if(main_state==pass) //pass状态计时器pass定时器加1
pass_count<=pass_count+1;
else
pass_count<=0;
end
//从状态机,用于输入4位密码
always@(posedge clk or negedge resetb)
begin
if(!resetb)
cmd_t<=0;
else
cmd_t<=-cmd[4];
end
always@(posedge clk or negedge resetb)
begin
if(!resetb)
sub_state<=first;
else
sub_state<=next_sub_state;
end
always@(cmd or cmd_t or sub_state)
//always@(cmd or sub_state)
begin
if(cmd_t==0&&cmd[4]==1)
case(cmd)
cancel://密码输入错误时,重复上一个状态
begin
if(sub_state==first)// 第1个密码输入错误
next_sub_state=first;
else
case(sub_state)
second: // 第2个密码输入错误
next_sub_state=first;
third: // 第3个密码输入错误
next_sub_state=second;
fourth: // 第4个密码输入错误
next_sub_state=third;
finish:
next_sub_state=fourth;
endcase
end
enter://4个密码输完时,进行确认
next_sub_state=first;
//以下4个命令位无效的命令,状态保持不变
5'b11100:
next_sub_state=next_sub_state;
5'b11101:
next_sub_state=next_sub_state;
5'b11110:
next_sub_state=next_sub_state;
5'b11111:
next_sub_state=next_sub_state;
//default为输入了某位密码,输入完自动将状态转入下一位
default:
case(sub_state)
first:
next_sub_state=second;
second:
next_sub_state=third;
third:
next_sub_state=fourth;
fourth:
next_sub_state=finish;
//当输入完4位密码以后状态保持不变,等待输入enter命
//令
finish:
next_sub_state=finish;
endcase
endcase
else
next_sub_state=sub_state;
end
//比较密码,产生正确或者错误信息
always@(posedge clk or negedge resetb)
begin
if(!resetb)
begin
correct<=0;
error<=0;
end
else if(cmd_t ==0&&cmd==enter)
if(password==PASSWORD)//密码正确时
begin
correct<=1;
error<=0;
end
else//密码错误时
begin
error<=1;
correct<=0;
end
else
begin
correct<=0;
error<=0;
end
end
//记录密码
always@(posedge clk or negedge resetb)
begin
if(!resetb)
password<=0;
else if(cmd_t==0&&cmd[4]==1)
case(sub_state)
first:
password[15:12]<=cmd[3:0];
second:
password[11:8]<=cmd[3:0];
third:
password[7:4]<=cmd[3:0];
fourth:
password[3:0]<=cmd[3:0];
default:
password<=password;
endcase
else
password<=password;
end
//记录错误次数
always@(posedge clk or negedge resetb)
begin
if(!resetb)
try_count<=0;
else if(error==1)
try_count<=try_count+1;
else if(main_state==pass||main_state==alarm)
try_count<=0;
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -