HDMI20协议解析_Audio_Sample
1.版本说明
日期 | 作者 | 版本说明 |
---|---|---|
202409XX | 风释雪 | 初始版本 |
2.概述
当通过HDMI传输音频信号时,Audio_Sample是必须要传输的数据包之一;
通过前端硬件或软件收到PCM原始音频数据后,需要通过Audio_Sample packet发送给sink端,
sink端收到后,结合协议解析出原始PCM音频数据,用来播放声音;
同时(重点),该协议还会按照IEC-60958打包传输通道状态信息,该信息包含音频采样位宽,
音频采样率,通道数量等信息,非常重要!!
3.目标
FPGA 实现 HDMI2.0 TX/RX功能,生成或解析对应的Audio Sample数据包,用于传输双通道立体声
4.协议解析
-
协议分类
-
协议格式
5.参数分析
-
layout
-
通常 HDMI只传输2个通道,因此 layout = 0;
-
sample_present.sp[3:0] : 有效通道使能bit,当传输2个通道时,4’b0001
-
sample_flat.sp[3:0] : 固定 4’b0000
-
B[3:0] : 音频帧起始状态,根据IEC-60958, 每一帧包含192个subframe,计数器0-191, 当等于0时,B[x] = 1
B.X [4 fields, 1 bit each] B.X =1 if Subpacket X contains the first frame in a 192
frame IEC 60958 Channel Status block; B.X = 0 otherwise
备注:需要先理解 IEC-60958
- L/R 左右声道数据
- P/C/U/V
P : 校验
U : 用户数据,固定 0
V : 固定 0
C : 状态信息bit,参考IEC-60958,该信息包含音频采样位宽,音频采样率,通道数量等信息,非常重要!!
6.IEC-60958
-
参考 https://blog.csdn.net/luckywang1103/article/details/88886810 (感谢分享)
-
参考 https://www.cnblogs.com/fellow1988/p/6445489.html (感谢分享)
-
总结 :
一个block,共 192 Frames, 一个Frames等于2个(左+右)subframe,每个subframe代表一个声道的音频数据+V/U/C/P+其他数据(不关心)
因此, 一个block,可以传输 192个左右声道数据,加192bit左右通道信息数据
7.C 通道信息
- 每个声道的通道信息共 192 bit, 每个audio sample packet 只传输1个bit,共需要192次才能传输完;
- C 通道信息包含 消费级 和 专业级, 日常使用为消费级;
status[0] : PRO = 1'b0 消费级
status[1] : AUDIO = 1'b0
status[2] : Copy = 1'b0
status[5:3] : Emphasis = 3'b000
status[7:6] : Mode = 2'b00
status[15:8] : Category Code = 8'b10000000
status[19:16] : Source Num = 4'b0000
status[23:20] : Channel Num = 4'b0001 (Left) 4'b0010 (Right)
status[27:24] : FS = 4'b0000(44.1K) 4'b1000(88.2K) 4'b1100(176.4K) 4'b0010 (48K) 4'b1010 (96K) 4'b1110 (192K)
status[29:28] : Clock Acc = 2'b00
status[32] : Word Max = 1'b0 Max word length is 20 bits , Word Max = 1'b1 Max word length is 24 bits,
status[35:33] : Word Length = IF(Word Max == 1'b0) : 3'b001(16bits), 3'b010(18bits) 3'b100(19bits) 3'b101(20bits) 3'b110(17bits)
-----------------Word Length = IF(Word Max == 1'b1) : 3'b001(20bits), 3'b010(22bits) 3'b100(23bits) 3'b101(24bits) 3'b110(21bits)
8.P 校验
P = ^ {C, U, V, DATA[23:0]}
9.软件实现
// ch1
wire [24 -1 : 0] ch1_data ;
wire ch1_c ; // 0 not use 1 use
wire ch1_u ; // 0 not use 1 use
wire ch1_v ; // 0 valid 1 no valid
wire ch1_p ;
// ch2
wire [24 -1 : 0] ch2_data ;
wire ch2_c ; // 0 not use 1 use
wire ch2_u ; // 0 not use 1 use
wire ch2_v ; // 0 valid 1 no valid
wire ch2_p ;
reg [192 - 1 : 0] status_l = 0;
reg [192 - 1 : 0] status_r = 0;
reg [8 - 1 : 0] cnt = 0;
always @(posedge clk) begin
status_l[0] <= 1'b0;
status_l[1] <= 1'b0;
status_l[2] <= 1'b0;
status_l[5:3] <= 3'b000;
status_l[7:6] <= 2'b00;
status_l[15:8] <= 8'b10000000;
status_l[19:16] <= 4'b0000;
status_l[23:20] <= 4'b0001;
status_l[27:24] <= (aud_fs == `ARG_AUD_44_1KFS) ? 4'b0000 : (aud_fs == `ARG_AUD_48KFS) ? 4'b0010 : 4'b0010 /* (48K) */;
status_l[29:28] <= 2'b00;
status_l[31:30] <= 2'b00;
status_l[32] <= 1'd1;
status_l[35:33] <= (aud_bit == `ARG_AUD_16BIT) ? 3'b001 : (aud_bit == `ARG_AUD_24BIT) ? 3'b101 : 3'b101 /* (24bits) */;
status_l[191:36] <= 156'd0;
status_r[0] <= 1'b0;
status_r[1] <= 1'b0;
status_r[2] <= 1'b0;
status_r[5:3] <= 3'b000;
status_r[7:6] <= 2'b00;
status_r[15:8] <= 8'b10000000;
status_r[19:16] <= 4'b0000;
status_r[23:20] <= 4'b0010;
status_r[27:24] <= (aud_fs == `ARG_AUD_44_1KFS) ? 4'b0000 : (aud_fs == `ARG_AUD_48KFS) ? 4'b0010 : 4'b0010 /* (48K) */;
status_r[29:28] <= 2'b00;
status_r[31:30] <= 2'b00;
status_r[32] <= 1'd1;
status_r[35:33] <= (aud_bit == `ARG_AUD_16BIT) ? 3'b001 : (aud_bit == `ARG_AUD_24BIT) ? 3'b101 : 3'b101 /* (24bits) */;
status_r[191:36] <= 156'd0;
end
assign {ch2_data, ch1_data} = aud_data;
assign ch1_c = status_l[cnt];
assign ch1_u = 1'd0;
assign ch1_v = 1'd0;
assign ch1_p = (^ch1_data[23:0]) ^ ch1_c ^ ch1_u ^ ch1_v;
assign ch2_c = status_r[cnt];
assign ch2_u = 1'd0;
assign ch2_v = 1'd0;
assign ch2_p = (^ch2_data[23:0]) ^ ch2_c ^ ch2_u ^ ch2_v;
5.参考文档
- EIA-CEA-861-D
- HDMI 1.4(1.4b/2.0)
- IEC-60958-1
- IEC-60958-3-2003