/*
 *   Titor - System - PS/2 controller wrapper
 *   Copyright (C) 2012,2013		Sean Ryan Moore
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

`ifdef INC_PS2_WRAPPER
`else
`define INC_PS2_WRAPPER

`timescale 1 ns / 100 ps

module PS2(
	ps2_clock,
	ps2_data,
	
	rx_data,
	rx_done,
	
	reset,
	clk
);
	`include "definition/Definition.v"
	
	inout								ps2_clock;
	inout								ps2_data;
	output	reg		[BYTE-1:0]			rx_data;
	output	reg							rx_done;
	input								reset;
	input								clk;
	
	localparam	BITTHROUGH		= 10;		// the number of bits to accept including Parity and Stop
	
	localparam	STATE_IDLE		= 32'd1,
				STATE_RX_BIT	= 32'd2;
	
			wire						devclk;
			wire						devclkneg;
			wire	[WORD-1:0]			bitcount;
			wire						bitarc;
			reg		[WORD-1:0]			state;
			reg		[BITTHROUGH-1:0]	shift_in;
			reg							postbitarc;

			reg		[BYTE-1:0]			clkbuf;
	
	// Clock line conditioning
	Debounce #(1*MICROS) stable (
		.linein(ps2_clock),
		.lineout(devclk),
		.reset(reset),
		.clk(clk)
	);
	Negedge tick (
		.linein(devclk),
		.lineout(devclkneg),
		.reset(reset),
		.clk(clk)
	);
	
	// Bit counting
	Radix_Counter #(BITTHROUGH) countoff (
		.carry_in((state==STATE_RX_BIT) && devclkneg),
		.carry_out(bitarc),
		.count(bitcount),
		.reset(reset),
		.clk(clk)
	);
	
	// Finite State Machine
	always @(posedge clk) begin
		if(reset)									state	<= STATE_IDLE;
		else if((state==STATE_IDLE) && devclkneg)	state	<= STATE_RX_BIT;
		else if((state==STATE_RX_BIT) && bitarc)	state	<= STATE_IDLE;
		else										state	<= state;
	end
	
	// Data capture
	always @(posedge clk) begin
		if(reset)			shift_in	<= 0;
		else if(devclkneg)	shift_in	<= {ps2_data, shift_in[BITTHROUGH-1:1]};
		else				shift_in	<= shift_in;
		
		if(reset)			postbitarc	<= 0;
		else				postbitarc	<= bitarc;
		
		if(reset)			rx_data	<= 0;
		else if(postbitarc)	rx_data	<= shift_in;
		else				rx_data	<= rx_data;
	end
	
	always @(posedge clk) begin
		if(reset)			rx_done		<= 0;
		else if(postbitarc)	rx_done		<= 1;
		else				rx_done		<= 0;
	end
endmodule

`endif
