基于FPGA的按键消抖实现

二、按键消抖

        因为是基于小梅哥开发板ACX720进行的开发设计,且后续有用到按键控制的功能,故本章进行按键消抖的程序设计以及功能验证,因为功能较为简单,modelsim仿真代码将不进行专门讲述。

        在小梅哥教材中右讲解按键消抖的基本原理,这里不进行专门讲述,详情请参考小梅哥的视频教程,按键控制机制如下图:

        如图所示,理论与实际图存在着抖动误差,但是一般的按键抖动误差为20ms左右,那在设计中,我将20ms设置为极限的抖动时间,那么通过延时等待这段时间再去进一步检测按键信号也是可行的,但是这就会与教材有所不同,及没有教材的反馈机制,但是一般使用过程中也不会有很高概率的“失效”现象。

        如上图所示,按键按下 --> 等待延时 -->状态确认 --> 按键恢复 --> 结束,此流程非常适合采用状态机进行设计,状态机流程使用如上,按键按下消抖流程就可以实现了,代码如下,下述edge_check为简单的检沿动作,我将其例化成模块以进行调用,这里不再进行讲述:

module key_filter #
(
   parameter            DELY = 20
)
(
   input                clk_sys           ,
   input                rst_sys           ,
   input                timer_1ms         ,
   input                timer_1s          ,
   //
   input                key_in            ,
   output               key_out     
);

// ********************************************************
// localparam
// ********************************************************
localparam  IDLE = 3'd0 ;
localparam  NAIT = 3'd1 ;
localparam  KENA = 3'd2 ;
localparam  PAIT = 3'd3 ;
localparam  OVER = 3'd4 ;

// ********************************************************
// signal
// ********************************************************
wire                    pedge          ;
wire                    nedge          ;

reg   [2:0]             cstate = IDLE  ;
reg   [2:0]             nstate = IDLE  ;

reg   [7:0]             cnt_delay = 0  ;
reg                     delay_done = 0 ;

reg                     key_reg = 0    ;
// ********************************************************
// peocess
// ********************************************************
always @ ( posedge clk_sys )
begin
   if( rst_sys )
      cstate <= IDLE ;
   else
      cstate <= nstate ;
end

always @ ( * )
begin
   case ( cstate )
      IDLE : begin
         if( nedge )
            nstate = NAIT ;
         else
            nstate = IDLE ;
      end
      NAIT : begin
         if( delay_done )
            nstate = KENA ;
         else
            nstate = NAIT ;
      end
      KENA : begin
         if( pedge )
            nstate = PAIT ;
         else
            nstate = KENA ;
      end
      PAIT : begin
         if( delay_done )
            nstate = OVER ;
         else
            nstate = PAIT ;
      end
      OVER : nstate = IDLE ;
      default: nstate = IDLE ;
   endcase      
end

always @ ( posedge clk_sys )
begin
   if( rst_sys || pedge || nedge )
      cnt_delay <= 0 ;
   else if( timer_1ms )
      cnt_delay <= cnt_delay + ~&cnt_delay ;
end

always @ ( posedge clk_sys )
begin
   if( rst_sys )
      delay_done <= 0 ;
   else if(( cstate == NAIT || cstate == PAIT ) && cnt_delay == DELY )
      delay_done <= 1 ;
   else
      delay_done <= 0 ;
end

always @ ( posedge clk_sys )
begin
   if( cstate == KENA )
      key_reg <= 1 ;
   else if( cstate == OVER )
      key_reg <= 0 ;
   else ;
end

// ========================================================
//
// ========================================================
edge_detect u0_edge_detect
(
   //input
   .clk              ( clk_sys         ),
   .sig_in           ( key_in          ),

   //output
   .p_edge           ( pedge           ),
   .n_edge           ( nedge           )
);

