前言
这是在我们大二上开始上课后的3个星期后布置的作业,在此期间,数电老师提醒我们要珍惜时间,自学verilog语法书,但我偷懒,结果到写这次作业时寸步难行,边学边写,写完了发现代码很不规范:没有封装文件,写法近似C++。还请各位珍惜开学那段相对清闲的时间,抓紧时间学习
一、题目
二、密码箱(用小脚丫实现)
1.功能说明
A. 上锁状态:仅蓝灯E14亮
a. J14,J11按键控制两位数密码输入,按一下其中一个按键,对应的变量和数码管显示数字+1(9+1=0)
b. 按一下K14按键,两位数密码输入复位归零
c. 按一下J9按键提交密码
B. 锁死状态:蓝E14和红灯G15亮度叠加
a. 按一下J9按键提交密码,若输入错误,则两位数密码输入复位归零
b. 若错误次数达3次,蓝E14和红灯G15亮度叠加,密码箱锁死1分钟,在此期间不能输入密码(按键J14,J11,K14,J9都不起作用)
C. 解锁状态:绿灯C14亮,蓝灯E14灭
a. 按一下J9按键提交密码,若输入正确,绿灯C14亮,蓝灯E14灭
b. 绿灯C14亮时,打开开关H13,则绿灯C14和蓝灯D12亮度叠加,可以修改密码
c. 绿灯C14亮时,关闭开关H13,蓝灯D12熄灭,密码固定
d. 绿灯C14亮且开关H13关闭时按下按键J9,绿灯C14灭,蓝灯E14亮,保险箱重新进入上锁状态
2.管脚分配
3.密码箱代码
module mimax (clk,rst,key,sw4,led2,led1,led3,led4,seg_led_1, seg_led_2,); input clk; // J5 时钟 input rst; //K14 复位按键 input [2:0] key; //J14,J11按键控制密码输入,J9按键提交密码 input sw4; //H13 开关控制密码修改 output reg [8:0] seg_led_1, seg_led_2; //两个数码管显示输入的数字 output reg led1,led2,led3,led4; //蓝E14,绿灯C14,蓝灯D12,红灯G15,共阳极彩色led //用一个时钟周期计算得period n=60*12*10^6--->十进制转二进制 parameter period=30'b101010111010100101010000000000; //计数器从0增加到period,密码箱锁死一分钟 reg [29:0] cnt; //计数器 wire [2:0] key_pulse; reg [3:0] a,b,a0,b0,i; reg [8:0] seg [9:0]; //定义了一个reg型的数组变量,相当于一个10*9的存储器,存储器一共有10个数,每个数有9位宽 //两位共阴极数码管 initial begin i=0; cnt=0; //初始输入:00 a=0; b=0; //初始密码:34 a0=3; b0=4; led1=0; //密码箱未解锁时蓝灯E14亮 led2=1; //密码箱未解锁时绿灯C14灭 led3=1; //密码箱未解锁或sw4开关关闭时,蓝灯D12灭 led4=1; //密码箱因为3次输入错误,锁定时用的红灯G15 //将seg赋值给seg_led_1,seg_led_2,在数码管上显示输入数字 seg[0] = 9'h3f; //对存储器中第一个数赋值9'b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字 0 seg[1] = 9'h06; //7段显示数字 1 seg[2] = 9'h5b; //7段显示数字 2 seg[3] = 9'h4f; //7段显示数字 3 seg[4] = 9'h66; //7段显示数字 4 seg[5] = 9'h6d; //7段显示数字 5 seg[6] = 9'h7d; //7段显示数字 6 seg[7] = 9'h07; //7段显示数字 7 seg[8] = 9'h7f; //7段显示数字 8 seg[9] = 9'h6f; //7段显示数字 9 seg_led_1=seg[0]; //刚通电时,两位数码管都显示0 seg_led_2=seg[0]; end //控制第一位输入密码 key[0]-a-a0 always @(posedge clk ) begin if(i==3) //当错误次数达到3次,保险箱将锁死1分钟,在此期间不能输入密码 begin led4=0; //锁死期间,蓝E14和红灯G15亮 cnt=cnt+1'b1; //当锁死时间达到一分钟,密码箱解锁,可以输入密码 if(cnt>period) begin cnt=0; //计数器和错误次数清零 i=0; led4=1;//红灯G15熄灭 end end //绿灯C14,红灯G15不亮时,按下J9按键提交密码,若密码错误 else if(key_pulse[2] && led2 && !(a==a0 && b==b0) && led4) begin i<=i+1; //错误次数+1 seg_led_1 <= seg[0]; //输入复位 a<=0; end else if (!rst && led4) begin seg_led_1 <= seg[0]; a<=0; end else if (key_pulse[0] && led4) //显示数字和实际输入一致 begin a<=(a+1)%10; seg_led_1 <= seg[(a+1)%10]; end else seg_led_1 <=seg_led_1; end //控制第二位输入密码 key[1]-b-b0 always @(posedge clk ) begin if(key_pulse[2] && led2 && !(a==a0 && b==b0) && led4 ) begin seg_led_2 <= seg[0]; //输入错误,第二个数字复位 b<=0; end else if (!rst && led4) begin seg_led_2 <= seg[0]; b<=0; end else if (key_pulse[1] && led4) begin b<=(b+1)%10; seg_led_2<= seg[(b+1)%10]; end else seg_led_2 <=seg_led_2; end //输入密码正确,密码箱解锁,之后可重新上锁,或者修改密码 always @ (posedge clk ) begin if(key_pulse[2] && a==a0 && b==b0 && led2 ) //绿灯C14不亮,密码输入正确后按下按键J9,绿灯C14亮,蓝灯E14灭 begin led2=0; led1=1; end else if(!led2 && sw4 ) //绿灯C14亮时,打开sw4,绿灯C14和蓝灯D12亮度叠加,可以修改密码; begin led3=0; if(!rst) begin a0<=0; b0<=0; end else if (key_pulse[0]) a0<=(a+1)%10; else if (key_pulse[1]) b0<=(b+1)%10; else begin a0<=a0; b0<=b0; end end else if(!led2 && !sw4 ) //绿灯C14亮时,关闭sw4,蓝灯D12熄灭,密码固定,回到刚解锁的状态 begin led3=1; if(!led2 && key_pulse[2] ) //绿灯C14亮且sw4关闭时按下按键J9,绿灯C14灭,蓝灯E14亮,保险箱重新上锁 begin led2=1; led1=0; end end else begin led2=led2; led1=led1; end end //例化消抖module,这里没有传递参数N,采用了默认的N=3 debounce u1 ( .clk (clk), .rst (rst), .key (key), .key_pulse (key_pulse) ); endmodule
4.按键消抖模块
参考altera_7deb [小脚丫STEP开源社区] (stepfpga.com)
设置其中的N来改变消抖按键的个数
5.总结
学号数电,风光无限!