/*
 * Avalon memory-mapped peripheral that generates VGA
 *
 * Stephen A. Edwards
 * Columbia University
 */

module vga_ball(input logic        clk,
	        input logic 	   reset,
		input logic [15:0]  writedata,
		input logic 	   write,
		input 		   chipselect,
		input logic [3:0]  address,

		output logic [7:0] VGA_R, VGA_G, VGA_B,
		output logic 	   VGA_CLK, VGA_HS, VGA_VS,
		                   VGA_BLANK_n,
		output logic 	   VGA_SYNC_n,
		output logic [1:0] audio_choose);

   logic [10:0]	   hcount;
   logic [9:0]     vcount;

   logic [7:0] 	background_r, background_g, background_b;
   logic [15:0] paddle_left, ball_h, ball_v, heart_status;
   logic [15:0] brick_status0, brick_status1, brick_status2, brick_status3, brick_status4, brick_status5, brick_status6;
   logic [15:0] score_number1, score_number2, score_number3;
   logic [15:0] game_status;	

   vga_counters counters(.clk50(clk), .*);

	always_ff @(posedge clk) 
		if (reset) begin
			background_r <= 8'h00;
			background_g <= 8'h00;
			background_b <= 8'h00;
			paddle_left <= 16'd230;//9 bits should be enough
			ball_h <= 16'd400;
                        ball_v <= 16'd400;
                        brick_status0 <= 16'b0000000000000000;//0000001111111000;
                        brick_status1 <= 16'b0000001111111111;
                        brick_status2 <= 16'b0000001111111111;
                        brick_status3 <= 16'b0000001111111111;
                        brick_status4 <= 16'b0000001111111111;
                        brick_status5 <= 16'b0000001111111111;
                        brick_status6 <= 16'b0000001111111111;
			heart_status  <= 16'b0000000000000111;
			score_number1  <= 16'd3;
			score_number2  <= 16'd4;
			score_number3  <= 16'd5;
			game_status    <= 16'd0;
			audio_choose  <= 2'b00;
		end 
		else if (chipselect && write)
			case (address)
				4'd0 : paddle_left <= writedata;
				4'd1 : ball_h <= writedata;
                                4'd2 : ball_v <= writedata;
                                4'd3 : brick_status0 <= writedata;
                                4'd4 : brick_status1 <= writedata;
                                4'd5 : brick_status2 <= writedata;
                                4'd6 : brick_status3 <= writedata;
                                4'd7 : brick_status4 <= writedata;
                                4'd8 : brick_status5 <= writedata;
                                4'd9 : brick_status6 <= writedata;
                                4'd10: heart_status <= writedata;
				4'd11: audio_choose  <= writedata;
				4'd12: score_number1 <= writedata;
				4'd13: score_number2 <= writedata;
				4'd14: score_number3 <= writedata;
				4'd15: game_status <= writedata;
			endcase

	logic [10:0] cry_address;
	logic [23:0] cry_output;
	cry cry_unit(.address(cry_address),.clock(clk),.q(cry_output));
	logic [1:0] cry_en;

	always_ff @(posedge clk) begin
		//cry1 upper left corner h=248, v=228
		if (hcount[10:1] >= 10'd248 && hcount[10:1] <= 10'd292 && vcount >= 10'd228 && vcount <= 10'd272 && game_status == 2) begin
			cry_en <= 2'b1;
			cry_address <= hcount[10:1]-10'd248 + (vcount-10'd228)*45;
		end
		//number2 upper left corner h=298, v=228
		else if (hcount[10:1] >= 10'd298 && hcount[10:1] <= 10'd342 && vcount >= 10'd228 && vcount <= 10'd272 && game_status == 2) begin
			cry_en <= 2'b1;
			cry_address <= hcount[10:1]-10'd298 + (vcount-10'd228)*45;
		end
		//number3 upper left corner h=348, v=228
		else if (hcount[10:1] >= 10'd348 && hcount[10:1] <= 10'd392 && vcount >= 10'd228 && vcount <= 10'd272 && game_status == 2) begin
			cry_en <= 2'b1;
			cry_address <= hcount[10:1]-10'd348 + (vcount-10'd228)*45;
		end		
		else begin
			cry_en <= 2'b0;
		end
	end

	logic [10:0] smile_address;
	logic [23:0] smile_output;
	smile smile_unit(.address(smile_address),.clock(clk),.q(smile_output));
	logic [1:0] smile_en;

	always_ff @(posedge clk) begin
		//smile1 upper left corner h=248, v=228
		if (hcount[10:1] >= 10'd248 && hcount[10:1] <= 10'd292 && vcount >= 10'd228 && vcount <= 10'd272 && game_status == 1) begin
			smile_en <= 2'b1;
			smile_address <= hcount[10:1]-10'd248 + (vcount-10'd228)*45;
		end
		//smile2 upper left corner h=298, v=228
		else if (hcount[10:1] >= 10'd298 && hcount[10:1] <= 10'd342 && vcount >= 10'd228 && vcount <= 10'd272 && game_status == 1) begin
			smile_en <= 2'b1;
			smile_address <= hcount[10:1]-10'd298 + (vcount-10'd228)*45;
		end
		//smile3 upper left corner h=348, v=228
		else if (hcount[10:1] >= 10'd348 && hcount[10:1] <= 10'd392 && vcount >= 10'd228 && vcount <= 10'd272 && game_status == 1) begin
			smile_en <= 2'b1;
			smile_address <= hcount[10:1]-10'd348 + (vcount-10'd228)*45;
		end		
		else begin
			smile_en <= 2'b0;
		end
	end

	logic [8:0] zero_address;
	logic [23:0] zero_output;
	zero zero_unit(.address(zero_address),.clock(clk),.q(zero_output));
	logic [1:0] zero_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 0) begin
			zero_en <= 2'b1;
			zero_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 0) begin
			zero_en <= 2'b1;
			zero_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 0) begin
			zero_en <= 2'b1;
			zero_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			zero_en <= 2'b0;
		end
	end

	logic [8:0] one_address;
	logic [23:0] one_output;
	one one_unit(.address(one_address),.clock(clk),.q(one_output));
	logic [1:0] one_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 1) begin
			one_en <= 2'b1;
			one_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 1) begin
			one_en <= 2'b1;
			one_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 1) begin
			one_en <= 2'b1;
			one_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			one_en <= 2'b0;
		end
	end

	logic [8:0] two_address;
	logic [23:0] two_output;
	two two_unit(.address(two_address),.clock(clk),.q(two_output));
	logic [1:0] two_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 2) begin
			two_en <= 2'b1;
			two_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 2) begin
			two_en <= 2'b1;
			two_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 2) begin
			two_en <= 2'b1;
			two_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			two_en <= 2'b0;
		end
	end

	logic [8:0] three_address;
	logic [23:0] three_output;
	three three_unit(.address(three_address),.clock(clk),.q(three_output));
	logic [1:0] three_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 3) begin
			three_en <= 2'b1;
			three_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 3) begin
			three_en <= 2'b1;
			three_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 3) begin
			three_en <= 2'b1;
			three_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			three_en <= 2'b0;
		end
	end

	logic [8:0] four_address;
	logic [23:0] four_output;
	four four_unit(.address(four_address),.clock(clk),.q(four_output));
	logic [1:0] four_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 4) begin
			four_en <= 2'b1;
			four_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 4) begin
			four_en <= 2'b1;
			four_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 4) begin
			four_en <= 2'b1;
			four_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			four_en <= 2'b0;
		end
	end

	logic [8:0] five_address;
	logic [23:0] five_output;
	five five_unit(.address(five_address),.clock(clk),.q(five_output));
	logic [1:0] five_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 5) begin
			five_en <= 2'b1;
			five_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 5) begin
			five_en <= 2'b1;
			five_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 5) begin
			five_en <= 2'b1;
			five_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			five_en <= 2'b0;
		end
	end

	logic [8:0] six_address;
	logic [23:0] six_output;
	six six_unit(.address(six_address),.clock(clk),.q(six_output));
	logic [1:0] six_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 6) begin
			six_en <= 2'b1;
			six_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 6) begin
			six_en <= 2'b1;
			six_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 6) begin
			six_en <= 2'b1;
			six_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			six_en <= 2'b0;
		end
	end

	logic [8:0] seven_address;
	logic [23:0] seven_output;
	seven seven_unit(.address(seven_address),.clock(clk),.q(seven_output));
	logic [1:0] seven_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 7) begin
			seven_en <= 2'b1;
			seven_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 7) begin
			seven_en <= 2'b1;
			seven_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 7) begin
			seven_en <= 2'b1;
			seven_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			seven_en <= 2'b0;
		end
	end

	logic [8:0] eight_address;
	logic [23:0] eight_output;
	eight eight_unit(.address(eight_address),.clock(clk),.q(eight_output));
	logic [1:0] eight_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 8) begin
			eight_en <= 2'b1;
			eight_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 8) begin
			eight_en <= 2'b1;
			eight_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 8) begin
			eight_en <= 2'b1;
			eight_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			eight_en <= 2'b0;
		end
	end

	logic [8:0] nine_address;
	logic [23:0] nine_output;
	nine nine_unit(.address(nine_address),.clock(clk),.q(nine_output));
	logic [1:0] nine_en;

	always_ff @(posedge clk) begin
		//number1 upper left corner h=108, v=4
		if (hcount[10:1] >= 10'd108 && hcount[10:1] <= 10'd127 && vcount >= 5'd6 && vcount <= 5'd25 && score_number1 == 9) begin
			nine_en <= 2'b1;
			nine_address <= hcount[10:1]-10'd108 + (vcount-5'd6)*20;
		end
		//number2 upper left corner h=128, v=4
		else if (hcount[10:1] >= 10'd128 && hcount[10:1] <= 10'd147 && vcount >= 5'd6 && vcount <= 5'd25 && score_number2 == 9) begin
			nine_en <= 2'b1;
			nine_address <= hcount[10:1]-10'd128 + (vcount-5'd6)*20;
		end
		//number3 upper left corner h=148, v=5
		else if (hcount[10:1] >= 10'd148 && hcount[10:1] <= 10'd167 && vcount >= 5'd6 && vcount <= 5'd25 && score_number3 == 9) begin
			nine_en <= 2'b1;
			nine_address <= hcount[10:1]-10'd148 + (vcount-5'd6)*20;
		end		
		else begin
			nine_en <= 2'b0;
		end
	end

	logic [10:0] score_address;
	logic [23:0] score_output;
	score score_unit(.address(score_address),.clock(clk),.q(score_output));
	logic [1:0] score_en;

	always_ff @(posedge clk) begin
		//score upper left corner h=25, v=6
		if (hcount[10:1] >= 10'd2 && hcount[10:1] <= 10'd101 && vcount >= 5'd6 && vcount <= 5'd25) begin
			score_en <= 2'b1;
			score_address <= hcount[10:1]-10'd2 + (vcount-10'd6)*100;
		end	
		else begin
			score_en <= 2'b0;
		end
	end

	logic [10:0] heart_address;
	logic [23:0] heart_output;
	heart heart_unit(.address(heart_address),.clock(clk),.q(heart_output));
	logic [1:0] heart_en;
	logic [4:0] heart_v, heart_h;

	always_ff @(posedge clk) begin
		//heart1 upper left corner h=555, v=5
		if (hcount[10:1] >= 10'd555 && hcount[10:1] <= 10'd578 && vcount >= 5'd5 && vcount <= 5'd26 && heart_status[0] == 1) begin
			heart_en <= 2'b1;
			heart_v <= vcount-5'd5;
                        heart_h <= hcount[10:1]-10'd555+1;
			if(heart_h==0)begin
				heart_v <= heart_v+1;
			end
			heart_address <= heart_h + heart_v*24;
		end
		//heart2 upper left corner h=585, v=5
		else if (hcount[10:1] >= 10'd585 && hcount[10:1] <= 10'd608 && vcount >= 5'd5 && vcount <= 5'd26 && heart_status[1] == 1) begin
			heart_en <= 2'b1;
			heart_v <= vcount-5'd5;
                        heart_h <= hcount[10:1]-10'd585+1;
			if(heart_h==0)begin
				heart_v <= heart_v+1;
			end
			heart_address <= heart_h + heart_v*24;
		end
		//heart3 upper left corner h=615, v=5
		else if (hcount[10:1] >= 10'd615 && hcount[10:1] <= 10'd638 && vcount >= 5'd5 && vcount <= 5'd26 && heart_status[2] == 1) begin
			heart_en <= 2'b1;
			heart_v <= vcount-5'd5;
                        heart_h <= hcount[10:1]-10'd615+1;
			if(heart_h==0)begin
				heart_v <= heart_v+1;
			end
			heart_address <= heart_h + heart_v*24;
		end		
		else begin
			heart_en <= 2'b0;
		end
	end

	logic [10:0] brick_blue_address;
	logic [23:0] brick_blue_output;
	brick_blue brick_blue_unit(.address(brick_blue_address),.clock(clk),.q(brick_blue_output));
	logic [1:0] brick_blue_en;

	always_ff @(posedge clk) begin
		//line 0
		/*if (hcount[10:7] == 4'd0 && vcount[9:5] == 5'd0 && brick_status0[0] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd1 && vcount[9:5] == 5'd0 && brick_status0[1] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd2 && vcount[9:5] == 5'd0 && brick_status0[2] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd3 && vcount[9:5] == 5'd0 && brick_status0[3] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd4 && vcount[9:5] == 5'd0 && brick_status0[4] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd5 && vcount[9:5] == 5'd0 && brick_status0[5] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd6 && vcount[9:5] == 5'd0 && brick_status0[6] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd7 && vcount[9:5] == 5'd0 && brick_status0[7] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd8 && vcount[9:5] == 5'd0 && brick_status0[8] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd9 && vcount[9:5] == 5'd0 && brick_status0[9] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end*/

		//line 2 
		if (hcount[10:7] == 4'd0 && vcount[9:5] == 5'd2 && brick_status2[0] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd1 && vcount[9:5] == 5'd2 && brick_status2[1] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd2 && vcount[9:5] == 5'd2 && brick_status2[2] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd3 && vcount[9:5] == 5'd2 && brick_status2[3] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd4 && vcount[9:5] == 5'd2 && brick_status2[4] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd5 && vcount[9:5] == 5'd2 && brick_status2[5] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd6 && vcount[9:5] == 5'd2 && brick_status2[6] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd7 && vcount[9:5] == 5'd2 && brick_status2[7] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd8 && vcount[9:5] == 5'd2 && brick_status2[8] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd9 && vcount[9:5] == 5'd2 && brick_status2[9] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		//line 4

		else if (hcount[10:7] == 4'd0 && vcount[9:5] == 5'd4 && brick_status4[0] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd1 && vcount[9:5] == 5'd4 && brick_status4[1] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd2 && vcount[9:5] == 5'd4 && brick_status4[2] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd3 && vcount[9:5] == 5'd4 && brick_status4[3] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd4 && vcount[9:5] == 5'd4 && brick_status4[4] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd5 && vcount[9:5] == 5'd4 && brick_status4[5] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd6 && vcount[9:5] == 5'd4 && brick_status4[6] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd7 && vcount[9:5] == 5'd4 && brick_status4[7] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd8 && vcount[9:5] == 5'd4 && brick_status4[8] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd9 && vcount[9:5] == 5'd4 && brick_status4[9] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		//line 6
		else if (hcount[10:7] == 4'd0 && vcount[9:5] == 5'd6 && brick_status6[0] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd1 && vcount[9:5] == 5'd6 && brick_status6[1] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd2 && vcount[9:5] == 5'd6 && brick_status6[2] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd3 && vcount[9:5] == 5'd6 && brick_status6[3] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd4 && vcount[9:5] == 5'd6 && brick_status6[4] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd5 && vcount[9:5] == 5'd6 && brick_status6[5] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd6 && vcount[9:5] == 5'd6 && brick_status6[6] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd7 && vcount[9:5] == 5'd6 && brick_status6[7] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd8 && vcount[9:5] == 5'd6 && brick_status6[8] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd9 && vcount[9:5] == 5'd6 && brick_status6[9] == 1) begin
			brick_blue_en <= 2'b1;
			brick_blue_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else begin
			brick_blue_en <= 2'b0;
		end
	end

	logic [10:0] brick_red_address;
	logic [23:0] brick_red_output;
	brick_red brick_red_unit(.address(brick_red_address),.clock(clk),.q(brick_red_output));
	logic [1:0] brick_red_en;

	always_ff @(posedge clk) begin
		//line 1
		if (hcount[10:7] == 4'd0 && vcount[9:5] == 5'd1 && brick_status1[0] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd1 && vcount[9:5] == 5'd1 && brick_status1[1] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd2 && vcount[9:5] == 5'd1 && brick_status1[2] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd3 && vcount[9:5] == 5'd1 && brick_status1[3] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd4 && vcount[9:5] == 5'd1 && brick_status1[4] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd5 && vcount[9:5] == 5'd1 && brick_status1[5] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd6 && vcount[9:5] == 5'd1 && brick_status1[6] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd7 && vcount[9:5] == 5'd1 && brick_status1[7] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd8 && vcount[9:5] == 5'd1 && brick_status1[8] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd9 && vcount[9:5] == 5'd1 && brick_status1[9] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		//line 3 
		else if (hcount[10:7] == 4'd0 && vcount[9:5] == 5'd3 && brick_status3[0] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd1 && vcount[9:5] == 5'd3 && brick_status3[1] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd2 && vcount[9:5] == 5'd3 && brick_status3[2] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd3 && vcount[9:5] == 5'd3 && brick_status3[3] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd4 && vcount[9:5] == 5'd3 && brick_status3[4] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd5 && vcount[9:5] == 5'd3 && brick_status3[5] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd6 && vcount[9:5] == 5'd3 && brick_status3[6] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd7 && vcount[9:5] == 5'd3 && brick_status3[7] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd8 && vcount[9:5] == 5'd3 && brick_status3[8] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd9 && vcount[9:5] == 5'd3 && brick_status3[9] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		//line 5
		else if (hcount[10:7] == 4'd0 && vcount[9:5] == 5'd5 && brick_status5[0] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd1 && vcount[9:5] == 5'd5 && brick_status5[1] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd2 && vcount[9:5] == 5'd5 && brick_status5[2] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd3 && vcount[9:5] == 5'd5 && brick_status5[3] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd4 && vcount[9:5] == 5'd5 && brick_status5[4] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd5 && vcount[9:5] == 5'd5 && brick_status5[5] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd6 && vcount[9:5] == 5'd5 && brick_status5[6] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd7 && vcount[9:5] == 5'd5 && brick_status5[7] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd8 && vcount[9:5] == 5'd5 && brick_status5[8] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else if (hcount[10:7] == 4'd9 && vcount[9:5] == 5'd5 && brick_status5[9] == 1) begin
			brick_red_en <= 2'b1;
			brick_red_address <= hcount[6:1]+vcount[4:0]*64;
		end
		else begin
			brick_red_en <= 2'b0;
		end
	end

	logic [10:0] ball_address;
	logic [23:0] ball_output;
	ball ball_unit(.address(ball_address),.clock(clk),.q(ball_output));
	logic [1:0] ball_en;
	logic [3:0] b_v;
	logic [3:0] b_h;
	always_ff @(posedge clk) begin
		//ball
		//if (hcount[10:5] == 6'd20 && vcount[9:4] == 6'd22) begin
		if (hcount[10:1] >= ball_h && hcount[10:1] < ball_h+16 && vcount[9:0] >= ball_v && vcount[9:0]<ball_v+16)begin
                        b_v <= vcount[9:0]-ball_v;
                        b_h <= hcount[10:1]-ball_h +1;

			if(b_h==0)begin
				b_v <= b_v+1;
			end
			ball_address <= b_h + b_v*16;
			ball_en <= 2'b1;
		end
		else begin
			ball_en <= 2'b0;
		end
	end
	
	logic [10:0] paddle_address;
	logic [23:0] paddle_output;
	paddle paddle_unit(.address(paddle_address),.clock(clk),.q(paddle_output));
	logic [1:0] paddle_en;
	logic [4:0] r_v;
	logic [6:0] r_h;
	always_ff @(posedge clk) begin
		//paddle
		if (hcount[10:1] >= paddle_left && hcount[10:1] < paddle_left + 90 && vcount[9:0] >= 10'd455 && vcount[9:0] <= 10'd474) begin
                        r_v <= vcount[9:0]-10'd455;
                        r_h <= hcount[10:1]-paddle_left+1;
                        paddle_address <= r_h + r_v * 90;
			paddle_en <= 2'b1;
		end
		else begin
			paddle_en <= 2'b0;
		end
	end
	//broken_blue bric_unit(.address(brick_address),.clock(clk),.q(brick_output));

	always_comb begin
		{VGA_R, VGA_G, VGA_B} = {background_r, background_g, background_b};
		if (VGA_BLANK_n ) begin
			if(heart_en) begin
				{VGA_R, VGA_G, VGA_B} = heart_output;
			end
			else if(score_en) begin
				{VGA_R, VGA_G, VGA_B} = score_output;
			end
			else if(zero_en) begin
				{VGA_R, VGA_G, VGA_B} = zero_output;
			end
			else if(one_en) begin
				{VGA_R, VGA_G, VGA_B} = one_output;
			end
			else if(two_en) begin
				{VGA_R, VGA_G, VGA_B} = two_output;
			end
			else if(three_en) begin
				{VGA_R, VGA_G, VGA_B} = three_output;
			end
			else if(four_en) begin
				{VGA_R, VGA_G, VGA_B} = four_output;
			end
			else if(five_en) begin
				{VGA_R, VGA_G, VGA_B} = five_output;
			end
			else if(six_en) begin
				{VGA_R, VGA_G, VGA_B} = six_output;
			end
			else if(seven_en) begin
				{VGA_R, VGA_G, VGA_B} = seven_output;
			end
			else if(eight_en) begin
				{VGA_R, VGA_G, VGA_B} = eight_output;
			end
			else if(nine_en) begin
				{VGA_R, VGA_G, VGA_B} = nine_output;
			end

			if(ball_en) begin
				{VGA_R, VGA_G, VGA_B} = ball_output;
			end

			if(brick_blue_en) begin
				{VGA_R, VGA_G, VGA_B} = brick_blue_output;
			end
			else if(brick_red_en) begin
				{VGA_R, VGA_G, VGA_B} = brick_red_output;
			end
			else if(paddle_en) begin
				{VGA_R, VGA_G, VGA_B} = paddle_output;
			end
			if(cry_en) begin
				{VGA_R, VGA_G, VGA_B} = cry_output;
			end
			else if(smile_en) begin
				{VGA_R, VGA_G, VGA_B} = smile_output;
			end

			if(hcount[3] == 1 && vcount == 27)begin
				{VGA_R, VGA_G, VGA_B} = {8'hff, 8'hff, 8'hff};
			end
			if(hcount[3] == 0 && vcount == 28)begin
				{VGA_R, VGA_G, VGA_B} = {8'hff, 8'hff, 8'hff};
			end
			if(hcount[3] == 1 && vcount == 29)begin
				{VGA_R, VGA_G, VGA_B} = {8'hff, 8'hff, 8'hff};
			end

		end
	end
	       
endmodule

module vga_counters(
 input logic 	     clk50, reset,
 output logic [10:0] hcount,  // hcount[10:1] is pixel column
 output logic [9:0]  vcount,  // vcount[9:0] is pixel row
 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          |____|
 */
   // Parameters for hcount
   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,800
   
   // Parameters for vcount
   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 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;
       
   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 0x5DF (0x57F)
   // 101 0010 0000 to 101 1101 1111
   assign VGA_HS = !( (hcount[10:8] == 3'b101) &
		      !(hcount[7:5] == 3'b111));
   assign VGA_VS = !( vcount[9:1] == (VACTIVE + VFRONT_PORCH) / 2);

   assign VGA_SYNC_n = 1'b0; // For putting sync on the green signal; unused
   
   // 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) );

   /* VGA_CLK is 25 MHz
    *             __    __    __
    * clk50    __|  |__|  |__|
    *        
    *             _____       __
    * hcount[0]__|     |_____|
    */
   assign VGA_CLK = hcount[0]; // 25 MHz clock: rising edge sensitive
   
endmodule
