基於FPGA的按鍵提示音設計

1. 設計要求架構

  按鍵按下,蜂鳴器要「叮」一聲。ide

2. 設計分析學習

  該設計方案採用野火征途MiNi FPGA開發板(intel-Cyclone IV -EP4CE10F17C8)實現,利用開發板的按鍵作輸入設備,無源蜂鳴器作輸出設備。硬件鏈接圖以下圖所示:spa

 

開發板晶振爲50MHz,提供系統時鐘信號,復位按鍵按下爲低電平,彈起爲高電平。無源蜂鳴器採用10KHz的方便驅動,每次發出聲音的時間爲0.1s。架構設計

(1)頂層模塊設計設計

端口及其含義:code

  • clk_50M:系統時鐘,50MHz;
  • rst_n: 系統復位信號,低電平有效;
  • key_in: 按鍵輸入信號
  • beep: 蜂鳴器驅動信號。

(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 

 

參考文獻:

(1)陪您一塊兒學習FPGA-郝旭帥團隊_嗶哩嗶哩_bilibili

相關文章
相關標籤/搜索