1
votes

I have a circuit designed to debounce a switch. It samples the signal every 1 ms and counts for 8ms in a shift register. When the register has counted 8 1ms ticks of a high signal ,we assume the signal is clean and output sig_clean goes high. For some reason, every tick of the 1KHz clock (the 1 ms clock), my clean signal drops to 0 and then goes right back up at the next tick of the onboard clock. Any idea why this is happening?

`timescale 1ns / 1ps

module debounce(
    input Clk100MHz, reset_n, Clk1KHzEn, sig,
    output reg sig_clean);

    reg [7:0] sigconfirm;

    initial sigconfirm = 8'b0000_0000;
    initial sig_clean = 0;

always@(posedge Clk100MHz)
    begin
        if(~reset_n)
            sig_clean <= 0;
        else
            if(Clk1KHzEn == 1)
                begin
                    if(sig == 1)
                        begin
                            sigconfirm[7] <= 1;
                            sigconfirm = sigconfirm >> 1;
                        end
                    else
                        begin
                            sigconfirm[7] <= 0;
                            sigconfirm = sigconfirm >> 1;
                        end
                end
    end

always@(posedge Clk100MHz)
    begin
        if(sigconfirm == 8'b1111_1111)
            sig_clean <= 1;
        else
            sig_clean <= 0;
    end 
endmodule

Waveform of error

The testbench:

`timescale 1ns / 1ps

module lab_7_top_tb();

reg Clk100MHz, BTNC, BTNU;
wire CA, CB, CC, CD, CE, CF, CG, DP;
wire [7:0] AN;

lab_7_top labtop(
    .Clk100MHz(Clk100MHz),
    .BTNC(BTNC),
    .BTNU(BTNU),
    .CA(CA),
    .CB(CB),
    .CC(CC),
    .CD(CD),
    .CE(CE),
    .CF(CF),
    .CG(CG),
    .DP(DP),
    .AN(AN)
);

initial Clk100MHz = 0;
always #5 Clk100MHz = ~Clk100MHz;

initial begin
    BTNC = 1'b1; BTNU = 1'b0;
    #100;
    BTNC = 1'b0;
    #1000;
    press_BTNU;
    #1000;
    press_BTNU;
    #1000;
    $finish;
end

task press_BTNU;
    begin
        $display("%d Start of press button task", $time);
        BTNU = 0;
        #1000;
        BTNU = 1;
        #1500;
        BTNU = 0;
        #1200;
        BTNU = 1;
        #1800;
        BTNU = 0;
        #1100;
        BTNU = 1;
        #15000;
        BTNU = 0;
        #1800;
        BTNU = 1;
        #1600;
        BTNU = 0;
        #1400;
        BTNU = 1;
        #1100;
        BTNU = 0;
        #15000;
        $display("%d End of press button task", $time);
    end
endtask

endmodule

2
It would be helpful if you show your testbench code.sharvil111
you have a race between sigconfirm and clock. Pleas use 'non-blocking' assignment when assign it in both cases sigconfirm <= sigconfirm >> 1;Serge

2 Answers

1
votes

Turns out the issue was 2 fixes: I fixed the blocking assignment like Serge suggested, and I swapped the order that sigconfirm shifted and assigned the bit, to get:

sigconfirm <= sigconfirm >> 1;
sigconfirm[7] <= 1'b1;

and now life is good!

0
votes

You put your reset of sig_clean in the wrong always block. Should be

always @(posedge Clk100MHz)
    if (!reset_n)
        sig_clean <= 0; 
    else if(sigconfirm == 8'b1111_1111)
            sig_clean <= 1;
         else
            sig_clean <= 0;
endmodule