FPGA学习之按键处理实现2
之前的方法其实很简单,基本上对于按键的消抖都是需要进行延迟的。可能也会有少数情况下也是可以不需要进行按键的去抖动的。
本程序采用仿顺序的操作,这样可能看起来会更好一点,样成这样的习惯后可能写程序的时候思路会更通畅一点
module key2(
input clk,rst_n,
input keyin,
output [7:0]smg_key,
output smgen
);
reg [7:0] timedata_r;
assign smg_key = timedata_r;
assign smgen = 1'b0;
reg keydown,keyup;
wire keydown_r,keyup_r;
reg key_r1,key_r2; //key down reg
reg key_r3,key_r4; //key up reg
//////////////=======detect whether the key is down======/////////////////
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
key_r1 <= 1'b1; // init the value 1 when the key is up
key_r2 <= 1'b1;
key_r3 <= 1'b0; // init the value 0 when the key is down
key_r4 <= 1'b0;
end
else
begin
key_r1 <= keyin;
key_r2<= key_r1;
key_r3 <= keyin;
key_r4<= key_r3;
end
assign keydown_r = key_r2 & (!key_r1); //when the key is down,the value of keydown_r1 is 1
assign keyup_r = (!key_r4) & (key_r3); //when the key is up, the value of keyup_r1 is 1
//////////////////===============FSM===================///////////////////////
parameter T1MS = 19'h7A120;
reg [18:0]delay_cnt;
reg [1:0]state;
reg key_flag;
reg key_out_r;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
key_flag <= 1'b0;
key_out_r <= 1'b0;
state <= 2'b00;
end
else
case(state)
2'b00 :
if(keydown_r == 1'b1) state <= 2'b01;
else if(keyup_r == 1'b1) state <= 2'b11;
2'b01 :
if(key_flag && delay_cnt == T1MS)
begin
state <= 2'b10;
key_flag <= 1'b0;
key_out_r <= 1'b0;
end
else
key_flag <= 1'b1;
2'b10 :
begin
key_out_r <= 1'b1;
state <= 2'b00;
end
2'b11 :
if(key_flag && delay_cnt == T1MS)
begin
state <= 2'b00;
key_flag <= 1'b0;
end
else
key_flag <= 1'b1;
default : state <= 2'b00;
endcase
/////////////////////////key check ////////////////////////////////////////////
////=======================================================================///
reg key_out_rr;
wire Key_down;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
//key_value <= 1'b0;
key_out_rr <= 1'b0;
end
else
key_out_rr <= key_out_r;
assign Key_down = !key_out_rr & key_out_r;
///////////////////////======delay module ===================/////////////
//===================================================================////
always @(posedge clk or negedge rst_n)
if(!rst_n)
delay_cnt <= 19'd0;
else
if(key_flag && delay_cnt == T1MS)
// begin
delay_cnt <= 19'd0;
else if(key_flag)
delay_cnt <= delay_cnt + 1'b1;
else
delay_cnt <= 19'd0;
/////////////============smg display module==================////////////////////
///==========================================================================///
reg [3:0] Smgbit;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
Smgbit <= 4'd0;
end
else if(Key_down)
if(Smgbit == 4'd9)
Smgbit <= 4'd0;
else
Smgbit <= Smgbit + 1'b1;
else
Smgbit <= Smgbit;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
timedata_r <= 8'hff;
end
else
case(Smgbit)
4'b0000 : timedata_r <= 8'hC0; //0
4'b0001 : timedata_r <= 8'hF9; //1
4'b0010 : timedata_r <= 8'hA4; //2
4'b0011 : timedata_r <= 8'hB0; //3
4'b0100 : timedata_r <= 8'h99; //4
4'b0101 : timedata_r <= 8'h92; //5
4'b0110 : timedata_r <= 8'h82; //6
4'b0111 : timedata_r <= 8'hF8; //7
4'b1000 : timedata_r <= 8'h80; //8
4'b1001 : timedata_r <= 8'h90; //9
4'b1010 : timedata_r <= 8'hBF; //-
default : timedata_r <= 8'hff;
endcase
endmodule