最近学了verilog语言,看到有位大佬设计的电子密码锁们就想自己试一试,但是照抄代码出现报错,自己尝试修复了一些小问题,但是还是有报错,自己实在搞不明白,所以来请教一下各位大佬,感谢。平台用的是wmware虚拟机支持win7的ISE。原博主链接:https://www.cnblogs.com/vv123/p/17436195.html#5333441
1.密码锁共有12个键, 0-9的数字键, 为取消键, #为确定键
2.开锁时,需要输入4位正确密码后,按#号键确定,密码锁可以打开,注意这里只要最后按#键前4位正确即可,密码门打开后30秒回到初始态。
3.如果连续3次输错密码,密码门自动死锁3分钟。
4.密码门有一个六位超级密码230419,输入后可以用户重置并且设置四位开锁密码, 用于设置新的开锁密码时,需要连续输入两次并按#确认,两次必须相同。否则设置失败。
5.无论是开锁还是设置密码可以按号来取消。
定义
`timescale 1ns / 1ps
module lock(
input wire clk,
input wire clr,
input wire [3:0] din, //数字键0-9,需要4bit
input wire confirm, //确定键'#'
input wire cancel, //取消键'*'
output reg unlock_ok, //成功开锁状态时,输出1
output reg reset_ok, //重设密码成功时,输出1
output reg locking //输错密码3次进入锁定状态时,输出1
);
//初始密码1234
reg [3:0] passwd0 = 1;
reg [3:0] passwd1 = 2;
reg [3:0] passwd2 = 3;
reg [3:0] passwd3 = 4;
//超级密码230419
reg [3:0] superwd0 = 2;
reg [3:0] superwd1 = 3;
reg [3:0] superwd2 = 0;
reg [3:0] superwd3 = 4;
reg [3:0] superwd4 = 1;
reg [3:0] superwd5 = 9;
//新密码
reg [3:0] newpasswd0 = 0, newpasswd1 = 0, newpasswd2 = 0, newpasswd3 = 0;
//开启状态保持时间
reg [5:0] open_time = 0;
//连续输错密码次数
reg [5:0] wrong_count = 0;
//锁定状态保持时间
reg [5:0] lock_time = 0;
//状态定义
reg[3:0] present_state_s, next_state_s;//当前状态,下一状态
parameter S0 = 3'b0, S1 = 3'b1, S2 = 3'b10, S3 = 3'b11;
parameter S4 = 3'b100; //等待键入确定键'#'
parameter Open = 3'b101; //开启状态
parameter Lock = 3'b110; //输错3次密码,锁定状态
//状态机S
always @(*) begin
case (present_state_s)
S0:
begin
if (din == passwd0) next_state_s <= S1;
else next_state_s <= S0;
if (confirm == 1)
begin
wrong_count <= wrong_count + 1;
if (wrong_count >= 3)
begin
next_state_s <= Lock;
end
else
next_state_s <= S0;
end
if (cancel == 1) next_state_s <= S0;
end
S1:
begin
if (din == passwd1) next_state_s <= S2;
else next_state_s <= S0;
if (confirm == 1)
begin
wrong_count <= wrong_count + 1;
if (wrong_count >= 3)
begin
next_state_s <= Lock;
end
else
next_state_s <= S0;
end
if (cancel == 1) next_state_s <= S0;
end
S2:
begin
if (din == passwd2) next_state_s <= S3;
else next_state_s <= S0;
if (confirm == 1)
begin
wrong_count <= wrong_count + 1;
if (wrong_count >= 3)
begin
next_state_s <= Lock;
end
else
next_state_s <= S0;
end
if (cancel == 1) next_state_s <= S0;
end
S3:
begin
if (din == passwd3) next_state_s <= S4;
else next_state_s <= S0;
if (confirm == 1)
begin
wrong_count <= wrong_count + 1;
if (wrong_count >= 3)
begin
next_state_s <= Lock;
end
else
next_state_s <= S0;
end
if (cancel == 1) next_state_s <= S0;
end
S4:
begin
if (confirm == 1) begin
next_state_s <= Open;
wrong_count <= 0;
end
else
next_state_s <= S0;
end
Open:
begin
if (open_time > 0)
next_state_s <= Open;
else
next_state_s <= S0;
end
Lock:
begin
if (lock_time > 0)
begin
next_state_s <= Lock;
end
else next_state_s <= S0;
end
endcase
end
//状态切换与输出
always @(posedge clk or posedge clr) begin
if (open_time > 0) begin
if (open_time == 1) unlock_ok <= 0;
open_time <= open_time - 1;
end
if (lock_time > 0) begin
if (lock_time == 1) begin
locking <= 0;
wrong_count <= 0;
end
lock_time <= lock_time - 1;
end
if (clr == 1) begin
present_state_s <= S0;
unlock_ok <= 0;
locking <= 0;
end
else
begin
if (present_state_s != Open && next_state_s == Open) begin
unlock_ok <= 1;
open_time <= 3;
end
if (present_state_s != Lock && next_state_s == Lock) begin
locking <= 1;
lock_time <= 3;
end
present_state_s <= next_state_s;
end
end
reg[5:0] present_state_t, next_state_t;
parameter T0 = 5'b0, T1 = 5'b1, T2 = 5'b10, T3 = 5'b11, T4 = 5'b100, T5 = 5'b101,
T6 = 5'b110, T7 = 5'b111, T8 = 5'b1000, T9 = 5'b1001, T10 = 5'b1010, T11 = 5'b1011,
T12 = 5'b1100, T13 = 5'b1101, T14 = 5'b1110, T15 = 5'b1111,
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 == 1)
present_state_t <= T0;
else
present_state_t <= next_state_t;
end
//状态机T
always @(*) begin
case (present_state_t)
T0: if (din == superwd0) next_state_t <= T1;
else next_state_t <= T0;
T1: if (din == superwd1) next_state_t <= T2;
else next_state_t <= T0;
T2: if (din == superwd2) next_state_t <= T3;
else next_state_t <= T0;
T3: if (din == superwd3) next_state_t <= T4;
else next_state_t <= T0;
T4: if (din == superwd4) next_state_t <= T5;
else next_state_t <= T0;
T5: if (din == superwd5) next_state_t <= T6;
else next_state_t <= T0;
T6: if (din == superwd0) next_state_t <= T7;
else next_state_t <= T0;
T7: if (din == superwd1) next_state_t <= T8;
else next_state_t <= T0;
T8: if (din == superwd2) next_state_t <= T9;
else next_state_t <= T0;
T9: if (din == superwd3) next_state_t <= T10;
else next_state_t <= T0;
T10: if (din == superwd4) next_state_t <= T11;
else next_state_t <= T0;
T11: if (din == superwd5) next_state_t <= T12;
else next_state_t <= T0;
T12:
begin
newpasswd0 <= din; next_state_t <= T13;
end
T13:
begin
newpasswd1 <= din; next_state_t <= T14;
end
T14:
begin
newpasswd2 <= din; next_state_t <= T15;
end
T15:
begin
newpasswd3 <= din; next_state_t <= T16;
end
T16:
if (din == newpasswd0) next_state_t <= T17;
else next_state_t <= T0;
T17:
if (din == newpasswd1) next_state_t <= T18;
else next_state_t <= T0;
T18:
if (din == newpasswd2) next_state_t <= T19;
else next_state_t <= T0;
T19:
if (din == newpasswd3) next_state_t <= T20;
else next_state_t <= T0;
T20:
if (confirm == 1) begin
next_state_t <= OK;
end
else next_state_t <= T0;
OK:
begin
passwd0 <= newpasswd0;
passwd1 <= newpasswd1;
passwd2 <= newpasswd2;
passwd3 <= newpasswd3;
next_state_t <= T0;
wrong_count <= 0;//重设密码后,重新计算连续输错的次数
end
default: next_state_t <= T0;
endcase
if (cancel == 1) next_state_t <= T0;
end
always @(posedge clk or posedge clr) begin
if (clr == 1) reset_ok <= 0;
else
if (present_state_t == OK)
reset_ok <= 1;
else
reset_ok <= 0;
end
endmodule
报错的话是:ERROR:Xst:899 - "lock.v" line 172: The logic for <wrong_count> does not match a known FF or Latch template. The description style you are using to describe a register or latch is not supported in the current software release.
报错中的第172行是状态切换与输出部分的:wrong_count <= 0;也就是下面if判断中的这句。
if (lock_time > 0) begin
if (lock_time == 1) begin
locking <= 0;
wrong_count <= 0;
end
lock_time <= lock_time - 1;
end