今天做一个按键控制LED灯的实验吧,四个按键控制四个LED等,按下按键来控制LED灯的亮灭。先上实验效果图:
由于按键按下存在抖动,为了防止LED多次翻转需要进行按键消抖处理,可以由一个状态机实现,状态机转移图如下:
主要是在状态S2进行判断,如果S0按下的按键值与延时20ms后的按键值相等,说明按键确实被按下了,在S3状态下进行输出,否则被认为是干扰脉冲,直接跳转到S0。核心代码如下:
always@(posedge clk)// use for state transfer
case(state)
//s0:if(key!=={num{1'b1}}) state<=s1; else state<=s0;
s0:if(key!==key_temp) state<=s1; else state<=s0;//这样做效果更好~
s1:if(count==WAIT_20MS) state<=s2; else state<=s1;
s2:if(key==key_temp) state<=s3; else state<=s0;
s3:state<=s0;
default:state<=s0;
endcase
//以下描述状态输出
always@(*)// output for sgnal
case(state)
s0:signal<={num{1'b1}};
s1:signal<={num{1'b1}};
s2:signal<={num{1'b1}};
s3:signal<=key_temp;
default:signal<={num{1'b1}};
endcase
always@(*)// output for finish
case(state)
s0:finish<=1'b0;
s1:finish<=1'b0;
s2:finish<=1'b0;
s3:finish<=1'b1;
default:finish<=1'b0;
endcase
在主代码中则在finish信号有效的情况下读取按键的具体值,再根据按键值对相应的led等取反输出。代码如下: always@(posedge clk) if(finish) case(signal) 4'b1110:led[0]<=~led[0]; 4'b1101:led[1]<=~led[1]; 4'b1011:led[2]<=~led[2]; 4'b0111:led[3]<=~led[3]; default:led<=led; endcase 感兴趣的同学,可以下载我的代码,是在vivado 2015下编写的: [attach]1187568
|