天天看點

【按鍵消抖】基于FPGA的按鍵消抖子產品開發

1.軟體版本

QUARTUSII8.1

Modelsim6.5d

2.系統源碼

module tops(
            i_clk,    //100M
            i_rst,    //系統複位功能,高電平複位,如果不使用這個角,那麼一直接低電平即可
            i_input1, //按鍵輸入1
            i_input2, //按鍵輸入2
            o_output1,//脈沖輸出1
            o_output2,//脈沖輸出2
            test_cnt1,//測試計數器1
            test_cnt2,//測試計數器2
            test_enable1,//測試使能信号
            test_enable2 //測試使能信号
           );
           
//100M等于10ns,是以1s中就是10_000_000個100M時鐘周期
//仿真的時候,為了友善看到仿真效果,是以将10_000_000改為一個較小的值10_000           
//parameter NUM = 32'd10000000;  //實際用        
parameter NUM = 32'd100;       //仿真用     
           
           
input       i_clk;//100M為10ns
input       i_rst;
input       i_input1;
input       i_input2;

output      o_output1;
output      o_output2;         
output[31:0]test_cnt1; 
output[31:0]test_cnt2; 
output      test_enable1;
output      test_enable2;


reg      o_output1    = 1'b0;
reg      o_output2    = 1'b0;  
reg      test_enable1 = 1'b0;
reg      test_enable2 = 1'b0;
reg[31:0]cnt1         = 32'd0;
reg[31:0]cnt2         = 32'd0;


reg      flag1        = 1'b1;
reg      flag2        = 1'b1;



always @(posedge i_clk or posedge i_rst)//處理主要程序
begin
     if(i_rst)//系統複位
     begin
     test_enable1 <= 1'b0;//定義使能信号
     test_enable2 <= 1'b0;//定義使能信号 
     cnt1         <= 32'd0;  
     cnt2         <= 32'd0; 
     flag1        <= 1'b1;  
     flag2        <= 1'b1; 
     end
else begin
          if(i_input1 == 1'b0 & i_input2 == 1'b1 & flag1 == 1'b1)//按下按鍵1,不按按鍵2
          begin
               //1s鐘内使能維持10_000_000個時鐘周期 
               
               cnt2 <= 32'd0;
               
               if(cnt1 < NUM)//不到1s
               begin
               cnt1 <= cnt1 + 32'd1;
               test_enable1 <= 1'b1;//輸出1個脈沖,//按下按鈕後,持續1s鐘
               test_enable2 <= 1'b0; 
               flag1        <= 1'b1;//用來屏蔽第二個按鈕  
               flag2        <= 1'b0;//用來屏蔽第二個按鈕                                
               end
               
               if(cnt1 == NUM)//到1s,停止輸出
               begin
               cnt1 <= cnt1;               
               test_enable1 <= 1'b0;
               test_enable2 <= 1'b0;  
               flag1        <= 1'b1; 
               flag2        <= 1'b1;                              
               end               
          end
   
          
          
          if(i_input1 == 1'b1 & i_input2 == 1'b0 & flag2 == 1'b1)//按下按鍵2,不按按鍵1
          begin
               //50s鐘内使能維持
               cnt1 <= 32'd0;
               
               if(cnt2 < 50*NUM)//不到50s
               begin
               cnt2 <= cnt2 + 32'd1;
               test_enable1 <= 1'b0;//輸出1個脈沖,//按下按鈕後,持續1s鐘
               test_enable2 <= 1'b1; 
               flag1        <= 1'b0;//用來屏蔽第1個按鈕  
               flag2        <= 1'b1;//用來屏蔽第1個按鈕                                
               end
               
               if(cnt2 == 50*NUM)//到1s,停止輸出
               begin
               cnt2 <= cnt2;               
               test_enable1 <= 1'b0;
               test_enable2 <= 1'b0;  
               flag1        <= 1'b1; 
               flag2        <= 1'b1;                              
               end              
          end
          
          
          if(i_input1 == 1'b1 & i_input2 == 1'b1)//不發生按鍵操作
          begin
          cnt1 <= 32'd0;
          cnt2 <= 32'd0;
          end
               
     end        
end
assign test_cnt1 = cnt1;
assign test_cnt2 = cnt2;

//下面根據是能信号,輸出脈沖

//定義兩個脈沖計數器
reg[31:0]pcnt1 = 32'd0;
reg[31:0]pcnt2 = 32'd0;
always @(posedge i_clk or posedge i_rst)//處理主要程序
begin
     if(i_rst)//系統複位
     begin
     pcnt1        <= 32'd0;
     pcnt2        <= 32'd0;
     o_output1    <= 1'b0;
     o_output2    <= 1'b0; 
     end
else begin
          if(test_enable1 == 1'b1)//1s内一個100ns的脈沖,即1s内發生一個10M的脈沖信号
          begin
          pcnt1 <= pcnt1 + 32'd1;
          
               if(pcnt1 < 32'd10)
               begin
               o_output1    <= 1'b1;//産生100ns的信号
               end
          else begin
               o_output1    <= 1'b0;
               end
          end
     else begin
          pcnt1        <= 32'd0;
          o_output1    <= 1'b0;    
          end
     
     
          if(test_enable2 == 1'b1)//50s内50個100ns的脈沖,即1s内發生一個10M的脈沖信号
          begin
          
               if(pcnt2 == NUM-1)
               begin
               pcnt2 <= 32'd0;
               end
          else begin
               pcnt2 <= pcnt2 + 32'd1;
               end     
          
          
               if(pcnt2 < 32'd10)
               begin
               o_output2    <= 1'b1;//産生100ns的信号
               end
          else begin
               o_output2    <= 1'b0;
               end
          end
     else begin
          pcnt2        <= 32'd0;
          o_output2    <= 1'b0;    
          end     

     end        
end
       
endmodule                 

3.仿真結論

QII自帶仿真說明:

【按鍵消抖】基于FPGA的按鍵消抖子產品開發

我們将波形進行局部放大:

【按鍵消抖】基于FPGA的按鍵消抖子產品開發

第一部分,可以看到input1為高,input2為低,說明2按下了,是以output2産生連續的50個脈沖。

【按鍵消抖】基于FPGA的按鍵消抖子產品開發

第二部分,input1為低,第一個按鍵按下了,是以隻産生一個高電平信号

【按鍵消抖】基于FPGA的按鍵消抖子產品開發

第三部分,還是第一個按鈕被按下了,是以隻産生一個脈沖。

Modelsim仿真說明:

【按鍵消抖】基于FPGA的按鍵消抖子產品開發

我們将仿真進行局部放大:

【按鍵消抖】基于FPGA的按鍵消抖子產品開發

按鍵一按下:

【按鍵消抖】基于FPGA的按鍵消抖子產品開發

按鍵二被按下;