一、實驗目的
-
掌握 Verilog 語言在硬件描述中的應用,通過編程實現分秒計數器的邏輯功能。
-
學習并實踐按鍵消抖的原理與實現方法,提升對硬件電路中信號處理的理解。
-
熟悉在 DE2-115 開發板上進行 Verilog 程序的開發、調試及下載驗證流程,將理論知識與實際硬件相結合 。
二、實驗環境
-
硬件平臺:DE2-115 開發板,該開發板搭載 Altera Cyclone IV E 系列 FPGA 芯片,提供豐富的外設資源,包括按鍵、數碼管等,便于進行各類數字邏輯實驗。
-
軟件工具:Quartus Prime 開發套件,用于 Verilog 代碼的編寫、綜合、布局布線以及下載到 FPGA 芯片中;ModelSim 用于 Verilog 代碼的功能仿真,驗證設計邏輯的正確性。
三、實驗原理
3.1 分秒計數器原理
分秒計數器本質是一個多級計數器。秒計數器以 1Hz 的時鐘信號作為計數脈沖,當秒計數器計數到 59 時,產生一個進位信號,觸發分計數器加 1。分計數器同樣在接收到進位信號時進行計數,當分計數器計數到 59 時,可根據需求選擇是否繼續進位或循環歸零。
3.2 按鍵消抖原理
機械按鍵在按下和釋放時,由于觸點的彈性作用,會產生短暫的抖動,導致信號不穩定。按鍵消抖通過在檢測到按鍵狀態變化后,啟動一個計數器,當計數器達到一定時間(如 10ms)且按鍵狀態未再變化時,才認為按鍵狀態有效,從而消除抖動帶來的干擾。
四、模塊設計與實現
4.1 按鍵消抖模塊(debounce.v)
module debounce (input wire clk,input wire rst_n,input wire btn_in,output reg btn_out
);parameter DEBOUNCE_TIME = 16'd250000; // 10ms @ 25MHzreg [15:0] cnt;reg btn_reg1, btn_reg2;// 同步輸入信號到時鐘域always @(posedge clk or negedge rst_n) beginif (!rst_n) beginbtn_reg1 <= 1'b0;btn_reg2 <= 1'b0;endelse beginbtn_reg1 <= btn_in;btn_reg2 <= btn_reg1;endend// 消抖計數器always @(posedge clk or negedge rst_n) beginif (!rst_n) begincnt <= 16'd0;btn_out <= 1'b0;endelse beginif (btn_reg2 != btn_out) begincnt <= cnt + 1'b1;if (cnt >= DEBOUNCE_TIME) beginbtn_out <= btn_reg2;cnt <= 16'd0;endendelsecnt <= 16'd0;endendendmodule
該模塊通過兩級觸發器將按鍵輸入信號同步到時鐘域,然后使用一個計數器在檢測到按鍵狀態變化時開始計數,當計數達到設定的消抖時間且按鍵狀態穩定時,輸出穩定的按鍵信號。
4.2 分秒計數器模塊(counter.v)
module counter (input wire clk,input wire rst_n,input wire pause,output reg [5:0] sec,output reg [5:0] min
);always @(posedge clk or negedge rst_n) beginif (!rst_n) beginsec <= 6'd0;min <= 6'd0;endelse if (!pause) beginif (sec == 6'd59) beginsec <= 6'd0;if (min == 6'd59)min <= 6'd0;elsemin <= min + 1'b1;endelsesec <= sec + 1'b1;endend
endmodule
在時鐘上升沿或復位信號有效時,對分秒計數器進行操作。當暫停信號無效時,秒計數器在計數到 59 后歸零并使分計數器加 1,分計數器計數到 59 后歸零,實現循環計數;當暫停信號有效時,計數器停止計數。
4.3 頂層模塊(top_module.v)
module top_module (input wire clk,input wire rst_n,input wire pause_btn,output reg [6:0] seg,output reg [3:0] an
);wire clean_pause;wire [5:0] sec;wire [5:0] min;debounce u1 (.clk(clk),.rst_n(rst_n),.btn_in(pause_btn),.btn_out(clean_pause));counter u2 (.clk(clk),.rst_n(rst_n),.pause(clean_pause),.sec(sec),.min(min));always @(*) begincase({an})4'b1110: beginan = 4'b1110;case(min[5:4])2'b00: seg = 7'b0000001;2'b01: seg = 7'b1001111;2'b10: seg = 7'b0010010;2'b11: seg = 7'b0000110;endcaseend4'b1101: beginan = 4'b1101;case(min[3:0])4'b0000: seg = 7'b0000001;4'b0001: seg = 7'b1001111;4'b0010: seg = 7'b0010010;4'b0011: seg = 7'b0000110;4'b0100: seg = 7'b1001100;4'b0101: seg = 7'b0100100;4'b0110: seg = 7'b0100000;4'b0111: seg = 7'b0001111;4'b1000: seg = 7'b0000000;4'b1001: seg = 7'b0000100;endcaseend4'b1011: beginan = 4'b1011;case(sec[5:4])2'b00: seg = 7'b0000001;2'b01: seg = 7'b1001111;2'b10: seg = 7'b0010010;2'b11: seg = 7'b0000110;endcaseend4'b0111: beginan = 4'b0111;case(sec[3:0])4'b0000: seg = 7'b0000001;4'b0001: seg = 7'b1001111;4'b0010: seg = 7'b0010010;4'b0011: seg = 7'b0000110;4'b0100: seg = 7'b1001100;4'b0101: seg = 7'b0100100;4'b0110: seg = 7'b0100000;4'b0111: seg = 7'b0001111;4'b1000: seg = 7'b0000000;4'b1001: seg = 7'b0000100;endcaseenddefault: beginan = 4'b1111;seg = 7'b1111111;endendcaseendendmodule
頂層模塊將按鍵消抖模塊和分秒計數器模塊實例化并連接,同時實現數碼管動態顯示邏輯,通過掃描不同位的數碼管,分時顯示分和秒的數值。
五、實驗結果與分析
程序在quartus上編譯無誤后,燒錄到板子上運行
將編譯后的程序下載到 DE2-115 開發板中,通過實際操作按鍵進行測試。按下復位按鍵,數碼管顯示 “00:00”;按下暫停按鍵,計數器暫停計數,數碼管數值保持不變;再次按下暫停按鍵,計數器繼續計數。數碼管能夠穩定、正確地顯示分和秒的數值,實驗功能成功實現。
六、總結
本次實驗成功在 DE2-115 板子上使用 Verilog 實現了具有按鍵暫停和按鍵消抖功能的分秒計數器。通過實驗,深入理解了 Verilog 語言的編程方法、按鍵消抖的原理以及 FPGA 開發流程。在實驗過程中,也遇到了如數碼管顯示編碼錯誤、時序匹配等問題,通過查閱資料和調試得以解決。