// video module for the DE1-SoC board
// Sept 19 2017
// Modified Feb 2018
// by Fred Aulich
// displays video from memory 624 X 420 [odd lines 624 X 210] + [even lines 624 X 210]
// updated for DE1-SoC

module monitor (
// video out chip

vid_clk		, // 25 Mhz clock to video chip
vsync			, // video vertical sync
hsync			, // video horizontal sync
vid_blank	, // video blank 
data_motl	, // odd data value 23 bits [23-16 CR, 15-8 CB, 7-0 Y]
data_moth	, // even data value 23 bits [23-16 CR, 15-8 CB, 7-0 Y]
address_mot , // video out address counter
video_mot	, // storage buffer for video out 
read			, // read from memory enable
oddeven		, // odd/even line enable
read_highh	, // read odd low byte [7-0]
read_lowh	 // read odd high byte [15-8]

);
// signal directions

input 		vid_clk;

output			read_lowh;
output			read_highh;

output[23:0] video_mot; 
output[15:0] address_mot;
output		 oddeven;

inout 		vsync;
inout 		hsync; 
inout			vid_blank;
inout			read;
inout[23:0]	data_motl;
inout[23:0]	data_moth;


// external module registers

reg[23:0]	video_mot;
reg[23:0]	data_motl;
reg[23:0]	data_moth;

// internal registers

reg[16:0]	ramaddress;  // general counter for memory 
reg[16:0]	ramaddressl_odd;  // low address read from memory 
reg[16:0]	ramaddressl_even; // high address read from memory 
reg[10:0]	contvidv; // vertical counter
reg[10:0]	contvidh; // horizontal counter

/////////////////////////////////
//// control values 				///
/////////////////////////////////

wire			vsync = ((contvidv >= 491) & (contvidv < 493))? 1'b0 : 1'b1;
wire			hsync = ((contvidh >= 664) & (contvidh < 760))? 1'b0 : 1'b1;
wire			vid_blank = ((contvidv >= 8) & (contvidv <  420) &(contvidh >= 20) & (contvidh < 624))? 1'b1 : 1'b0;
wire			clrvidh = (contvidh <= 800) ? 1'b0 : 1'b1;
wire  		clrvidv = (contvidv <= 525) ? 1'b0 : 1'b1;
wire  		ramvidv = ( ( (contvidv <= 420) ) ? 1'b0 : 1'b1); 

///////////////////////////////////////////
//////// memory enables						////
///////////////////////////////////////////

wire			adden = ( (( contvidh < 624) & (contvidv <= 420) ) ? 1'b1 : 1'b0); // address enable

wire			read_lowh = ( ramaddressl_odd[0] ) ? 1'b0 : 1'b1; // odd address enable

wire			read_highh = ( ramaddressl_even[0] ) ? 1'b0 : 1'b1; // high address enable

//////////////////////////////
/// assignment pins        ///
//////////////////////////////

parameter address_low = 19'h00000;  // lower address start at 0 meg

assign	read = (ramaddress[0]);

assign oddeven = contvidv[0];

assign address_mot = ( oddeven ) ? ramaddressl_even[16:1] : ramaddressl_odd[16:1];


/////////////////////////////////
// horizontal counter        ////
/////////////////////////////////

always @ (posedge vid_clk )

begin 

		if(clrvidh)
		begin
		contvidh <= 0;
		end
		
		else
		begin
		contvidh <= contvidh + 1;
		end
end

//////////////////////////////////////////
//vertical counter when clrvidv is low ///
//////////////////////////////////////////

always @ (posedge vid_clk)

begin 

		if (clrvidv)
		begin
		contvidv <= 0;
		end
		
		else
		begin
			if
			(contvidh == 798)
			begin
			contvidv <= contvidv + 1; // 798 horizontal pixels
			end
		end
end

////////////////////////////////////////////////////////
// general address counter out from memory to monitor //
////////////////////////////////////////////////////////

always @ (posedge vid_clk )

begin 

		if(ramvidv)
		begin
		ramaddress <= address_low;// memory reset to "0"
		end
		
		else
		begin
		if (adden )
			begin
			ramaddress <= ramaddress + 1;
			end 
		end
end

////////////////////////////////////////////////////////
// address counter out to monitor odd lines for memory /
////////////////////////////////////////////////////////

always @ (posedge vid_clk )

begin 

		if(ramvidv)
		begin
		ramaddressl_odd <= address_low;// memory reset to "0"
		end
		
		else
		begin
		if (adden & !oddeven )
			begin
			ramaddressl_odd <= ramaddressl_odd + 1;
			end 
		end
end

///////////////////////////////////////////////////////////
// address counter out to monitor even lines for memory  //
///////////////////////////////////////////////////////////

always @ (posedge vid_clk)

begin 

		if (ramvidv)
		begin
		ramaddressl_even <= address_low; // memory reset to "0"
		end
		
		else
		begin
			if
			(adden & oddeven )
			begin
			ramaddressl_even <= ramaddressl_even + 1; // 798 horizontal pixels
			end
		end
end


//////////////////////////////////////////////////////////////////
//////// latch address and data from memory		23 bits		   ///
//////////////////////////////////////////////////////////////////

always @ (negedge vid_clk) // 25 Mhz clock

begin
		
		
		if (!read_lowh )
		
		begin

		video_mot[23:0] <= data_motl[23:0]; // single pixel YCRCB odd lines

		end
		
		else
		
		
		if (!read_highh )
		
		begin

		video_mot[23:0] <= data_moth[23:0]; // single pixel YCRCB even lines

		end

end		

endmodule
	