按键的硬件设计
正点原子开发板中的按键模块的硬件设计如上图所示,由五个按键,第一个是 FPGA主芯片的复位按键,下面四个是控制按键。按键按下的时候会呈现一个低电平,这样话电路就导通。
按键实现的效果
按键状态 | LED显示效果 |
---|---|
无按键按下 | 四个LED灯全灭 |
按下KEY0 | 自右向左的流水灯 |
按下KEY1 | 自左向右的流水灯 |
按下KEY2 | 四个LED灯同时闪烁 |
按下KEY3 | 四个LED灯全亮 |
系统框图
FPGA的主芯片,输入50Hhz的系统时钟和rst复位信号,然后由四个按键控制LED灯的动作。每隔0.2S就对LED灯状态进行动作,所以需要一个0.2s的计数器和一个状态计数器,然后通过选择LED模式进行控制四个LED灯的每种模式状态。
程序编写
// 按键控制LED包括三个模块:计数器、状态计数器、按键控制LED模块
module key_led(
input clk, //定义系统时钟
input rst_n, //定义复位信号
input [3:0] key, //定义4位的按键信号的寄存器变量
output reg [3:0] led //定义4个LED灯的寄存器类型变量
);
//reg define
reg [23:0] cnt; //定义24位的计数,算出方法:系统频率50Hz,周期为20ns,而计数器为0.2s,得到计数次数为0.2s/20ns=10000000,转换成二进制就是24位
reg [ 1:0] led_ctrl; //led的每个灯的状态控制
//0.2s的计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 24'd0; //复位时计数置零
else
if(cnt < 24'd1000_0000)
cnt <= cnt + 1'b1; //小于0.2s时,计数累加
else
cnt <= 24'd0; //等于0.2s时,计数置零
end
//每隔0.2s改变LED四个灯状态计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
led_ctrl <= 2'd0; //复位按下,led四个等全部熄灭
else
if(cnt == 24'd1000_0000)
led_ctrl <= led_ctrl + 1'b1; //计数等于0.2s时,led四个灯依次状态累加
else
led_ctrl <= led_ctrl; //计数小于0.2s时,led四个灯状态不变
end
//根据按键来改变各个状态下所有点亮的LED
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
led <= 4'b0; //复位按下,四个灯熄灭
else
if(key[0] == 1'b0) //按键0按下,从右向左流水灯
case(led_ctrl) //由四个灯的状态决定
2'd0: led <= 4'b1000; //开发板上的灯的高位是在右边,所以程序里面从右开始置1
2'd1: led <= 4'b0100;
2'd2: led <= 4'b0010;
2'd3: led <= 4'b0001;
endcase
else if(key[1] == 1'b0) //按键1按下,从左向右的流水灯
case(led_ctrl)
2'd0: led <= 4'b0001;
2'd1: led <= 4'b0010;
2'd2: led <= 4'b0100;
2'd3: led <= 4'b1000;
endcase
else if(key[2] == 1'b0) //按键2按下,4个LED灯进行闪烁
case(led_ctrl)
2'd0: led <= 4'b1111;
2'd1: led <= 4'b0000;
2'd2: led <= 4'b1111;
2'd3: led <= 4'b0000;
endcase
else if(key[3] == 1'b0) //按键3按下,全亮
led <= 4'b1111;
else
led <= 4'b0000; //无按键按下时,全灭
end
endmodule