//Legal Notice: (C)2006 Altera Corporation. All rights reserved. Your
//use of Altera Corporation's design tools, logic functions and other
//software and tools, and its AMPP partner logic functions, and any
//output files any of the foregoing (including device programming or
//simulation files), and any associated documentation or information are
//expressly subject to the terms and conditions of the Altera Program
//License Subscription Agreement or other applicable license agreement,
//including, without limitation, that your use is for the sole purpose
//of programming logic devices manufactured by Altera and sold by Altera
//or its authorized distributors.  Please refer to the applicable
//agreement for further details.


module CII_Starter_TOP
	(
		////////////////////	Clock Input	 	////////////////////	 
		CLOCK_24,						//	24 MHz
		CLOCK_27,						//	27 MHz
		CLOCK_50,						//	50 MHz
		EXT_CLOCK,						//	External Clock
		////////////////////	Push Button		////////////////////
		KEY,							//	Pushbutton[3:0]
		////////////////////	DPDT Switch		////////////////////
		SW,								//	Toggle Switch[9:0]
		////////////////////	7-SEG Dispaly	////////////////////
		HEX0,							//	Seven Segment Digit 0
		HEX1,							//	Seven Segment Digit 1
		HEX2,							//	Seven Segment Digit 2
		HEX3,							//	Seven Segment Digit 3
		////////////////////////	LED		////////////////////////
		LEDG,							//	LED Green[7:0]
		LEDR,							//	LED Red[9:0]
		////////////////////////	UART	////////////////////////
		UART_TXD,						//	UART Transmitter
		UART_RXD,						//	UART Receiver
		/////////////////////	SDRAM Interface		////////////////
		DRAM_DQ,						//	SDRAM Data bus 16 Bits
		DRAM_ADDR,						//	SDRAM Address bus 12 Bits
		DRAM_LDQM,						//	SDRAM Low-byte Data Mask 
		DRAM_UDQM,						//	SDRAM High-byte Data Mask
		DRAM_WE_N,						//	SDRAM Write Enable
		DRAM_CAS_N,						//	SDRAM Column Address Strobe
		DRAM_RAS_N,						//	SDRAM Row Address Strobe
		DRAM_CS_N,						//	SDRAM Chip Select
		DRAM_BA_0,						//	SDRAM Bank Address 0
		DRAM_BA_1,						//	SDRAM Bank Address 0
		DRAM_CLK,						//	SDRAM Clock
		DRAM_CKE,						//	SDRAM Clock Enable
		////////////////////	Flash Interface		////////////////
		FL_DQ,							//	FLASH Data bus 8 Bits
		FL_ADDR,						//	FLASH Address bus 22 Bits
		FL_WE_N,						//	FLASH Write Enable
		FL_RST_N,						//	FLASH Reset
		FL_OE_N,						//	FLASH Output Enable
		FL_CE_N,						//	FLASH Chip Enable
		////////////////////	SRAM Interface		////////////////
		SRAM_DQ,						//	SRAM Data bus 16 Bits
		SRAM_ADDR,						//	SRAM Address bus 18 Bits
		SRAM_UB_N,						//	SRAM High-byte Data Mask 
		SRAM_LB_N,						//	SRAM Low-byte Data Mask 
		SRAM_WE_N,						//	SRAM Write Enable
		SRAM_CE_N,						//	SRAM Chip Enable
		SRAM_OE_N,						//	SRAM Output Enable
		////////////////////	SD_Card Interface	////////////////
		SD_DAT,							//	SD Card Data
		SD_DAT3,						//	SD Card Data 3
		SD_CMD,							//	SD Card Command Signal
		SD_CLK,							//	SD Card Clock
		////////////////////	USB JTAG link	////////////////////
		TDI,  							// CPLD -> FPGA (data in)
		TCK,  							// CPLD -> FPGA (clk)
		TCS,  							// CPLD -> FPGA (CS)
	    TDO,  							// FPGA -> CPLD (data out)
		////////////////////	I2C		////////////////////////////
		I2C_SDAT,						//	I2C Data
		I2C_SCLK,						//	I2C Clock
		////////////////////	PS2		////////////////////////////
		PS2_DAT,						//	PS2 Data
		PS2_CLK,						//	PS2 Clock
		////////////////////	VGA		////////////////////////////
		VGA_HS,							//	VGA H_SYNC
		VGA_VS,							//	VGA V_SYNC
		VGA_R,   						//	VGA Red[3:0]
		VGA_G,	 						//	VGA Green[3:0]
		VGA_B,  						//	VGA Blue[3:0]
		////////////////	Audio CODEC		////////////////////////
		AUD_ADCLRCK,					//	Audio CODEC ADC LR Clock
		AUD_ADCDAT,						//	Audio CODEC ADC Data
		AUD_DACLRCK,					//	Audio CODEC DAC LR Clock
		AUD_DACDAT,						//	Audio CODEC DAC Data
		AUD_BCLK,						//	Audio CODEC Bit-Stream Clock
		AUD_XCK,						//	Audio CODEC Chip Clock
		////////////////////	GPIO	////////////////////////////
		GPIO_0,							//	GPIO Connection 0
		GPIO_1							//	GPIO Connection 1
	);

	////////////////////////	Clock Input	 	////////////////////////
	input	[1:0]	CLOCK_24;				//	24 MHz
	input	[1:0]	CLOCK_27;				//	27 MHz
	input			CLOCK_50;				//	50 MHz
	input			EXT_CLOCK;				//	External Clock
	////////////////////////	Push Button		////////////////////////
	input	[3:0]	KEY;					//	Pushbutton[3:0]
	////////////////////////	DPDT Switch		////////////////////////
	input	[9:0]	SW;						//	Toggle Switch[9:0]
	////////////////////////	7-SEG Dispaly	////////////////////////
	output	[6:0]	HEX0;					//	Seven Segment Digit 0
	output	[6:0]	HEX1;					//	Seven Segment Digit 1
	output	[6:0]	HEX2;					//	Seven Segment Digit 2
	output	[6:0]	HEX3;					//	Seven Segment Digit 3
	////////////////////////////	LED		////////////////////////////
	output	[7:0]	LEDG;					//	LED Green[7:0]
	output	[9:0]	LEDR;					//	LED Red[9:0]
	////////////////////////////	UART	////////////////////////////
	output			UART_TXD;				//	UART Transmitter
	input			UART_RXD;				//	UART Receiver
	///////////////////////		SDRAM Interface	////////////////////////
	inout	[15:0]	DRAM_DQ;				//	SDRAM Data bus 16 Bits
	output	[11:0]	DRAM_ADDR;				//	SDRAM Address bus 12 Bits
	output			DRAM_LDQM;				//	SDRAM Low-byte Data Mask 
	output			DRAM_UDQM;				//	SDRAM High-byte Data Mask
	output			DRAM_WE_N;				//	SDRAM Write Enable
	output			DRAM_CAS_N;				//	SDRAM Column Address Strobe
	output			DRAM_RAS_N;				//	SDRAM Row Address Strobe
	output			DRAM_CS_N;				//	SDRAM Chip Select
	output			DRAM_BA_0;				//	SDRAM Bank Address 0
	output			DRAM_BA_1;				//	SDRAM Bank Address 0
	output			DRAM_CLK;				//	SDRAM Clock
	output			DRAM_CKE;				//	SDRAM Clock Enable
	////////////////////////	Flash Interface	////////////////////////
	inout	[7:0]	FL_DQ;					//	FLASH Data bus 8 Bits
	output	[21:0]	FL_ADDR;				//	FLASH Address bus 22 Bits
	output			FL_WE_N;				//	FLASH Write Enable
	output			FL_RST_N;				//	FLASH Reset
	output			FL_OE_N;				//	FLASH Output Enable
	output			FL_CE_N;				//	FLASH Chip Enable
	////////////////////////	SRAM Interface	////////////////////////
	inout	[15:0]	SRAM_DQ;				//	SRAM Data bus 16 Bits
	output	[17:0]	SRAM_ADDR;				//	SRAM Address bus 18 Bits
	output			SRAM_UB_N;				//	SRAM High-byte Data Mask 
	output			SRAM_LB_N;				//	SRAM Low-byte Data Mask 
	output			SRAM_WE_N;				//	SRAM Write Enable
	output			SRAM_CE_N;				//	SRAM Chip Enable
	output			SRAM_OE_N;				//	SRAM Output Enable
	////////////////////	SD Card Interface	////////////////////////
	inout			SD_DAT;					//	SD Card Data
	inout			SD_DAT3;				//	SD Card Data 3
	inout			SD_CMD;					//	SD Card Command Signal
	output			SD_CLK;					//	SD Card Clock
	////////////////////////	I2C		////////////////////////////////
	inout			I2C_SDAT;				//	I2C Data
	output			I2C_SCLK;				//	I2C Clock
	////////////////////////	PS2		////////////////////////////////
	input		 	PS2_DAT;				//	PS2 Data
	input			PS2_CLK;				//	PS2 Clock
	////////////////////	USB JTAG link	////////////////////////////
	input  			TDI;					// CPLD -> FPGA (data in)
	input  			TCK;					// CPLD -> FPGA (clk)
	input  			TCS;					// CPLD -> FPGA (CS)
	output 			TDO;					// FPGA -> CPLD (data out)
	////////////////////////	VGA			////////////////////////////
	output			VGA_HS;					//	VGA H_SYNC
	output			VGA_VS;					//	VGA V_SYNC
	output	[3:0]	VGA_R;   				//	VGA Red[3:0]
	output	[3:0]	VGA_G;	 				//	VGA Green[3:0]
	output	[3:0]	VGA_B;   				//	VGA Blue[3:0]
	////////////////////	Audio CODEC		////////////////////////////
	inout			AUD_ADCLRCK;			//	Audio CODEC ADC LR Clock
	input			AUD_ADCDAT;				//	Audio CODEC ADC Data
	inout			AUD_DACLRCK;			//	Audio CODEC DAC LR Clock
	output			AUD_DACDAT;				//	Audio CODEC DAC Data
	inout			AUD_BCLK;				//	Audio CODEC Bit-Stream Clock
	output			AUD_XCK;				//	Audio CODEC Chip Clock
	////////////////////////	GPIO	////////////////////////////////
	inout	[35:0]	GPIO_0;					//	GPIO Connection 0
	inout	[35:0]	GPIO_1;					//	GPIO Connection 1
	
	//	Turn off all display
	assign	HEX0		=	7'h7F;
	assign	HEX1		=	7'h7F;
	assign	HEX2		=	7'h7F;
	assign	HEX3		=	7'h7F;
