// --------------------------------------------------------------------
// Copyright (c) 2007 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:	HDMI loopback or TX only 
//
// --------------------------------------------------------------------
//
// Revision History :
// --------------------------------------------------------------------
//   Ver  :| Author            :| Mod. Date :| Changes Made:
//   V1.0 :| BEN               :| 15/12/11  :| Initial Revision
// --------------------------------------------------------------------
`include "vpg_source\vpg.h"
module TR4_HDMI_TX_RX(

		////////// CLOCK //////////
	OSC_50_BANK1,
	OSC_50_BANK3,
	OSC_50_BANK4,
	OSC_50_BANK7,
	OSC_50_BANK8,

		////////// LED //////////
		LED,  

		////////// BUTTON //////////
		BUTTON,

	//////////// HSMC-A, HSMC-A connect to HDMI HDMI_RX //////////
	EDID_WP_N,
	HDMI_RX_BD,
	HDMI_RX_DE,
	HDMI_RX_DSD,
	HDMI_RX_EVENODD,
	HDMI_RX_GD,
	HDMI_RX_HS,
	HDMI_RX_I2S,
	HDMI_RX_INT_N,
	HDMI_RX_MCLK,
	HDMI_RX_MUTE,
	HDMI_RX_PCLK,
	HDMI_RX_PCSCL,
	HDMI_RX_PCSDA,
	HDMI_RX_RD,
	HDMI_RX_RST_N,
	HDMI_RX_SCDT,
	HDMI_RX_SCK,
	HDMI_RX_SPDIF,
	HDMI_RX_VS,
	HDMI_RX_WS,
	HDMI_RX0_CEC,
	HDMI_RX0_DDC_SCL,
	HDMI_RX0_DDC_SDA,
	HDMI_RX0_HPD_N,
	HDMI_RX1_CEC,
	HDMI_RX1_DDC_SCL,
	HDMI_RX1_DDC_SDA,
	HDMI_RX1_HPD_N,

	//////////// HSMC-D, HSMC-D connect to HDMI HDMI_TX //////////
	HDMI_TX_BD,
	HDMI_TX_CEC,
	HDMI_TX_DCLK,
	HDMI_TX_DE,
	HDMI_TX_DSR0L,
	HDMI_TX_DSR0R,
	HDMI_TX_DSR1L,
	HDMI_TX_DSR1R,
	HDMI_TX_DSR2L,
	HDMI_TX_DSR2R,
	HDMI_TX_DSR3L,
	HDMI_TX_DSR3R,
	HDMI_TX_GD,
	HDMI_TX_HS,
	HDMI_TX_I2S,
	HDMI_TX_INT_N,
	HDMI_TX_MCLK,
	HDMI_TX_PCLK,
	HDMI_TX_PCSCL,
	HDMI_TX_PCSDA,
	HDMI_TX_RD,
	HDMI_TX_RST_N,
	HDMI_TX_SCK,
	HDMI_TX_SPDIF,
	HDMI_TX_VS,
	HDMI_TX_WS,

	);
//=======================================================
//  PORT declarations
//=======================================================
////////// CLOCK //////////
input 		          		OSC_50_BANK1;
input 		          		OSC_50_BANK3;
input 		          		OSC_50_BANK4;
input 		          		OSC_50_BANK7;
input 		          		OSC_50_BANK8;


////////// LED //////////
output    	[3:0]           	LED;

////////// BUTTON //////////
input     	[3:0]           	BUTTON;

//////////// HSMC-A, HSMC-A connect to HDMI HDMI_RX //////////
output		          		EDID_WP_N;
//audio
input 		     [3:0]		HDMI_RX_I2S;
input 		          		HDMI_RX_SPDIF;
input 		          		HDMI_RX_SCK;
input 		          		HDMI_RX_MCLK;
input 		          		HDMI_RX_MUTE;
input 		          		HDMI_RX_WS;
input 		          		HDMI_RX_DSD;
//vidoi
input 		    [11:0]		HDMI_RX_BD;
input 		    [11:0]		HDMI_RX_RD;
input 		    [11:0]		HDMI_RX_GD;
input 		          		HDMI_RX_HS;
input 		          		HDMI_RX_VS;
input 		          		HDMI_RX_DE;
input 		          		HDMI_RX_EVENODD;
input 		          		HDMI_RX_PCLK;
//ddc
output 		          		HDMI_RX0_DDC_SCL;
inout 		          		HDMI_RX0_DDC_SDA;
output 		          		HDMI_RX1_DDC_SCL;
inout 		          		HDMI_RX1_DDC_SDA;
inout 		          		HDMI_RX0_CEC;
output		          		HDMI_RX0_HPD_N;
inout 		          		HDMI_RX1_CEC;
output		          		HDMI_RX1_HPD_N;
//config
input 		          		HDMI_RX_INT_N;
output		          		HDMI_RX_RST_N;
output		          		HDMI_RX_PCSCL;
inout 		          		HDMI_RX_PCSDA;
input 		          		HDMI_RX_SCDT;


//////////// HSMC-D, HSMC-D connect to HDMI HDMI_TX //////////
output		    [11:0]		HDMI_TX_BD;
inout 		          		HDMI_TX_CEC;
output		          		HDMI_TX_DCLK;
output		          		HDMI_TX_DE;
output		          		HDMI_TX_DSR0L;
output		          		HDMI_TX_DSR0R;
output		          		HDMI_TX_DSR1L;
output		          		HDMI_TX_DSR1R;
output		          		HDMI_TX_DSR2L;
output		          		HDMI_TX_DSR2R;
output		          		HDMI_TX_DSR3L;
output		          		HDMI_TX_DSR3R;
output		    [11:0]		HDMI_TX_GD;
output		          		HDMI_TX_HS;
output		     [3:0]		HDMI_TX_I2S;
input 		          		HDMI_TX_INT_N;
output		          		HDMI_TX_MCLK;
output		          		HDMI_TX_PCLK;
output		          		HDMI_TX_PCSCL;
inout 		          		HDMI_TX_PCSDA;
output		    [11:0]		HDMI_TX_RD;
output		          		HDMI_TX_RST_N;
output		          		HDMI_TX_SCK;
output		          		HDMI_TX_SPDIF;
output		          		HDMI_TX_VS;
output		          		HDMI_TX_WS;

//=======================================================
//  REG/WIRE declarations
//=======================================================


wire reset_n;
wire pll_100M;

wire gen_sck;
wire gen_i2s;
wire gen_ws;


sys_pll sys_pll_inst(
							.areset(1'b0),
							.inclk0(OSC_50_BANK7),
							.c0    (pll_100M),
							.c1    (gen_sck),
							.locked(reset_n)
						  );

TR4_HDMI_TX_RX_SOPC u0 (
        .pll_io                                     (),                                     //                              c1_out_clk.clk
        .bidir_port_to_and_from_the_hdmi_rx1_ep_sda (HDMI_RX1_DDC_SDA), //     hdmi_rx1_ep_sda_external_connection.export
        .areset_to_the_pll                          (),                          //                      pll_areset_conduit.export
        .bidir_port_to_and_from_the_hdmi_rx_i2c_sda (HDMI_RX_PCSDA), //     hdmi_rx_i2c_sda_external_connection.export
        .out_port_from_the_hdmi_tx_mode_change      (vpg_disp_mode_change),      // hdmi_tx_mode_change_external_connection.export
        .out_port_from_the_hdmi_rx_edid_wp          (EDID_WP_N),          //     hdmi_rx_edid_wp_external_connection.export
        .out_port_from_the_hdmi_tx_disp_mode        (vpg_disp_mode),        //   hdmi_tx_disp_mode_external_connection.export
        .in_port_to_the_pio_button                  (BUTTON),                  //          pio_button_external_connection.export
        .out_port_from_the_pio_led                  (LED[3:0]),                  //             pio_led_external_connection.export
        .phasedone_from_the_pll                     (),                     //                   pll_phasedone_conduit.export
        .pll_cpu                                    (),                                    //                              c0_out_clk.clk
        .bidir_port_to_and_from_the_hdmi_rx0_ep_scl (HDMI_RX0_DDC_SCL), //     hdmi_rx0_ep_scl_external_connection.export
        .out_port_from_the_hdmi_rx_sync             (rx_sync),             //        hdmi_rx_sync_external_connection.export
        .out_port_from_the_hdmi_tx_vpg_color        (vpg_disp_color),        //   hdmi_tx_vpg_color_external_connection.export
        .out_port_from_the_hdmi_rx_hpd_n            ({HDMI_RX1_HPD_N,HDMI_RX0_HPD_N}),            //       hdmi_rx_hpd_n_external_connection.export
        .clk                                        (pll_100M),                                        //                              clk_clk_in.clk
        .out_port_from_the_hdmi_tx_i2c_scl          (HDMI_TX_PCSCL),          //     hdmi_tx_i2c_scl_external_connection.export
        .reset_n                                    (reset_n),                                    //                        clk_clk_in_reset.reset_n
        .out_port_from_the_hdmi_rx_reset_n          (HDMI_RX_RST_N),          //     hdmi_rx_reset_n_external_connection.export
        .in_port_to_the_hdmi_tx_irq_n               (HDMI_TX_INT_N),               //       hdmi_tx_irq_n_external_connection.export
        .out_port_from_the_hdmi_tx_reset_n          (HDMI_TX_RST_N),          //     hdmi_tx_reset_n_external_connection.export
        .bidir_port_to_and_from_the_hdmi_tx_i2c_sda (HDMI_TX_PCSDA), //     hdmi_tx_i2c_sda_external_connection.export
        .locked_from_the_pll                        (),                        //                      pll_locked_conduit.export
        .out_port_from_the_hdmi_rx_i2c_scl          (HDMI_RX_PCSCL),          //     hdmi_rx_i2c_scl_external_connection.export
        .bidir_port_to_and_from_the_hdmi_rx0_ep_sda (HDMI_RX0_DDC_SDA), //     hdmi_rx0_ep_sda_external_connection.export
        .i2s_sd_from_the_i2s_tx                     (gen_i2s),                     //                      i2s_tx_conduit_end.sd
        .i2s_ws_from_the_i2s_tx                     (gen_ws),                     //                                        .ws
        .i2s_sck_to_the_i2s_tx                      (gen_sck),                      //                                        .sck
        .bidir_port_to_and_from_the_hdmi_rx1_ep_scl (HDMI_RX1_DDC_SCL), //     hdmi_rx1_ep_scl_external_connection.export
//        .bidir_port_to_and_from_the_hdmi_rx_cec     (),     //         hdmi_rx_cec_external_connection.export
        .in_port_to_the_hdmi_rx_irq_n               (HDMI_RX_INT_N)                //       hdmi_rx_irq_n_external_connection.export
    );
	 
//============== video pattern generator =====================
//wire 		user_change_mode;
wire 					vpg_disp_mode_change;
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 		[7:0]		vpg_r;
wire 		[7:0]		vpg_g;
wire 		[7:0]		vpg_b;


vpg	vpg_inst(
					.clk_100    (pll_100M),
					.reset_n    (reset_n),
					.mode       (vpg_disp_mode),
					.mode_change(vpg_disp_mode_change),
					.disp_color (vpg_disp_color),
					.vpg_pclk   (vpg_pclk),
					.vpg_de     (vpg_de),
					.vpg_hs     (vpg_hs),
					.vpg_vs     (vpg_vs),
					.vpg_r      (vpg_r),
					.vpg_g      (vpg_g),
					.vpg_b      (vpg_b)
					);

//===== latch hdmi source video
reg					rx_de;
reg					rx_hs;
reg					rx_vs;
reg		[11:0]	rx_r;
reg		[11:0]	rx_g;
reg		[11:0]	rx_b;

reg		[11:0]	rx_r_1;
reg		[11:0]	rx_g_1;
reg		[11:0]	rx_b_1;

reg		[11:0]	rx_r_2;
reg		[11:0]	rx_g_2;
reg		[11:0]	rx_b_2;

always @ (negedge HDMI_RX_PCLK)
	begin
			rx_de  <= HDMI_RX_DE;
			rx_hs  <= HDMI_RX_HS;
			rx_vs  <= HDMI_RX_VS;
			rx_r_2 <= HDMI_RX_RD;
			rx_g_2 <= HDMI_RX_GD;
			rx_b_2 <= HDMI_RX_BD;
			rx_r_1 <= rx_r_2;
			rx_g_1 <= rx_g_2;
			rx_b_1 <= rx_b_2;
			rx_r   <= rx_r_1;
			rx_g   <= rx_g_1;
			rx_b   <= rx_b_1;
	end

	
//===== source selection, from pattern generator or hdmi-rx
wire	 rx_sync;
//assign HDMI_TX_PCLK = rx_sync?HDMI_RX_PCLK			:~vpg_pclk; // shift 180 degree for gen clock
clk_slector clk_slector_inst(
									  .data0 (~vpg_pclk),
									  .data1 (HDMI_RX_PCLK),
									  .sel   (rx_sync),
									  .result(HDMI_TX_PCLK)
									);	

source_selector source_selector_inst(
												 .data0x({vpg_de, vpg_hs, vpg_vs, vpg_r, 4'b0000, vpg_g, 4'b0000, vpg_b, 4'b0000}),
												 .data1x({rx_de, rx_hs, rx_vs, rx_r,rx_g,rx_b}),
												 .sel   (rx_sync),
												 .result({HDMI_TX_DE, HDMI_TX_HS, HDMI_TX_VS, HDMI_TX_RD,HDMI_TX_GD,HDMI_TX_BD})
												);
//=== audio
assign HDMI_TX_MCLK 	= HDMI_RX_MCLK;
// i2s
assign HDMI_TX_SCK   = rx_sync ? HDMI_RX_SCK : gen_sck;
assign HDMI_TX_I2S   = rx_sync ? HDMI_RX_I2S : {gen_i2s, gen_i2s, gen_i2s, gen_i2s};
assign HDMI_TX_WS    = rx_sync ? HDMI_RX_WS  : gen_ws;

//================================================
// spdif
//assign HDMI_TX_SPDIF 	= HDMI_RX_SPDIF;
// DSD
//assign HDMI_TX_DCLK 	= HDMI_RX_SCK;
//assign HDMI_TX_DSD_L	= {HDMI_RX_DSD, HDMI_RX_SPDIF, HDMI_RX_I2S[2], HDMI_RX_I2S[0]};
//assign HDMI_TX_DSD_R	= {HDMI_RX_MUTE, HDMI_RX_I2S[3], HDMI_RX_I2S[1], HDMI_RX_WS};

endmodule
