上节介绍了按键防抖电路的实现。
这节用上节用按键去抖模块来控制LED等亮灭。
利用按键控制fpga开发板上的LED等亮灭,要求每按一次就会LED灯就会跳转到下一个LED亮。正常情况下:使用用按键控制LED亮
一、不使用按键去抖模块:
- verilog代码实现:
//led direct connect to key-led 不使用按键去抖模块,按键每次按下时,LED灯亮移位。
module led (key_i,rst_n_i,led_o);
input key_i,rst_n_i;
output reg [3:0] led_o;
always@(negedge key_i or negedge rst_n_i)
begin
if (! rst_n_i)
led_o <= 4'b0001;
else if (led_o == 4'b1000)
led_o <= 4'b0001;
else
led_o <= (led_o << 1);
end
endmodule
- RTL功能仿真结果:可以看到,由于按键key_i的抖动,led的状态不确定。
- 当我们将此程序下载到板子时,观看现象,可以看到,当按键key按下时,LED灯不是按照我们想要的加一效果显示,而是按一次,出现多次LED闪烁的情况,原因在于按键按下时,信号没有没被滤波,从而检测到很多按键下降沿,期间,LED灯亮最终停留位置不确定。
- 需要注意的地方是,上板调试的情况下,在不使用时钟模块的情况下的管脚约束文件中,在默认情况下,需要添加:
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets XXX]
如果利用按键代替时钟边沿的效果:
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets <name>]
否则会遇到不能正常编译通过的情况。
一、使用按键去抖模块,连接起来:
- key按键防抖模块与led模块连接在一起,创建一个顶层文件:
//top module 顶层模块,将上面两个子模块连接起来。
module key_filter_top(
key_i,rst_n_i,led_o,clk_i,
);
input key_i,rst_n_i,clk_i;
output [3:0] led_o;
wire key_state1;
led u_led( //led模块
.key_i(key_state1),
.rst_n_i(rst_n_i),
.led_o(led_o)
);
key u_key( //按键去抖模块。
.clk_i(clk_i),
.rst_n_i(rst_n_i),
.key_i(key_i),
.key_state(key_state1)
);
endmodule
测试模块:
module key_test(
);
reg clk_i, rst_n_i,key_i;
//wire key_state;
wire [3:0] led_o;
//instance
key_filter_top u3(
.clk_i(clk_i),
.key_i(key_i),
.rst_n_i(rst_n_i),
.led_o(led_o)
);
initial
begin
clk_i = 1;
rst_n_i = 0;
key_i = 1;
#100
rst_n_i =1;
#20
key_i=0;
repeat(10)
begin
#100 key_i= ~key_i;
end
#5000
key_i=1;
repeat(10)
begin
#100 key_i= ~key_i;
end
#5000
key_i=0;
repeat(10)
begin
#100 key_i= ~key_i;
end
end
always begin
#0.001 clk_i = ~ clk_i;
end
endmodule
- 仿真结果:
可以看到每当按键按下时,经过20ms的延时后,led灯才会跳转。 - 上板调试:(具体过程可以参考之前我写的博文:) 用Vivado 经过综合、编译、生成bit流文件
开发板供电,连接好下载器等,打开vivado的硬件管理,然后把bit流文件下载至fpga中
可以观察到,当我们按键一次时,led灯跳转一次,不会出现多次跳转。