20211018更新
後來發其實這樣的寫法有點問題
近期在玩DE1 verilog 程式設計,其中關於Button設計細節
- Debounce 機制
- 模組定義
- FSM 定義
- FSM 實作
20211018更新
在FSM 實作的部分我把count也加進去output logic,
如此不妥,
1是output邏輯汙染不再只是輸出,
2是讓output邏輯無法以@(*)輸出,造成clk delay
可以改為使用timer倒數, 在特定state enable, 直到倒數完成送個wire訊號回來跳state
Debounce 機制
簡單來說就是避免Button在按壓時的彈跳
預期的按壓訊號(button通常是low active):
───┐ ┌─────── |
然而,實際可能的按壓訊號:
───┐ ┌─┐ ┌─────────┐ ┌──┐ ┌───┐ |
所以我們count那些可能錯誤的low active,超過一定數字就認定為使用者真的按下按鈕
模組定義
先來看一下模組定義
module btn_debounce |
- count次數 : 監測可能錯誤的low active次數,數值太小會無法濾掉
錯誤的按壓
,數值太大按鈕反應太慢
- 外部頻率 : 系統頻率,按鈕的反應時間以這個為準,例如使用50MHz,反應時間就是 20ns*5000 = 100us
- reset訊號 : 系統重置訊號,若收到該訊號,要立刻讓按鈕停止輸出、數數等動作
- 按壓訊號 : 來自真實按鈕的按壓訊號,帶有雜訊
- 輸出訊號 : 經過debounce輸出的訊號,應該要乾淨、單一
FSM 定義
為了使此模組更好理解,此處使用 Moore FSM,定義四個狀態:
( Mealy 可以在轉state時輸出
參考 (原創) 有限狀態機FSM coding style整理 (SOC) (Verilog))
localparam IDLE = 0; // wait for button press |
並且定義目前狀態以及未來狀態, 以及定義了一個多bit的count register,作為count用
FSM 實作
共分三個部分:
- next state logic 根據
目前state
以及外部輸入
判斷下一個 state - state reg 根據 clk 跳至下一個 state 以及實作 reset
- output logic 根據目 state 輸出
架構如下:
┌────────────────┐ ┌──────────────┐ ┌────────────┐ |
// Moore FSM: next state logic |
程式碼實作:
- IDLE 狀態: 等待按下按鈕,將counter清空
- PRESS 狀態: 確認以按下按鈕,開始count
- FIRE 狀態: 完成count,送出訊號
- RELEASE 狀態: 計算放開時count,放開足夠久就回到IDLE
注意
- 對於有試著將output logic設計為 always@(*) 但會引來 Error: (vsim-3601)
其因Sensitive List已經與內部邏輯成為迴圈 - 此處設計State為一般版本,如果設計成one hot會更好移轉以及Debug