//	assign	LEDG		=	8'h00;
	assign	LEDR		=	10'h000;
	
	//	All inout port turn to tri-state
	assign	DRAM_DQ		=	16'bz;
	assign	FL_DQ		=	8'bz;
	assign	SRAM_DQ		=	16'bz;
	assign	SD_DAT		=	1'bz;
	assign	I2C_SDAT	=	1'bz;
	assign	AUD_ADCLRCK	=	1'bz;
	assign	AUD_DACLRCK	=	1'bz;
	assign	AUD_BCLK	=	1'bz;
	assign	GPIO_0		=	36'bz;
//	assign	GPIO_1		=	36'bz;
	

	reg		[9:0]	osc_counter;
	reg		[25:0]	hst_counter;
	
	reg 			osc_reset;
	reg 			osc_bit_num;
	wire	[9:0]	osc_start_addr;
	reg 	[9:0]	osc_addr;
	wire	[15:0]	osc_q;

	reg 			hst_reset;
	reg 	[1:0]	hst_bit_num;
	reg 	[11:0]	hst_addr;
	wire	[31:0]	hst_q;

	reg		[3:0]	state0, state1, state2;
	reg				adc_fifo_rdreq;
	wire			adc_fifo_rdempty;
	reg				adc_fifo_aclr;
	reg				rd_uart, wr_uart;
	wire			tx_full, rx_empty;

	wire	[7:0]	RxD_data;
	reg		[7:0]	TxD_data;

	wire	[4:0]	led;

	reg				adc_data_ready;
	wire			adc_dr, adc_or;
