|
module keytest (clk, key, ledout, weiout, key_count);
input clk;
input [4:0] key;
output reg [7:0] ledout;
output reg [7:0] weiout;
parameter key_init = 0;
parameter key_delay = 1;
parameter key_check = 2;
reg [15:0] state_clk_count;
output reg [3:0] key_count ;
reg state_clk;
reg [1:0] key_state;
reg [4:0] key_temp;
initial
begin
key_state = key_init;
state_clk = 0;
state_clk_count = 4'b0000;
key_count = 4'b0000;
key_temp = 4'b1111;
ledout = 7'b11000000;
weiout = ~8'b1000_0000;
end
//狀態(tài)機時鐘分頻
always @(posedge clk)
begin
state_clk_count <= state_clk_count + 1;
if(state_clk_count == 16'hffff)
state_clk <= ~ state_clk;
end
//狀態(tài)機
always @(posedge state_clk )
begin
//key_temp <= key; //把鍵碼的值賦給寄存器
case (key_state)
key_init :
if(key == 5'b11111)
key_state <= key_init;
else
key_state <=key_delay;
key_delay :
if(key == 5'b11111)
key_state <= key_init;
else
key_state <=key_check;
key_check :
if(key == 5'b11111) //釋放按鍵后,按鍵計數(shù)+1
begin
key_count <= key_count +1;
key_state <= key_init;
end
else //按鍵按下時,維持此狀態(tài),直到按鍵釋放
begin
key_state <= key_check;
key_temp <= key; //把鍵碼的值賦給寄存器
end
default :
key_state <= key_init;
endcase
end
always @(state_clk or key_count)
begin
case (key_count)
4'b0001 : ledout = 7'b11111001; // 1
4'b0010 : ledout = 7'b10100100; // 2
4'b0011 : ledout = 7'b10110000; // 3
4'b0100 : ledout = 7'b10011001; // 4
4'b0101 : ledout = 7'b10010010; // 5
4'b0110 : ledout = 7'b10000010; // 6
4'b0111 : ledout = 7'b11111000; // 7
4'b1000 : ledout = 7'b10000000; // 8
4'b1001 : ledout = 7'b10010000; // 9
4'b1010 : ledout = 7'b10001000; // A
4'b1011 : ledout = 7'b10000011; // B
4'b1100 : ledout = 7'b11000110; // C
4'b1101 : ledout = 7'b10100001; // D
4'b1110 : ledout = 7'b10000110; // E
4'b1111 : ledout = 7'b10001110;
default : ledout = 7'b11000000;
endcase
end
endmodule
程序如上,主要思想是將按鍵按下分為幾個狀態(tài):初始化、延時消抖、按鍵檢測,同時,為了實現(xiàn)按鍵的計數(shù),在本程序中的key_check狀態(tài)中,當(dāng)按鍵按下時,把鍵值賦值給鍵值寄存器,等到按鍵松開后,才進(jìn)行鍵值處理,這樣可以較好的實現(xiàn)按鍵按下計數(shù)。當(dāng)有幾個按鍵時,程序如下所示,思想與上例相同。
module keytest (clk, key, ledout, weiout, key_id,key_count_o);
input clk;
input [4:0] key;
output reg [7:0] ledout;
output reg [7:0] weiout;
output reg [3:0] key_id; //鍵碼
output reg [3:0] key_count_o; //連續(xù)按鍵次數(shù)
parameter key_init = 0; //按鍵狀態(tài)
parameter key_delay = 1;
parameter key_check = 2;
reg [15:0] state_clk_count; //狀態(tài)機時鐘分頻計數(shù)
reg [3:0] key_count [4:0]; //5個按鍵中,每個按鍵連續(xù)按鍵次數(shù)寄存
reg state_clk; //狀態(tài)機時鐘
reg [1:0] key_state; //按鍵狀態(tài)寄存
reg [4:0] key_temp; //鍵值寄存器
initial
begin
key_state = key_init;
state_clk = 0;
state_clk_count = 4'b0000;
key_id = 4'b0000;
key_temp = 4'b1111;
ledout = 7'b11000000;
weiout = ~8'b1000_0000;
end
//狀態(tài)機時鐘分頻
always @(posedge clk)
begin
state_clk_count <= state_clk_count + 1;
if(state_clk_count == 16'hffff)
state_clk <= ~ state_clk;
end
//狀態(tài)機
always @(posedge state_clk )
begin
case (key_state)
key_init :
if(key == 5'b11111)
key_state <= key_init;
else
key_state <=key_delay;
key_delay :
if(key == 5'b11111)
key_state <= key_init;
else
key_state <=key_check;
key_check :
if(key == 5'b11111) //釋放按鍵后,按鍵計數(shù)+1
begin
case (key_temp)
5'b01111:
begin
key_id <= 1;
key_count_o <= key_count[0];
key_count[0] <= key_count[0] + 1;
key_count[1] <= 0;
key_count[2] <= 0;
key_count[3] <= 0;
key_count[4] <= 0;
end
5'b10111:
begin
key_id <= 2;
key_count_o <= key_count[1];
key_count[1] <= key_count[1] + 1;
key_count[0] <= 0;
key_count[2] <= 0;
key_count[3] <= 0;
key_count[4] <= 0;
end
5'b11011:
begin
key_id <= 3;
key_count_o <= key_count[2];
key_count[2] <= key_count[2] + 1;
key_count[0] <= 0;
key_count[1] <= 0;
key_count[3] <= 0;
key_count[4] <= 0;
end
5'b11101 :
begin
key_id <= 4;
key_count_o <= key_count[3];
key_count[3] <= key_count[3] + 1;
key_count[4] <= 0;
key_count[0] <= 0;
key_count[1] <= 0;
key_count[2] <= 0;
end
5'b11110 :
begin
key_id <= 5;
key_count_o <= key_count[4];
key_count[4] <= key_count[4] + 1;
key_count[0] <= 0;
key_count[1] <= 0;
key_count[2] <= 0;
key_count[3] <= 0;
end
default :
begin
key_id <= 0;
key_count[0] <= 0;
key_count[1] <= 0;
key_count[2] <= 0;
key_count[3] <= 0;
key_count[4] <= 0;
key_count_o <= 0;
end
endcase
key_state <=key_init;
end
else //按鍵按下時,維持此狀態(tài),直到按鍵釋放
begin
key_state <= key_check;
key_temp <= key; //把鍵碼的值賦給寄存器
end
default :
key_state <= key_init;
endcase
end
always @(state_clk or key_count_o or key_id)
begin
case (key_count_o) //數(shù)碼管段選
4'b0001 : ledout = 7'b11111001; // 1
4'b0010 : ledout = 7'b10100100; // 2
4'b0011 : ledout = 7'b10110000; // 3
4'b0100 : ledout = 7'b10011001; // 4
4'b0101 : ledout = 7'b10010010; // 5
4'b0110 : ledout = 7'b10000010; // 6
4'b0111 : ledout = 7'b11111000; // 7
4'b1000 : ledout = 7'b10000000; // 8
4'b1001 : ledout = 7'b10010000; // 9
4'b1010 : ledout = 7'b10001000; // A
4'b1011 : ledout = 7'b10000011; // B
4'b1100 : ledout = 7'b11000110; // C
4'b1101 : ledout = 7'b10100001; // D
4'b1110 : ledout = 7'b10000110; // E
4'b1111 : ledout = 7'b10001110;
default : ledout = 7'b11000000;
endcase
case (key_id) //按照鍵碼進(jìn)行數(shù)碼管位選
1 : weiout = ~8'b1000_0000;
2 : weiout = ~8'b0100_0000;
3 : weiout = ~8'b0010_0000;
4 : weiout = ~8'b0001_0000;
5 : weiout = ~8'b0000_1000;
default : weiout = ~8'b1000_0000;
endcase
end
|
|