一、实现目标
用触摸按钮控制LED灯的点亮熄灭。 LED灯的初始状态为熄灭状态,按下触摸按钮后LED灯点亮,再次按下后LED灯熄灭
未按下键时为高电平,按下键时为低电平。 LED灯点亮高电平
因此,每次检测到键信号下降时,都需要改变LED灯的状态
二、实现方法
输入信号:
1 ) sys_clk表示系统时钟
2 ) sys_rst_n表示复位信号
3 ) touch_key表示触摸信号
输出信号:
1 ) LED_out表示控制led灯的信号
下面直接结合波形图。
图1 :下降沿检测
引入三个中间变量:
1 ) touch_en表示触摸使能信号,每次按下触摸按钮时触摸信号会提高1个时钟周期。
2 ) touch_key1是与触摸信号touch_key时钟上升沿同步的信号
3 ) touch_key2是touch_key1延迟了1个时钟周期信号
当touch_key1为低电平,touch_key2位高电平时,检测到touch_key下降沿到来然后将touch_en提高1个时钟,如果touch_en高,则反转led_out。
附加Verilog代码:
module touch _ ctrl _ led (inputwiresys _ clk,//时钟信号input wire sys_rst_n,//复位信号input wire touch_key,///抽头//触摸使能信号reg touch_key1; 使touch_key与时钟信号同步的reg touch_key2; 与touch_key1延迟一个时钟的always @ (posedge sys _ clkornegedgesys _ rst _ n ) if(sys_rst_n==1'B0 ) begintouch _ be endelsebegintouch _ key1=touch _ key; 使touch_key与时钟信号同步的touch_key2=touch_key1; touch_key1和1时钟延迟end//边缘检测(negedge下降沿) /如果在此使用always语句,则touch_en延迟1个时钟周期(在posedge上升沿检测情况下,为//在touch_key1为低电平且touch_key2为高电平情况下, touch_en提升一个时钟周期always @ (posedge sys _ clkornegedgesys_RST_n ) if(sys_ ) clkornegedgesys _ rst _ n ) if elseled_out=led_out; 最终模块
三.扩张
如果代码中touch_en的赋值语句使用always语句而不是assign语句,则:
always @ (posedge sys _ clkornegedgesys _ rst _ n ) if ) sys_rst_n==1'B0 ) touch_en=1'b0; else if (touch _ key1==1' B0 touch _ key2==1' B1 ) touch_en=1'b1; else touch_en=1'b0; 波形图中touch_en的波形比图1延迟1个时钟周期:
图2
touch_en1是assign语句中的波形,touch_en2是always语句中的波形
如果是上升沿检测,则将touch_en变为1的条件变更为touch_key1为高电平、touch_key2为低电平即可
用assign语句表示如下。
assigntouch_en=()~touch_key2) (~touch_key2) );