/*
 * snake.v
 * 
 * Snake - FPGA class project
 * 
 * 
 * Authors: Dario De Micco - Marta Martelossi
 * Contact: <email???>
 * Release date: oct 2013
 * 
 * References: "Tetris" class project
 *
 * 
 * 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 2 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, write to the Free Software
 * 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * 
 * MA 02110-1301, USA.
 * 
 */
 
// this is the main module. (top level entity) 
 
module snake (
		////////////////////	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		////////////////////////////////
inout		 			PS2_DAT;				//	PS2 Data
inout					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
////////////////////////////////////////////////////////////////////	

////////////////////////PARAMETER OVERRIDE////////////////////////////////

// codec parameters based on format of audio files (submodule)
defparam		audout0.CHANNEL_NUM = 2,
				audout0.DATA_WIDTH = 16,
				audout0.REF_CLK = 18432000,
				audout0.SAMPLE_RATE = 32000;

// audio data reader from flash
defparam		audio0.CHANNEL_NUM = 1,
				audio0.DATA_WIDTH = 16,
				audio0.REF_CLK = 18432000,
				audio0.SAMPLE_RATE = 32000;

//codec parameters based on format of audio files
parameter	REF_CLK			=	18432000;	//	18.432	MHz
parameter	SAMPLE_RATE		=	32000;		//	32		KHz
parameter	DATA_WIDTH		=	16;			//	16		Bits
parameter	CHANNEL_NUM		=	2;			//	Stereo

///////////////////////////////////////////////////////////////////////


// disable sdram
assign DRAM_CS_N=1'b1;	// chip select

//	Flash
assign	FL_RST_N	=	reset_n;
assign	FL_WE_N		=	1'b1;
assign	FL_CE_N		=	1'b0;
assign	FL_OE_N		=	1'b0;	


// audio connections
wire	CLK_18_4;

// assign	AUD_ADCLRCK	=	AUD_DACLRCK;
wire [DATA_WIDTH-1:0]	odata_tmp;
wire audio_WR;
wire [DATA_WIDTH-1:0]	audio_data;


assign	AUD_ADCLRCK	=	AUD_DACLRCK;

/*
// export clocks
// allow ext monitoring of system and peripherals clocks
assign GPIO_0[0]=clock_rnd;
assign GPIO_0[1]=CLOCK_50;
assign GPIO_0[2]=CLOCK_27[0];
assign GPIO_0[3]=clk_25;
assign GPIO_0[4]=clock_5hz;
assign GPIO_0[5]=clock_1hz;
assign GPIO_0[6]=VGA_HS;
assign GPIO_0[7]=VGA_VS;
assign GPIO_0[8]=I2C_SCLK;
assign GPIO_0[9]=AUD_BCLK;
assign GPIO_0[14]=AUD_DACLRCK;
assign GPIO_0[11]=AUD_XCK;
assign GPIO_0[12]=PS2_CLK;
*/

wire gameover;	
	
wire [9:0] ledbus;

assign LEDR=(gameover)?10'h3FF:ledbus;

wire clk_25, clock_1hz, clock_5hz;

wire reset_in;

wire vga_cal;

assign reset_in = SW[9];

assign ost_enable = ~SW[3];
assign sfx_enable = ~SW[4];

assign LEDG[0]=SW[0];
assign LEDG[1]=SW[1];

assign LEDG[3]=ost_play;
assign LEDG[4]=sfx_play;
// assign LEDG[6:5]=audio_sample_idx;

assign LEDG[7]=SW[9];
assign vga_cal=SW[8];

assign SRAM_UB_N = 1'b0;
assign SRAM_LB_N = 1'b0;


// sram arbiter connections
wire [15:0] vga_data;
wire [17:0] vga_addr;
wire vga_req;
wire vga_ack;
wire vga_lock;


wire [15:0] game_data;
wire [17:0] game_addr;
wire game_req;
wire game_ack;

wire bufselect;


// kb
wire [7:0] scancode; 
wire kbstrobe;
reg enterstrobe;
wire	enterkey;
reg kback, kbreq;

// Reset delay
wire reset, reset_n;

assign reset=~reset_n;

Reset_Delay	rst0	(.iRST(~reset_in), .iCLK(CLOCK_50), .oRESET(reset_n) );


// audio codec clock 18.432mhz 
Audio_PLL 	PLL1	(.areset(reset), .inclk0(CLOCK_27[0]),.c0(CLK_18_4));


// audio codec config
I2C_AV_Config 	u1	(	//	Host Side
						.iCLK(CLOCK_50),
						.iRST_N(reset_n),
						//	I2C Side
						.I2C_SCLK(I2C_SCLK),
						.I2C_SDAT(I2C_SDAT));


// audio DAC interface with FIFO
AUDIO_DAC_FIFO audout0
    (
      .iCLK_18_4 (CLK_18_4),
      .iDATA     (audio_data),
      .iRST_N    (reset_n),
      .iWR       (audio_WR),
      .iWR_CLK   (CLOCK_50),
      .oAUD_BCK  (AUD_BCLK),
      .oAUD_DATA (AUD_DACDAT),
      .oAUD_LRCK (AUD_DACLRCK),
      .oAUD_XCK  (AUD_XCK),
      .oDATA     (odata_tmp)
    );
	 
wire [1:0] audio_sample_idx;
wire audioready;

wire ost_play, sfx_play;
wire ost_active, sfx_active;
assign ost_play = ost_active & ~gameover & ost_enable;
assign sfx_play = sfx_active & sfx_enable;
wire ost_enable, sfx_enable;
  
// audio reading FSM
audio_fsm		audio0(.clock(CLOCK_50), .reset(reset),
					.enable(sfx_play),
					.flash_address(FL_ADDR), .flash_data(FL_DQ), 
					.fifo_full(odata_tmp[0]), 	.audio_data(audio_data), .fifo_WR (audio_WR),
					.sample_idx(audio_sample_idx),
					.audioready(audioready),
					.ost_enable(ost_play)
					);

// slow clocks generator  
clk_slow			divtime(.CLOCK_50(CLOCK_50), .CLOCK_1(clock_1hz), .CLOCK_5(clock_5hz), .reset(reset)
					);

// leds  
kitt				light0 (.clock(clock_5hz&~SW[1]), .reset(reset), .ledbus(ledbus)
					);  
  
// video system
sram_arbiter 	arb0 (	.clock(CLOCK_50), .reset(reset), 
					.sram_address(SRAM_ADDR), .sram_data(SRAM_DQ), .sram_ce_n(SRAM_CE_N), .sram_we_n(SRAM_WE_N), .sram_oe_n(SRAM_OE_N),
					.port_a_address(vga_addr), .port_a_data(vga_data), .port_a_req(vga_req), .port_a_ack(vga_ack), .lock(vga_lock),
					.port_b_address(game_addr), .port_b_data(game_data), .port_b_req(game_req), .port_b_ack(game_ack)
					);

clk_div 			divisore0 (	.clk_25(clk_25), .clk_50(CLOCK_50), .reset(reset)
					);

vgaoutput 		vga0 (	.clock(clk_25), .fast_clock(CLOCK_50), .reset(reset),
					.sram_address(vga_addr), .sram_data(vga_data), .sram_readreq(vga_req), .sram_readack(vga_ack), .fifo_warning(vga_lock),
					.r(VGA_R), .g(VGA_G), .b(VGA_B), .HSync(VGA_HS), .VSync(VGA_VS),
					.bufselect(bufselect), .calibrate(vga_cal)
					);


// input only mode
PS2_Controller	ps2_0(.CLOCK_50(CLOCK_50), .reset(reset),
					.the_command(), .send_command(1'b0),
					.PS2_CLK(PS2_CLK), .PS2_DAT(PS2_DAT),
					.command_was_sent(), .error_communication_timed_out(),
					.received_data(scancode),	.received_data_en(kbstrobe)	
					);	


/*
ps2keyb			keyb0(.ps2_clk(PS2_CLK), .ps2_data(PS2_DAT), 
					.sys_clk(CLOCK_50), .reset_n(~reset_in),
					.scancode(scancode), .strobe(kbstrobe)); 
					
					
*/
				
				
/*
testbench		tb0 (	.clock(CLOCK_50), .reset(reset_in),
					.sram_address(game_addr), .sram_data(game_data), .sram_writereq(game_req), .sram_writeack(game_ack),
					.bufselect(bufselect)
					);

*/

wire [2:0]	current_level;
wire [2:0]	fruit_count;

hex7				leveldisplay (.clock(CLOCK_50), .in({1'b0,current_level}), .out(HEX0) );
hex7				ftcntdisplay (.clock(CLOCK_50), .in({1'b0,fruit_count}), .out(HEX2) );

// turn off remaining digits
assign HEX1=8'hFF;
assign HEX3=8'hFF;

wire clock_rnd;

rndclk_pll		PLL2 (.areset(reset), .inclk0(CLOCK_50), .c0(clock_rnd));

gameblock		gb0 (	.clock(CLOCK_50), .reset(reset),
					.sram_address(game_addr), .sram_data(game_data), .sram_writereq(game_req), .sram_writeack(game_ack),
					.kb_scancode(scancode),.ps2strobe(kbstrobe), 
					.bufselect(bufselect),
					.ost_play(ost_active),.sfx_play(sfx_active),.sfx_idx(audio_sample_idx),.audioready(audioready),
					.clock_1hz(clock_1hz), .clock_5hz(clock_5hz), .fast_clock(clock_rnd),
					.pushbuttons(SW[0]),.KEY(KEY),.externalpause(~SW[1]),
					.gameover(gameover), 
					//.icurrent_level({SW[7],SW[6],SW[5]})
					.ocurrent_level(current_level),
					.ofruit_count(fruit_count),
					);

					
endmodule




