用FPGA邏輯消抖動(dòng)
我們將一個(gè)開(kāi)關(guān)連接到FPGA上,連接方式如下圖:機(jī)械開(kāi)關(guān)的問(wèn)題就是有抖動(dòng),每次按一下開(kāi)關(guān),你會(huì)得到下面的信號(hào):
本文引用地址:http://cafeforensic.com/article/202312/454265.htm這種信號(hào)很少碰到,多數(shù)情況是下面的這種:
我們可以用FPGA的計(jì)數(shù)器來(lái)記錄按鍵的次數(shù),并通過(guò)數(shù)碼管顯示出來(lái): 上電的時(shí)候,一起是好的:
如果按十次鍵,得到下面的結(jié)果:
顯然不對(duì)。
那如何解決呢? 一種方式是添加一個(gè)R/C濾波器,再跟一個(gè)施密特觸發(fā)器之后送給FPGA,當(dāng)然還有更簡(jiǎn)單的方式,就是在FPGA內(nèi)部進(jìn)行消抖動(dòng)。 FPGA擅長(zhǎng)簡(jiǎn)單的運(yùn)算,讓我們使用FPGA中的計(jì)數(shù)器來(lái)查看按下或釋放按鈕的時(shí)間。只有當(dāng)計(jì)數(shù)器達(dá)到最大值時(shí),我們才確定按鈕已經(jīng)改變了狀態(tài)。
PB是按鈕信號(hào)(在本例中為低電平有效)。它可能包含毛刺,并且對(duì)任何時(shí)鐘都是異步的,所以它基本上是不可用的。我們將使PB與時(shí)鐘(本例中為20MHz)同步,然后創(chuàng)建三個(gè)無(wú)毛刺、與時(shí)鐘同步的按鈕輸出。每個(gè)輸出都將是高電平有效的,并指示按鈕的不同狀態(tài)(按鈕狀態(tài),剛剛按下,剛剛釋放)。
module PushButton_Debouncer( input clk, input PB, // "PB" is the glitchy, asynchronous to clk, active low push-button signal // from which we make three outputs, all synchronous to the clock output reg PB_state, // 1 as long as the push-button is active (down) output PB_down, // 1 for one clock cycle when the push-button goes down (i.e. just pushed) output PB_up // 1 for one clock cycle when the push-button goes up (i.e. just released) ); // First use two flip-flops to synchronize the PB signal the "clk" clock domain reg PB_sync_0; always @(posedge clk) PB_sync_0 <= ~PB; // invert PB to make PB_sync_0 active high reg PB_sync_1; always @(posedge clk) PB_sync_1 <= PB_sync_0; // Next declare a 16-bits counter reg [15:0] PB_cnt; // When the push-button is pushed or released, we increment the counter // The counter has to be maxed out before we decide that the push-button state has changed wire PB_idle = (PB_state==PB_sync_1); wire PB_cnt_max = &PB_cnt; // true when all bits of PB_cnt are 1's always @(posedge clk)if(PB_idle) PB_cnt <= 0; // nothing's going onelsebegin PB_cnt <= PB_cnt + 16'd1; // something's going on, increment the counter if(PB_cnt_max) PB_state <= ~PB_state; // if the counter is maxed out, PB changed! end assign PB_down = ~PB_idle & PB_cnt_max & ~PB_state; assign PB_up = ~PB_idle & PB_cnt_max & PB_state; endmodule
我們使用了一個(gè)16位計(jì)數(shù)器。如果使用20MHz的系統(tǒng)時(shí)鐘,則需要3ms才能達(dá)到最大值。從用戶的角度來(lái)看,3ms是很短暫的,但毛刺已經(jīng)消失了。根據(jù)你的按鈕的毛刺程度和你的系統(tǒng)時(shí)鐘速度,你可能需要調(diào)整計(jì)數(shù)器的寬度。
評(píng)論