module VGA_LED_Emulator(
 input logic 	     clk50, reset,
 input logic [7:0]  hex0, hex1, hex2, hex3, hex4, hex5, hex6, hex7, hex8, hex9,
						  hex10, hex11, hex12, hex13, hex14, hex15, hex16, hex17, hex18, hex19,
						  hex20, hex21, hex22, hex23, hex24, hex25, hex26, hex27, hex28, hex29,
						  hex30, hex31, hex32, hex33, hex34, hex35, hex36, hex37, hex38, hex39,
						  hex40, hex41, hex42, hex43, hex44, hex45, hex46, hex47, hex48, hex49,
						  hex50, hex51, hex52, hex53, hex54, hex55, hex56, hex57, hex58, hex59,
 output logic [7:0] VGA_R, VGA_G, VGA_B,
 output logic 	     VGA_CLK, VGA_HS, VGA_VS, VGA_BLANK_n, VGA_SYNC_n);

/*
 * 640 X 480 VGA timing for a 50 MHz clock: one pixel every other cycle
 * 
 *HCOUNT 1599 0             1279       1599 0
 *            _______________              ________
 * __________|    Video      |____________|  Video
 * 
 * 
 * |SYNC| BP |<-- HACTIVE -->|FP|SYNC| BP |<-- HACTIVE
 *       _______________________      _____________
 * |____|       VGA_HS          |____|
 */

 	parameter radius_square = 20'd 1024;
 
   parameter HACTIVE      = 11'd 1280,
             HFRONT_PORCH = 11'd 32,
             HSYNC        = 11'd 192,
             HBACK_PORCH  = 11'd 96,   
             HTOTAL       = HACTIVE + HFRONT_PORCH + HSYNC + HBACK_PORCH; //1600

   parameter VACTIVE      = 10'd 480,
             VFRONT_PORCH = 10'd 10,
             VSYNC        = 10'd 2,
             VBACK_PORCH  = 10'd 33,
             VTOTAL       = VACTIVE + VFRONT_PORCH + VSYNC + VBACK_PORCH; //525

   logic [10:0]			     hcount; // Horizontal counter
   logic 			     endOfLine;
   
   always_ff @(posedge clk50 or posedge reset)
     if (reset)          hcount <= 0;
     else if (endOfLine) hcount <= 0;
     else  	         hcount <= hcount + 11'd 1;

   assign endOfLine = hcount == HTOTAL - 1;

	
   // Vertical counter
   logic [9:0] 			     vcount;
	logic[9:0]			vcount_plus1;
   logic 			     endOfField;
   
   always_ff @(posedge clk50 or posedge reset)
     if (reset)          vcount <= 0;
     else if (endOfLine)
       if (endOfField)   vcount <= 0;
       else              vcount <= vcount + 10'd 1;

   assign endOfField = vcount == VTOTAL - 1;

   // Horizontal sync: from 0x520 to 0x57F
   // 101 0010 0000 to 101 0111 1111
   assign VGA_HS = !( (hcount[10:7] == 4'b1010) & (hcount[6] | hcount[5]));
   assign VGA_VS = !( vcount[9:1] == (VACTIVE + VFRONT_PORCH) / 2);

   assign VGA_SYNC_n = 1; // For adding sync to video signals; not used for VGA
   
   // Horizontal active: 0 to 1279     Vertical active: 0 to 479
   // 101 0000 0000  1280	       01 1110 0000  480	       
   // 110 0011 1111  1599	       10 0000 1100  524        
   assign VGA_BLANK_n = !( hcount[10] & (hcount[9] | hcount[8]) ) &
			!( vcount[9] | (vcount[8:5] == 4'b1111) );   

   assign VGA_CLK = hcount[0]; // 25 MHz clock: pixel latched on rising edge
 





 
///////////////////////////
/*     added by cong     */
///////////////////////////		
		logic					inEdge;
		logic 				insurface;
		logic 				inBall_1;
		logic 				inBall_2;
		logic 				inBall_3;
		logic 				inBall_4;		
		logic 				inHole;
		logic 				inEndPoint;
		logic					shelter;	
		logic [10:0]		hcount_s;  
		
		logic 				hitSurface_s1;
		logic 				hitSurface_s2;
		logic 				hitSurface_s3;
		logic 				hitSurface_s4;
		logic 				hitSurface_s5;
		
		logic 				hitEdge_s1;
		logic 				hitEdge_s2;
		logic 				hitEdge_s3;
		logic 				hitEdge_s4;
		logic 				hitEdge_s5;
		
		logic					hitSurface_b;
///////////////////////////
/*      Framebuffer      */
///////////////////////////
		logic					fb_odd_wren;
		logic[127:0]		fb_odd_out;
		integer				fb_odd_waddr;
		integer				fb_odd_raddr;
		integer				fb_odd_addr;
		
		logic					fb_even_wren;
		logic[127:0]		fb_even_out;
		integer				fb_even_waddr;
		integer				fb_even_raddr;
		integer				fb_even_addr;

//////////////////////////
//  Space  information  //
//////////////////////////		
		integer				x;
		integer 				y;
		integer 				z;
		integer 				x_r1;
		integer 				y_r1;
		integer	 			z_r1;
		integer 				x_r2;
		integer 				y_r2;
		integer	 			z_r2;
		integer				x0;
				
		integer				sin__x;
		integer				cos__x;
		integer				sin__y;
		integer				cos__y;

		integer				scan_count;
		integer				vcount_integer;
		integer				hcount_s_pack;
		integer 				hcount_s_surface;
		integer				hcount_s_edge;
		integer				hcount_s_ball_1;		
		integer				hcount_s_ball_2;
		integer				hcount_s_ball_3;		
		integer				hcount_s_ball_4;		
		integer				hcount_s_hole;		
		integer				hcount_s_endPoint;
		
		reg [15:0][7:0]	plane;
		logic[127:0]		plane_r;
		reg [3:0]			section_sel = 4'b0;

//////////////////////////
//  object information  //
//////////////////////////

//  square one
		integer	x1_s1;
		integer	x2_s1;
		integer	y1_s1;
		integer	y2_s1;
		integer	z1_s1;
		integer	z2_s1;
		
//  square two
		integer	x1_s2;
		integer	x2_s2;
		integer	y1_s2;
		integer	y2_s2;
		integer	z1_s2;
		integer	z2_s2;
		
//  square three
		integer	x1_s3;
		integer	x2_s3;
		integer	y1_s3;
		integer	y2_s3;
		integer	z1_s3;
		integer	z2_s3;
		
//  square four
		integer	x1_s4;
		integer	x2_s4;
		integer	y1_s4;
		integer	y2_s4;
		integer	z1_s4;
		integer	z2_s4;
		
//  square five
		integer	x1_s5;
		integer	x2_s5;
		integer	y1_s5;
		integer	y2_s5;
		integer	z1_s5;
		integer	z2_s5;		

//  end point
		integer  x_ep;
		integer	x1_ep;
		integer	x2_ep;
		integer	y_ep;
		integer  z_ep;
		integer	z1_ep;
		integer	z2_ep;
		
//  ball one
		integer	x_b1;
		integer	y_b1;
		integer	z_b1;
		integer	x1_b1;
		integer	y1_b1;
		integer	z1_b1;
		integer	x2_b1;
		integer	y2_b1;
		integer	z2_b1;
		
//  ball two
		integer	x_b2;
		integer	y_b2;
		integer	z_b2;
		integer	x1_b2;
		integer	y1_b2;
		integer	z1_b2;
		integer	x2_b2;
		integer	y2_b2;
		integer	z2_b2;

//  ball three
		integer	x_b3;
		integer	y_b3;
		integer	z_b3;
		integer	x1_b3;
		integer	y1_b3;
		integer	z1_b3;
		integer	x2_b3;
		integer	y2_b3;
		integer	z2_b3;
		
//  ball four
		integer	x_b4;
		integer	y_b4;
		integer	z_b4;
		integer	x1_b4;
		integer	y1_b4;
		integer	z1_b4;
		integer	x2_b4;
		integer	y2_b4;
		integer	z2_b4;
///////////////////////////
/*ball select information*/
///////////////////////////
		reg[1:0] 		ball_select;

		integer	x1_b;
		integer	y1_b;
		integer	z1_b;
		integer	x2_b;
		integer	y2_b;
		integer	z2_b;
	
/////////////////////
/*state information*/
/////////////////////
		logic		start = 1'b0;
		logic		gameover;
		
//////////////////////
/* set object value */
//////////////////////

//  end point 
		assign   x_ep = {{24{hex7[7]}}, hex7};
		assign 	y_ep = {{24{hex8[7]}}, hex8};
		assign   z_ep = {{24{hex9[7]}}, hex9};
		assign 	x1_ep = x_ep - 5;
		assign 	x2_ep = x_ep + 5;
		assign 	z1_ep = z_ep - 5;
		assign 	z2_ep = z_ep + 5;
		
//  square one
		assign	x1_s1 = {{24{hex10[7]}}, hex10};//-50;
		assign	x2_s1 = {{24{hex11[7]}}, hex11};//-40;
		assign	y1_s1 = {{24{hex12[7]}}, hex12};//-50;
		assign	y2_s1 = {{24{hex13[7]}}, hex13};//-40;
		assign	z1_s1 = {{24{hex14[7]}}, hex14};//-50;
		assign	z2_s1 = {{24{hex15[7]}}, hex15};//50;
		
//  square two
		assign	x1_s2 = {{24{hex16[7]}}, hex16};//-40;
		assign	x2_s2 = {{24{hex17[7]}}, hex17};//20;
		assign	y1_s2 = {{24{hex18[7]}}, hex18};//40;
		assign	y2_s2 = {{24{hex19[7]}}, hex19};//50;
		assign	z1_s2 = {{24{hex20[7]}}, hex20};//-50;
		assign	z2_s2 = {{24{hex21[7]}}, hex21};//-40;
		
//  square three
		assign	x1_s3 = {{24{hex22[7]}}, hex22};//40;
		assign	x2_s3 = {{24{hex23[7]}}, hex23};//50;
		assign	y1_s3 = {{24{hex24[7]}}, hex24};//0;
		assign	y2_s3 = {{24{hex25[7]}}, hex25};//10;
		assign	z1_s3 = {{24{hex26[7]}}, hex26};//-10;
		assign	z2_s3 = {{24{hex27[7]}}, hex27};//50;
		
//  square four
		assign	x1_s4 = {{24{hex28[7]}}, hex28};//-20;
		assign	x2_s4 = {{24{hex29[7]}}, hex29};//50;
		assign	y1_s4 = {{24{hex30[7]}}, hex30};//-20;
		assign	y2_s4 = {{24{hex31[7]}}, hex31};//-10;
		assign	z1_s4 = {{24{hex32[7]}}, hex32};//40;
		assign	z2_s4 = {{24{hex33[7]}}, hex33};//50;
		
//  square five
		assign	x1_s5 = {{24{hex34[7]}}, hex34};//-50;
		assign	x2_s5 = {{24{hex35[7]}}, hex35};//20;
		assign	y1_s5 = {{24{hex36[7]}}, hex36};//-20;
		assign	y2_s5 = {{24{hex37[7]}}, hex37};//-10;
		assign	z1_s5 = {{24{hex38[7]}}, hex38};//0;
		assign	z2_s5 = {{24{hex39[7]}}, hex39};//10;		
		
//	 ball one 
		assign   x_b1 = {{24{hex40[7]}}, hex40};
		assign   y_b1 = {{24{hex41[7]}}, hex41};
		assign   z_b1 = {{24{hex42[7]}}, hex42};
		assign 	x1_b1 = x_b1 - 4;
		assign 	y1_b1 = y_b1 - 4;
		assign 	z1_b1 = z_b1 - 4;
		assign 	x2_b1 = x_b1 + 4;
		assign 	y2_b1 = y_b1 + 4;
		assign 	z2_b1 = z_b1 + 4;
		
//  ball two
		assign   x_b2 = {{24{hex43[7]}}, hex43};
		assign   y_b2 = {{24{hex44[7]}}, hex44};
		assign   z_b2 = {{24{hex45[7]}}, hex45};
		assign 	x1_b2 = x_b2 - 4;
		assign 	y1_b2 = y_b2 - 4;
		assign 	z1_b2 = z_b2 - 4;
		assign 	x2_b2 = x_b2 + 4;
		assign 	y2_b2 = y_b2 + 4;
		assign 	z2_b2 = z_b2 + 4;

//  ball three		
		assign 	x_b3 = {{24{hex46[7]}}, hex46};
		assign 	y_b3 = {{24{hex47[7]}}, hex47};
		assign 	z_b3 = {{24{hex48[7]}}, hex48};
		assign 	x1_b3 = x_b3 - 4;
		assign 	y1_b3 = y_b3 - 4;
		assign 	z1_b3 = z_b3 - 4;
		assign 	x2_b3 = x_b3 + 4;
		assign 	y2_b3 = y_b3 + 4;
		assign 	z2_b3 = z_b3 + 4;
	
//  ball four
		assign 	x_b4 = {{24{hex49[7]}}, hex49};
		assign 	y_b4 = {{24{hex50[7]}}, hex50};
		assign 	z_b4 = {{24{hex51[7]}}, hex51};
		assign 	x1_b4 = x_b4 - 4;
		assign 	y1_b4 = y_b4 - 4;
		assign 	z1_b4 = z_b4 - 4;
		assign 	x2_b4 = x_b4 + 4;
		assign 	y2_b4 = y_b4 + 4;
		assign 	z2_b4 = z_b4 + 4;

/////////////////////////////////////////////////////
/*                Control Signal                   */
/////////////////////////////////////////////////////			
		assign hcount_s = hcount - 11'd128;  

		assign hcount_s_pack = hcount_s[5:1] - 1'b1;
		assign hcount_s_surface = {hcount_s_pack[4:1], 3'd0}; 
		assign hcount_s_edge = {hcount_s_pack[4:1], 3'd1};
		assign hcount_s_ball_1 = {hcount_s_pack[4:1], 3'd2}; 
		assign hcount_s_ball_2 = {hcount_s_pack[4:1], 3'd3};
		assign hcount_s_ball_3 = {hcount_s_pack[4:1], 3'd4}; 
		assign hcount_s_ball_4 = {hcount_s_pack[4:1], 3'd5};
		assign hcount_s_hole = {hcount_s_pack[4:1], 3'd6};
		assign hcount_s_endPoint = {hcount_s_pack[4:1], 3'd7};
				
		assign fb_odd_wren   = !vcount[1] && (hcount_s == 11'd290 || hcount_s == 11'd590 || hcount_s == 11'd890 || hcount_s == 11'd1190);
		assign fb_even_wren  =  vcount[1] && (hcount_s == 11'd290 || hcount_s == 11'd590 || hcount_s == 11'd890 || hcount_s == 11'd1190);
		assign fb_odd_waddr  = {section_sel, vcount[8:2]};
		assign fb_odd_raddr  = {hcount_s[9:6], vcount[8:2]};
		assign fb_even_waddr = {section_sel, vcount[8:2] + 7'd1};
		assign fb_even_raddr = {hcount_s[9:6], vcount[8:2]};
		assign fb_odd_addr   = fb_odd_wren  ? fb_odd_waddr  : fb_odd_raddr;
		assign fb_even_addr  = fb_even_wren ? fb_even_waddr : fb_even_raddr;
		
		assign insurface = vcount[1] ? fb_odd_out[hcount_s_surface] : fb_even_out[hcount_s_surface];
		assign inEdge = vcount[1] ? fb_odd_out[hcount_s_edge] : fb_even_out[hcount_s_edge];
		assign inBall_1 = vcount[1] ? fb_odd_out[hcount_s_ball_1] : fb_even_out[hcount_s_ball_1];
		assign inBall_2 = vcount[1] ? fb_odd_out[hcount_s_ball_2] : fb_even_out[hcount_s_ball_2];
		assign inBall_3 = vcount[1] ? fb_odd_out[hcount_s_ball_3] : fb_even_out[hcount_s_ball_3];
		assign inBall_4 = vcount[1] ? fb_odd_out[hcount_s_ball_4] : fb_even_out[hcount_s_ball_4];
		assign inHole = vcount[1] ? fb_odd_out[hcount_s_hole] : fb_even_out[hcount_s_hole];
		assign inEndPoint = vcount[1] ? fb_odd_out[hcount_s_endPoint] : fb_even_out[hcount_s_endPoint];
		
		assign shelter = hcount_s[10] || hcount_s[10:2] == 9'd0;	
		
		assign x1_b = ball_select == 0 ? x1_b1 :
						  ball_select == 1 ? x1_b2 :
						  ball_select == 2 ? x1_b3 :
						                     x1_b4;
		assign y1_b = ball_select == 0 ? y1_b1 :
						  ball_select == 1 ? y1_b2 :
						  ball_select == 2 ? y1_b3 :
						                     y1_b4;
		assign z1_b = ball_select == 0 ? z1_b1 :
						  ball_select == 1 ? z1_b2 :
						  ball_select == 2 ? z1_b3 :
						                     z1_b4;
													
		assign x2_b = ball_select == 0 ? x2_b1 :
						  ball_select == 1 ? x2_b2 :
						  ball_select == 2 ? x2_b3 :
						                     x2_b4;
		assign y2_b = ball_select == 0 ? y2_b1 :
						  ball_select == 1 ? y2_b2 :
						  ball_select == 2 ? y2_b3 :
						                     y2_b4;
		assign z2_b = ball_select == 0 ? z2_b1 :
						  ball_select == 1 ? z2_b2 :
						  ball_select == 2 ? z2_b3 :
						                     z2_b4;
/////////////////////////////////////////////////////
/*                 Buffer Mapping                  */
/////////////////////////////////////////////////////			
		genvar i,j;
		generate
			for(j=0; j<16; j=j+1)
			begin:plane_buffer_mapping_loop1
				for(i=0; i<8; i=i+1) 
				begin: plane_buffer_mapping_loop2
					assign plane_r[8*j + i] = plane[j][i];
				end
			end
		endgenerate

/////////////////////////////////////////////////////
/*                Function & Task                  */
/////////////////////////////////////////////////////			
		function hitSurface;
			input integer x_r, y_r, z_r, x1_s, x2_s, y1_s, y2_s, z1_s, z2_s;
			begin
				hitSurface = (x_r == x1_s || x_r == x2_s) && y_r >= y1_s && y_r <= y2_s && z_r >= z1_s && z_r <= z2_s ||
								 (y_r == y1_s || y_r == y2_s) && z_r >= z1_s && z_r <= z2_s && x_r >= x1_s && x_r <= x2_s ||
								 (z_r == z1_s || z_r == z2_s) && x_r >= x1_s && x_r <= x2_s && y_r >= y1_s && y_r <= y2_s;
			end
		endfunction
				
		function hitEdge;
			input integer x_r, y_r, z_r, x1_s, x2_s, y1_s, y2_s, z1_s, z2_s;
			begin
				hitEdge = (x_r == x1_s || x_r == x2_s) && (y_r == y1_s || y_r == y2_s) && z_r >= z1_s && z_r <= z2_s ||
							 (y_r == y1_s || y_r == y2_s) && (z_r == z1_s || z_r == z2_s) && x_r >= x1_s && x_r <= x2_s ||
							 (z_r == z1_s || z_r == z2_s) && (x_r == x1_s || x_r == x2_s) && y_r >= y1_s && y_r <= y2_s;
			end
		endfunction

/////////////////////////////////////////////////////
/*                sequential logic                 */
/////////////////////////////////////////////////////			
		always_ff @(posedge clk50) begin
		//ball select
			ball_select = ball_select + 2'b1;
		
			start <= ((hex4[0] == 1'b1)&&gameover);
			
		//initial 
			if (hcount_s == 11'd0 || hcount_s == 11'd300 || hcount_s == 11'd600 || hcount_s == 11'd900) begin 
				scan_count <= 0;
				section_sel[2:0] <= section_sel[2:0] + 3'b1;
				for (x = 0; x < 16; x++) plane[x] <= 8'b0;
			end
			
			if (endOfLine && endOfField) begin
				section_sel[3] <= !section_sel[3];
			end 
			
			if (scan_count != 256) begin
				scan_count <= scan_count + 1;		
				for (x = 0; x < 16; x++) begin
						x0 = {24'b0,section_sel, x[3:0]} - 128;
												
						x_r1 = x0;
						y_r1 = ((cos__x*y + sin__x*z)>>>12);
						z_r1 = ((-sin__x*y + cos__x*z)>>>12);
						
						x_r2 = ((-sin__y*z_r1 + cos__y*x_r1)>>>12);
						y_r2 = y_r1;
						z_r2 = ((cos__y*z_r1 + sin__y*x_r1)>>>12);
			
						hitSurface_b = hitSurface(x_r2, y_r2, z_r2, x1_b, x2_b, y1_b, y2_b, z1_b, z2_b);
							
						hitSurface_s1 = hitSurface(x_r2, y_r2, z_r2, x1_s1, x2_s1, y1_s1, y2_s1, z1_s1, z2_s1);
						hitSurface_s2 = hitSurface(x_r2, y_r2, z_r2, x1_s2, x2_s2, y1_s2, y2_s2, z1_s2, z2_s2);
						hitSurface_s3 = hitSurface(x_r2, y_r2, z_r2, x1_s3, x2_s3, y1_s3, y2_s3, z1_s3, z2_s3);
						hitSurface_s4 = hitSurface(x_r2, y_r2, z_r2, x1_s4, x2_s4, y1_s4, y2_s4, z1_s4, z2_s4);
						hitSurface_s5 = hitSurface(x_r2, y_r2, z_r2, x1_s5, x2_s5, y1_s5, y2_s5, z1_s5, z2_s5);
						
						hitEdge_s1 = hitEdge(x_r2, y_r2, z_r2, x1_s1, x2_s1, y1_s1, y2_s1, z1_s1, z2_s1);
						hitEdge_s2 = hitEdge(x_r2, y_r2, z_r2, x1_s2, x2_s2, y1_s2, y2_s2, z1_s2, z2_s2);
						hitEdge_s3 = hitEdge(x_r2, y_r2, z_r2, x1_s3, x2_s3, y1_s3, y2_s3, z1_s3, z2_s3);
						hitEdge_s4 = hitEdge(x_r2, y_r2, z_r2, x1_s4, x2_s4, y1_s4, y2_s4, z1_s4, z2_s4);
						hitEdge_s5 = hitEdge(x_r2, y_r2, z_r2, x1_s5, x2_s5, y1_s5, y2_s5, z1_s5, z2_s5);
						
						if (plane[x] == 8'b0) plane[x][0] <= hitSurface_s1 ||	hitSurface_s2 || hitSurface_s3 || hitSurface_s4 || hitSurface_s5;
						
						if (plane[x] == 8'b0) plane[x][1] <= hitEdge_s1 ||	hitEdge_s2 || hitEdge_s3 || hitEdge_s4 || hitEdge_s5;// || ball_edge;
						
						if (plane[x] == 8'b0) plane[x][6] <= hex5[0] && hitSurface_s1 || hex5[1] && hitSurface_s2 || hex5[2] && hitSurface_s3 || 
																		 hex5[3] && hitSurface_s4 || hex5[4] && hitSurface_s5;
						
						if (plane[x] == 8'b0) plane[x][7] <= x_r2 >= x1_ep && x_r2 <= x2_ep && y_r2 == y_ep && z_r2 >= z1_ep && z_r2 <= z2_ep;
			
						if (plane[x] == 8'b0 && ball_select == 2'd0) plane[x][2] <= hitSurface_b;												
	
						if (plane[x] == 8'b0 && ball_select == 2'd1) plane[x][3] <= hitSurface_b;
//																											
						if (plane[x] == 8'b0 && ball_select == 2'd2) plane[x][4] <= hitSurface_b;			
	
						if (plane[x] == 8'b0 && ball_select == 2'd3) plane[x][5] <= hitSurface_b;							
			
				end
			end
		end
			

		sin_x sinx(.address(address_sinx), .clock(clk50), .q(sin__x));
		cos_x cosx(.address(address_cosx), .clock(clk50), .q(cos__x));
		sin_y siny(.address(address_siny), .clock(clk50), .q(sin__y));
		cos_y cosy(.address(address_cosy), .clock(clk50), .q(cos__y));
		
		
		FrameBuffer fb_odd(	.address(fb_odd_addr), 
									.clock(clk50), 
									.data(plane_r), 
									.wren(fb_odd_wren), 
									.q(fb_odd_out));
									
		FrameBuffer fb_even(	.address(fb_even_addr), 
									.clock(clk50),
									.data(plane_r), 
									.wren(fb_even_wren), 
									.q(fb_even_out));	
						
		logic [11:0]				address_sinx;
		logic [11:0]				address_cosx;
		logic [11:0]				address_siny;
		logic [11:0]				address_cosy;
		
		logic [29:0]				gameover_counter = 30'b0;
		logic [1:0] 				state, next;
		logic 						flash = 1'b0;
		logic [5:0]					flash_counter = 6'b0;

		always_ff @(posedge clk50)
		if(gameover)
			gameover_counter <= gameover_counter + 1'b1;	
		else
			gameover_counter <= 30'b0;	


		assign address_sinx = gameover ? gameover_counter[29:18] : {hex3[3:0],hex2};
		assign address_cosx = gameover ? gameover_counter[29:18] : {hex3[3:0],hex2};
		assign address_siny = gameover ? gameover_counter[29:18] : {hex1[3:0],hex0};
		assign address_cosy = gameover ? gameover_counter[29:18] : {hex1[3:0],hex0};
		
		logic [7:0]					win_r;
		logic [7:0]					win_g;
		logic [7:0]					win_b;
		logic							in_win;
		logic [13:0]				win_addr;
		
		win win_rgb(.address(win_addr), .clock(clk50), .q({win_r,win_g,win_b}));
		assign in_win = ((hcount >= 11'd464 && hcount <= 11'd720) && (vcount >= 10'd164 && vcount <= 10'd291)) ? |({win_r,win_g,win_b}): 1'b0;
		assign win_addr[13:7] = ((hcount >= 11'd464 && hcount <= 11'd720) && (vcount >= 10'd164 && vcount <= 10'd291)) ? (vcount[6:0] - 7'd36) : 7'b0;
		assign win_addr[6:0] = ((hcount >= 11'd464 && hcount <= 11'd720) && (vcount >= 10'd164 && vcount <= 10'd291)) ? (hcount[7:1] - 7'd104) : 7'b0;
			

		assign gameover = hex6[0];
		
		always_comb begin		
			vcount_integer = vcount[9:1];	
			y = vcount_integer - 128;
			z = scan_count - 128;
			{VGA_R, VGA_G, VGA_B} = flash ? {8'hff, 8'hff, 8'hff} : {8'h0, 8'h0, 8'h0}; // black
			
				case (gameover) 
				1'b0: begin
					if (insurface) {VGA_R, VGA_G, VGA_B} = {8'hff, 8'hff, 8'hff}; // white	
					if (inHole) {VGA_R, VGA_G, VGA_B} = {8'hff, 8'hff, 8'h0}; // golden 			
					if (inEndPoint) {VGA_R, VGA_G, VGA_B} = {8'hff, 8'hff, 8'h0};
					if (inEdge) {VGA_R, VGA_G, VGA_B} = {8'h0, 8'h0, 8'h0}; // black
					if (inBall_1) {VGA_R, VGA_G, VGA_B} = {8'hff, 8'h66, 8'hff}; // pink	
					if (inBall_2) {VGA_R, VGA_G, VGA_B} = {8'hFF, 8'h30, 8'h30}; // red
					if (inBall_3) {VGA_R, VGA_G, VGA_B} = {8'h56, 8'hca, 8'h32}; // green				
					if (inBall_4) {VGA_R, VGA_G, VGA_B} = {8'h66, 8'h66, 8'hff}; // blue
					if (shelter) {VGA_R, VGA_G, VGA_B} = {8'h0, 8'h0, 8'h0}; // black
					end
				1'b1: begin
					if (in_win)
						{VGA_R, VGA_G, VGA_B} = {win_r, win_g, win_b};
					else begin
						if (insurface) {VGA_R, VGA_G, VGA_B} = {8'hff, 8'hff, gameover_counter[25:18]}; // white
						if (inEdge) {VGA_R, VGA_G, VGA_B} = {gameover_counter[25:18], gameover_counter[25:18], 8'h0}; // black
						if (inBall_1) {VGA_R, VGA_G, VGA_B} = {8'hff, gameover_counter[25:18], 8'hff}; // pink				
						if (inBall_2) {VGA_R, VGA_G, VGA_B} = {gameover_counter[25:18], 8'hca, gameover_counter[25:18]}; // green
						if (inBall_3) {VGA_R, VGA_G, VGA_B} = {8'hff, 8'hdd, gameover_counter[25:18]}; // yellow					
						if (inBall_4) {VGA_R, VGA_G, VGA_B} = {gameover_counter[25:18], gameover_counter[25:18], 8'hff}; // blue
						if (shelter) {VGA_R, VGA_G, VGA_B} = {8'h0, 8'h0, 8'h0}; // black
					end
					end
				endcase	
		end  
		
endmodule 
