// ============================================================================
// I2C_HDMI_Config.v — ADV7513 HDMI transmitter configuration via I2C
// ============================================================================
//
// Derived from Terasic DE-series reference design (I2C_HDMI_Config.v).
// Original copyright belongs to Terasic Technologies Inc.; this file is
// distributed under the terms of the Terasic Reference Design license that
// ships with the DE25-Nano System CD (free use on Terasic hardware,
// copyright notice retained).
//
// retroDE modifications (2025-2026):
//   - LUT_SIZE expanded to 38 entries
//   - Audio configuration for I2S input @ 48 kHz, MCLK 12.288 MHz
//   - HPD override (0xD6 = 0xC0) for monitors that misreport hot-plug
//   - AVI InfoFrame configured for full-range RGB 444 output
//   - Comments documenting each ADV7513 register write
//
// ============================================================================

`timescale 1ns/1ps

module I2C_HDMI_Config (	//	Host Side
					iCLK,
					iRST_N,
					//	I2C Side
					I2C_SCLK,
					I2C_SDAT,
					HDMI_TX_INT,
					READY,
					//	Ch166: sticky NACK watchdog
					ERROR
					 );
//	Host Side
input				iCLK;
input				iRST_N;
//	I2C Side: SCL is actively driven by the master; SDA is open-drain
//	(master drives low / releases to 1'bz; slave drives ACK).
output			I2C_SCLK;
inout				I2C_SDAT;
input				HDMI_TX_INT;
output READY ;
//	Ch166: ERROR latches HIGH if the same LUT entry NACKs
//	NACK_LIMIT consecutive times (chip absent, address wrong,
//	bus shorted). Sticky until iRST_N. Cleared on reset.
output ERROR;

//	Internal Registers/Wires
reg	[15:0]	mI2C_CLK_DIV;
reg	[23:0]	mI2C_DATA;
reg				mI2C_CTRL_CLK;
reg				mI2C_GO;
wire				mI2C_END;
wire				mI2C_ACK;
reg	[15:0]	LUT_DATA;
reg	[5:0]		LUT_INDEX;
reg	[3:0]		mSetup_ST;
reg READY ;

//	Clock Setting
parameter	CLK_Freq	=	50000000;	//	50	MHz
parameter	I2C_Freq	=	20000;		//	20	KHz
//	LUT Data Number
parameter	LUT_SIZE	=	38;
//	Ch166 - NACK watchdog threshold (consecutive retries on the
//	same LUT entry before ERROR latches). At I2C_Freq=20 kHz a
//	full byte transaction is ~1.5 ms, so 16 retries ~= 24 ms before
//	we declare the bus dead - generous enough for real-world bus
//	settling but well short of a stuck-LED user complaint.
parameter	NACK_LIMIT	=	16;

/////////////////////	I2C Control Clock	////////////////////////
always@(posedge iCLK or negedge iRST_N)
begin
	if(!iRST_N)
	begin
		mI2C_CTRL_CLK	<=	0;
		mI2C_CLK_DIV		<=	0;
	end
	else
	begin
		if( mI2C_CLK_DIV	< (CLK_Freq/I2C_Freq) )
			mI2C_CLK_DIV	<=	mI2C_CLK_DIV+1;
		else
		begin
			mI2C_CLK_DIV	<=	0;
			mI2C_CTRL_CLK	<=	~mI2C_CTRL_CLK;
		end
	end
end

////////////////////////////////////////////////////////////////////
I2C_Controller 	u0	(	.CLK(mI2C_CTRL_CLK),			//	Controller work clock
						.CLK_EN(1'b1),					//	Advance every controller clock
						.CLK_PHASE(mI2C_CTRL_CLK),		//	Phase for SCL generation
						.I2C_SCLK(I2C_SCLK),				//	I2C CLOCK
 	 	 	 	 	 	.I2C_SDAT(I2C_SDAT),				//	I2C DATA
						.I2C_DATA(mI2C_DATA),			//	DATA:[SLAVE_ADDR,SUB_ADDR,DATA]
						.GO(mI2C_GO),						//	GO transfor
						.END(mI2C_END),					//	END transfor
						.W_R(1'b0),						//	Ch165 audit Low — tie retained-compat port off (always WRITE)
						.ACK(mI2C_ACK),					//	ACK
						.RESET(iRST_N)	);
////////////////////////////////////////////////////////////////////
//////////////////////	Config Control	////////////////////////////
always@(posedge mI2C_CTRL_CLK or negedge iRST_N)
begin
	if(!iRST_N)
	begin
	   READY       <= 0;
		LUT_INDEX	<=	0;
		mSetup_ST	<=	0;
		mI2C_GO		<=	0;
	end
	else
	begin
		if(LUT_INDEX<LUT_SIZE)
		begin
			READY<=0;
			case(mSetup_ST)
			0:	begin
					mI2C_DATA	<=	{8'h72,LUT_DATA};
					mI2C_GO		<=	1;
					mSetup_ST	<=	1;
				end
			1:	begin
					if(mI2C_END)
					begin
						if(!mI2C_ACK)
						mSetup_ST	<=	2;
						else
						mSetup_ST	<=	0;
						mI2C_GO		<=	0;
					end
				end
			2:	begin
					LUT_INDEX	<=	LUT_INDEX+1;
					mSetup_ST	<=	0;
				end
			endcase
		end
		else
		begin
		  READY<=1;
		  if(!HDMI_TX_INT)
		  begin
		    LUT_INDEX <= 0;
		  end
		  else
		    LUT_INDEX <= LUT_INDEX;
		end
	end
end
////////////////////////////////////////////////////////////////////
//////////////////  Ch166 NACK watchdog (sticky)  //////////////////
//
// Counts consecutive NACK retries on the *current* LUT entry.
// In the config FSM above, state 1 sees mI2C_END at the end of
// each I2C transaction; if mI2C_ACK is HIGH (slave didn't drive
// the ACK bit LOW), the FSM bounces back to state 0 and retries
// the same LUT_DATA. State 2 means the byte ACKed and LUT_INDEX
// is about to advance, so we clear the retry count there. Once
// the count hits NACK_LIMIT, ERROR latches HIGH (sticky until
// iRST_N) so the top level can surface a stuck bus on an LED.
reg [7:0]	nack_retries;
reg			error_latched;
always @(posedge mI2C_CTRL_CLK or negedge iRST_N)
begin
	if (!iRST_N)
	begin
		nack_retries  <= 0;
		error_latched <= 1'b0;
	end
	else
	begin
		if (mSetup_ST == 1 && mI2C_END && mI2C_ACK)
		begin
			nack_retries <= nack_retries + 1;
			if (nack_retries == NACK_LIMIT - 1)
				error_latched <= 1'b1;
		end
		else if (mSetup_ST == 2)
		begin
			nack_retries <= 0;
		end
	end
end
assign ERROR = error_latched;
////////////////////////////////////////////////////////////////////
/////////////////////	Config Data LUT	  //////////////////////////
always@(*)
begin
	case(LUT_INDEX)
	//	Video Config Data
	00	:	LUT_DATA	<=	16'h9803;  //Must be set to 0x03 for proper operation
	01	:	LUT_DATA	<=	16'hD6C0;  //HPD override: force HPD always-high (bits[7:6]=11)
	02	:	LUT_DATA	<=	16'h0100;  //Set 'N' value at 6144
	03	:	LUT_DATA	<=	16'h0218;  //Set 'N' value at 6144
	04	:	LUT_DATA	<=	16'h0300;  //Set 'N' value at 6144
	05	:	LUT_DATA	<=	16'h0a01;  //MCLK ratio = 256x fs (12.288 MHz / 48 kHz)
	06	:	LUT_DATA	<=	16'h0b2e;  //MCLK Active
	07	:	LUT_DATA	<=	16'h0cbc;  //Serial Audio standard i2s, R0x0C[1:0] = '00
	08	:	LUT_DATA	<=	16'h1402;  //Audio Word Length 16 bit, stereo (2 channels)
	09	:	LUT_DATA	<=	16'h1520;  //Input 444 (RGB or YCrCb) with Separate Syncs, 48kHz fs
	10	:	LUT_DATA	<=	16'h1630;  //Output format 444, 24-bit input
	11	:	LUT_DATA	<=	16'h1846;  //Disable CSC
	12	:	LUT_DATA	<=	16'h4080;  //General control packet enable
	13	:	LUT_DATA	<=	16'h4110;  //Power down control
	14	:	LUT_DATA	<=	16'h49A8;  //Set dither mode - 12-to-10 bit
	15	:	LUT_DATA	<=	16'h5510;  //AVI InfoFrame byte 1: Y=RGB, A0=active fmt valid
	16	:	LUT_DATA	<=	16'h5608;  //AVI InfoFrame byte 2: active format aspect
	17	:	LUT_DATA	<=	16'h5708;  //AVI InfoFrame byte 3: Q=10 (full range RGB 0-255)
	18	:	LUT_DATA	<=	16'h94C0;  //INT enable 1: HPD + monitor sense only
	19	:	LUT_DATA	<=	16'h9500;  //INT enable 2: all disabled
	20	:	LUT_DATA	<=	16'h96C0;  //Clear HPD + monitor sense status (matches 0x94 enable mask)
	21	:	LUT_DATA	<=	16'h7301;  //Info frame Ch count = 2 (stereo)
	22	:	LUT_DATA	<=	16'h7600;  //Speaker allocation: FL+FR (stereo)
	23	:	LUT_DATA	<=	16'h9803;  //Must be set to 0x03 for proper operation
	24	:	LUT_DATA	<=	16'h9902;  //Must be set to Default Value
	25	:	LUT_DATA	<=	16'h9ae0;  //Must be set to 0b1110000
	26	:	LUT_DATA	<=	16'h9c30;  //PLL filter R1 value
	27	:	LUT_DATA	<=	16'h9d61;  //Set clock divide
	28	:	LUT_DATA	<=	16'ha2a4;  //Must be set to 0xA4 for proper operation
	29	:	LUT_DATA	<=	16'ha3a4;  //Must be set to 0xA4 for proper operation
	30	:	LUT_DATA	<=	16'ha504;  //Must be set to Default Value
	31	:	LUT_DATA	<=	16'hab40;  //Must be set to Default Value
	32	:	LUT_DATA	<=	16'haf16;  //Select HDMI mode
	33	:	LUT_DATA	<=	16'hba60;  //No clock delay
	34	:	LUT_DATA	<=	16'hd1ff;  //Must be set to Default Value
	35	:	LUT_DATA	<=	16'hde10;  //Must be set to Default for proper operation
	36	:	LUT_DATA	<=	16'he460;  //Must be set to Default Value
	37	:	LUT_DATA	<=	16'hfa7d;  //Nbr of times to look for good phase
	default:		LUT_DATA	<=	16'h9803;
	endcase
end
////////////////////////////////////////////////////////////////////
endmodule
