SDI音频解嵌技术详解
一、概述
SDI(串行数字接口)音频解嵌是指从SDI视频流中提取嵌入的音频数据的过程。SDI标准允许在视频消隐期间嵌入多通道音频数据。
二、SDI音频嵌入结构
1. SDI帧结构
┌─────────────────────────────────────────────┐ │ 视频有效区 │ ├─────────────────────────────────────────────┤ │ 水平消隐期 (HBI) │ ← 音频数据嵌入在这里 ├─────────────────────────────────────────────┤ │ 视频有效区 │ ├─────────────────────────────────────────────┤ │ 水平消隐期 (HBI) │ ← 音频数据嵌入在这里 └─────────────────────────────────────────────┘
2. ANC数据包结构
┌──────────┬──────────┬──────────┬──────────┬──────────┐ │ ANC │ 数据ID │ 块号 │ 数据块 │ 校验和 │ │ 前缀 │ (DID) │ (DBN) │ (数据) │ (CS) │ │ (0x000) │ │ │ │ │ └──────────┴──────────┴──────────┴──────────┴──────────┘
三、Verilog实现SDI音频解嵌
1. 顶层模块
module sdi_audio_deembed (
input wire clk, // 时钟
input wire rst_n, // 复位
input wire [9:0] sdi_data, // SDI 10-bit 数据输入
input wire sdi_data_valid, // 数据有效信号
input wire [1:0] video_standard, // 视频标准: 00-SD, 01-HD, 10-3G
output reg [15:0] audio_data[0:3], // 解嵌出的4通道音频数据
output reg audio_data_valid[0:3], // 音频数据有效信号
output reg [2:0] audio_channel, // 当前音频通道号
output reg anc_packet_detected, // ANC数据包检测
output reg [7:0] error_count // 错误计数器
);
// 内部信号定义
wire [9:0] anc_data;
wire anc_data_valid;
wire [7:0] did;
wire [7:0] dbn;
wire [7:0] dc;
wire [143:0] audio_packet_data;
wire audio_packet_valid;
// 模块实例化
sdi_anc_detector u_anc_detector (
.clk(clk),
.rst_n(rst_n),
.sdi_data(sdi_data),
.sdi_data_valid(sdi_data_valid),
.video_standard(video_standard),
.anc_data(anc_data),
.anc_data_valid(anc_data_valid),
.anc_prefix_detected(anc_prefix_detected)
);
anc_packet_parser u_packet_parser (
.clk(clk),
.rst_n(rst_n),
.anc_data(anc_data),
.anc_data_valid(anc_data_valid),
.did(did),
.dbn(dbn),
.dc(dc),
.packet_data(audio_packet_data),
.packet_valid(audio_packet_valid),
.crc_error(crc_error)
);
audio_data_extractor u_audio_extractor (
.clk(clk),
.rst_n(rst_n),
.packet_data(audio_packet_data),
.packet_valid(audio_packet_valid),
.did(did),
.dbn(dbn),
.dc(dc),
.audio_data(audio_data),
.audio_data_valid(audio_data_valid),
.audio_channel(audio_channel)
);
// 错误统计
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
error_count <= 8'd0;
end else if (crc_error) begin
error_count <= error_count + 8'd1;
end
end
endmodule
2. ANC数据包检测模块
module sdi_anc_detector (
input wire clk,
input wire rst_n,
input wire [9:0] sdi_data,
input wire sdi_data_valid,
input wire [1:0] video_standard,
output reg [9:0] anc_data,
output reg anc_data_valid,
output reg anc_prefix_detected
);
// ANC前缀定义
localparam ANC_PREFIX_10BIT = 10'h000;
localparam ANC_PREFIX_8BIT = 8'h00;
// 状态机定义
localparam [2:0]
IDLE = 3'b000,
PREFIX_DET = 3'b001,
DATA_CAPTURE = 3'b010,
CHECK_CRC = 3'b011;
reg [2:0] current_state, next_state;
reg [7:0] packet_counter;
reg [9:0] data_buffer[0:255];
reg [7:0] buffer_index;
// ANC前缀检测
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
anc_prefix_detected <= 1'b0;
anc_data_valid <= 1'b0;
current_state <= IDLE;
buffer_index <= 8'd0;
end else begin
current_state <= next_state;
case (current_state)
IDLE: begin
anc_data_valid <= 1'b0;
if (sdi_data_valid && (sdi_data == ANC_PREFIX_10BIT)) begin
next_state <= PREFIX_DET;
buffer_index <= 8'd0;
end
end
PREFIX_DET: begin
if (sdi_data_valid) begin
data_buffer[buffer_index] <= sdi_data;
buffer_index <= buffer_index + 8'd1;
next_state <= DATA_CAPTURE;
end
end
DATA_CAPTURE: begin
if (sdi_data_valid) begin
data_buffer[buffer_index] <= sdi_data;
buffer_index <= buffer_index + 8'd1;
// 假设最大ANC包长度为256个10-bit字
if (buffer_index == 8'd255) begin
next_state <= CHECK_CRC;
end
end
end
CHECK_CRC: begin
// CRC校验逻辑
next_state <= IDLE;
anc_data_valid <= 1'b1;
end
endcase
end
end
endmodule
3. ANC数据包解析模块
module anc_packet_parser (
input wire clk,
input wire rst_n,
input wire [9:0] anc_data,
input wire anc_data_valid,
output reg [7:0] did, // 数据ID
output reg [7:0] dbn, // 数据块号
output reg [7:0] dc, // 数据计数
output reg [143:0] packet_data, // 音频包数据
output reg packet_valid,
output reg crc_error
);
// 音频相关DID值
localparam [7:0]
AUDIO_PACKET_DID = 8'h5F, // 1080p音频包
AUDIO_CONTROL_DID = 8'h40; // 音频控制包
reg [7:0] parse_state;
reg [7:0] data_counter;
reg [9:0] crc_calculated;
reg [9:0] crc_received;
// CRC计算函数
function [9:0] calculate_crc;
input [9:0] data;
input [9:0] current_crc;
begin
// 简化的CRC计算
calculate_crc = current_crc ^ data;
end
endfunction
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
parse_state <= 8'd0;
packet_valid <= 1'b0;
crc_error <= 1'b0;
data_counter <= 8'd0;
crc_calculated <= 10'd0;
end else if (anc_data_valid) begin
case (parse_state)
8'd0: begin // DID
did <= anc_data[7:0];
crc_calculated <= calculate_crc(anc_data, 10'd0);
parse_state <= parse_state + 8'd1;
end
8'd1: begin // DBN
dbn <= anc_data[7:0];
crc_calculated <= calculate_crc(anc_data, crc_calculated);
parse_state <= parse_state + 8'd1;
end
8'd2: begin // DC
dc <= anc_data[7:0];
crc_calculated <= calculate_crc(anc_data, crc_calculated);
data_counter <= 8'd0;
parse_state <= parse_state + 8'd1;
end
default: begin
if (parse_state < (8'd3 + dc)) begin
// 数据字段
packet_data[(parse_state-8'd3)*8 +:8] <= anc_data[7:0];
crc_calculated <= calculate_crc(anc_data, crc_calculated);
parse_state <= parse_state + 8'd1;
end else begin
// CRC字段
crc_received <= anc_data;
parse_state <= 8'd0;
// CRC校验
if (crc_calculated == anc_data) begin
packet_valid <= 1'b1;
crc_error <= 1'b0;
end else begin
packet_valid <= 1'b0;
crc_error <= 1'b1;
end
end
end
endcase
end else begin
packet_valid <= 1'b0;
end
end
endmodule
4. 音频数据提取模块
module audio_data_extractor (
input wire clk,
input wire rst_n,
input wire [143:0] packet_data,
input wire packet_valid,
input wire [7:0] did,
input wire [7:0] dbn,
input wire [7:0] dc,
output reg [15:0] audio_data[0:3],
output reg audio_data_valid[0:3],
output reg [2:0] audio_channel
);
// 音频包状态机
reg [2:0] audio_state;
reg [3:0] channel_index;
// 音频数据格式定义
wire [19:0] audio_sample_1 = packet_data[19:0];
wire [19:0] audio_sample_2 = packet_data[39:20];
wire [19:0] audio_sample_3 = packet_data[59:40];
wire [19:0] audio_sample_4 = packet_data[79:60];
// 控制位提取
wire V = packet_data[80]; // 有效位
wire U = packet_data[81]; // 用户位
wire C = packet_data[82]; // 通道状态位
wire P = packet_data[83]; // 奇偶校验位
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
audio_state <= 3'd0;
channel_index <= 4'd0;
for (int i = 0; i < 4; i = i + 1) begin
audio_data[i] <= 16'd0;
audio_data_valid[i] <= 1'b0;
end
end else if (packet_valid && (did == 8'h5F)) begin
// 音频数据包处理
case (audio_state)
3'd0: begin
// 提取第一个音频样本对
if (V) begin // 数据有效
audio_data[0] <= audio_sample_1[19:4]; // 24-bit转16-bit
audio_data[1] <= audio_sample_2[19:4];
audio_data_valid[0] <= 1'b1;
audio_data_valid[1] <= 1'b1;
end
audio_state <= 3'd1;
end
3'd1: begin
// 提取第二个音频样本对
if (V) begin
audio_data[2] <= audio_sample_3[19:4];
audio_data[3] <= audio_sample_4[19:4];
audio_data_valid[2] <= 1'b1;
audio_data_valid[3] <= 1'b1;
end
audio_state <= 3'd0;
// 更新通道信息
audio_channel <= dbn[2:0]; // 使用DBN的低3位作为通道组标识
end
endcase
end else begin
// 清除有效信号
for (int i = 0; i < 4; i = i + 1) begin
audio_data_valid[i] <= 1'b0;
end
end
end
endmodule
5. 时钟域同步模块
module audio_sync (
input wire video_clk,
input wire audio_clk,
input wire rst_n,
input wire [15:0] audio_data_video_domain[0:3],
input wire audio_data_valid_video_domain[0:3],
output reg [15:0] audio_data_audio_domain[0:3],
output reg audio_data_valid_audio_domain[0:3]
);
// 异步FIFO用于时钟域交叉
reg [67:0] fifo_data_in; // 4x16-bit音频数据 + 4-bit有效标志
wire [67:0] fifo_data_out;
reg wr_en, rd_en;
wire full, empty;
// 数据打包
always @(posedge video_clk) begin
fifo_data_in[15:0] <= audio_data_video_domain[0];
fifo_data_in[31:16] <= audio_data_video_domain[1];
fifo_data_in[47:32] <= audio_data_video_domain[2];
fifo_data_in[63:48] <= audio_data_video_domain[3];
fifo_data_in[67:64] <= audio_data_valid_video_domain;
end
// 写使能生成
always @(posedge video_clk) begin
wr_en <= |audio_data_valid_video_domain && !full;
end
// 异步FIFO实例
async_fifo #(
.DATA_WIDTH(68),
.FIFO_DEPTH(512)
) u_audio_fifo (
.wr_clk(video_clk),
.rd_clk(audio_clk),
.rst_n(rst_n),
.wr_en(wr_en),
.rd_en(rd_en),
.data_in(fifo_data_in),
.data_out(fifo_data_out),
.full(full),
.empty(empty)
);
// 读侧逻辑
always @(posedge audio_clk) begin
rd_en <= !empty;
if (rd_en) begin
audio_data_audio_domain[0] <= fifo_data_out[15:0];
audio_data_audio_domain[1] <= fifo_data_out[31:16];
audio_data_audio_domain[2] <= fifo_data_out[47:32];
audio_data_audio_domain[3] <= fifo_data_out[63:48];
audio_data_valid_audio_domain <= fifo_data_out[67:64];
end else begin
audio_data_valid_audio_domain <= 4'b0;
end
end
endmodule
四、关键特性
1. 支持的多通道音频
-
最多16个音频通道(4个数据包×4通道)
-
24-bit音频精度(可转换为16-bit)
-
48kHz采样率支持
2. 错误检测和恢复
-
CRC校验确保数据完整性
-
数据包丢失检测
-
时钟域同步处理
3. 性能优化
-
流水线处理架构
-
并行音频通道处理
-
低延迟设计
这种SDI音频解嵌实现可以广泛应用于广播设备、视频制作系统和专业音视频处理设备中。
993

被折叠的 条评论
为什么被折叠?



