fpga按鍵消抖
key_s0:判斷按鍵是否按下,如果是,轉移到狀態 key_s1;
key_s1:10ms 後再次判斷按鍵是否按下,如果是,轉移狀態到 key_s2,否則繼續回到 key_s0;
key_s2:判斷按鍵是否抬起,如果是,轉移狀態到 key_s3
key_s1:10ms 後再次判斷按鍵是否抬起,如果是,轉移狀態到 key_s0,否則繼續回到 key_s2;
將按鍵按下到鬆開,將整個過程,分成了四個部分,也就是四個狀態,狀態機就是狀態轉化。
由於按鍵經常用,消抖也是個非常重要的部分,為消抖寫個模組,方便後面用。我們起個名字 super_key.
首先是模組的輸入輸出,
時鐘輸入,按鍵輸出,按鍵狀態輸出
module super_key(
input clk_i,
input key_i,
output key_cap
);(mark_debug = 「true」)這個東西,標識出要探測的訊號。觀察波形才會用(到時候再補)。
比如(mark_debug = 「true」) reg [1:0] key_s = 2』b0;
(mark_debug = 「true」) reg [1:0] key_s_r = 2』b0;
(mark_debug = 「true」) wire en_10ms ;
引數別名
parameter clk_freq = 100000000;
parameter cnt_10ms = (clk_freq/100 - 1』b1);
parameter key_s0 = 2』d0;
parameter key_s1 = 2』d1;
parameter key_s2 = 2』d2;
parameter key_s3 = 2』d3;
用來計數 reg [24:0] cnt10ms = 25』d0;
連續賦值
assign en_10ms = (cnt10ms == cnt_10ms);
assign key_cap = (key_skey_s2)&&(key_s_rkey_s1); (下面講)
由原理圖知道 按鍵按下為,低電平。
**實現
從上面我們就可以看出來,我們沒10ms判斷一下按鍵狀態,從而實現按鍵狀態改變。
第一部分計時10ms,第二部分 狀態改變
第一部分 十毫秒延時
always @(posedge clk_i)begin
if(cnt10ms < cnt_10ms)
cnt10ms <= cnt10ms + 1』b1;
else
cnt10ms <= 25』d0;
end非常簡單 時鐘上公升沿 cnt10ms ++,擠滿置0。
看上面連續賦值語句 10ms計時到的時候,en_10ms會置1,
第二部分 狀態改變
always @(posedge clk_i)begin
key_s_r <= key_s;
endalways @(posedge clk_i)begin
if(en_10ms)begin
case(key_s)
key_s0:begin
if(!key_i)
key_s <= key_s1;
endkey_s1:begin
if(!key_i)
key_s <= key_s2;
else
key_s <= key_s0;
endkey_s2:begin
if(key_i)
key_s <= key_s3;
endkey_s3:begin
if(key_i)
key_s <= key_s0;
else
key_s <= key_s2;
endendcase
endend
10ms捕獲一次按鍵狀態,滿足對應條件,進入下乙個狀態,否則回到最初狀態。
總體** :
`timescale 1ns / 1ps
module super_key(
input clk_i,
input key_i,
output key_cap
);parameter clk_freq = 100000000;
parameter cnt_10ms = (clk_freq/100 - 1』b1);
parameter key_s0 = 2』d0;
parameter key_s1 = 2』d1;
parameter key_s2 = 2』d2;
parameter key_s3 = 2』d3;
reg [24:0] cnt10ms = 25』d0;
(mark_debug = 「true」) reg [1:0] key_s = 2』b0;
(mark_debug = 「true」) reg [1:0] key_s_r = 2』b0;
(mark_debug = 「true」) wire en_10ms ;
assign en_10ms = (cnt10ms == cnt_10ms);
assign key_cap = (key_skey_s2)&&(key_s_rkey_s1);
always @(posedge clk_i)begin
if(cnt10ms < cnt_10ms)
cnt10ms <= cnt10ms + 1』b1;
else
cnt10ms <= 25』d0;
endalways @(posedge clk_i)begin
key_s_r <= key_s;
endalways @(posedge clk_i)begin
if(en_10ms)begin
case(key_s)
key_s0:begin
if(!key_i)
key_s <= key_s1;
endkey_s1:begin
if(!key_i)
key_s <= key_s2;
else
key_s <= key_s0;
endkey_s2:begin
if(key_i)
key_s <= key_s3;
endkey_s3:begin
if(key_i)
key_s <= key_s0;
else
key_s <= key_s2;
endendcase
endend
endmodule
疑問 1:
always @(posedge clk_i)begin
key_s_r <= key_s;
end有什麼用
疑問2:
assign key_cap = (key_skey_s2)&&(key_s_rkey_s1); (下面講)
always @(posedge clk_i)begin
key_s_r <= key_s;
endkey_s_r <= key_s; ,則(key_skey_s2)&&(key_s_rkey_s1) 必為0
疑問1解答:
我們是當按鍵按下到松下,記一次按鍵按下事件。
疑問2解答:
由問題1我們知道按鍵按下事件 是按鍵從按下到鬆開整個過程,
由**我們可以發現key_s是每十毫秒改變一次,key_s發生,是在下個時鐘上公升沿才將值賦給key_s_r。
也就是在莫乙個時刻 key_s是現態 key_s_r是上乙個狀態。
FPGA 按鍵消抖
今天簡單的說說按鍵消抖,原理特別好理解,其實就是延時,做一定時間的延時後取值一次,就能夠得到特定的消抖後的狀態了。為什麼要消抖?見圖 我們可以看到,但按鍵按下的那一刻,存在一段時間的抖動,同時在釋放按鍵的一段時間裡也是存在抖動的,這就可能導致狀態在識別的時候可能檢測為多次的按鍵,因為執行過程中普通的...
FPGA之按鍵消抖
按鍵是一種常用的人機互動輸入介面,對於機械按鍵來說,在按下或彈起的時候,按鍵輸入值往往伴隨著輸入抖動。消除抖動的方式有很多種,以下是用fpga實現按鍵消抖。實現原理 當檢測到按鍵按下 一般按下為低電平 時開始計時 用計數器實現 大概10ms後檢測按鍵狀態,如果按鍵狀態為低電平,說明按鍵按下,輸出低電...
2014 3 12 FPGA學習 按鍵消抖
生性愚鈍,現在才終於明白fpga的按鍵消抖原理。先貼一段別人的 dule key debounce sys clk sys rstn key in led out 輸入輸出訊號 input sys clk input sys rstn input key in output led out 暫存器定...