// ============================================================================ // 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