edge_detect u1_edge_detect
(
   //input
   .clk              ( clk_sys         ),
   .sig_in           ( key_reg         ),

   //output
   .p_edge           ( key_out         ),
   .n_edge           (                 )
);


endmodule

        进行完设计后,将丢按键消抖代码进行验证,可以进行modelsim仿真,也可进行上板验证,这里通过上板验证控制LED显示,显示代码如下:

module key_led #
(
   parameter                     KNUM = 5
)
(
   input                         clk_sys        ,
   input                         rst_sys        ,
   input                         timer_1ms      ,
   input                         timer_1s       ,
   //
   input       [KNUM-1:0]        key_in         ,
   output reg  [7:0]             led_out
);

// ********************************************************
// signal
// ********************************************************
wire        [KNUM-1:0]           key_flag       ;

wire                             key_rst        ;
wire                             key_add        ;
wire                             key_sub        ;
wire                             key_lef        ;
wire                             key_rih        ;


// ********************************************************
// process
// ********************************************************
assign key_rst = key_flag[0]  ; // 复位
assign key_add = key_flag[1]  ; // 按键+
assign key_sub = key_flag[2]  ; // 按键-
assign key_lef = key_flag[3]  ; // 按键左移
assign key_rih = key_flag[4]  ; // 按键右移

always @ ( posedge clk_sys )
begin
   if( rst_sys || key_rst)
      led_out <= 0 ;
   else if( key_add )
      led_out <= led_out + 1 ;
   else if( key_sub )
      led_out <= led_out - 1 ;
   else if( key_lef )
      led_out <= led_out << 1 ;
   else if( key_rih )
      led_out <= led_out >> 1 ;
   else ;
end

// ========================================================
//
// ========================================================
key_filter u_key_filter[KNUM-1:0]
(
   .clk_sys           ( clk_sys             ),
   .rst_sys           ( rst_sys             ),
   .timer_1ms         ( timer_1ms           ),
   .timer_1s          ( timer_1s            ),
   //
   .key_in            ( key_in              ),
   .key_out           ( key_flag            )
);


endmodule

        如此本章内容实现就讲完了,最终的modelsim仿真以及上班实现就不再此进行公布。

FPGA读写OV5640摄像头显示例程 Verilog逻辑源码Quartus工程文件+文档说明,FPGA型号Cyclone4E系列中的EP4CE6F17C8,Quartus版本17.1。 本实验将采用 500 万像素的 OV5640 摄像头模组(模块型号:AN5640)为大家显示更高分辨率 的视频画面。OV5640 摄像头模组最大支持 QSXGA (2592x1944)的拍照功能,支持 1080P、720P、 VGA、QVGA 视频图像输出。本实验将 OV5640 配置为 RGB565 输出,先将视频数据写入外部存储 器,再从外部存储器读取送到 VGA、LCD 等显示模块。 module top( input clk, input rst_n, output cmos_scl, //cmos i2c clock inout cmos_sda, //cmos i2c data input cmos_vsync, //cmos vsync input cmos_href, //cmos hsync refrence,data valid input cmos_pclk, //cmos pxiel clock output cmos_xclk, //cmos externl clock input [7:0] cmos_db, //cmos data output cmos_rst_n, //cmos reset output cmos_pwdn, //cmos power down output vga_out_hs, //vga horizontal synchronization output vga_out_vs, //vga vertical synchronization output[4:0] vga_out_r, //vga red output[5:0] vga_out_g, //vga green output[4:0] vga_out_b, //vga blue output sdram_clk, //sdram clock output sdram_cke, //sdram clock enable output sdram_cs_n, //sdram chip select output sdram_we_n, //sdram write enable output sdram_cas_n, //sdram column address strobe output sdram_ras_n, //sdram row address strobe output[1:0] sdram_dqm, //sdram data enable output[1:0] sdram_ba, //sdram bank address output[12:0] sdram_addr, //sdram address inout[15:0] sdram_dq //sdram data ); parameter
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值