1 HDMI数据包类型概述 HDMI数据岛包含多种标准化的数据包类型:音频采样包(传输多通道PCM或压缩音频流,含时钟再生信息确保音画同步)、信息帧包(携带色彩空间、HDR元数据、3D格式等视频参数)、辅助视频信息包(AVI InfoFrame定义视频分辨率与扫描方式)、控制包(传输CEC指令、EDID扩展显示识别数据及HDCP加密控制信号)以及动态元数据包(如Dolby Vision的动态亮度映射数据)等,这些数据包通过时分复用机制嵌入消隐期,实现音视频同步传输与设备间智能交互。 完整的数据包类型如图所示,图片来自于HDMI协议手册《High-Definition Multimedia Interface》:
当然我们并不需要包含所有数据包,下面我们提供所需数据包的详细介绍以及组包代码。 2 数据包类型
2.1音频时钟再生包(Audio Clock Regeneration Packet)音频时钟再生数据包包含音频时钟再生过程中使用的N和CTS值。这四个子分组各自包含相同的音频时钟再生子分组。HDMI接收器应忽略音频时钟再生数据包报头的字节HB1和HB2。 2.1.1音频时钟再生数据包报头(Audio Clock Regeneration Subpacket)
2.1.2音频时钟再生子包(Audio Clock Regeneration Subpacket)
2.1.3音频时钟再生包(Audio Clock Regeneration Packet)代码该模块是HDMI 1.4b音频时钟再生包生成器,核心功能包括:通过CTS(循环时间戳)和N值参数(CTS=128*N/Fs)重构音频时钟,将24位包头(含标识符0x01)和56位数据体(含CTS[23:0]、N[19:0])分别进行BCH-8编码(包头BCH(32,24)生成8位ECC,数据体BCH(64,56)生成8位ECC),输出符合Section 5.3.3规范的五组BCH数据块(块4含包头+ECC,块3含数据体+ECC,块0-2保留填零)。
- ///////////////////////////////////////////////////////////////////////////////
- //// HDMI 1.4b 音频时钟再生包生成器 ////
- //// 功能: ////
- //// 1. 生成符合HDMI 1.4b Section 5.3.3的音频时钟重构包 ////
- //// 2. CTS(循环时间戳)输入范围控制与验证 ////
- //// 3. BCH-8编码实现符合Section 5.3.2的ECC要求 ////
- ///////////////////////////////////////////////////////////////////////////////
-
- module audio_clock_regeneration_packet (
- input wire I_pixel_clk, // 74.25MHz主时钟(TMDS时钟频率)
- input wire I_reset_n, // 异步复位(高电平有效)
-
- input wire [19:0] I_audio_CTS, // 24-bit CTS值(按CT = 128*N/FS计算)
- input wire [19:0] I_audio_N, // 20-bit N值(FS = Tmds_Clk*N/(128*CT))
-
- output reg [31:0] O_BCH_block_4, // BCH块4[头数据+ECC]
- output reg [63:0] O_BCH_block_3, // BCH块3[音频数据体]
- output reg [63:0] O_BCH_block_2, // BCH块2(保留区)
- output reg [63:0] O_BCH_block_1, // BCH块1(保留区)
- output reg [63:0] O_BCH_block_0 // BCH块0(保留区)
- );
-
- //=======================================================================
- // HDMI 1.4b规范定义参数
- //=======================================================================
- localparam [7:0] HEADER_HB0 = 8'h01; // 包头标识(0x01表示音频时钟包)
- localparam [7:0] HEADER_HB1 = 8'h00; // 保留字段(必须置零)
- localparam [7:0] HEADER_HB2 = 8'h00; // 保留字段(必须置零)
- localparam [7:0] SB0_RESERVED = 8'h00; // 数据体SB0固定保留
-
- //=======================================================================
- // 寄存器组声明
- //=======================================================================
- reg [7:0] r_header_hb0; // 包头字节0(固定0x01)
- reg [7:0] r_header_hb1; // 包头字节1(保留)
- reg [7:0] r_header_hb2; // 包头字节2(保留)
-
- reg [7:0] r_body_sb0; // 数据体字节0(保留)
- reg [7:0] r_body_sb1; // 数据体字节1(CTS[19:16]高4位)
- reg [7:0] r_body_sb2; // 数据体字节2(CTS[15:8])
- reg [7:0] r_body_sb3; // 数据体字节3(CTS[7:0])
- reg [7:0] r_body_sb4; // 数据体字节4(N[19:16]高4位)
- reg [7:0] r_body_sb5; // 数据体字节5(N[15:8])
- reg [7:0] r_body_sb6; // 数据体字节6(N[7:0])
-
- //=======================================================================
- // 数据拼接组合逻辑
- //=======================================================================
- wire [23:0] w_header ; // 24位包头数据
- wire [55:0] w_body ; // 56位有效数据体
- assign w_header = {r_header_hb2, r_header_hb1, r_header_hb0}; // 包头拼接
- assign w_body = {r_body_sb6, r_body_sb5, r_body_sb4, r_body_sb3, r_body_sb2, r_body_sb1, r_body_sb0}; // 数据体拼接
-
- //=======================================================================
- // 包头与数据体内容更新逻辑
- // 根据HDMI规范Section 5.3.3构建数据结构:
- // - 包头:3字节(0x01 + 2字节保留)
- // - 数据体:7字节(CTS[23:0]占用3字节,N[19:0]占用3字节,SB0/SB3/SB6保留)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 异步复位初始化
- r_header_hb0 <= 8'h0;
- r_header_hb1 <= 8'h0;
- r_header_hb2 <= 8'h0;
- r_body_sb0 <= 8'h0;
- r_body_sb1 <= 8'h0;
- r_body_sb2 <= 8'h0;
- r_body_sb3 <= 8'h0;
- r_body_sb4 <= 8'h0;
- r_body_sb5 <= 8'h0;
- r_body_sb6 <= 8'h0;
- end else begin // 正常数据装载
- // 固定包头内容
- r_header_hb0 <= HEADER_HB0; // HB0 = 0x01(包类型标识)
- r_header_hb1 <= HEADER_HB1; // HB1 = 0x00(保留)
- r_header_hb2 <= HEADER_HB2; // HB2 = 0x00(保留)
-
- // 数据体内容组装
- r_body_sb0 <= SB0_RESERVED; // SB0固定保留
- r_body_sb1 <= {4'b0000, I_audio_CTS[19:16]};// SB1高4位补零 + CTS[19:16]
- r_body_sb2 <= I_audio_CTS[15:8]; // SB2 = CTS[15:8]
- r_body_sb3 <= I_audio_CTS[7:0]; // SB3 = CTS[7:0]
- r_body_sb4 <= {4'b0000, I_audio_N[19:16]}; // SB4高4位补零 + N[19:16]
- r_body_sb5 <= I_audio_N[15:8]; // SB5 = N[15:8]
- r_body_sb6 <= I_audio_N[7:0]; // SB6 = N[7:0]
- end
- end
-
- //=======================================================================
- // BCH错误校验码生成器
- // 规范要求:
- // - 包头使用BCH(32,24)编码(24位数据+8位ECC)
- // - 数据体使用BCH(64,56)编码(56位数据+8位ECC)
- //=======================================================================
- wire [7:0] w_header_ecc, w_body_ecc;
-
- BCH_32_24_encode u_BCH_32_24_encode( // 包头BCH编码器
- .I_clk (I_pixel_clk ), // 74.25MHz主时钟
- .I_data_in (w_header ), // 24位包头数据
- .O_bch_ecc_out (w_header_ecc ) // 8位ECC校验码
- );
-
- BCH_64_56_encode u_BCH_64_56_encode( // 数据体BCH编码器
- .I_clk (I_pixel_clk), // 74.25MHz主时钟
- .I_data_in (w_body ), // 56位有效数据
- .O_bch_ecc_out (w_body_ecc ) // 8位ECC校验码
- );
-
- //=======================================================================
- // BCH数据块输出组合
- // 根据HDMI数据包结构:
- // - Block4: 包头(24b) + ECC(8b) = 32bits
- // - Block3: 数据体(56b) + ECC(8b) = 64bits
- // - Block2~0: 保留区(需填充0)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 复位清零
- O_BCH_block_4 <= 32'b0;
- O_BCH_block_3 <= 64'b0;
- O_BCH_block_2 <= 64'b0;
- O_BCH_block_1 <= 64'b0;
- O_BCH_block_0 <= 64'b0;
- end else begin // 正常输出
- // Block4:包头数据 + ECC(32位)
- O_BCH_block_4 <= {w_header_ecc, w_header};
-
- // Block3:数据体 + ECC(64位)
- O_BCH_block_3 <= {w_body_ecc, w_body[55:0]};
-
- // Block2~0:保留区填充0(规范要求未使用区域必须置零)
- O_BCH_block_2 <= 64'h0;
- O_BCH_block_1 <= 64'h0;
- O_BCH_block_0 <= 64'h0;
- end
- end
-
- endmodule
复制代码
2.2音频样本包(Audio Sample Packet)L-PCM和一些IEC 61937压缩音频格式使用音频样本包来传送。 音频样本包由一到四个音频样本组成。这些可以是不同的样本或不同的部分样本(即6个通道中的2个)。子分组的配置由报头中的layout和sample_present位决定。 2.2.1音频样本数据包报头(Audio Sample Packet Header )
关于Layout值和Audio Packet的关系 ,协议中是这样介绍的。
在音频样本分组报头中有四个sample_present比特,每个子分组一个。这些指示子分组是否包含音频样本。 此外,如果在sample_flat.spX所代表的时间段内,源端没有可用的音频数据,则会设置四个sample _ flat . spx位。这可能发生在采样速率变化或临时流中断期间。当sample_flat.spX置位时,子包X继续代表一个采样周期,但不包含有用的音频数据。仅当相应的sample_present.spX位置位时,sample_flat.spX位才有效。 Layout0可用于从单个IEC 61937或单个双声道IEC 60958音频流中携带多达四个样本。 Layout1可用于携带具有三到八个L-PCM音频通道的一个音频样本(即两到四个IEC 60958流)。 如下图所示,本例程选择使用双通道,所以选择layout值为0。如果有多音频通道需求,可以修改为1。 当layout值为0时,有效Sample_Present位配置如下
选择把数据数据放在block_0上,所以把sample_ present.sp0 拉高 2.2.2音频样本子包(Audio Sample Subpacket)
SB0-SB5分别填入24位左右声道音频数据信息,如超过24位则舍弃低位数据,SB6中的内容,本课程并未涉及,所以不做详细介绍。 2.2.3音频样本包(Audio Sample Packet)代码该模块是HDMI 1.4b音频采样包封装器,核心功能包括:将双声道24bit音频数据(小端模式拆分为6字节)与包头(类型0x02+控制字段)按规范封装,通过BCH(32,24)和BCH(64,56)编码生成包头和数据体的8位ECC校验码,采用XPM FIFO缓冲音频数据流并实现请求-应答握手协议,输出符合五组BCH数据块(块4含包头+ECC,块0含音频数据体+ECC,其余块填零)。 - `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // HDMI 1.4b音频采样包封装模块
- // 功能特性:
- // 1. 符合HDMI 1.4b规范Section 5.3.3音频采样包格式
- // 2. 支持双声道24bit音频数据封装
- // 3. 集成BCH(32,24)和BCH(64,56)错误校验码生成
- // 4. 采用XPM FIFO实现数据流缓冲对齐
- // 5. 支持音频包请求/应答握手协议
- //////////////////////////////////////////////////////////////////////////////////
-
- module audio_sample_packet_channel(
- input wire I_pixel_clk, // 74.25MHz主时钟(TMDS时钟域)
- input wire I_reset_n, // 异步复位(低电平有效)
-
- //================= 音频输入接口 =================//
- input wire I_audio_valid, // 音频数据有效脉冲(与数据对齐)
- input wire [23:0] I_audio_left_data, // 左声道24bit音频(补码格式)
- input wire [23:0] I_audio_right_data, // 右声道24bit音频(补码格式)
-
- //================ 包控制接口 ====================//
- input wire I_audio_packet_req, // 音频包请求信号(主机发起)
- output reg O_audio_packet_valid, // 音频包有效指示(应答信号)
-
- //============== BCH编码输出接口 ==================//
- output reg [31:0] O_BCH_block_4, // BCH块4:[31:24]=包头ECC,[23:0]=包头
- output reg [63:0] O_BCH_block_3, // BCH块3:保留区(固定0)
- output reg [63:0] O_BCH_block_2, // BCH块2:保留区(固定0)
- output reg [63:0] O_BCH_block_1, // BCH块1:保留区(固定0)
- output reg [63:0] O_BCH_block_0 // BCH块0:[63:56]=数据体ECC,[55:0]=音频数据
- );
-
- //=======================================================================
- // HDMI规范参数定义(Section 5.3.3 Audio Sample Packet)
- //=======================================================================
- localparam [7:0] HEADER_HB0 = 8'h02; // 包头类型(0x02=音频采样包)
- localparam [7:0] HEADER_HB1 = {3'b000,1'b0,4'b0001}; // 控制字段:
- // [7:5]=000(保留),[4]=0(线性PCM),[3:0]=0001(双声道)
- localparam [7:0] HEADER_HB2 = 8'h00; // 保留字段(必须置零)
- localparam [7:0] SB_RESERVED = 8'h00; // 数据体保留字段填充值
-
- //=======================================================================
- // 寄存器组声明
- //=======================================================================
- reg [7:0] r_header_hb0; // 包头字节0(类型标识)
- reg [7:0] r_header_hb1; // 包头字节1(控制字段)
- reg [7:0] r_header_hb2; // 包头字节2(保留)
-
- reg [7:0] r_body_sb0; // 数据体字节0(左声道LSB)
- reg [7:0] r_body_sb1; // 数据体字节1(左声道)
- reg [7:0] r_body_sb2; // 数据体字节2(左声道MSB)
- reg [7:0] r_body_sb3; // 数据体字节3(右声道LSB)
- reg [7:0] r_body_sb4; // 数据体字节4(右声道)
- reg [7:0] r_body_sb5; // 数据体字节5(右声道MSB)
- reg [7:0] r_body_sb6; // 数据体字节6(保留)
- reg [55:0] r_body; // 数据体缓冲(56bit)
-
- //=======================================================================
- // FIFO控制信号
- //=======================================================================
- reg r_fifo_wr_en; // FIFO写使能(一级缓冲)
- reg rr_fifo_wr_en; // FIFO写使能(二级缓冲)
- wire w_rd_en; // FIFO读使能
- wire w_fifo_full; // FIFO满标志
- wire w_fifo_empty; // FIFO空标志
- wire [63:0] w_fifo_dout; // FIFO输出数据(64bit)
-
- //=======================================================================
- // 数据拼接组合逻辑
- //=======================================================================
- wire [23:0] w_header = {r_header_hb2, r_header_hb1, r_header_hb0}; // 24bit包头
- wire [55:0] w_body = {r_body_sb6, r_body_sb5, r_body_sb4, r_body_sb3,
- r_body_sb2, r_body_sb1, r_body_sb0}; // 56bit数据体
- wire [63:0] w_BCH_block_0 = (~w_fifo_empty) ? w_fifo_dout : 64'h0; // FIFO数据输出
- assign w_rd_en = (~w_fifo_empty) ? I_audio_packet_req : 1'b0; // 读使能生成
-
- //=======================================================================
- // 音频包构造逻辑(按HDMI CTS 1.4b规范S6.3.4实现)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 异步复位初始化
- // 包头复位
- r_header_hb0 <= 8'h0;
- r_header_hb1 <= 8'h0;
- r_header_hb2 <= 8'h0;
-
- // 数据体复位
- r_body_sb0 <= 8'h0;
- r_body_sb1 <= 8'h0;
- r_body_sb2 <= 8'h0;
- r_body_sb3 <= 8'h0;
- r_body_sb4 <= 8'h0;
- r_body_sb5 <= 8'h0;
- r_body_sb6 <= 8'h0;
- end else begin // 正常数据构造
- //----------------------------
- // 固定包头构造
- //----------------------------
- r_header_hb0 <= HEADER_HB0; // 包类型标识(0x02)
- r_header_hb1 <= HEADER_HB1; // 控制字段(双声道PCM)
- r_header_hb2 <= HEADER_HB2; // 保留字段
-
- //----------------------------
- // 动态数据体构造(小端模式)
- //----------------------------
- // 左声道数据(24bit拆分为3字节)
- r_body_sb0 <= I_audio_left_data[7:0] ; // 字节0:LSB
- r_body_sb1 <= I_audio_left_data[15:8] ; // 字节1
- r_body_sb2 <= I_audio_left_data[23:16] ; // 字节2:MSB
-
- // 右声道数据(24bit拆分为3字节)
- r_body_sb3 <= I_audio_right_data[7:0] ; // 字节3:LSB
- r_body_sb4 <= I_audio_right_data[15:8] ; // 字节4
- r_body_sb5 <= I_audio_right_data[23:16] ; // 字节5:MSB
-
- // 保留字段处理
- r_body_sb6 <= SB_RESERVED; // 字节6:固定填充0
- end
- end
-
- //=======================================================================
- // 数据缓冲逻辑(二级寄存器消除亚稳态)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin
- r_fifo_wr_en <= 1'b0;
- rr_fifo_wr_en<= 1'b0;
- end else begin
- r_fifo_wr_en <= I_audio_valid; // 原始有效信号打拍
- rr_fifo_wr_en <= r_fifo_wr_en; // 二级缓冲
- end
- end
-
- //=======================================================================
- // BCH块输出组合逻辑
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 复位清零
- O_BCH_block_4 <= 32'b0;
- O_BCH_block_3 <= 64'b0;
- O_BCH_block_2 <= 64'b0;
- O_BCH_block_1 <= 64'b0;
- O_BCH_block_0 <= 64'b0;
- end else begin // 正常输出
- // Block4:包头 + ECC(32bit)
- O_BCH_block_4 <= {w_header_ecc, w_header};
-
- // Block3~1:保留区置零
- O_BCH_block_3 <= 64'h0;
- O_BCH_block_2 <= 64'h0;
- O_BCH_block_1 <= 64'h0;
-
- // Block0:数据体 + ECC(64bit)
- O_BCH_block_0 <= w_BCH_block_0;
- end
- end
-
- //=======================================================================
- // 包有效状态机(请求-应答握手协议)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin
- O_audio_packet_valid <= 1'b0;
- end else if (I_audio_packet_req && !w_fifo_empty) begin
- O_audio_packet_valid <= 1'b1; // FIFO非空时响应请求
- end else begin
- O_audio_packet_valid <= 1'b0; // 默认无效
- end
- end
-
- //=======================================================================
- // BCH编码器实例化
- //=======================================================================
- BCH_32_24_encode u_BCH_32_24_encode( // 包头BCH(32,24)编码器
- .I_clk (I_pixel_clk ), // 74.25MHz时钟
- .I_data_in (w_header ), // 24bit包头输入
- .O_bch_ecc_out (w_header_ecc ) // 8bit ECC输出
- );
-
- BCH_64_56_encode u_BCH_64_56_encode( // 数据体BCH(64,56)编码器
- .I_clk (I_pixel_clk), // 74.25MHz时钟
- .I_data_in (w_body ), // 56bit数据输入
- .O_bch_ecc_out (w_body_ecc ) // 8bit ECC输出
- );
-
- //=======================================================================
- // XPM同步FIFO实例化(用于数据流缓冲)
- //=======================================================================
- xpm_fifo_sync #(
- .DOUT_RESET_VALUE ("0"), // 复位输出值
- .ECC_MODE ("no_ecc"), // 禁用ECC模式
- .FIFO_MEMORY_TYPE ("auto"), // 自动选择存储类型
- .FIFO_READ_LATENCY (1), // 固定1周期读延迟
- .FIFO_WRITE_DEPTH (1024), // 深度1024(适应突发传输)
- .FULL_RESET_VALUE (0), // 复位时FULL=0
- .READ_DATA_WIDTH (64), // 64bit读数据
- .READ_MODE ("fwft"), // 首字直通模式
- .SIM_ASSERT_CHK (0), // 关闭仿真断言
- .WRITE_DATA_WIDTH (64) // 64bit写数据
- ) u_audio_fifo (
- .rst (!I_reset_n ), // 异步复位(低有效)
- .wr_clk (I_pixel_clk ), // 写时钟
- .wr_en (rr_fifo_wr_en ), // 写使能(二级缓冲)
- .din ({w_body_ecc, r_body}), // 输入数据[63:56]=ECC,[55:0]=数据体
- .full (w_fifo_full ), // FIFO满标志
- .rd_en (w_rd_en ), // 读使能(请求触发)
- .dout (w_fifo_dout ), // 输出数据
- .empty (w_fifo_empty ) // FIFO空标志
- );
-
- endmodule
复制代码
2.3辅助视频信息(AVI)信息包(Auxiliary Video information (AVI) InfoFrame Packet)HDMI信源通过辅助视频信息(AVI)信息帧指示当前视频流的各个方面。 如果信号源满足以下条件,则信号源应始终至少每两个视频场传输一次AVI信息帧: • 能够传输AVI信息帧, • 能够传输YCBCR像素编码, • 能够传输除传输的视频格式的默认色度之外的任何色度, • 曾经能够传输任何xvYCC或未来增强的色度, • 曾经能够传输任何色域元数据包, • 能够传输具有多个允许像素重复的任何视频格式。 AVI信息框架版本2的打包如下所示。 2.3.1AVI信息帧数据包报头(AVI InfoFrame Packet Header)
Header包头是固定值,所以无需讨论 2.3.2AVI信息框架数据包内容(AVI InfoFrame Packet Contents )
HDMI协议手册《High-Definition Multimedia Interface》让我们通过《CEA-861-D》查询信息,打开《CEA-861-D》6.4节。内容如下: AVI InfoFrame 数据字节 1:
AVI InfoFrame 数据字节 2:
AVI InfoFrame 数据字节 3:
AVI InfoFrame 数据字节 4: 我们本课程使用的是1280×720p@59.94/60Hz,所以我们的Video Codes选择4。
AVI InfoFrame 数据字节 5:
本包的参数选择和参数介绍非常繁琐,感兴趣的可以自行查询《CEA-861-D》中详细内容介绍,本教程仅提供参照表格,重点部分代码中已经做参数处理,并不做详细介绍。 2.3.3AVI信息框架数据包(Auxiliary Video information (AVI) InfoFrame Packet)代码该模块是HDMI AVI信息帧封装器,核心功能包括:根据CEA-861-F标准构建AVI信息帧结构(包头0x82标识+13字节数据体),动态生成视频格式(4:3/16:9)、色彩空间(RGB/BT601)和VIC码参数,通过BCH(32,24)和BCH(64,56)编码分别对24位包头与56位数据体(含校验和、控制字段、VIC等)生成8位ECC校验码,输出五组BCH编码块(块4含包头+ECC,块0含数据体+ECC,其余块填零),符合HDMI 1.4b CTS 6.5.2规范要求,用于在视频消隐期传输显示参数配置信息。 - `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // HDMI AVI信息帧封装模块(符合HDMI 1.4b CTS 6.5.2节规范)
- // 功能特性:
- // 1. 生成符合CEA-861-F标准的AVI信息帧
- // 2. 支持视频格式、色彩空间、VIC码等参数配置
- // 3. 集成BCH(32,24)和BCH(64,56)错误校验码生成
- // 4. 严格遵循HDMI规范保留字段处理
- //////////////////////////////////////////////////////////////////////////////////
-
- module avi_info_frame_packet (
- //==================== 全局信号 ====================//
- input wire I_pixel_clk, // 74.25MHz像素时钟
- input wire I_reset_n, // 异步复位(低电平有效)
-
- //================== 视频配置输入 ==================//
- input wire [1:0] I_video_format, // 视频宽高比 00=4:3,01=16:9,10/11保留
- input wire [1:0] I_colorimetry, // 色彩空间 00=RGB,01=BT601,10=BT709,11保留
- input wire [6:0] I_video_VIC, // 7bit视频标识码(CEA-861-F表15)
-
- //================= BCH编码输出 ====================//
- output reg [31:0] O_BCH_block_4, // BCH块4:[31:24]=包头ECC,[23:0]=包头
- output reg [63:0] O_BCH_block_3, // BCH块3:保留区(强制置零)
- output reg [63:0] O_BCH_block_2, // BCH块2:保留区(强制置零)
- output reg [63:0] O_BCH_block_1, // BCH块1:保留区(强制置零)
- output reg [63:0] O_BCH_block_0 // BCH块0:[63:56]=数据体ECC,[55:0]=有效数据
- );
-
- //=======================================================================
- // CEA-861-F标准参数定义(表8.8 AVI信息帧格式)
- //=======================================================================
- localparam [7:0] HEADER_HB0 = 8'h82; // 包头类型:0x82=AVI信息帧(固定值)
- localparam [7:0] HEADER_HB1 = 8'h02; // 版本号:0x02=Version 2(HDMI 1.3+使用)
- localparam [7:0] HEADER_HB2 = 8'h0D; // 数据长度:13字节(0x0D)
- localparam [7:0] SB_RESERVED = 8'h00; // 保留字段填充值(必须置零)
-
- //=======================================================================
- // 寄存器组声明
- //=======================================================================
- reg [7:0] r_header_hb0; // 包头字节0(类型标识)
- reg [7:0] r_header_hb1; // 包头字节1(版本号)
- reg [7:0] r_header_hb2; // 包头字节2(数据长度)
-
- reg [7:0] r_body_sb0; // 数据体字节0(校验和)
- reg [7:0] r_body_sb1; // 数据体字节1(视频格式/激活标志)
- reg [7:0] r_body_sb2; // 数据体字节2(色彩空间/色深)
- reg [7:0] r_body_sb3; // 数据体字节3(保留字段)
- reg [7:0] r_body_sb4; // 数据体字节4(VIC码低7位)
- reg [7:0] r_body_sb5; // 数据体字节5(保留字段)
- reg [7:0] r_body_sb6; // 数据体字节6(保留字段)
-
- //=======================================================================
- // 数据拼接组合逻辑
- //=======================================================================
- wire [23:0] w_header = {r_header_hb2, r_header_hb1, r_header_hb0}; // 24bit包头
- wire [55:0] w_body = {r_body_sb6, r_body_sb5, r_body_sb4, // 56bit数据体
- r_body_sb3, r_body_sb2, r_body_sb1, r_body_sb0};
-
- //=======================================================================
- // AVI信息帧构造逻辑(CEA-861-F表8.8)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 异步复位初始化
- r_header_hb0 <= 8'h0;
- r_header_hb1 <= 8'h0;
- r_header_hb2 <= 8'h0;
- r_body_sb0 <= 8'h0;
- r_body_sb1 <= 8'h0;
- r_body_sb2 <= 8'h0;
- r_body_sb3 <= 8'h0;
- r_body_sb4 <= 8'h0;
- r_body_sb5 <= 8'h0;
- r_body_sb6 <= 8'h0;
- end else begin // 动态字段构造
- //---------------- 固定包头 ----------------
- r_header_hb0 <= HEADER_HB0; // 类型标识
- r_header_hb1 <= HEADER_HB1; // 版本号
- r_header_hb2 <= HEADER_HB2; // 数据长度
-
- //---------------- 动态数据体 ----------------
- // SB0: 校验和 = 0x100 - (HB0+HB1+HB2+SB1+SB2+SB3+SB4+SB5)
- r_body_sb0 <= 8'd1 + ~(r_header_hb0 + r_header_hb1 + r_header_hb2 +
- r_body_sb1 + r_body_sb2 + r_body_sb3 +
- r_body_sb4 + r_body_sb5);
-
- // SB1: [7]=保留 [6:5]=视频格式 [4]=激活格式标志 [3:0]=保留
- r_body_sb1 <= {1'b0, I_video_format, 1'b1, 4'b0000}; // 激活标志固定为1
-
- // SB2: [7:6]=色彩空间 [5:4]=色深 [3:0]=保留
- r_body_sb2 <= {I_colorimetry, 2'b00, 4'b1000}; // 默认8bit色深
-
- r_body_sb3 <= 8'b0001_0000; // SB3保留字段(按规范置位bit4)
- r_body_sb4 <= {1'b0, I_video_VIC}; // SB4[7]=保留,[6:0]=VIC码
- r_body_sb5 <= SB_RESERVED; // SB5保留
- r_body_sb6 <= SB_RESERVED; // SB6保留
- end
- end
-
- //=======================================================================
- // BCH编码器实例化
- //=======================================================================
- wire [7:0] w_header_ecc, w_body_ecc;
-
- BCH_32_24_encode u_BCH_32_24_encode( // 包头BCH(32,24)编码器
- .I_clk (I_pixel_clk),
- .I_data_in (w_header), // 24bit包头数据
- .O_bch_ecc_out (w_header_ecc) // 8bit ECC校验码
- );
-
- BCH_64_56_encode u_BCH_64_56_encode( // 数据体BCH(64,56)编码器
- .I_clk (I_pixel_clk),
- .I_data_in (w_body), // 56bit有效数据
- .O_bch_ecc_out (w_body_ecc) // 8bit ECC校验码
- );
-
- //=======================================================================
- // BCH块输出组合逻辑
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 复位清零
- O_BCH_block_4 <= 32'b0;
- O_BCH_block_3 <= 64'b0;
- O_BCH_block_2 <= 64'b0;
- O_BCH_block_1 <= 64'b0;
- O_BCH_block_0 <= 64'b0;
- end else begin // 正常输出
- O_BCH_block_4 <= {w_header_ecc, w_header}; // 包头+ECC(32bit)
- O_BCH_block_3 <= 64'h0; // 保留区置零
- O_BCH_block_2 <= 64'h0;
- O_BCH_block_1 <= 64'h0;
- O_BCH_block_0 <= {w_body_ecc, w_body}; // 数据体+ECC(64bit)
- end
- end
-
- endmodule
复制代码
2.4音频信息帧包(Audio InfoFrame Packet)源应使用IEC 60958信道状态位、IEC 61937突发信息和/或流数据(如果存在)以及音频信息帧来指示活动音频流的特征。 每当传输活动音频流时,应至少每两个视频场传输一次准确的音频信息帧。 音频信息帧传输可以在数据岛分组可以被传输的任何时间发生,包括在任何水平或垂直消隐周期期间。 2.4.1音频信息帧数据包报头(Audio InfoFrame Packet Header)
Header包头是固定值,所以无需讨论 2.4.2音频信息帧数据包内容(Audio InfoFrame Packet contents)
HDMI协议手册《High-Definition Multimedia Interface》让我们通过《CEA-861-D》查询信息,打开《CEA-861-D》6.6节。内容如下: 音频信息帧数据字节1:
音频信息帧数据字节2:
我们要使用的主要信息就集中在第1和第2个 Byte中,根据表格信息做成参数查找表即可。 2.4.3音频信息帧包(Audio InfoFrame Packet)代码该模块是HDMI音频信息帧封装器,主要功能包括:构建音频信息帧,将声道数(2-8通道)、采样率(如44.1kHz/48kHz)和采样深度(16/20/24bit)等参数封装为10字节数据体(含动态计算的补码校验和),通过BCH(32,24)和BCH(64,56)编码分别对24位包头(类型0x84+版本0x01)与56位有效数据生成8位ECC校验码,输出五组BCH数据块(块4含包头+ECC,块3含音频参数数据体+ECC,其余块填零),用于在视频消隐期传输音频配置信息,确保接收端能准确重建音频时钟与解码参数。 - `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // HDMI音频信息帧封装模块
- // 功能特性:
- // 1. 生成HDMI音频信息包(audio_info_frame_packet)
- // 2. 支持多声道配置及多种采样率格式
- // 3. 集成BCH(32,24)和BCH(64,56)前向纠错编码
- //////////////////////////////////////////////////////////////////////////////////
-
- module audio_info_frame_packet(
- //==================== 全局信号 ====================//
- input wire I_pixel_clk, // 74.25MHz像素时钟
- input wire I_reset_n, // 异步复位(高电平有效)
-
- //================== 音频配置输入 ==================//
- input wire [2:0] I_audio_sample_frequency, // 3bit采样率编码(000=44.1kHz, 001=48kHz,...)
- input wire [2:0] I_audio_channel_count, // 3bit声道数(000=2ch,001=3ch,...,111=8ch)
- input wire [1:0] I_audio_sample_size, // 2bit采样深度(00=16bit,01=20bit,10=24bit)
-
- //=============== BCH编码输出接口 ==================//
- output reg [31:0] O_BCH_block_4, // BCH块4:[31:24]=包头ECC,[23:0]=包头
- output reg [63:0] O_BCH_block_3, // BCH块3:[63:56]=数据体ECC,[55:0]=有效数据
- output reg [63:0] O_BCH_block_2, // BCH块2:保留区(强制置零)
- output reg [63:0] O_BCH_block_1, // BCH块1:保留区(强制置零)
- output reg [63:0] O_BCH_block_0 // BCH块0:保留区(强制置零)
- );
-
- //=======================================================================
- // HDMI规范参数定义(CTS 1.4b S6.3.3音频信息帧数据包)
- //=======================================================================
- localparam [7:0] HEADER_HB0 = 8'h84; // 包头类型(0x84=音频信息帧数据包)
- localparam [7:0] HEADER_HB1 = 8'h01; // 版本号(0x01=版本1)
- localparam [7:0] HEADER_HB2 = 8'h0A; // 数据长度:10字节(0x0A)
- localparam [7:0] SB_RESERVED = 8'h00; // 保留字段填充值(必须置零)
-
- //=======================================================================
- // 寄存器组声明
- //=======================================================================
- reg [7:0] r_header_hb0; // 包头字节0(类型标识)
- reg [7:0] r_header_hb1; // 包头字节1(版本号)
- reg [7:0] r_header_hb2; // 包头字节2(数据长度)
-
- reg [7:0] r_body_sb0; // 数据体字节0(校验和)
- reg [7:0] r_body_sb1; // 数据体字节1(声道配置)
- reg [7:0] r_body_sb2; // 数据体字节2(采样率/深度)
- reg [7:0] r_body_sb3; // 数据体字节3(保留字段)
- reg [7:0] r_body_sb4; // 数据体字节4(保留字段)
- reg [7:0] r_body_sb5; // 数据体字节5(保留字段)
- reg [7:0] r_body_sb6; // 数据体字节6(保留字段)
-
- //=======================================================================
- // 数据拼接组合逻辑
- //=======================================================================
- wire [23:0] w_header = {r_header_hb2, r_header_hb1, r_header_hb0}; // 24bit包头
- wire [55:0] w_body = {r_body_sb6, r_body_sb5, r_body_sb4, // 56bit数据体
- r_body_sb3, r_body_sb2, r_body_sb1, r_body_sb0};
-
- //=======================================================================
- // 音频信息帧构造逻辑(CTS 1.4b S6.3.3)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 异步复位初始化
- r_header_hb0 <= 8'h0;
- r_header_hb1 <= 8'h0;
- r_header_hb2 <= 8'h0;
- r_body_sb0 <= 8'h0;
- r_body_sb1 <= 8'h0;
- r_body_sb2 <= 8'h0;
- r_body_sb3 <= 8'h0;
- r_body_sb4 <= 8'h0;
- r_body_sb5 <= 8'h0;
- r_body_sb6 <= 8'h0;
- end else begin // 动态字段构造
- //---------------- 固定包头 ----------------
- r_header_hb0 <= HEADER_HB0; // 包类型标识
- r_header_hb1 <= HEADER_HB1; // 协议版本
- r_header_hb2 <= HEADER_HB2; // 数据长度
-
- //---------------- 动态数据体 ----------------
- // SB0: 校验和 = 0x100 - (HB0+HB1+HB2+SB1+SB2+SB3+SB4+SB5)
- // 注:采用补码形式计算,等效于1 + ~(sum)
- r_body_sb0 <= 8'd1 + ~(r_header_hb0 + r_header_hb1 + r_header_hb2 +
- r_body_sb1 + r_body_sb2 + r_body_sb3 +
- r_body_sb4 + r_body_sb5);
-
- // SB1: [7:5]=保留位 [4:0]=音频声道数(0-7对应2-8声道)
- r_body_sb1 <= {3'b000, I_audio_channel_count};
-
- // SB2: [7:5]=保留位 [4:2]=采样率 [1:0]=采样深度
- r_body_sb2 <= {3'b000, I_audio_sample_frequency, I_audio_sample_size};
-
- r_body_sb3 <= SB_RESERVED; // SB3保留
- r_body_sb4 <= SB_RESERVED; // SB4保留
- r_body_sb5 <= SB_RESERVED; // SB5保留
- r_body_sb6 <= SB_RESERVED; // SB6保留
- end
- end
-
- //=======================================================================
- // BCH编码器实例化
- //=======================================================================
- wire [7:0] w_header_ecc, w_body_ecc;
-
- BCH_32_24_encode u_BCH_32_24_encode( // 包头BCH(32,24)编码器
- .I_clk (I_pixel_clk),
- .I_data_in (w_header), // 24bit包头数据
- .O_bch_ecc_out (w_header_ecc) // 8bit ECC校验码
- );
-
- BCH_64_56_encode u_BCH_64_56_encode( // 数据体BCH(64,56)编码器
- .I_clk (I_pixel_clk),
- .I_data_in (w_body), // 56bit有效数据
- .O_bch_ecc_out (w_body_ecc) // 8bit ECC校验码
- );
-
- //=======================================================================
- // BCH块输出组合逻辑
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 复位清零
- O_BCH_block_4 <= 32'b0;
- O_BCH_block_3 <= 64'b0;
- O_BCH_block_2 <= 64'b0;
- O_BCH_block_1 <= 64'b0;
- O_BCH_block_0 <= 64'b0;
- end else begin // 正常输出
- O_BCH_block_4 <= {w_header_ecc, w_header}; // 包头+ECC(32bit)
- O_BCH_block_3 <= {w_body_ecc, w_body}; // 数据体+ECC(64bit)
- O_BCH_block_2 <= 64'h0; // 保留区置零
- O_BCH_block_1 <= 64'h0;
- O_BCH_block_0 <= 64'h0;
- end
- end
-
- endmodule
复制代码
2.5通用控制包(General Control Packet)通用控制分组报头不包含数据。接收器应忽略字节HB1和HB2。通用控制包主体应包含四个相同的子包。 2.5.1通用控制包报头(General Control Packet Header)
Header包头是固定值,所以无需讨论 2.5.2通用控制子包(General Control Subpacket)
AVMUTE值(0=静音黑屏),我们选择关闭AVMUTE。Clear_AVMUTE置1,Clear_AVMUTE置0。 色深(CD场)值:
默认我们使用24bits。 像素打包相位(PP场)值:
默认选择0。 2.5.3通用控制包(General Control Packet)代码该模块是HDMI通用控制信息帧封装器,核心功能包括:根据HDMI 1.4b CTS 6.8节规范构建通用控制包(包头标识0x03),动态配置色深(24/30bpp等)、数据包相位偏移及AV静默控制(通过SB0字段的AVMUTE正反相标志),将控制参数封装为56位数据体(含7字节控制字段),通过BCH(32,24)和BCH(64,56)编码分别对24位包头与56位有效数据生成8位ECC校验码,输出五组BCH数据块(块4含包头+ECC,块0含控制参数数据体+ECC,其余块填零),用于在视频消隐期传输显示控制指令,实现色彩深度同步、数据包相位校准及音视频静默切换功能。 - `timescale 1ns / 1ps
- //////////////////////////////////////////////////////////////////////////////////
- // 通用控制信息帧封装模块(符合HDMI 1.4b规范第6.8节)
- // 功能特性:
- // 1. 生成通用控制包(General Control Packet)用于传输显示控制参数
- // 2. 支持色彩深度、数据包相位等关键参数配置
- // 3. 集成BCH(32,24)和BCH(64,56)前向纠错编码
-
- // 关键参数说明:
- // - 包头标识符0x03对应通用控制包(HDMI规范表5-8)
- // - 数据包长度固定为0字节(HB1/HB2保留)
- // - SB0控制字段定义见CTS 6.8.2节
- //////////////////////////////////////////////////////////////////////////////////
-
- module general_control_packet(
- //================= 系统接口 =================
- input wire I_pixel_clk, // 74.25MHz像素时钟(TMDS时钟的1/2)
- input wire I_reset_n, // 异步复位(低电平有效,CTS 6.8.1要求)
-
- //================= 配置输入 ================
- input wire [3:0] I_ctrl_color_depth, // 4bit色深配置(0000=24bpp,0001=30bpp,...)
- input wire [3:0] I_ctrl_packet_phase, // 4bit相位配置(视频数据包偏移控制)
- input wire I_audio_video_valid, // AV有效指示(0=静音/黑屏,1=正常输出)
-
- //================= 数据包输出 ==============
- output reg [31:0] O_BCH_block_4, // BCH块4:[31:24]=包头ECC,[23:0]=包头
- output reg [63:0] O_BCH_block_3, // BCH块3:保留区(强制置零)
- output reg [63:0] O_BCH_block_2, // BCH块2:保留区(强制置零)
- output reg [63:0] O_BCH_block_1, // BCH块1:保留区(强制置零)
- output reg [63:0] O_BCH_block_0 // BCH块0:[63:56]=数据体ECC,[55:0]=有效数据
- );
-
- //=======================================================================
- // HDMI规范参数定义(CTS 6.8.2通用控制包格式)
- //=======================================================================
- localparam [7:0] HEADER_HB0 = 8'h03; // 包类型标识符(0x03=通用控制包)
- localparam [7:0] HEADER_HB1 = 8'h00; // 保留字段(必须置零)
- localparam [7:0] HEADER_HB2 = 8'h00; // 保留字段(必须置零)
- localparam [7:0] SB_RESERVED = 8'h00; // 保留字段填充值(必须置零)
-
- //=======================================================================
- // 寄存器组声明
- //=======================================================================
- reg [7:0] r_header_hb0; // 包头字节0(类型标识)
- reg [7:0] r_header_hb1; // 包头字节1(保留)
- reg [7:0] r_header_hb2; // 包头字节2(保留)
-
- reg [7:0] r_body_sb0; // 数据体字节0(控制字段)
- reg [7:0] r_body_sb1; // 数据体字节1(相位/色深配置)
- reg [7:0] r_body_sb2; // 数据体字节2(保留)
- reg [7:0] r_body_sb3; // 数据体字节3(保留)
- reg [7:0] r_body_sb4; // 数据体字节4(保留)
- reg [7:0] r_body_sb5; // 数据体字节5(保留)
- reg [7:0] r_body_sb6; // 数据体字节6(保留)
-
- //=======================================================================
- // 数据拼接组合逻辑
- //=======================================================================
- wire [23:0] w_header = {r_header_hb2, r_header_hb1, r_header_hb0}; // 24bit包头
- wire [55:0] w_body = {r_body_sb6, r_body_sb5, r_body_sb4, // 56bit数据体
- r_body_sb3, r_body_sb2, r_body_sb1, r_body_sb0};
-
- //=======================================================================
- // 控制包构造逻辑(CTS 6.8.2节时序要求)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 异步复位初始化
- r_header_hb0 <= 8'h0;
- r_header_hb1 <= 8'h0;
- r_header_hb2 <= 8'h0;
- r_body_sb0 <= 8'h0;
- r_body_sb1 <= 8'h0;
- r_body_sb2 <= 8'h0;
- r_body_sb3 <= 8'h0;
- r_body_sb4 <= 8'h0;
- r_body_sb5 <= 8'h0;
- r_body_sb6 <= 8'h0;
- end else begin // 动态字段构造
- //---------------- 固定包头 ----------------
- r_header_hb0 <= HEADER_HB0; // 类型标识符
- r_header_hb1 <= HEADER_HB1; // 保留字段
- r_header_hb2 <= HEADER_HB2; // 保留字段
-
- //---------------- 动态数据体 ----------------
- // SB0: [7:4]=保留 [3]=AVMUTE(0=静音黑屏)[2:1]=保留 [0]=AVMUTE反相
- // 注:CTS 6.8.2要求AVMUTE标志需同时设置正反相信号
- r_body_sb0 <= {4'b0000,I_audio_video_valid, 2'b00, ~I_audio_video_valid};
-
- // SB1: [7:4]=相位配置 [3:0]=色深配置
- r_body_sb1 <= {I_ctrl_packet_phase, I_ctrl_color_depth};
-
- r_body_sb2 <= SB_RESERVED; // SB2保留
- r_body_sb3 <= SB_RESERVED; // SB3保留
- r_body_sb4 <= SB_RESERVED; // SB4保留
- r_body_sb5 <= SB_RESERVED; // SB5保留
- r_body_sb6 <= SB_RESERVED; // SB6保留
- end
- end
-
- //=======================================================================
- // BCH编码器实例化
- //=======================================================================
- wire [7:0] w_header_ecc, w_body_ecc;
-
- BCH_32_24_encode u_BCH_32_24_encode( // 包头BCH(32,24)编码器
- .I_clk (I_pixel_clk),
- .I_data_in (w_header), // 24bit包头数据
- .O_bch_ecc_out (w_header_ecc) // 8bit ECC校验码
- );
-
- BCH_64_56_encode u_BCH_64_56_encode( // 数据体BCH(64,56)编码器
- .I_clk (I_pixel_clk),
- .I_data_in (w_body), // 56bit有效数据
- .O_bch_ecc_out (w_body_ecc) // 8bit ECC校验码
- );
-
- //=======================================================================
- // BCH块输出组合逻辑(HDMI规范S5.3.2分组规则)
- //=======================================================================
- always @(posedge I_pixel_clk or negedge I_reset_n) begin
- if (!I_reset_n) begin // 复位清零
- O_BCH_block_4 <= 32'b0;
- O_BCH_block_3 <= 64'b0;
- O_BCH_block_2 <= 64'b0;
- O_BCH_block_1 <= 64'b0;
- O_BCH_block_0 <= 64'b0;
- end else begin // 正常输出
- O_BCH_block_4 <= {w_header_ecc, w_header}; // 包头+ECC(32bit)
- O_BCH_block_3 <= 64'h0; // 保留区置零
- O_BCH_block_2 <= 64'h0;
- O_BCH_block_1 <= 64'h0;
- O_BCH_block_0 <= {w_body_ecc, w_body}; // 数据体+ECC(64bit)
- end
- end
-
- endmodule
复制代码
3 数据包仿真
3.1音频时钟再生包(Audio Clock Regeneration Packet)仿真
固定数值输出,不过多解释 3.2音频样本包(Audio Sample Packet)仿真
输出数据信息与输入数据信息保持一致。 3.3辅助视频信息(AVI)信息包(Auxiliary Video information (AVI) InfoFrame Packet)仿真
固定数值输出,不过多解释 3.4音频信息帧包(Audio InfoFrame Packet)仿真
3.5通用控制包(General Control Packet)仿真
固定数值输出,不过多解释
|