//	wire 	[11:0]	adc_data;
	reg 	[11:0]	adc_data;
    wire	[11:0]	raw_data;
    wire	[11:0]	uwt_data;
    wire	[1:0]	uwt_flag;
 
	assign 	GPIO_1[21:0]=	22'bz;
	assign 	adc_or		=	GPIO_1[35];
//	assign 	adc_data	=	GPIO_1[34:23];
//	assign 	adc_dr		=	GPIO_1[22];
	assign	adc_dr		=	CLOCK_24[0];

	assign	LEDG		=	{3'h0, led};

	assign	led[4]		=	hst_counter[23];

    uart uart_unit (
		.clk(CLOCK_50),
		.reset(1'b0),
		.rd_uart(rd_uart),
		.wr_uart(wr_uart),
		.rx(UART_RXD),
		.w_data(TxD_data),
		.tx_full(tx_full),
		.rx_empty(rx_empty),
		.r_data(RxD_data),
		.tx(UART_TXD));

	adc_fifo adc_fifo_unit (
		.adc_dr(adc_dr),
		.adc_or(adc_or),
		.adc_data(adc_data),
		.aclr(adc_fifo_aclr),
		.rdclk(CLOCK_50),
		.rdreq(adc_fifo_rdreq),
		.rdempty(adc_fifo_rdempty),
		.raw_data(raw_data),
		.uwt_data({uwt_flag, uwt_data}));

	histogram histogram_unit (
		.clk(CLOCK_50),
		.reset(hst_reset),
		.data_ready(adc_data_ready),
		.data(raw_data),
		.address(hst_addr),
		.q(hst_q),
		.led(led[3:0])
	);
	
	oscilloscope oscilloscope_unit (
		.clk(CLOCK_50),
		.reset(osc_reset),
		.data_ready(adc_data_ready),
		.raw_data(raw_data),
		.uwt_data(uwt_data),
		.threshold(16'd100),
		.address(osc_addr),
		.start_address(osc_start_addr),
		.q(osc_q)
	);


	always @ (posedge CLOCK_50)
	begin

		case (state0)
			1:
			begin
				if (~adc_fifo_rdempty)
				begin
					adc_fifo_rdreq <= 1'b1;
					adc_data_ready <= 1'b1;
					state0 <= 4'd2;
				end
			end

			2:
			begin
				adc_fifo_rdreq <= 1'b0;
				adc_data_ready <= 1'b0;
				state0 <= 4'd1;
			end

			default:
			begin
				state0 <= 4'd1;
			end
		endcase

		case (state1)
			1:
			begin
				rd_uart <= 1'b0;
				hst_reset <= 1'b0;
				osc_reset <= 1'b0;
				state1 <= 4'd2;
			end

			2: 
			begin
				if (~rx_empty)
				begin
					rd_uart <= 1'b1;
					case (RxD_data)
						8'h30:
						begin
							hst_reset <= 1'b1;
							state1 <= 4'd1;
						end
						8'h31: state1 <= 4'd3;
						8'h32:
						begin
							osc_reset <= 1'b1;
							state1 <= 4'd1;
						end
						8'h33: state1 <= 4'd7;
					endcase
				end
				else
				begin
					rd_uart <= 1'b0;
				end				
			end

			3:
			begin
				// start hst transfer
				rd_uart <= 1'b0;
				hst_addr <= 12'h0;
				hst_bit_num <= 2'd0;	
				state1 <= 4'd4;
			end

			4:
			begin
				case (hst_bit_num)
					2'd0: TxD_data <= hst_q[7:0];
					2'd1: TxD_data <= hst_q[15:8];
					2'd2: TxD_data <= hst_q[23:16];
					2'd3: TxD_data <= hst_q[31:24];
//					2'd0: TxD_data <= 8'd255;
//					2'd1: TxD_data <= 8'd0;
//					2'd2: TxD_data <= 8'd0;
//					2'd3: TxD_data <= 8'd0;
				endcase
				wr_uart <= 0;
			    state1 <= 4'd5;
			end

			5:
			begin
				if (~tx_full)
				begin
					wr_uart <= 1;
					state1 <= 4'd6;
				end
			end

			6:
			begin
				wr_uart <= 0;
				if (&hst_bit_num)
				begin
					hst_bit_num <= 2'd0;				
					if (&hst_addr)
					begin
						state1 <= 4'd1;
					end
					else
					begin
						hst_addr <= hst_addr + 12'd1;
						state1 <= 4'd4;
					end
				end
				else
				begin
					hst_bit_num <= hst_bit_num + 2'd1;				
					state1 <= 4'd4;
				end
			end


			7:
			begin
				// start osc transfer
				rd_uart <= 1'b0;
				osc_addr <= osc_start_addr;
				osc_bit_num <= 1'd0;
				osc_counter <= 10'd0;	
				state1 <= 4'd8;
			end

			8:
			begin
				case(osc_bit_num)
					1'd0: TxD_data <= osc_q[7:0];
					1'd1: TxD_data <= osc_q[15:8];
				endcase
				wr_uart <= 0;
			    state1 <= 4'd9;
			end

			9:
			begin
				if (~tx_full)
				begin
					wr_uart <= 1;
					state1 <= 4'd10;
				end
			end

			10:
			begin
				wr_uart <= 0;
				if (osc_bit_num)
				begin
					osc_bit_num <= 1'd0;				
					if (&osc_counter)
					begin
						state1 <= 4'd1;
					end
					else
					begin
						osc_addr <= osc_addr + 10'd1;
						osc_counter <= osc_counter + 10'd1;
						state1 <= 4'd8;
					end
				end
				else
				begin
					osc_bit_num <= osc_bit_num + 1'd1;				
					state1 <= 4'd8;
				end
			end

			default:
			begin
				// default state is the first one
				state1 <= 4'd1;
			end
		endcase
	end

	always @ (posedge adc_dr)
	begin
		case (state2)
			1: 
			begin
				adc_data <= 12'd0;
				state2 <= 4'd2;
			end
			
			2:
			begin
				adc_data <= 12'd1024;
				state2 <= 4'd3;
			end

			3:
			begin
				adc_data <= 12'd2048;
				state2 <= 4'd4;
			end

			4:
			begin
				adc_data <= 12'd3072;
				state2 <= 4'd5;
			end

			5:
			begin
				adc_data <= 12'd4095;
				state2 <= 4'd1;
			end

			default:
			begin
				state2 <= 4'd1;
			end
		endcase
	end
	
endmodule