按键消抖(2)

这篇文章详细解析了一个使用32位计数器和双级D触发器实现的按键抖动去抖电路。通过异或操作检测键值变化,计数器控制输出稳定状态,介绍上升沿和下降沿信号采集方法。核心在于理解异或运算在锁定键值变化和计时器控制中的应用。
摘要由CSDN通过智能技术生成
//*******************************************************************************/

`timescale 1 ns / 100 ps
module  ax_debounce 
(
    input       clk, 
    input       rst, 
    input       button_in,
    output reg  button_posedge,
    output reg  button_negedge,
    output reg  button_out
);
 ---------------- internal constants --------------
parameter N = 32 ;           // debounce timer bitwidth
parameter FREQ = 50;         //model clock :Mhz
parameter MAX_TIME = 20;     //ms
localparam TIMER_MAX_VAL =   MAX_TIME * 1000 * FREQ;
---------------- internal variables ---------------
reg  [N-1 : 0]  q_reg;      // timing regs
reg  [N-1 : 0]  q_next;
reg DFF1, DFF2;             // input flip-flops
wire q_add;                 // control flags
wire q_reset;
reg button_out_d0;
 ------------------------------------------------------

contenious assignment for counter control
assign q_reset = (DFF1  ^ DFF2);          // xor input flip flops to look for level chage to reset counter
assign q_add = ~(q_reg == TIMER_MAX_VAL); // add to counter when q_reg msb is equal to 0
    
 combo counter to manage q_next 
always @ ( q_reset, q_add, q_reg)
begin
    case( {q_reset , q_add})
        2'b00 :
                q_next <= q_reg;
        2'b01 :
                q_next <= q_reg + 1;
        default :
                q_next <= { N {1'b0} };
    endcase     
end

 Flip flop inputs and q_reg update
always @ ( posedge clk or posedge rst)
begin
    if(rst == 1'b1)
    begin
        DFF1 <= 1'b0;
        DFF2 <= 1'b0;
        q_reg <= { N {1'b0} };
    end
    else
    begin
        DFF1 <= button_in;
        DFF2 <= DFF1;
        q_reg <= q_next;
    end
end

 counter control
always @ ( posedge clk or posedge rst)
begin
	if(rst == 1'b1)
		button_out <= 1'b1;
    else if(q_reg == TIMER_MAX_VAL)
        button_out <= DFF2;
    else
        button_out <= button_out;
end

always @ ( posedge clk or posedge rst)
begin
	if(rst == 1'b1)
	begin
		button_out_d0 <= 1'b1;
		button_posedge <= 1'b0;
		button_negedge <= 1'b0;
	end
	else
	begin
		button_out_d0 <= button_out;
		button_posedge <= ~button_out_d0 & button_out;
		button_negedge <= button_out_d0 & ~button_out;
	end	
end
endmodule 

原理

    模块中通过了两级 D 触发器来寄存键值,只有当键值稳定时才将键值输出。我们可以看到在 assign 赋值语句中有一条“assign a_reset=(DFF1 ^ DFF2)”,学过数字电路的应该都知道“ ^ ” 是异或运算符,运算符两边相同运算结果为 0, 不同运算结果为 1。在程序中 DFF1 和 DFF2 比较 运算后的值通过“assign”赋给“a_reset”表示比较锁存键值的前后两级寄存器的值是否一致,只 有前后两级寄存器的值一致,也就是 a_reset 的值为 0 时才表示当前锁存的键值没有变化。当计 数器累加到“TIMER_MAX_VAL”,表示锁存的键值已经稳定可以输出。另外在模块中我们可以看 到“{.......}”符号,要注意这可不是大括号,这表示位拼接运算符,其作用是将运算符内的两位, 或是多位信号拼接在一起。

    最后,程序中需要说明的是“button_posedge”和“button_negedge”两个输出信号,这是一 种常用的上升沿和下降沿的采集方法,其描述的 RTL 视图如下:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值