// video module for the DE1-SoC board
// Sept 18 2017
// modified Feb 2018
// by Fred Aulich
// capture frame from video in and save in  memory [16 address 48 data input/output]
// updated for DE1-SoC add on chip memory

module video (
// video out chip
videorgb		, // 23 bit video value 8 red, 8 blue, 8 green
clk			, // 50 Mhz clock 
vid_clk		, // 25 Mhz clock to video chip
clk_27		, // 27 Mhz clock for video in chip
clken			, // clock enable for 27 Mhz clock
vid_hs		, // horizontal sync camera capture
vid_vs		, // vertical sync camera capture
video_in		, // 8 bit video input from camera
sda			, // serial data bus
scl			, // clock line serial data bus
vsync			, // video vertical sync
hsync			, // video horizontal sync
vid_blank	, // video blank 
swt			, // switch inputs
led			, // LED outputs
gpio			 // general purpose registers

);
// signal directions

output[23:0]	videorgb;
output[7:0]		led;
output[15:0] 	gpio;
output			clken;
output 			scl;


input			clk;
input 		clk_27;
input[7:0] 	video_in;
input[7:0]	swt;

inout		sda;
inout		vid_hs;
inout		vid_vs;
inout		vid_clk;
inout 	vsync;
inout 	hsync; 
inout		vid_blank;

// registered pin

reg[10:0]	clkcount; // clock divider

//////////////////////////////////////
///// monitor module					/////
//////////////////////////////////////

wire[23:0]	videorgb;
wire[23:0] 	video_mot;
wire[15:0] 	address_mot;
wire 			hsync;
wire			vsync;
wire			vid_blank;
wire 			read;
wire 			read_lowh;
wire 			read_highh;
wire 			oddeven;

//////////////////////////////////////
/// camera  module					 ////
//////////////////////////////////////

wire[15:0] 	address_cam;
wire 			vid_ldll;
wire 			vid_ldlh;
wire 			vid_udll;
wire 			vid_udlh;
wire 			vid_ldhl;
wire 			vid_ldhh;
wire 			vid_udhl;
wire 			vid_udhh;
wire			clk_27;
wire			clk_13;


////////////////////////////////////////////
//  memory module from library			/////
////////////////////////////////////////////

wire[23:0]	data_caml;  // data from camera
wire[23:0]	data_camh;
wire[47:0]  data_in;
wire[23:0]  data_motl;
wire[23:0]  data_moth;
wire[47:0]  data_q;
wire[5:0]	vid_en;
wire[15:0]	rdaddress;
wire[15:0]	wraddress;
wire[15:0]  address;

///////////////////////////////////////////////////////
//// modules for video in, video out and I2C programmer
///////////////////////////////////////////////////////


camera  u0(

		.clk_27(clk_27),		// 27 Mhz clock
		.vid_vs(vid_vs),			// vertical sync
		.vid_hs(vid_hs),			// horizontal sync
		.video_in(video_in),		// video in data from camera
		.address_cam(address_cam),
		.data_caml(data_caml),
		.data_camh(data_camh),
		
		.vid_ldll(vid_ldll),
		.vid_ldhl(vid_ldhl),
		.vid_ldlh(vid_ldlh),
		.vid_ldhh(vid_ldhh),
		.vid_udll(vid_udll),
		.vid_udhl(vid_udhl),
		.vid_udlh(vid_udlh),
		.vid_udhh(vid_udhh)		
		
	

);

monitor u1 (			
			.vid_clk(vid_clk),			// 25 Mhz clock to video chip
			.vsync(vsync), 			// video vertical sync
			.hsync(hsync), 			// video horizontal sync
			.vid_blank(vid_blank), // video blank 
			.data_motl(data_motl),   // data from memory low byte
			.data_moth(data_moth),
			.read_highh(read_highh),
			.read_lowh(read_lowh),
			.read(read),
			.address_mot(address_mot),
			.oddeven(oddeven),
			.video_mot(video_mot)
);

I2C_programmer u2(
 
			.RESET(swt[1]),			//  27 MHz clock enable 
			.i2c_clk(clk_27),		//  27 Mhz clk from DE2
			.I2C_SCLK(scl),		// I2C clock 40K
			.TRN_END(TRN_END),
			.ACK(ACK),
			.ACK_enable(ACK_enable),
			.I2C_SDATA(sda)		// bi directional serial data 
 );
 
 /////////////////////////////////////////////////
 // on board memory modules
 /////////////////////////////////////////////////
 
ram_16 u3 (

			.clock(clk),
			.wraddress(wraddress),
			.rdaddress(rdaddress),
			.data(data_in),
			.byteena_a(vid_en),
			.q(data_q),
			.rden(read),
			.wren(!read)
);

//////////////////////////////////////////////////////////////
///       variables for loading  I2C programmer          /////
//////////////////////////////////////////////////////////////
 
 wire scl; 
 wire sda; 
 
 wire ACK ;
 wire ACK_enable;
 wire [23:0] data_23;
 wire TRN_END;
 
///////////////////////////////////
/// general clock divider     /////
///////////////////////////////////

 
 always @ (posedge clk )

begin 
	if (!swt[0]) 
		begin		
		clkcount = 0;
		end
		
		else
		begin
		clkcount <= clkcount + 1;
		end
end

	
///////////////////////////////////////
//     fixed output values       //////
///////////////////////////////////////

	 assign wraddress = address_cam;
	 assign rdaddress = address_mot;
	 assign data_in[47:24] = data_camh;
	 assign data_in[23:0] = data_caml;
	 assign data_motl = data_q[23:0];
	 assign data_moth = data_q[47:24];
	 
	 assign vid_en[0] = vid_ldll;
	 assign vid_en[1] = vid_ldlh; 
	 assign vid_en[2] = vid_ldhh;

	 assign vid_en[3] = vid_udll;
	 assign vid_en[4] = vid_udlh;
	 assign vid_en[5] = vid_udhh;

	 assign vid_clk = clkcount[0]; // 25 Mhz clock	
	 assign clken = swt[0]; 		 // camera reset
	 assign led = swt;
	 assign videorgb = video_mot;

//////////////////////////////////////////////////
// outputs to debug circuit gpio(0)	         /////
//////////////////////////////////////////////////
	
	assign gpio[0] = vid_clk;
	assign gpio[1] = read_lowh;
	assign gpio[2] = read_highh;
	assign gpio[3] = read;
	assign gpio[4] = vid_udll;
	assign gpio[5] = vid_udlh;
	assign gpio[6] = vid_udhh;
	assign gpio[7] = clk_27;

	assign gpio[15:8] = address_mot[7:0];


endmodule	
