为什么在这个Verilog HDL代码中使用两个触发器而不是一个?

为什么在这个Verilog HDL代码中使用两个触发器而不是一个?,verilog,fpga,hdl,intel-fpga,Verilog,Fpga,Hdl,Intel Fpga,这个代码是一个按钮去Bouncer。 但我不明白为什么会有两个触发器: reg PB_sync_0; always @(posedge clk) PB_sync_0 <= ~PB; // invert PB to make PB_sync_0 active high reg PB_sync_1; always @(posedge clk) PB_sync_1 <= PB_sync_0; reg-PB\u-sync\u 0;always@(posedge clk)PB_sync

这个代码是一个按钮去Bouncer。 但我不明白为什么会有两个触发器:

reg PB_sync_0;  always @(posedge clk) PB_sync_0 <= ~PB;  // invert PB to make PB_sync_0 active high
reg PB_sync_1;  always @(posedge clk) PB_sync_1 <= PB_sync_0;

reg-PB\u-sync\u 0;always@(posedge clk)PB_sync_0此代码的autor使用2个触发器将PB信号同步到clk域。
正如他在一篇评论中提到的那样,“PB”是一种与clk异步的故障。

不同步时钟域转换上的信号可能会导致系统中的亚稳态,如工具IC所述

请参见此处的最后一张图片:这也解释了这一点。去抖动器做两件事:1)将外部异步输入同步到内部时钟,2)消除物理按钮的反弹。同步是用双触发器处理的,在这里你可以通过其他评论中的链接找到详细的描述。因为这个问题主要是关于电子(去抖动)的,所以可能应该移动到,尽管可能是重复的。Verilog问题在stackoverflow上很受欢迎,但应该是关于编写Verilog而不是硬件要求。这不是关于去抖动,而是关于亚稳定性。
reg PB_sync_1;  always @(posedge clk) PB_sync_1 <= ~PB;
module PushButton_Debouncer(
    input clk,
    input PB,  // "PB" is the glitchy, asynchronous to clk, active low push-button signal

    // from which we make three outputs, all synchronous to the clock
    output reg PB_state,  // 1 as long as the push-button is active (down)
    output PB_down,  // 1 for one clock cycle when the push-button goes down (i.e. just pushed)
    output PB_up   // 1 for one clock cycle when the push-button goes up (i.e. just released)
);

// First use two flip-flops to synchronize the PB signal the "clk" clock domain
reg PB_sync_0;  always @(posedge clk) PB_sync_0 <= ~PB;  // invert PB to make PB_sync_0 active high
reg PB_sync_1;  always @(posedge clk) PB_sync_1 <= PB_sync_0;

// Next declare a 16-bits counter
reg [15:0] PB_cnt;

// When the push-button is pushed or released, we increment the counter
// The counter has to be maxed out before we decide that the push-button state has changed

wire PB_idle = (PB_state==PB_sync_1);
wire PB_cnt_max = &PB_cnt;  // true when all bits of PB_cnt are 1's

always @(posedge clk)
if(PB_idle)
    PB_cnt <= 0;  // nothing's going on
else
begin
    PB_cnt <= PB_cnt + 16'd1;  // something's going on, increment the counter
    if(PB_cnt_max) PB_state <= ~PB_state;  // if the counter is maxed out, PB changed!
end

assign PB_down = ~PB_idle & PB_cnt_max & ~PB_state;
assign PB_up   = ~PB_idle & PB_cnt_max &  PB_state;
endmodule