基于Roebi EDA实现I2C通讯之(二)按键控制数据读/写(key_filter)

一、前置分析

我们使用按键控制数据读/写,首先需要编写按键模块,由于按键的物理特性,按下会发生抖动,需要软件消抖。常用软件方法去抖,即检测出按键闭合后执行一个延时程序,根据抖动的时间为5ms~10ms,我们产生一个20ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。

基于Roebi EDA实现I2C通讯之(二)按键控制数据读/写(key_filter)_第1张图片

当有20ms的时间内都没有抖动就说明按键已经处于稳定状态了。

接下来我们定义一个计数器cnt_20ms,用于计数20ms。假如输入时钟信号为50Mhz,计数器只需计数到999_999,就计数了20ms。reg [19:0]cnt_20ms

基于Roebi EDA实现I2C通讯之(二)按键控制数据读/写(key_filter)_第2张图片

①只要在时钟上升沿检测到key_in为高电平,则计数值清零

②在稳定态,使得cnt_20ms计数到999_999,停止计数,发现cnt_20ms计数器计数到999_998的次数只有一个,而且最接近999_999,在既保证去抖动时间的前提下使key_flag信号只产生一个脉冲信号

二、Robei EDA代码编写

        基于Roebi EDA实现I2C通讯之(二)按键控制数据读/写(key_filter)_第3张图片

key_filter.v

reg [19:0]cnt_20ms;

always@(posedge clk or negedge reset)
if(reset == 0)
  cnt_20ms <= 0;
else if(key_in == 1)
  cnt_20ms <= 1;
else begin
  if(cnt_20ms < 999_999)
		cnt_20ms <= cnt_20ms + 1;
  else
  cnt_20ms <= 999_999;
end

always@(posedge clk or negedge reset)
if(reset == 0)
  key_flag <=0;
else if(cnt_20ms == 999_998)
  key_flag <= 1;
else
  key_flag <= 0;

tb.v

initial clk = 1;
always#10 clk = ~clk;
initial begin 
reset = 0;
#20;
reset = 1;
key_in = 1;
#25;
key_in = 0;
#25;
key_in = 1;
#25;
key_in = 0;
#25;
#25;
#21000_000;
key_in = 1;
#25;
key_in = 0;
#10;
key_in = 1;
#25;
key_in = 0;
#25;
key_in = 1;
#25;
key_in = 0;
#25;
#25;
#200_000;
$finish;
end

Robei EDA仿真结果

基于Roebi EDA实现I2C通讯之(二)按键控制数据读/写(key_filter)_第4张图片

仿真验证无误

三、引脚约束、上板验证

上板子验证,还是写了个led灯翻转的程序具体程序见之前的哈。

四、总结

至此结束,在上板子验证时原本直接把key_flag接到led灯的引脚上,但是由于key_flag只产生一个时钟周期的高电平,所以无法完成验证,需要自行写一个led_ctrl.v和top.v文件。

你可能感兴趣的:(fpga开发)