module bad_debouncer( clk, in, out, r, en ); // *** INPUTS *** input clk, r, en; input in; // *** OUTPUTS *** output out; // We want to assign this value via combinational logic so it also needs // to be a reg. reg out; // *** COMBINATIONAL SIGNALS *** // More combinational signals for the counter reg counter_reset, counter_enable; // *** DELAY COUNTER *** // Define a basic 20-bit counter by having the input be the output plus // one. Note that we are using the reset and enables on the dffre. wire [19:0] counter_out; dffre #(20) counter( .clk(clk), .d(counter_out+20'b1), .q(counter_out), .r(counter_reset || r), .en(counter_enable && en) ); // *** DEBOUNCING FSM *** // Define our states-- I've selected one-hot encoding `define LOW 4'b0001 `define WAIT_HIGH 4'b0010 `define HIGH 4'b0100 `define WAIT_LOW 4'b1000 // next_state_d is a reg because we want to assign combinational logic to it reg [3:0] next_state_d; // current_state_q is a wire becaues we just want to route it to our case // statement. wire [3:0] current_state_q; // Next state logic always @(current_state_q or in or counter_out[19]) begin case (current_state_q) // LOW: We are currently low and are outputing a 0 // unless the in goes high. Then we want to go and // output a high ignoring any changes until the counter // resets. Notice that we are keepign the couter // reset and disabled. `LOW: begin out = 1'b0; counter_reset = 1'b1; counter_enable = 1'b0; if (in) begin next_state_d = `WAIT_HIGH; end else begin next_state_d = `LOW; end end // WAIT_HIGH: We are waiting to go high after a low-to-high // transition. Here we are ignoring the input (and keeping // the output high) until the timer expires. Then we will // go and wait for a high-to-low transition. `WAIT_HIGH : begin out = 1'b1; counter_reset = 1'b0; counter_enable = 1'b1; if (counter_out[19]) begin next_state_d = `HIGH; end else begin next_state_d = `WAIT_HIGH; end end // HIGH: This is the same as LOW but with the output being high. // I.e., we are waiting for a high-to-low transition. `HIGH : begin out = 1'b1; counter_reset = 1'b1; counter_enable = 1'b0; if (~in) begin next_state_d = `WAIT_LOW; end else begin next_state_d = `HIGH; end end // WAIT_LOW: Here we got a high-to-low transition so we output a 0 // and ignore the input until the counter expires, then we go back // to waiting for a low-to-high transition. `WAIT_LOW : begin out = 1'b0; counter_reset = 1'b0; counter_enable = 1'b1; if (counter_out[19]) begin next_state_d = `LOW; end else begin next_state_d = `WAIT_LOW; end end // We have the default case in here because we will start up // with all FFs being 0, so we need to get into our initial // LOW (0001) state. default : begin out = 1'b0; counter_reset = 1'b1; counter_enable = 1'b0; next_state_d = `LOW; end endcase end // State register dffre #(4) state( .clk(clk), .d(next_state_d), .q(current_state_q), .r(r), .en(en) ); endmodule