// ports.v
// (c) 2017 David R. Hunter
//
// This is the port interface for the MicroVIP
//
// Revisions:
// 	08/16/17		DH		- initial version
//		08/20/17		DH		- continuously latch input port data with TPB
// 	09/01/17		DH		- add port 4 I/O
//
// ports used:		[] = future
//		#	OUT				IN
// 	1 	video off		video on
//		2	keypad			[ASCII Keyboard]
//		3	output port		input port
//		4	[I2C out]		[I2C in]
//		5	control reg		[UART status]
//		6	[UART txd]		[UART rxd]
//		7	SPI out			SPI in		(!Q = CS)	
//
// Video on/off are only strobe lines to PIXIE
// NOTE: with automatic ROM map, PORT 4 out to turn off ROM map 
// in original VIP is not needed



module ports(n,n0,mrd_n,tpb,din,dout,in_enb1,
			out_stb1,out_stb2,out_stb3,out_stb4,out_stb5,out_stb6,out_stb7,
			out_data2,out_data3,out_data4,out_data5,out_data6,out_data7,
			in_data2,in_data3,in_data4,in_data5,in_data6,in_data7			
			);

		input 	[2:0]n;				// port select lines from microprocessor
		output	n0;					// signal indicating N=0
		input		mrd_n;				// microprocessor read line
		input		tpb;					// timing pulse B
		input		[7:0]din;			// data from microprocessor
		output	[7:0]dout;			// data to microprocessor
		output	in_enb1;				// decoded input enable (video on)
		output	out_stb1;			// decoded output strobes
		output	out_stb2;
		output	out_stb3;
		output	out_stb4;
		output	out_stb5;
		output	out_stb6;
		output	out_stb7;		
		output	[3:0]out_data2;	// data to ports (keypad is only 4 bits)
		output	[7:0]out_data3;
		output	[7:0]out_data4;
		output	[7:0]out_data5;
		output	[7:0]out_data6;
		output	[7:0]out_data7;
		input		[7:0]in_data2;		// data from ports
		input		[7:0]in_data3;
		input		[7:0]in_data4;
		input		[7:0]in_data5;
		input		[7:0]in_data6;
		input		[7:0]in_data7;
		
		reg		[7:0]in_data3_latch;	// latch for input port
		
		// input 1 enable generator (decode with tpb to make a pulse)
		assign in_enb1 = ((n == 3'b001) & mrd_n & tpb);
		
		// output strobe generation
		assign out_stb1 = ((n == 3'b001) & (!mrd_n) & tpb);
		assign out_stb2 = ((n == 3'b010) & (!mrd_n) & tpb);
		assign out_stb3 = ((n == 3'b011) & (!mrd_n) & tpb);
		assign out_stb4 = ((n == 3'b100) & (!mrd_n) & tpb);
		assign out_stb5 = ((n == 3'b101) & (!mrd_n) & tpb);
		assign out_stb6 = ((n == 3'b110) & (!mrd_n) & tpb);
		assign out_stb7 = ((n == 3'b111) & (!mrd_n) & tpb);
		
		// input port assignment (just a pass through)
		assign out_data2 = din[3:0];		// keypad only uses lower 4 bits of bus
		assign out_data3 = din;
		assign out_data4 = din;
		assign out_data5 = din;
		assign out_data6 = din;
		assign out_data7 = din;
		
		// capture input port data with TPB
		// as long as data is held for at least 8 clocks (>4.5us) it will be captured
		// so the input strobe can be used for handshaking
		always @(posedge tpb)
		begin
			in_data3_latch <= in_data3;
		end
		
		// multiplex data to processor from ports
		assign dout = 	(n == 3'b010) ? in_data2 :
							(n == 3'b011) ? in_data3_latch :
							(n == 3'b100) ? in_data4 :
							(n == 3'b101) ? in_data5 :
							(n == 3'b110) ? in_data6 :
							(n == 3'b111) ? in_data7 : 8'h00;
							
		// set n0
		assign n0 = (n == 3'b000);
		
endmodule
