/*
 * Seven-segment LED emulator
 *
 * Stephen A. Edwards, Columbia University
 */

module BALL_Emulator(
 input logic 	    clk50, reset,
 input logic [9:0]  x_coords,y_coords,
 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          |____|
 */
   // 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
   
   // 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 [10:0]			     hcount; // Horizontal counter
                                             // Hcount[10:1] indicates pixel column (0-639)
   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 			     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; // 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) );   

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

   logic isBall; // hcount or vcount are close to the center of the ball
   
   logic [10:0] 			     x_dist; 
   logic [10:0] 			     y_dist; 
	
	//
	logic  [5:0]				  character_address;
	logic 							rom_output;
	logic [7:0]						char_rom_data;
	
	/* x distance has to be divided by two since x_axis has double the pixels for some reason */
	assign x_dist = (x_coords > hcount[10:1]) ? ((x_coords - hcount[10:1])):((hcount[10:1] - x_coords));
	assign y_dist = (y_coords > vcount) ? (y_coords - vcount):(vcount - y_coords);

   assign isBall = ( (x_dist*x_dist + y_dist*y_dist) < 200);
	
	
	//
	char_gen_rom char_rom_unit(
			.clock(clk50),
			.address({character_address,vcount[2:0]}),
			.q(char_rom_data)
	);

	logic [23:0] brick_output;
	logic [14:0] brick_address;
	brickimage brick_unit(
	.clock(clk50),
	.address(brick_address),
	.q(brick_output)
	);
	always_ff @(posedge clk50) begin
		if(vcount>=0 && vcount <=31 &&hcount[10:1]>=0 && hcount[10:1]<=127) begin
			brick_address<=vcount*128+hcount[10:1];
			{VGA_R, VGA_G, VGA_B} <=brick_output;
		end
	end
	
	assign rom_output=char_rom_data[~hcount[3:1]];//hcount LSB => char_rom_data MSB
	
	always_comb begin
		character_address=6'o40;// space by default
		if (vcount<8) begin
			case (hcount[10:4])
				//7'd1: character_address=6'o14;
				//7'd2: character_address=6'o11;
				//7'd3: character_address=6'o26;
				//7'd4: character_address=6'o05;
				//7'd5: character_address=6'o23;
				
				7'd72: character_address=6'o23;
				7'd73: character_address=6'o03;
				7'd74: character_address=6'o17;
				7'd75: character_address=6'o22;
				7'd76: character_address=6'o05;
			
			endcase
				
				
		end
	
	end
	
   always_comb begin
      {VGA_R, VGA_G, VGA_B} = {8'h00, 8'h00, 8'h00}; // Black
	
		if (rom_output)
			{VGA_R, VGA_G, VGA_B} = {8'hff, 8'hff, 8'h00};
   end  
   
endmodule // VGA_LED_Emulator
