// See http://www.abramovbenjamin.net/calc.html.  You also need to modify the clock period in 
// the clock megafunction tool

`define DATA_WIDTH 16
// 1024 x 768 (60 hz)
//`define h_total 11'd1328
//`define v_total 11'd806
//`define h_sync 11'd136
//`define v_sync 11'd6
//`define h_back 11'd144
//`define v_back 11'd29
//`define h_front 11'd24
//`define v_front 11'd3

// 640 x 480 (60 hz)
`define h_display 11'd640
`define v_display 11'd480
`define h_total 11'd800
`define v_total 11'd524
`define h_sync 11'd96
`define v_sync 11'd2
`define h_back 11'd48
`define v_back 11'd31
`define h_front 11'd16
`define v_front 11'd11

module top(
//////////////////// INPUTS ///////////////////////////////////////// 
input  CLOCK_50,     		// System clock
input  [17:0] SW,				// Switches on board
input  [0:0] KEY,				// KEY[0]

///////////////////VGA OUTPUTS ///////////////////////////////////////
output reg [9:0] VGA_R,		// Red color for VGA at current pixel
output reg [9:0] VGA_B,		// Blue color  for VGA at current pixel.
output reg [9:0] VGA_G,		// Green  color  for VGA at current pixel
output VGA_CLK,				// VGA clock 
output VGA_HS,					// Horizontal Sync
output VGA_VS,					// Vert. sync
output VGA_BLANK,	
output VGA_SYNC);


wire on;
wire reset = !KEY[0];    //Pressing KEY[0] causes a reset.
wire [8:0] FTV=SW[8:0];

reg  [10:0] counter_pixel;
wire [10:0] next_counter_pixel;

reg  [10:0]	counter_line; 
wire [10:0] next_counter_line;

reg  [10:0] count;
wire [10:0] next_count;
wire signed [`DATA_WIDTH-1:0]	DDS_output;  	
wire signed [`DATA_WIDTH-1:0]	value;  	//Data to output.
wire lineend;

clock u0(reset, CLOCK_50, VGA_CLK);

assign	next_counter_pixel = (counter_pixel == `h_total - 11'd1)? 11'd0 : counter_pixel + 11'd1;
assign	next_counter_line  = (counter_line  == `v_total - 11'd1) ?  11'd0 : 
							 (counter_pixel == `h_total - 11'd1) ?  counter_line + 11'd1 : counter_line;
							 
assign	VGA_HS = (counter_pixel < `h_total - `h_sync);
assign	VGA_VS = (counter_line  < `v_total - `v_sync); 

assign	VGA_BLANK = ((counter_pixel >= `h_back - 11'd1) && (counter_pixel < `h_total - `h_sync - `h_front)) && ((counter_line >= `v_back - 11'd1) && (counter_line < `v_total - `v_sync - `v_front));
assign	VGA_SYNC = 1'b0;


always @(posedge VGA_CLK)
begin
	if(on)
	begin
		VGA_R = 0; //make this an input
		VGA_B = 0;
		VGA_G = 0;
	end
	else
	begin
		VGA_R = -1;
		VGA_B = -1;
		VGA_G = -1;
	end
end
always @(posedge VGA_CLK)
begin
	if (reset)
	begin
		counter_pixel <=  11'd0;
		counter_line  <=  11'd0;
	end
	else
	begin
		counter_pixel <=  next_counter_pixel;
		counter_line  <=  next_counter_line;
	end
end

// DDS related stuff.
assign lineend=(counter_pixel == `h_total - 11'd1);  // We use lineend to reset the counter.


DDS inst0(VGA_CLK, FTV, lineend, DDS_output);

wire signed [24:0] scaledOutput = 9'sd200*DDS_output; // DDS_output is in the range of [-32768, 32767]
wire signed [9:0] scaledOutputShifted = scaledOutput[24:15];
assign value = scaledOutputShifted + 9'sd250; // value is now in the range of [50, 450]
assign on=(value==counter_line);
endmodule

////////// DDS module ///////////////////////////////
module DDS (clock,    //clock at fs
				FTV,	    //Frequency tuning value
				lineend,  //Reset the counter at the start of each pass.
				dataOut   //DATA_WIDETH bits data value we want to output.
				);
input 			clock;							
input [8:0] 	FTV;
input lineend;
output reg		[`DATA_WIDTH-1:0]	dataOut;  	//Data to output.
reg	[9:0] counter;


always@(posedge clock)
if(lineend)
	counter <= 0;
else
	counter <= counter + FTV;
   
   
always@*
begin
    case(counter[9:6])
			 0 : dataOut   <= 0;
			 1 : dataOut   <= 12539;
			 2 : dataOut   <= 23170;
			 3 : dataOut   <= 30273;
			 4 : dataOut   <= 32767;
			 5 : dataOut   <= 30273;
			 6 : dataOut   <= 23170;
			 7 : dataOut   <= 12539;
			 8 : dataOut   <= 0;
			 9 : dataOut   <= -12539;
			10 : dataOut   <= -23170;
			11 : dataOut   <= -30273;
			12 : dataOut   <= -32767;
			13 : dataOut   <= -30273;
			14 : dataOut   <= -23170;
			15 : dataOut   <= -12539;
	default	:
		   dataOut		<=		0		;
	endcase
end
endmodule 
