前言
在按键控制蜂鸣器发声章节中我们学习了按键消抖,以及在流水灯章节中学习了控制led的亮灭。本章节将结合前面两章的内容,使用按键控制四个led的状态。
一、按键分类
“自锁”是指开关能通过锁定机构保持某种状态(通或断),“轻触”是说明操作开关使用的力量大小。cyclone IV开发板上的按键属于轻触式按键。
二、实验任务
使用开发板上的四个按键控制四个LED灯。按下不同的按键时,四个LED灯显示不同效果。
三、按键原理图
四、系统框图
四个按键外加时钟和复位信号作为输入,两个计数器模块分别用于0.2s时间的计数和状态的计数。led模式选择模块根据状态计数器的改变,来改变四个led的状态,形成不同的样式。
五、项目代码
module key_led(
input clk ,//时钟50MHz
input rst_n,//复位信号,下降沿有效negtive
input [3:0] key ,//四个按键
output reg [3:0] led //四个led灯
);
parameter TIME = 24'd10_000_000;//0.2S
reg [23:0] cnt ;//计数器0.2S
reg [1:0] state;//记录四个led状态
//0.2s计数器模块
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin//复位
cnt <= 24'd0;//计数器清0
end
else if(cnt == TIME - 1)begin//记满10_000_000,0~9_999_999
cnt <= 24'd0;//计数器清0
end
else begin
cnt <= cnt + 1'd1;//其他情况下计数器加1
end
end
//状态计数模块
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin//复位信号
state <= 2'd0;//状态清0
end
else if(cnt == TIME - 1)begin//记满10_000_000,0~9_999_999 0.2s
state <= state + 2'd1;//状态加1
end
else begin
state <= state;//其他情况状态保持不变
end
end
//状态控制led模块
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin//复位信号
led <= 4'b0000;//led全灭
end
else if(key[0] == 0)begin//右边第1个按键按下,按键低电平0有效
case(state)//判断状态的值
2'd0: led <= 4'b0001;//右边第1个led灯亮
2'd1: led <= 4'b0010;//右边第2个led灯亮
2'd2: led <= 4'b0100;//右边第3个led灯亮
2'd3: led <= 4'b1000;//右边第4个led灯亮
default:;//默认情况不能忘,可以不写,但是要把stat情况考虑完
endcase
end
else if(key[1] == 0)begin//右边第2个按键按下,按键低电平0有效
case(state)//判断状态的值
2'd0: led <= 4'b1000;//左边第1个led灯亮
2'd1: led <= 4'b0100;//左边第2个led灯亮
2'd2: led <= 4'b0010;//左边第3个led灯亮
2'd3: led <= 4'b0001;//左边第4个led灯亮
default:;
endcase
end
else if(key[2] == 0)begin//右边第3个按键按下,按键低电平0有效
case(state)
2'd0: led <= 4'b1111;//全亮
2'd1: led <= 4'b0000;//全灭
2'd2: led <= 4'b1111;//全亮
2'd3: led <= 4'b0000;//全灭
default:;
endcase
end
else if(key[3] == 0)begin//右边第4个按键按下,按键低电平0有效
case(state)
2'd0: led <= 4'b1111;//全亮
2'd1: led <= 4'b1111;//全亮
2'd2: led <= 4'b1111;//全亮
2'd3: led <= 4'b1111;//全亮
default:;
endcase
end
else begin
led <= 4'b0000;//其他情况默认4个led灯全灭
end
end
endmodule
代码部分没有对4个按键进行消抖,最后代码上板后,并没有达到我们想要得效果。按键必须按住不放led才会显示对应的状态。感兴趣的朋友们可以想一想,怎么编写一个消抖模块对4个按键进行消抖。
六、仿真代码
`timescale 1ns/1ns//单位/精度
module key_led_tb();
reg clk ;//时钟信号
reg rst_n;//复位信号
reg [3:0] key ;//按键信号
wire [3:0] led ;//led灯信号
parameter TIME = 10;//间隔时间,由10_000_000变为10,便于仿真观察
parameter CYCLE = 20;//周期20ns
always #(CYCLE/2) clk = ~clk;//每10ns翻转一次,刚好模拟时钟周期50MHz
initial begin
clk = 1'b0;//初始时钟为低电平
rst_n = 1'b0;//复位信号置0,下降沿有效,初始化
#(CYCLE);//时钟20ns
rst_n = 1'b1;//复位信号置1
#(CYCLE * TIME * 4);//4个led灯,4个间隔,所以乘以4
key = 4'b1110;//按下右边第1个按键
#(CYCLE * TIME * 4);
key = 4'b1101;//按下右边第2个按键
#(CYCLE * TIME * 4);
key = 4'b1011;//按下右边第3个按键
#(CYCLE * TIME * 4);
key = 4'b0111;//按下右边第4个按键
#(CYCLE * TIME * 4);
$stop;//停止
end
//实例化模块
key_led #(.TIME (TIME)) u_key_led
(
.clk (clk) ,//时钟50MHz
.rst_n (rst_n),//复位信号,下降沿有效
.key (key) ,//按键信号
.led (led)//led灯
);
endmodule
七、管脚分配
元件 | 管脚 |
---|---|
LED0 | G15 |
LED1 | F16 |
LED2 | F15 |
LED3 | D16 |
KEY0 | E15 |
KEY1 | E16 |
KEY2 | M16 |
KEY3 | M15 |
COLOCK(时钟) | E1 |
八、运行效果
按键控制led灯
总结
以上就是今天要讲的内容,本文结合之前所学内容,使用4个按键控制4个led灯的状态。在按键部分,没有对按键进行消抖,感兴趣的朋友们可以评论区附上你们的按键消抖代码。