// --------------------------------------------------------------------
// Copyright (c) 2010 by Terasic Technologies Inc. 
// --------------------------------------------------------------------
//
// Permission:
//
//   Terasic grants permission to use and modify this code for use
//   in synthesis for all Terasic Development Boards and Altera Development 
//   Kits made by Terasic.  Other use of this code, including the selling 
//   ,duplication, or modification of any portion is strictly prohibited.
//
// Disclaimer:
//
//   This VHDL/Verilog or C/C++ source code is intended as a design reference
//   which illustrates how these types of functions can be implemented.
//   It is the user's responsibility to verify their design for
//   consistency and functionality through the use of formal
//   verification methods.  Terasic provides no warranty regarding the use 
//   or functionality of this code.
//
// --------------------------------------------------------------------
//           
//                     Terasic Technologies Inc
//                     356 Fu-Shin E. Rd Sec. 1. JhuBei City,
//                     HsinChu County, Taiwan
//                     302
//
//                     web: http://www.terasic.com/
//                     email: support@terasic.com
//
// --------------------------------------------------------------------
//
// Major Functions:	Camera link on DE4 
//                   Camera link -> HSMC - B
//                   DVI         -> HSMC - A
//                   Camera link type -> STC - CLC1500 of sensor technolgies America, inc.
// --------------------------------------------------------------------
//
// Revision History : 
// --------------------------------------------------------------------
//   Ver  :| Author            :| Mod. Date :| Changes Made:
//   V1.0 :| Peli Li           :| 2010/10/14:| Initial Revision
// --------------------------------------------------------------------
//=======================================================
//  This code is generated by Terasic System Builder
//=======================================================
`include "vpg.h"
module DE4_CLR(

	//////// CLOCK //////////
	GCLKIN,
	GCLKOUT_FPGA,
	OSC_50_BANK2,
	OSC_50_BANK3,
	OSC_50_BANK4,
	OSC_50_BANK5,
	OSC_50_BANK6,
	OSC_50_BANK7,
	PLL_CLKIN_p,

	//////// External PLL //////////
	MAX_I2C_SCLK,
	MAX_I2C_SDAT,

	//////// LED x 8 //////////
	LED,

	//////// BUTTON x 4, EXT_IO and CPU_RESET_n //////////
	BUTTON,
	CPU_RESET_n,
	EXT_IO,

	//////// DIP SWITCH x 8 //////////
	SW,

	//////// SLIDE SWITCH x 4 //////////
	SLIDE_SW,

	//////// SEG7 //////////
	SEG0_D,
	SEG0_DP,
	SEG1_D,
	SEG1_DP,

	//////// Temperature //////////
	TEMP_INT_n,
	TEMP_SMCLK,
	TEMP_SMDAT,

	//////// Current //////////
	CSENSE_ADC_FO,
	CSENSE_CS_n,
	CSENSE_SCK,
	CSENSE_SDI,
	CSENSE_SDO,

	//////// Fan //////////
	FAN_CTRL,

	//////// EEPROM //////////
	EEP_SCL,
	EEP_SDA,

	//////// SDCARD //////////
	SD_CLK,
	SD_CMD,
	SD_DAT,
	SD_WP_n,

	//////// RS232 //////////
	UART_CTS,
	UART_RTS,
	UART_RXD,
	UART_TXD,

	//////// Ethernet x 4 //////////
	ETH_INT_n,
	ETH_MDC,
	ETH_MDIO,
	ETH_RST_n,
	ETH_RX_p,
	ETH_TX_p,

	//////// Flash and SRAM Address/Data Share Bus //////////
	FSM_A,
	FSM_D,

	//////// Flash Control //////////
	FLASH_ADV_n,
	FLASH_CE_n,
	FLASH_CLK,
	FLASH_OE_n,
	FLASH_RESET_n,
	FLASH_RYBY_n,
	FLASH_WE_n,

	//////// SSRAM Control //////////
	SSRAM_ADV,
	SSRAM_BWA_n,
	SSRAM_BWB_n,
	SSRAM_CE_n,
	SSRAM_CKE_n,
	SSRAM_CLK,
	SSRAM_OE_n,
	SSRAM_WE_n,

	//////// 3-Ports High-Speed USB OTG //////////
	OTG_A,
	OTG_CS_n,
	OTG_D,
	OTG_DC_DACK,
	OTG_DC_DREQ,
	OTG_DC_IRQ,
	OTG_HC_DACK,
	OTG_HC_DREQ,
	OTG_HC_IRQ,
	OTG_OE_n,
	OTG_RESET_n,
	OTG_WE_n,

	//////// DDR2 SODIMM //////////
	M1_DDR2_addr,
	M1_DDR2_ba,
	M1_DDR2_cas_n,
	M1_DDR2_cke,
	M1_DDR2_clk,
	M1_DDR2_clk_n,
	M1_DDR2_cs_n,
	M1_DDR2_dm,
	M1_DDR2_dq,
	M1_DDR2_dqs,
	M1_DDR2_dqsn,
	M1_DDR2_odt,
	M1_DDR2_ras_n,
	M1_DDR2_SA,
	M1_DDR2_SCL,
	M1_DDR2_SDA,
	M1_DDR2_we_n,

	//////// HSMC-A //////////
	DVI_EDID_WP,
	DVI_RX_CLK,
	DVI_RX_CTL,
	DVI_RX_D,
	DVI_RX_DDCSCL,
	DVI_RX_DDCSDA,
	DVI_RX_DE,
	DVI_RX_HS,
	DVI_RX_SCDT,
	DVI_RX_VS,
	DVI_TX_CLK,
	DVI_TX_CTL,
	DVI_TX_D,
	DVI_TX_DDCSCL,
	DVI_TX_DDCSDA,
	DVI_TX_DE,
	DVI_TX_DKEN,
	DVI_TX_HS,
	DVI_TX_HTPLG,
	DVI_TX_ISEL,
	DVI_TX_MSEN,
	DVI_TX_PD_N,
	DVI_TX_SCL,
	DVI_TX_SDA,
	DVI_TX_VS,

	//////// HSMC-B //////////
	CLR_CLKIN_n1,
	CLR_CLKIN_n2,
	CLR_CLKIN_p1,
	CLR_CLKIN_p2,
	CLR_CLKIN0,
	CLR_CLKOUT_n2,
	CLR_CLKOUT_p2,
	CLR_D,
//	CLR_GXB_RX_p,
//	CLR_GXB_TX_p,
	CLR_OUT_n1,
	CLR_OUT_p1,
	CLR_OUT0,
	CLR_RX_n,
	CLR_RX_p,
	CLR_TX_n,
	CLR_TX_p,

	//////// HSMC I2C //////////
	HSMC_SCL,
	HSMC_SDA 
);

//=======================================================
//  PARAMETER declarations
//=======================================================
parameter  IMAGE_WITH   =  32'h00000400;
parameter IMAGE_HEIGHT  =  32'h00000300;
//note: if you want to change the image resolution,you should change the belows:
//1.the ccd_capture output image resolution
//2.RAW2RGB module (line buffer taps distance)
//3.DDR2 frame buffer size
//4.DVI output resolution
//=======================================================
//  PORT declarations
//=======================================================

//////////// CLOCK //////////
input		          		GCLKIN;
output		          	GCLKOUT_FPGA;
input		          		OSC_50_BANK2;
input		          		OSC_50_BANK3;
input		          		OSC_50_BANK4;
input		          		OSC_50_BANK5;
input		          		OSC_50_BANK6;
input		          		OSC_50_BANK7;
input		          		PLL_CLKIN_p;

//////////// External PLL //////////
output		          	MAX_I2C_SCLK;
inout		          		MAX_I2C_SDAT;

//////////// LED x 8 //////////
output		   [7:0]		LED;

//////////// BUTTON x 4, EXT_IO and CPU_RESET_n //////////
input		     [3:0]		BUTTON;
input		          		CPU_RESET_n;
inout		          		EXT_IO;

//////////// DIP SWITCH x 8 //////////
input		     [7:0]		SW;

//////////// SLIDE SWITCH x 4 //////////
input		     [3:0]		SLIDE_SW;

//////////// SEG7 //////////
output		   [6:0]		SEG0_D;
output		        		SEG0_DP;
output		   [6:0]		SEG1_D;
output		        		SEG1_DP;

//////////// Temperature //////////
input		          		TEMP_INT_n;
output		        		TEMP_SMCLK;
inout		          		TEMP_SMDAT;

//////////// Current //////////
output		          	CSENSE_ADC_FO;
output	     [1:0]		CSENSE_CS_n;
output		          	CSENSE_SCK;
output		        		CSENSE_SDI;
input		          		CSENSE_SDO;

//////////// Fan //////////
output		          	FAN_CTRL;

//////////// EEPROM //////////
output		          	EEP_SCL;
inout		          		EEP_SDA;

//////////// SDCARD //////////
output		          	SD_CLK;
inout		          		SD_CMD;
inout		     [3:0]		SD_DAT;
input		          		SD_WP_n;

//////////// RS232 //////////
output		          	UART_CTS;
input		          		UART_RTS;
input		          		UART_RXD;
output		          	UART_TXD;

//////////// Ethernet x 4 //////////
input		     [3:0]		ETH_INT_n;
output		  [3:0]	   ETH_MDC;
inout		     [3:0]		ETH_MDIO;
output		          	ETH_RST_n;
input		     [3:0]		ETH_RX_p;
output		  [3:0]		ETH_TX_p;

//////////// Flash and SRAM Address/Data Share Bus //////////
output		 [25:1]		FSM_A;
inout		    [15:0]		FSM_D;

//////////// Flash Control //////////
output		            FLASH_ADV_n;
output		          	FLASH_CE_n;
output		          	FLASH_CLK;
output		          	FLASH_OE_n;
output		          	FLASH_RESET_n;
input		             	FLASH_RYBY_n;
output		          	FLASH_WE_n;

//////////// SSRAM Control //////////
output		          	SSRAM_ADV;
output		          	SSRAM_BWA_n;
output		          	SSRAM_BWB_n;
output		          	SSRAM_CE_n;
output		          	SSRAM_CKE_n;
output		          	SSRAM_CLK;
output		          	SSRAM_OE_n;
output		          	SSRAM_WE_n;

//////////// 3-Ports High-Speed USB OTG //////////
output		  [17:1]		OTG_A;
output		          	OTG_CS_n;
inout		  	  [31:0]		OTG_D;
output		          	OTG_DC_DACK;
input		      	    	OTG_DC_DREQ;
input		          		OTG_DC_IRQ;
output		          	OTG_HC_DACK;
input		          		OTG_HC_DREQ;
input		          		OTG_HC_IRQ;
output		          	OTG_OE_n;
output		          	OTG_RESET_n;
output		          	OTG_WE_n;

//////////// DDR2 SODIMM //////////
output		  [15:0]		M1_DDR2_addr;
output		   [2:0]		M1_DDR2_ba;
output		        		M1_DDR2_cas_n;
output		   [1:0]		M1_DDR2_cke;
inout		  	   [1:0]		M1_DDR2_clk;
inout		    	[1:0]		M1_DDR2_clk_n;
output		   [1:0]		M1_DDR2_cs_n;
output		   [7:0]		M1_DDR2_dm;
inout		     [63:0]	   M1_DDR2_dq;
inout		   	[7:0]		M1_DDR2_dqs;
inout		     [7:0]		M1_DDR2_dqsn;
output		   [1:0]		M1_DDR2_odt;
output		        		M1_DDR2_ras_n;
output		   [1:0]		M1_DDR2_SA;
output		        		M1_DDR2_SCL;
inout		          		M1_DDR2_SDA;
output		        		M1_DDR2_we_n;

//////////// HSMC-A //////////
output		        		DVI_EDID_WP;
input		          		DVI_RX_CLK;
input		    [3:1]		DVI_RX_CTL;
input		   [23:0]	   DVI_RX_D;
inout		          		DVI_RX_DDCSCL;
inout		          		DVI_RX_DDCSDA;
input		          		DVI_RX_DE;
input		          		DVI_RX_HS;
input		          		DVI_RX_SCDT;
input		         	 	DVI_RX_VS;
output		          	DVI_TX_CLK;
output		  [3:1]	   DVI_TX_CTL;
output		  [23:0]		DVI_TX_D;
inout		          		DVI_TX_DDCSCL;
inout		         	 	DVI_TX_DDCSDA;
output		          	DVI_TX_DE;
output		          	DVI_TX_DKEN;
output		          	DVI_TX_HS;
output		          	DVI_TX_HTPLG;
output		          	DVI_TX_ISEL;
output		          	DVI_TX_MSEN;
output		          	DVI_TX_PD_N;
output		          	DVI_TX_SCL;
inout		          		DVI_TX_SDA;
output		          	DVI_TX_VS;

//////////// HSMC-B //////////
input		          		CLR_CLKIN_n1;
input		        		  	CLR_CLKIN_n2;
input		         	 	CLR_CLKIN_p1;
input		          		CLR_CLKIN_p2;
input		          		CLR_CLKIN0;
input		          	   CLR_CLKOUT_n2;
input		             	CLR_CLKOUT_p2;
input		     [3:0]	   CLR_D;
//input		     [7:0]		CLR_GXB_RX_p;
//output		     [7:0]		CLR_GXB_TX_p;
input 		          	CLR_OUT_n1;
input 		          	CLR_OUT_p1;
input 		          	CLR_OUT0;
input		    [16:0]	   CLR_RX_n;
input		 	 [16:0]	   CLR_RX_p;
input		 	 [16:0]	   CLR_TX_n;
input		  	 [16:0]	   CLR_TX_p;

//////////// HSMC I2C //////////
output		          	HSMC_SCL;
inout		    	      	HSMC_SDA;

//=======================================================
//  REG/WIRE declarations
//=======================================================
// CAMERA LINK
wire							CLR_CLK_120;
wire							CLR_BASE_CLK;
wire		 [9:0]			CLR_BASE_D;
wire							CLR_BASE_FVAL;
wire							CLR_BASE_DVAL;

wire	    [15:0]	      Read_DATA1;
wire	    [15:0]	      Read_DATA2;

wire	    [15:0]	      X_Cont;
wire	    [15:0]	      Y_Cont;
wire		 [9:0]		   cap_data;
wire						   cap_dval;
wire                    oWRITE_w1;
wire		 [9:0]			red;
wire	  	 [9:0]		   green;
wire		 [9:0]		   blue;
wire                    dval;

// LED
assign	 LED[7:2]	=	6'b111111;
wire					       start;
wire						    rst_n;
wire                     wrt_full_port0;
wire                     ip_init_done;
wire                     pll_100M;
wire                     pll_100K;
wire                     reset_n_dvi;

//=======================================================
//  External PLL Configuration ==========================
//=======================================================

//  Signal declarations
wire [ 3: 0]               clk1_set_wr, clk2_set_wr, clk3_set_wr;
wire                       rstn;
wire                       conf_ready;
wire                       counter_max;
wire  [7:0]                counter_inc;
reg   [7:0]                auto_set_counter;
reg                        conf_wr;

//  Structural coding
assign clk1_set_wr = 4'd4; //100 MHZ
assign clk2_set_wr = 4'd4; //100 MHZ
assign clk3_set_wr = 4'd4; //100 MHZ

assign rstn = CPU_RESET_n;
assign counter_max = &auto_set_counter;
assign counter_inc = auto_set_counter + 1'b1;

always @(posedge OSC_50_BANK2 or negedge rstn)
	if(!rstn)
	begin
		auto_set_counter <= 0;
		conf_wr <= 0;
	end 
	else if (counter_max)
		conf_wr <= 1;
	else
		auto_set_counter <= counter_inc;

ext_pll_ctrl ext_pll_ctrl_Inst(
	.osc_50(OSC_50_BANK2), //50MHZ
	.rstn(rstn),

	// device 1 (HSMA_REFCLK)
	.clk1_set_wr(clk1_set_wr),
	.clk1_set_rd(),

	// device 2 (HSMB_REFCLK)
	.clk2_set_wr(clk2_set_wr),
	.clk2_set_rd(),

	// device 3 (PLL_CLKIN/SATA_REFCLK)
	.clk3_set_wr(clk3_set_wr),
	.clk3_set_rd(),

	// setting trigger
	.conf_wr(conf_wr), // 1T 50MHz 
	.conf_rd(), // 1T 50MHz

	// status 
	.conf_ready(conf_ready),

	// 2-wire interface 
	.max_sclk(MAX_I2C_SCLK),
	.max_sdat(MAX_I2C_SDAT)

);

//=======================================================
//  Structural coding
//=======================================================
//
//Camera Link HSMC-B
//CLR_RXCLK_BASE --->pixclk
assign	CLR_BASE_CLK	=	CLR_CLKIN_p1;
assign	CLR_BASE_D[0]	=	CLR_OUT0;
assign	CLR_BASE_D[1]	=	CLR_CLKIN0;
assign	CLR_BASE_D[2]	=	CLR_D[0];
assign	CLR_BASE_D[3]	=	CLR_D[2];
assign	CLR_BASE_D[4]	=	CLR_TX_p[0];
assign	CLR_BASE_D[5]	=	CLR_TX_p[1];
assign	CLR_BASE_D[6]	=	CLR_TX_n[4];
assign	CLR_BASE_D[7]	=	CLR_TX_n[0];
assign	CLR_BASE_D[8]	=	CLR_D[1];
assign	CLR_BASE_D[9]	=	CLR_D[3];
assign	CLR_BASE_FVAL	=	CLR_TX_n[5];
assign	CLR_BASE_DVAL	=	CLR_TX_p[6];

//switch on the fan
assign FAN_CTRL = 1'b1;
//DVI
assign DVI_TX_ISEL 	=   1'b0; 	// disable i2c
assign DVI_TX_SCL 	=   1'b1; 	// BSEL=0, 12-bit, dual-edge input
assign DVI_TX_HTPLG  =   1'b1; 	// Note. *** EDGE=1, primary latch to occur on the rising edge of the input clock IDCK+
assign DVI_TX_SDA 	=   1'b1;  	// DSEL=X (VREF=3.3V)
assign DVI_TX_PD_N   =   1'b1;
//reset module
Reset_Delay	Reset_Delay_cmp
		(
			.iCLK(OSC_50_BANK2),
//			.iCLK(CLR_BASE_CLK),
			.iRST(BUTTON[0]),
			.oRST_0(),
			.oRST_1(rst_n),
			.oRST_2(start)
		);
//camera link video capture
CCD_Capture  CCD_Capture_cmp
		(
			.iRST_n(rst_n),				
			.iGO(start),					
			.iWidth(IMAGE_WITH),			   
			.iHeight(IMAGE_HEIGHT),			

			.iCLK(CLR_BASE_CLK),			
			.iDATA(CLR_BASE_D),			
			.iFVAL(CLR_BASE_FVAL),		
			.iLVAL(CLR_BASE_DVAL),		
			.oX_CONT(X_Cont),				
			.oY_CONT(Y_Cont),				
			.oDATA(cap_data),				
			.oDVAL(cap_dval),				
			.oFINISH(LED[0]),				
			.oFIFO_DVAL(oWRITE_w1),		
			.oLED(LED[1]),
			.oWidth(oWidth),
			.oHeight(oHeight),
			.oStatus(oStatus)
		);
//bayer filter output change to 10-bit RGB
RAW2RGB  RAW2RGB_cmp
		(
			.iX_Cont(X_Cont),				
			.iY_Cont(Y_Cont),				
			.iDATA(cap_data),				
			.iDVAL(cap_dval),				
			.iCLK(CLR_BASE_CLK),			
			.iRST(rst_n),				
			.oRed(red),						
			.oGreen(green),				
			.oBlue(blue),					
			.oDVAL(dval)					
		);

//DDR2 Read and Write as Frame Buffer
ddr2_multi_port   u8    (
                         // global signals
						   .clk_50(OSC_50_BANK2),
						   .reset_n(rst_n),

						 // the_Read_Port0   
						   .iCLK_F_to_the_Read_Port0(vpg_pclk),
						   .iIP_INIT_DONE_to_the_Read_Port0(ip_init_done),
						   .iREAD_ACK_F_to_the_Read_Port0(vpg_de),
						   .iRST_n_F_to_the_Read_Port0(read_rstn),
						   .oEMPTY_F_from_the_Read_Port0(),
						   .oPORT_READY_F_from_the_Read_Port0(),
						   .oREAD_DATA_F_from_the_Read_Port0({Read_DATA1,Read_DATA2}),
						   
						 // the_Write_Port0     
						   .iCLK_F_to_the_Write_Port0(CLR_BASE_CLK),
						   .iFLUSH_REQ_F_to_the_Write_Port0(),
						   .iIP_INIT_DONE_to_the_Write_Port0(ip_init_done),
						   .iRST_n_F_to_the_Write_Port0(rst_n),
						   .iWRITE_DATA_F_to_the_Write_Port0({1'b0,green[9:5],blue[9:0],1'b0,green[4:0],red[9:0]}), 
						   .iWRITE_F_to_the_Write_Port0(dval),
						   .oBURST_COUNT_from_the_Write_Port0(),
						   .oFLUSH_BUSY_F_from_the_Write_Port0(),
						   .oFULL_F_from_the_Write_Port0(wrt_full_port0),
						  						  
						  // the_ddr2   
						   .global_reset_n_to_the_ddr2(rst_n),
						   .local_init_done_from_the_ddr2(ip_init_done),
						   .mem_addr_from_the_ddr2(M1_DDR2_addr),
						   .mem_ba_from_the_ddr2(M1_DDR2_ba),
						   .mem_cas_n_from_the_ddr2(M1_DDR2_cas_n),
						   .mem_cke_from_the_ddr2(M1_DDR2_cke),
						   .mem_clk_n_to_and_from_the_ddr2(M1_DDR2_clk_n),
						   .mem_clk_to_and_from_the_ddr2(M1_DDR2_clk),
						   .mem_cs_n_from_the_ddr2(M1_DDR2_cs_n),
						   .mem_dm_from_the_ddr2(M1_DDR2_dm),
						   .mem_dq_to_and_from_the_ddr2(M1_DDR2_dq),
						   .mem_dqs_to_and_from_the_ddr2(M1_DDR2_dqs),
						   .mem_dqsn_to_and_from_the_ddr2(M1_DDR2_dqsn),
						   .mem_odt_from_the_ddr2(M1_DDR2_odt),
						   .mem_ras_n_from_the_ddr2(M1_DDR2_ras_n),
						   .mem_we_n_from_the_ddr2(M1_DDR2_we_n),
                        
                         );
//prevent from read at starting because of none data in the ddr2
reg	[15:0]write_cnt;
always@(posedge CLR_BASE_CLK)
	if (~BUTTON[0])
		write_cnt <= 0;
	else if ( (dval) & (write_cnt != 65536) )
		write_cnt <= write_cnt + 1;
			                  
reg	read_rstn;
	always@(posedge CLR_BASE_CLK)
		begin
			if (~BUTTON[0])
				read_rstn <= 0;
			else if (write_cnt == 256)
				read_rstn <= 1;
		end

//system clocks generate
sys_pll sys_pll_inst(
	.areset(1'b0),
	.inclk0(OSC_50_BANK2),
	.c0(pll_100M),
	.c1(pll_100K),
	.c2(CLR_CLK_120),//25M 
	.locked(reset_n_dvi)
	);
//---------------------------------------------------//
//				DVI Mode Change Button Monitor 			 //
//---------------------------------------------------//
wire		[3:0]	vpg_mode;	
//`ifdef SXGA_1280x1024p60
	assign vpg_mode = `MODE_1024x768;
//`else
//assign vpg_mode = `MODE_720x480;
//`endif
//----------------------------------------------//
// 			 Video Pattern Generator	  	   	//
//----------------------------------------------//
wire [3:0]	vpg_disp_mode;
wire [1:0]	vpg_disp_color;
wire vpg_pclk;
wire vpg_de;
wire vpg_hs;
wire vpg_vs;
wire [23:0]	vpg_data;
vpg	vpg_inst(
	.clk_100(pll_100M),
	.reset_n(read_rstn & reset_n_dvi),//
	.mode(vpg_mode),
	.mode_change(1'b0),
	.disp_color(`COLOR_RGB444),       
	.vpg_pclk(vpg_pclk),
	.vpg_de(vpg_de),
	.vpg_hs(vpg_hs),
	.vpg_vs(vpg_vs),
	.vpg_r(vpg_data[23:16]), //
	.vpg_g(vpg_data[15:8]), //
	.vpg_b(vpg_data[7:0]) //
);
//DVI Signal
assign DVI_TX_DE = vpg_de;
assign DVI_TX_HS = vpg_hs;
assign DVI_TX_VS = vpg_vs;
assign DVI_TX_CLK = vpg_pclk;
//DVI data source selection via SW[0]
assign DVI_TX_D = SW[0] ? {Read_DATA2[9:2],Read_DATA1[14:10],Read_DATA2[14:12],Read_DATA1[9:2]} : vpg_data;


endmodule
