/* This module recieves a single bit input, dataIn, and creates a debounced output, 
dataOut. The the circuit will create a delay of 2ms to account for the mechanical ringing,
assuming that you have a 50MHz clock driving the module. [50MHz corresponds to 20nsec of 
delay for the clock. To obtain a 2ms delay, a counter must count up to 100,000 (MaxCount). 
e.g. 100,000*20ns=2ms.] In order to achieve this functionality, a a$state machine has been 
designed. The a$state machine resets in the 00 a$state, which assumes dataIn=0. If dataIn=0, 
you remain at the 00 a$state. If dataIn=1, you move to a debounce a$state, 01. In this a$state,
a counter is enabled (CEN) to count to 100,000, creating the 2ms delay. The output signal,
dataOut remains low until the counter reaches 100,000. At this point, the counter tells
the a$state machine it is done counting (using the Done signal) and the a$state machine can
move on to the next a$state (10). The a$state machine will remain in this a$state as long as 
the input is high. If the input goes low, the a$state machine will move to another a$state (11)
that enables the counter again to count to 100,000. Once the counter has reached 100,000,
the a$state machine returns to the initial a$state, 00. The counter is reset in the 00 and 10 
states through the CR signal.*/

module debounce(clock, reset, dataIn, dataOut);

input clock, reset, dataIn;	//dataIn comes from the I/O board.
output dataOut;		//dataOut goes to your circuit.

reg dataOut; 
reg [1:0] state, nextstate;	//state variables for the state machine
reg Done, CEN, CR;		//CEN= counter enable CR=counter reset Done=tells the a$state machine that the counter is done counting
reg [16:0] Q;			//output of the counter
 
parameter MaxCount = 100000;
//parameter MaxCount = 16;	//for test only
parameter s0=2'b00, s1=2'b01, s2=2'b10, s3=2'b11;

//state register 
always @ (posedge clock or posedge reset)
   if (reset)      
	state <= 2'b00;
   else         
	state <= nextstate;

//next state decoder
always @ (state or dataIn or Done)
	case (state)
	s0:	nextstate<=(dataIn)? s1:s0;
	s1:	if (~Done)
			nextstate<=s1;
		else
			nextstate<=(dataIn)? s2:s0;
	s2:	nextstate<=(dataIn)? s2:s3;
	s3:	if (~Done)
			nextstate<=s3;
		else
			nextstate<=(dataIn)? s2:s0;
	default: nextstate<=s0;
	endcase

//output decoder
always @ (state) begin
	dataOut<= (state==s2 | state==s3);
	CEN <= (state==s1 | state==s3);
	CR <= (state==s1 | state==s3);
	end

//counter
always @ (posedge clock or negedge CR)
	if (CR==0)
		Q<=0; 
	else if (CEN)
		Q<=Q+1;
	else
		Q<=Q;

always @ (Q)
	 Done <= (Q==MaxCount);

endmodule