实现触摸按键触摸后 led 灯闪烁,再次触摸时 led 灯停止闪烁。
(野火ALTERA FPGA 教程作业训练题)
基本思路是:两个part并行嘛,一个part实现LED闪烁的部分,一直运行,另一个part检测按键按下的下降沿;
由更高一级的touch_en控制LED这一级。
注意touch_en只是一个脉冲信号,所以不能用作条件赋值语句的条件,而是需要重新设置一个touch_flag变量,作为电平信号,方可使用。
代码如下,亲测可行,未写testbench。
//实现触摸按键触摸后 led 灯闪烁,再次触摸时 led 灯停止闪烁。
//基本思路是,两个模块并行嘛,设置一个LED闪烁的部分,一直运行,只是由touch_en更高一级的控制
module touch_ctrl_led_flash
#(
parameter CNT_MAX = 25'd24_999_999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire touch_key ,
output wire led_out
);
reg [24:0] cnt ;
reg touch_flag ;//设置一个flag,每次touch_en有效后翻转,即为电平信号,使用此信号
reg led ;//这个是闪烁的led,只需要将其赋值给led_out即可。
reg touch_key_dly1 ;//将touch_key同步到时钟下
reg touch_key_dly2 ;//对touch_key_dly1进行打一拍的操作
wire touch_en ;
assign touch_en = (~touch_key_dly1) & touch_key_dly2;
//对 touch_key 信号延迟两个时钟周期用来产生触摸按键信号
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
begin
touch_key_dly1 <= 1'b0;
touch_key_dly2 <= 1'b0;
end
else
begin
touch_key_dly1 <= touch_key ;
touch_key_dly2 <= touch_key_dly1;
end
end
//assign led_out = (touch_en) ? led : 1'b1;这样写不对,因为只有很短暂的时间touch_en=1
//输出部分逻辑
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
touch_flag <= 1'b1;
else if(touch_en)
touch_flag <= ~touch_flag;
end
assign led_out = (touch_flag) ? led : 1'b1;
//对LED闪烁的控制部分
//计数器
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt <= 25'd0;
else if(cnt == CNT_MAX)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
end
//led 闪烁部分代码
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
led <= 1'd1; //初始不亮
else if(cnt == CNT_MAX)
led <= ~led;
end
endmodule