问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 42 人浏览分享

开启左侧

HDMI-IP项目-主讲TPG图像音频信号上板演示(EDID读取)-连载十

[复制链接]
42 0
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未供电,扬声器/耳机孔均无信号。

640?wx_fmt=png&from=appmsg
2 读取显示器EDID

EDID读取的驱动实现中,采用米联客提供的uii2c.v模块作为底层I²C通信核心,其详细原理可参考《米联客FPGA程序设计基础实验》课程资料。

本章聚焦于搭建顶层控制模块edid_reader,通过精准的状态机调度uii2c.v模块完成EDID数据时序控制、地址解析及数据包解析等关键操作,最终实现EDID数据的完整提取,避免重复讲解底层通信协议实现细节。

  1. module edid_reader (
  2.     input         I_clk,         // 50MHz时钟输入
  3.     input         I_reset_n,     // 低电平复位
  4.     inout         IO_edid_sda,   // EDID SDA总线
  5.     output        O_edid_scl     // EDID SCL时钟
  6. );
  7. // I2C控制器参数
  8. localparam WRITE_BYTES = 2;     // 器件地址+寄存器地址
  9. localparam READ_BYTES  = 128;   // EDID数据长度
  10. localparam CLK_DIV     = 499;   // 100kHz @50MHz
  11. // 状态机定义
  12. localparam [2:0]   S_IDLE               = 3'd0;
  13. localparam [2:0]   S_START_WRITE        = 3'd1;
  14. localparam [2:0]   S_WRITE_DATA         = 3'd2;
  15. localparam [2:0]   S_START_WAIT_BUSY1   = 3'd3;
  16. localparam [2:0]   S_STOP               = 3'd4;
  17. localparam [2:0]   S_ERROR              = 3'd5;
  18. reg [3:0] state         ;
  19. reg [7:0] retry_cnt     ;
  20. reg [10:0] timeout_cnt  ;
  21. // 控制信号
  22. reg         iic_req ;
  23. reg [15:0]  wr_data_reg ; // 默认写数据:0xA0 + 0x00
  24. reg [7 :0]  wr_cnt       = 8'd0;//写数据计数器
  25. reg [7 :0]  rd_cnt       = 8'd0;//读数据计数器
  26. wire       iic_busy;
  27. wire       iic_bus_error;
  28. wire [7:0]  edid_data;    // 当前读取的EDID数据
  29. wire        edid_valid;    // EDID数据有效标志
  30. // I2C控制器实例化
  31. uii2c #(
  32.     .WMEN_LEN(WRITE_BYTES),
  33.     .RMEN_LEN(READ_BYTES),
  34.     .CLK_DIV(CLK_DIV)
  35. ) u_i2c_ctrl (
  36.     .clk_i(I_clk),
  37.     .rstn_i(I_reset_n),
  38.     .iic_scl(O_edid_scl),
  39.     .iic_sda(IO_edid_sda),
  40.     .wr_data(wr_data_reg),
  41.     .wr_cnt(wr_cnt),
  42.     .rd_data(edid_data),
  43.     .rd_cnt(rd_cnt),
  44.     .iic_req(iic_req),
  45.     .iic_busy(iic_busy),
  46.     .iic_bus_error(iic_bus_error)
  47. );
  48. always @(posedge I_clk or negedge I_reset_n) begin
  49.     if (!I_reset_n) begin
  50.         timeout_cnt <= 0;
  51.     end
  52.     else if (timeout_cnt[10])begin
  53.         timeout_cnt <= timeout_cnt;
  54.     end
  55.     else timeout_cnt <= timeout_cnt +1 ;
  56. end
  57. // 主状态机
  58. always @(posedge I_clk or negedge I_reset_n) begin
  59.     if (!I_reset_n) begin
  60.         state <= S_IDLE;
  61.         iic_req <= 0;
  62.         retry_cnt <= 0;
  63.     end else begin
  64.         case (state)
  65.             S_IDLE: begin
  66.                 if (timeout_cnt[10]) begin
  67.                     state <= S_START_WRITE;
  68.                     wr_data_reg <= {8'h00,8'hA0}; // 写地址+寄存器
  69.                 end else begin
  70.                     state <= S_IDLE;
  71.                 end
  72.             end
  73.             S_START_WRITE: begin
  74.                 if (!iic_busy) begin
  75.                     iic_req <= 1;
  76.                     wr_cnt  <= 8'd2;
  77.                     rd_cnt  <= 8'd128; //不需要读数据
  78.                     state <= S_START_WAIT_BUSY1;
  79.                 end
  80.                 else state <= S_START_WRITE;
  81.             end
  82.             S_START_WAIT_BUSY1:begin
  83.                 if (iic_busy) begin
  84.                     state <= S_WRITE_DATA;
  85.                 end
  86.                 else begin  
  87.                     state <= S_START_WAIT_BUSY1;
  88.                 end
  89.             end
  90.             S_WRITE_DATA: begin
  91.                     iic_req <= 0;
  92.                 if (!iic_bus_error) begin
  93.                     if (!iic_busy) begin
  94.                         state <= S_STOP;
  95.                         end
  96.                     else state <= S_WRITE_DATA;
  97.                 end  
  98.                 else state <= S_ERROR;
  99.             end
  100.             S_STOP: begin
  101.                 state <= S_STOP; // 完成读取
  102.             end
  103.             S_ERROR: begin
  104.                 iic_req <= 0;
  105.                 if (!I_reset_n)                     
  106.                 state <= S_IDLE; // 重试机制
  107.                 else begin
  108.                 state <= S_ERROR; // 重试机制
  109.                 end
  110.             end
  111.         endcase
  112.     end
  113. end
  114. // 有效信号生成
  115. assign edid_valid = (state == S_STOP) && !iic_busy;
  116. endmodule
复制代码
3 工程建立
640?wx_fmt=png&from=appmsg

通过TPG参数可控制测试信号源的生成模式:当参数设置为1时,系统将调用IP内部集成的TPG测试图像模块及模拟音频信号;若参数设置为0,则基于外部输入控制信号生成数据岛时序,同时图像与音频信号均采用实际采集数据。

完成管脚绑定与编译后,需通过硬件板级测试验证功能完整性及信号同步性。

4测试结果
640?wx_fmt=png&from=appmsg

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

0

粉丝

303

主题
精彩推荐
热门资讯
网友晒图
图文推荐

  • 微信公众平台

  • 扫描访问手机版