// (default 640x480) 60Hz VGA Driver
// but can take parameters when initialised
// to output sync signals for any screen
// resolution
//
//                 					        |- LINE
//        __________________________ ____|
//       |                          |    |
//       |                          |    |
//       |     				         |    |
//       |     				         |    |
//       |      DISPLAY AREA        |    |
//       |                          |    |
//       |                          |    |
//       |                          |    |
//       --------------------------------- V_RES
//       |                          |
//       |                          |
//       ---------------------------- SCANLINES
	
module sync_generator(
	// inputs
	input wire clk,							// base clock
	input wire pix_enable,					// pixel clock
	input wire reset,							// reset: restarts frame
	// outputs
	output reg hsync,							// horizontal sync
	output reg vsync,							// vertical sync
	output wire [9:0] x,						// current pixel x position
	output wire [9:0] y,						// current pixel y position
	output reg blanking						// high when in vertical blanking area
	);

	// default resolution if no parameters are passed
	parameter H_RES = 640;					// horizontal display resolution
	parameter V_RES = 480;					// vertical display resolution

	// no-draw area definitions
	localparam H_FRONT_PORCH = 16;
	localparam HSYNC_WIDTH = 96;
	localparam H_BACK_PORCH = 48;
	localparam V_FRONT_PORCH = 10;
	localparam VSYNC_HEIGHT	= 2;
	localparam V_BACK_PORCH = 33;
	
	// total screen resolution
	localparam LINE	= H_RES + H_FRONT_PORCH + HSYNC_WIDTH + H_BACK_PORCH;			// complete line (inc. horizontal blanking area)
	localparam SCANLINES	= V_RES + V_FRONT_PORCH + VSYNC_HEIGHT + V_BACK_PORCH;	// total scan lines (inc. vertical blanking area)
	
	// useful trigger points
	localparam HS_STA = H_RES + H_FRONT_PORCH - 1;					// horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
	localparam HS_END	= H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1;// horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
	localparam VS_STA = V_RES + V_FRONT_PORCH;						// vertical sync ON
	localparam VS_END = V_RES + V_FRONT_PORCH + VSYNC_HEIGHT;	// vertical sync OFF
	
	reg [9:0] h_count;						// line position
	reg [9:0] v_count;						// SCANLINES position
	
	// keep x and y bound within the display area
	assign x = (h_count < H_RES) ? h_count : (H_RES - 1'b1);		// x = H_RES-1 if current pixel is after display area
	assign y = (v_count < V_RES) ? v_count : (V_RES - 1'b1);		// y = VS_END-1 if v_count is outside display area
	
	always @(posedge clk, posedge reset)
	begin
		if (reset)	// reset to start of frame
		begin
			h_count <= 1'b0;
			v_count <= 1'b0;
			blanking <= 1'b0;
		end
		else
		begin
			if (pix_enable)	// once per pixel
			begin
			
				// check for generation of HSYNC pulse
				if (h_count == HS_STA)
				begin
					hsync <= 1'b1;		// turn on HSYNC pulse
				end
				else if (h_count == HS_END)
					hsync <= 1'b0;		// turn off HSYNC pulse
				
				// check for generation of VSYNC pulse
				if (v_count == VS_STA)
				begin
					vsync <= 1'b1;		// turn on VSYNC pulse
				end
				else if (v_count == VS_END)
					vsync <= 1'b0;		// turn off VSYNC pulse
				
				// reset h_count & increment v_count at end of scanline
				if (h_count == LINE)	// end of line
				begin
					h_count <= 1'b0;
					v_count <= v_count + 1'b1;	// increment v_count to next scanline
				end
				else
					h_count <= h_count + 1'b1;	// otherwise, just increment horizontal counter
				
				// reset v_count and blanking at bottom of screen
				if (v_count == SCANLINES)	// end of SCANLINES
				begin
					v_count	<= 1'b0;
					blanking <= 1'b0;
				end
				
				// finally, set flags according to h_count & v_count
				if (v_count == V_RES)
					blanking <= 1'b1;
				
			end
		end
	end
endmodule
