`timescale 1 ns / 1 ps

module Decode ( 
	input   	Reset,
	input   	Sclk,
	input   	phaseA,
	input   	phaseB,
	output reg	ce,
	output reg	updown
);	

	// LR means left-right (counter-clockwise), RL = right-left (clockwise).   

	localparam [2:0] WAIT		= 4'b000;
	localparam [2:0] LR1 		= 4'b001;
	localparam [2:0] LR2 		= 4'b011;
	localparam [2:0] LR3 		= 4'b010;
	localparam [2:0] RL1 		= 4'b100;
	localparam [2:0] RL2 		= 4'b101;
	localparam [2:0] RL3 		= 4'b111;	
	localparam [2:0] COUNT		= 4'b110;
	
	reg [3:0] 	state; 
	reg [3:0]	next_state;
	wire		jk;	
	wire		count;	  
	wire 		phase_a_filtered;  
	wire 		phase_b_filtered; 
	wire [1:0]	quad;

	low_pass_filter phase_a_filter( 
		.clock_i(Sclk),
		.reset_i(Reset),
		.phase_i(phaseA),
		.filtered_phase_o(phase_a_filtered)
	);		

	low_pass_filter phase_b_filter( 
		.clock_i(Sclk),
		.reset_i(Reset),
		.phase_i(phaseB),
		.filtered_phase_o(phase_b_filtered)
	);	 
	
	assign quad = { phase_b_filtered, phase_a_filtered };

	always @(posedge Sclk)
		if (Reset) state <= WAIT;
		else state <= next_state;
		
	// The '// ?' are the physically un-reachable next_states.	

	always @* begin
    	next_state = 4'bx;
		case (state)	
			WAIT  : 
				case (quad)
					2'b00 :	next_state = WAIT ;
					2'b01 :	next_state = RL1;
					2'b10 :	next_state = LR1;
					2'b11 :	next_state = WAIT ;	
				endcase			
				
			LR1 :	  
				case (quad)
					2'b00 :	next_state = WAIT ;
					2'b01 :	next_state = LR1;	  	// ?
					2'b10 :	next_state = LR1;
					2'b11 :	next_state = LR2;	
				endcase
			
			LR2 :			
				case (quad)
					2'b00 :	next_state = LR2;		// ?
					2'b01 :	next_state = LR3;
					2'b10 :	next_state = LR1;
					2'b11 :	next_state = LR2;		// ?
				endcase
			
			LR3 :		
				case (quad)
					2'b00 :	next_state = COUNT;
					2'b01 :	next_state = LR3;
					2'b10 :	next_state = LR3; 		// ?
					2'b11 :	next_state = LR2;	
				endcase	   
			
			RL1 :	
				case (quad)
					2'b00 :	next_state = WAIT ;
					2'b01 :	next_state = RL1;
					2'b10 :	next_state = RL1;  		// ?
					2'b11 :	next_state = RL2;	
				endcase
			
			RL2 :
				case (quad)
					2'b00 :	next_state = RL2;		// ?
					2'b01 :	next_state = RL1;
					2'b10 :	next_state = RL3;
					2'b11 :	next_state = RL2;		// ?
				endcase
				
			RL3 :	   
				case (quad)
					2'b00 :	next_state = COUNT;
					2'b01 :	next_state = RL3;	  	// ?
					2'b10 :	next_state = RL3;
					2'b11 :	next_state = RL2;	
				endcase		   
				
			COUNT :
				next_state = WAIT ;
			
			default : next_state = WAIT ;	
		endcase 
	end		// of always @*	    
		
	assign jk = ( (next_state == RL1) & ~updown) | 
				(~(next_state == LR1) &  updown); 
	
	always @(posedge Sclk)
		if (Reset) updown  <= 1'b0;
		else updown <= jk;	
			
	assign count = (next_state == COUNT) ? 1 : 0;
			
	always @(posedge Sclk)
		if (Reset) ce  <= 1'b0;
		else ce <= count;
	
endmodule



