Search code examples
verilogsystem-verilog

Debouncer in Verilog


I'm trying to implement this debouncer circuit in Verilog. This is the code I got, and I believe it should work, but it doesn't. The problem is that the button_debounce signal is always 0.

enter image description here

module divider(clk, reset, divded_clock_out);
    input clk;
    input reset;
    
    output reg divded_clock_out;
    reg [19:0]counter;
    
    always @(posedge clk or negedge reset)
    begin
        if(!reset)
            counter <= 0;
        else
        begin
            if (counter == 999999)
                counter <= 0;
            else
                counter <= counter + 1;
                
            if (counter < 499999)
                divded_clock_out <= 0;
            else
                divded_clock_out <= 1;
        end
    end

endmodule
module dff(clk, D, Q, reset);
    input clk;
    input reset;
    input D;
    output reg Q;
    
    always @ (posedge clk or posedge reset)
    begin
        if(reset)
            Q <= 1'b0;
        else
            Q <= D;
    end
endmodule

module debounce(clk, button, button_debounce, reset);
    input clk;
    input reset;
    input button;
    output button_debounce;
    wire [2:0]reg_wire;
    
    dff reg1(clk, button, reg_wire[0], reset);
    dff reg2(clk, reg_wire[0], reg_wire[1], reset);
    dff reg3(clk, reg_wire[1], reg_wire[2], reset);
    
    assign button_debounce = reg_wire[0] & reg_wire[1] & reg_wire[2];
endmodule
module debouncer_tb();
    reg clk;
    reg reset;
    reg button;
    
    wire divded_clock_out;
    wire button_debounce;
    
    initial begin
        clk = 0;
        reset = 0;
        button = 0;
        #10;
        reset = 1;
        button = 1;
    end
    
    always #10 clk=~clk;
    
    divider uut(clk, reset, divded_clock_out);
    
    debounce uut2(divded_clock_out, button, button_debounce);
endmodule

The divider works as expected, and I believe it's only a problem with the debouncer module. For the simulation testbench, the output of the divider is correct and the output of the debouncer is always 0, and it should be 1 when the button input changes to 1.


Solution

  • When I run a simulation, I get the following compile warning:

        debounce uut2(divded_clock_out, button, button_debounce);
                    |
    xmelab: *W,CUVWSI : 1 input port was not connected:
    xmelab: reset
    

    The debounce module has 4 ports, but you only connected 3 of them. Check your log files to see if you have a similar message.

    Also, when I run the simulation, I see button_debounce as X (unknown), not 0.

    When I change:

    debounce uut2(divded_clock_out, button, button_debounce);
    

    to:

    debounce uut2(divded_clock_out, button, button_debounce, ~reset);
    

    I see button_debounce go to 1, as desired. I added reset to the connection list. Note that I inverted the reset signal because your dff modules use an active-high reset, whereas the divider uses an active-low reset.

    However, using connection-by-order, as shown above, is error prone. It is better to use connection-by-name:

    debounce uut2 (
        .clk                (divded_clock_out),
        .button             (button),
        .button_debounce    (button_debounce),
        .reset              (~reset)
    );