SDI音频解嵌

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音频解嵌实现可以广泛应用于广播设备、视频制作系统和专业音视频处理设备中。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值