| 1概述 前面几讲期我们介绍了很多理论知识,但是当我们完成了所有的前期准备工作,准备将编码完成后的数据输出到显示器上的时候,发现并不能发出声音。这是由以下硬件协议和信号处理机制共同决定的: 1. 协议层阻断  HDMI/DP规范要求:  - 主机必须通过EDID中的`音频描述符`(Audio Descriptor)确认显示器支持音频功能,才会启用音频数据包封装。  - 即使强制发送音频包(如通过显卡驱动绕过检测),显示器端的HDMI接收芯片(如Silicon Image SiI9033)会因未收到EDID中的`AUDIO_SUPPORT`标志,直接丢弃TMDS中的音频数据包。  2. 固件级静默  显示器主控芯片(如联发科MTK 5891)在启动时检测EDID中的`Speaker Allocation`字段:  - 若未检测到有效音频配置,会关闭音频DAC模块的电源(如TI TAS5707),物理上阻断音频信号输出。  - 即使音频数据到达显示器,因DAC未供电,扬声器/耳机孔均无信号。   2 读取显示器EDID
 在EDID读取的驱动实现中,采用米联客提供的uii2c.v模块作为底层I²C通信核心,其详细原理可参考《米联客FPGA程序设计基础实验》课程资料。 本章聚焦于搭建顶层控制模块edid_reader,通过精准的状态机调度uii2c.v模块完成EDID数据时序控制、地址解析及数据包解析等关键操作,最终实现EDID数据的完整提取,避免重复讲解底层通信协议实现细节。 3 工程建立复制代码module edid_reader (
    input         I_clk,         // 50MHz时钟输入
    input         I_reset_n,     // 低电平复位
    inout         IO_edid_sda,   // EDID SDA总线
    output        O_edid_scl     // EDID SCL时钟
);
// I2C控制器参数
localparam WRITE_BYTES = 2;     // 器件地址+寄存器地址
localparam READ_BYTES  = 128;   // EDID数据长度
localparam CLK_DIV     = 499;   // 100kHz @50MHz
// 状态机定义
localparam [2:0]   S_IDLE               = 3'd0;
localparam [2:0]   S_START_WRITE        = 3'd1;
localparam [2:0]   S_WRITE_DATA         = 3'd2;
localparam [2:0]   S_START_WAIT_BUSY1   = 3'd3;
localparam [2:0]   S_STOP               = 3'd4;
localparam [2:0]   S_ERROR              = 3'd5;
reg [3:0] state         ;
reg [7:0] retry_cnt     ;
reg [10:0] timeout_cnt  ;
// 控制信号
reg         iic_req ;
reg [15:0]  wr_data_reg ; // 默认写数据:0xA0 + 0x00
reg [7 :0]  wr_cnt       = 8'd0;//写数据计数器
reg [7 :0]  rd_cnt       = 8'd0;//读数据计数器
wire       iic_busy;
wire       iic_bus_error;
wire [7:0]  edid_data;    // 当前读取的EDID数据
wire        edid_valid;    // EDID数据有效标志
// I2C控制器实例化
uii2c #(
    .WMEN_LEN(WRITE_BYTES),
    .RMEN_LEN(READ_BYTES),
    .CLK_DIV(CLK_DIV)
) u_i2c_ctrl (
    .clk_i(I_clk),
    .rstn_i(I_reset_n),
    .iic_scl(O_edid_scl),
    .iic_sda(IO_edid_sda),
    .wr_data(wr_data_reg),
    .wr_cnt(wr_cnt),
    .rd_data(edid_data),
    .rd_cnt(rd_cnt),
    .iic_req(iic_req),
    .iic_busy(iic_busy),
    .iic_bus_error(iic_bus_error)
);
always @(posedge I_clk or negedge I_reset_n) begin
    if (!I_reset_n) begin
        timeout_cnt <= 0;
    end
    else if (timeout_cnt[10])begin
        timeout_cnt <= timeout_cnt;
    end
    else timeout_cnt <= timeout_cnt +1 ;
end
// 主状态机
always @(posedge I_clk or negedge I_reset_n) begin
    if (!I_reset_n) begin
        state <= S_IDLE;
        iic_req <= 0;
        retry_cnt <= 0;
    end else begin
        case (state)
            S_IDLE: begin
                if (timeout_cnt[10]) begin
                    state <= S_START_WRITE;
                    wr_data_reg <= {8'h00,8'hA0}; // 写地址+寄存器
                end else begin
                    state <= S_IDLE;
                end
            end
            S_START_WRITE: begin
                if (!iic_busy) begin
                    iic_req <= 1;
                    wr_cnt  <= 8'd2;
                    rd_cnt  <= 8'd128; //不需要读数据
                    state <= S_START_WAIT_BUSY1;
                end
                else state <= S_START_WRITE;
            end
            S_START_WAIT_BUSY1:begin
                if (iic_busy) begin
                    state <= S_WRITE_DATA;
                end
                else begin  
                    state <= S_START_WAIT_BUSY1;
                end
            end
            S_WRITE_DATA: begin
                    iic_req <= 0;
                if (!iic_bus_error) begin
                    if (!iic_busy) begin
                        state <= S_STOP;
                        end
                    else state <= S_WRITE_DATA;
                end  
                else state <= S_ERROR;
            end
            S_STOP: begin
                state <= S_STOP; // 完成读取
            end
            S_ERROR: begin
                iic_req <= 0;
                if (!I_reset_n)                     
                state <= S_IDLE; // 重试机制
                else begin
                state <= S_ERROR; // 重试机制
                end
            end
        endcase
    end
end
// 有效信号生成
assign edid_valid = (state == S_STOP) && !iic_busy;
endmodule
   通过TPG参数可控制测试信号源的生成模式:当参数设置为1时,系统将调用IP内部集成的TPG测试图像模块及模拟音频信号;若参数设置为0,则基于外部输入控制信号生成数据岛时序,同时图像与音频信号均采用实际采集数据。 完成管脚绑定与编译后,需通过硬件板级测试验证功能完整性及信号同步性。4测试结果 
   
 
 |