1. 設計要求架構
按鍵按下,蜂鳴器要「叮」一聲。ide
2. 設計分析學習
該設計方案採用野火征途MiNi FPGA開發板(intel-Cyclone IV -EP4CE10F17C8)實現,利用開發板的按鍵作輸入設備,無源蜂鳴器作輸出設備。硬件鏈接圖以下圖所示:spa
開發板晶振爲50MHz,提供系統時鐘信號,復位按鍵按下爲低電平,彈起爲高電平。無源蜂鳴器採用10KHz的方便驅動,每次發出聲音的時間爲0.1s。架構設計
(1)頂層模塊設計設計
端口及其含義:code
(2)架構設計blog
根據系統功能描述,該系統可由按鍵消抖模塊、邊沿檢測模塊和蜂鳴器驅動模塊組成,按鍵消抖模塊負責對按鍵進行消抖操做,當邊沿檢測模塊檢測到按鍵按下時,會產出一個週期高電平的脈衝信號key_flag,利用該脈衝產出一個長度爲0.1s方波信號,驅動蜂鳴器發聲。開發
3. 設計實現get
(1)按鍵消抖模塊的設計與實現
1 module key_filter( 2 input wire clk, 3 input wire rst_n, 4 input wire key_n, 5 6 output reg key_out 7 ); 8 9 localparam IDLE = 4'b0001; 10 localparam FILTER0 = 4'b0010; 11 localparam DOWN = 4'b0100; 12 localparam FILTER1 = 4'b1000; 13 14 parameter T_10MS = 19'd500_000; 15 16 reg key_n_r; 17 reg key_n_rr; 18 reg [3:0] c_state; 19 reg [3:0] n_state; 20 reg [18:0] cnt; 21 22 always@(posedge clk)begin 23 key_n_r <= key_n; 24 key_n_rr <= key_n_r; 25 end 26 27 always@(posedge clk or negedge rst_n)begin 28 if(rst_n == 1'b0) 29 c_state <= IDLE; 30 else 31 c_state <= n_state; 32 end 33 34 always@(*)begin 35 case(c_state) 36 IDLE : begin 37 if(key_n_rr == 1'b0) 38 n_state = FILTER0; 39 else 40 n_state = IDLE; 41 end 42 43 FILTER0 : begin 44 if(key_n_rr == 1'b1) 45 n_state = IDLE; 46 else 47 if(cnt < T_10MS - 1'b1) 48 n_state = FILTER0; 49 else 50 n_state = DOWN; 51 end 52 53 DOWN : begin 54 if(key_n_rr == 1'b0) 55 n_state = DOWN; 56 else 57 n_state = FILTER1; 58 end 59 60 FILTER1 : begin 61 if(key_n_rr == 1'b0) 62 n_state = DOWN; 63 else 64 if(cnt < T_10MS - 1'b1) 65 n_state = FILTER1; 66 else 67 n_state = IDLE; 68 end 69 default : n_state = IDLE; 70 endcase 71 end 72 73 always@(posedge clk or negedge rst_n)begin 74 if(rst_n == 1'b0) 75 cnt <= 19'd0; 76 else begin 77 case(c_state) 78 IDLE : cnt <= 19'd0; 79 80 FILTER0 : begin 81 if(key_n_rr == 1'b1) 82 cnt <= 19'd0; 83 else 84 if(cnt < T_10MS - 1'b1) 85 cnt <= cnt + 1'b1; 86 else 87 cnt <= 19'd0; 88 end 89 90 DOWN : cnt <= 19'd0; 91 92 FILTER1 : begin 93 if(key_n_rr == 1'b0) 94 cnt <= 19'd0; 95 else 96 if(cnt < T_10MS - 1'b1) 97 cnt <= cnt + 1'b1; 98 else 99 cnt <= 19'd0; 100 end 101 default : cnt <= 19'd0; 102 endcase 103 end 104 end 105 106 always@(posedge clk or negedge rst_n)begin 107 if(rst_n == 1'b0) 108 key_out <= 1'b1; 109 else 110 if(c_state == DOWN || c_state == FILTER1) 111 key_out <= 1'b0; 112 else 113 key_out <= 1'b1; 114 end 115 116 endmodule
(2)邊沿檢測模塊的設計與實現
1 module edge_check( 2 input wire clk_50M, 3 input wire rst_n, 4 input wire key_out, 5 6 output wire key_flag 7 ); 8 9 reg key_out_reg; 10 11 always@(posedge clk_50M or negedge rst_n)begin 12 if(rst_n == 1'b0) 13 key_out_reg <= 1'b0; 14 else 15 key_out_reg <= key_out; 16 end 17 18 assign key_flag = key_out_reg && (~key_out); 19 20 endmodule
(3)蜂鳴器驅動模塊的設計與實現
1 module beep_drive( 2 input wire clk_50M, 3 input wire rst_n, 4 input wire key_flag, 5 6 output wire beep 7 ); 8 9 parameter FREQ = 10_000; 10 parameter HALF = 50_000_000/(2*FREQ); 11 parameter T_100MS = 5_000_000; 12 13 reg [25:0] cnt; 14 reg wave_10k; 15 reg [25:0] count; 16 wire valid; 17 18 always@(posedge clk_50M or negedge rst_n)begin 19 if(rst_n == 1'b0) 20 cnt <= 26'd0; 21 else 22 if(cnt < HALF - 1'b1) 23 cnt <= cnt + 1'b1; 24 else 25 cnt <= 26'd0; 26 end 27 28 always@(posedge clk_50M or negedge rst_n)begin 29 if(rst_n == 1'b0) 30 wave_10k <= 1'b0; 31 else 32 if(cnt == HALF -1'b1) 33 wave_10k <= ~wave_10k; 34 else 35 wave_10k <= wave_10k; 36 end 37 38 always@(posedge clk_50M or negedge rst_n)begin 39 if(rst_n == 1'b0) 40 count <= T_100MS; 41 else 42 if(key_flag == 1'b1) 43 count <= 26'd0; 44 else if(count < T_100MS) 45 count <= count + 1'b1; 46 else 47 count <= count; 48 end 49 50 assign valid = (count < T_100MS) ? 1'b1 : 1'b0; 51 52 assign beep = wave_10k && valid; 53 54 endmodule
1 `timescale 1ns/1ps 2 3 module beep_drive_tb(); 4 reg clk_50M; 5 reg rst_n; 6 reg key_flag; 7 8 wire beep; 9 10 defparam beep_drive_inst.T_100MS = 500; 11 defparam beep_drive_inst.FREQ = 1000_000; 12 13 beep_drive beep_drive_inst( 14 .clk_50M (clk_50M), 15 .rst_n (rst_n), 16 .key_flag (key_flag), 17 18 .beep (beep) 19 ); 20 21 initial clk_50M = 1'b0; 22 always #10 clk_50M = ~clk_50M; 23 24 initial begin 25 rst_n = 1'b0; key_flag = 1'b0; 26 #201; 27 rst_n = 1'b1; 28 repeat(5)begin 29 @(posedge clk_50M); #2; 30 key_flag = 1'b1; 31 @(posedge clk_50M); #2; 32 key_flag = 1'b0; 33 #(20*1000); 34 end 35 #500;$stop; 36 end 37 38 endmodule
參考文獻: