SDI音频加嵌

SDI音频加嵌技术详解

一、概述

       SDI音频加嵌是将音频数据嵌入到SDI视频流的水平消隐期间的过程。这是广播和专业视频制作中的关键技术。

二、SDI音频加嵌系统架构

1. 系统框图

┌─────────────┐    ┌──────────────┐    ┌──────────────┐    ┌─────────────┐
│  音频输入   │───▶│ 音频处理与    │───▶│ ANC数据包    │───▶│ SDI视频     │
│  模块       │    │ 格式化        │    │ 生成器       │     │ 混合器      │
└─────────────┘    └──────────────┘    └──────────────┘    └─────────────┘
                         │                       │                  │
┌─────────────┐          |                       |         ┌─────────────┐
│  视频输入    │────────────────────────────────────────────┤   SDI输出   │
│  模块       │                                            │             │
└─────────────┘                                            └─────────────┘

三、Verilog实现SDI音频加嵌

1. 顶层加嵌模块

module sdi_audio_embed (
    input wire clk_74mhz,           // 74.25/74.176 MHz SDI时钟
    input wire clk_audio,           // 音频时钟
    input wire rst_n,
    
    // 视频输入
    input wire [9:0] video_data_in,
    input wire video_data_valid,
    input wire [1:0] video_standard, // 00-SD, 01-HD, 10-3G
    
    // 音频输入
    input wire [15:0] audio_ch1_data,
    input wire [15:0] audio_ch2_data,
    input wire [15:0] audio_ch3_data,
    input wire [15:0] audio_ch4_data,
    input wire audio_data_valid,
    
    // 控制信号
    input wire [3:0] audio_channel_enable,
    input wire embed_enable,
    
    // 输出
    output reg [9:0] sdi_data_out,
    output reg sdi_data_valid,
    output reg [3:0] audio_embedded_status
);

// 内部信号
wire [9:0] anc_packet_data;
wire anc_packet_valid;
wire [9:0] video_data_delayed;
wire in_hblank;
wire [10:0] line_number;
wire [10:0] pixel_count;

// 视频时序检测
video_timing_detector u_timing_detector (
    .clk(clk_74mhz),
    .rst_n(rst_n),
    .video_data(video_data_in),
    .data_valid(video_data_valid),
    .video_standard(video_standard),
    .in_hblank(in_hblank),
    .line_number(line_number),
    .pixel_count(pixel_count),
    .hblank_start(hblank_start),
    .hblank_end(hblank_end)
);

// 音频数据处理
audio_data_processor u_audio_processor (
    .clk_audio(clk_audio),
    .clk_video(clk_74mhz),
    .rst_n(rst_n),
    .audio_ch1_data(audio_ch1_data),
    .audio_ch2_data(audio_ch2_data),
    .audio_ch3_data(audio_ch3_data),
    .audio_ch4_data(audio_ch4_data),
    .audio_data_valid(audio_data_valid),
    .audio_channel_enable(audio_channel_enable),
    .processed_audio_data(processed_audio_data),
    .processed_audio_valid(processed_audio_valid),
    .audio_group(audio_group)
);

// ANC数据包生成
anc_packet_generator u_anc_generator (
    .clk(clk_74mhz),
    .rst_n(rst_n),
    .audio_data(processed_audio_data),
    .audio_valid(processed_audio_valid),
    .audio_group(audio_group),
    .line_number(line_number),
    .video_standard(video_standard),
    .anc_packet_data(anc_packet_data),
    .anc_packet_valid(anc_packet_valid),
    .packet_ready(packet_ready)
);

// SDI数据混合器
sdi_data_mixer u_data_mixer (
    .clk(clk_74mhz),
    .rst_n(rst_n),
    .video_data_in(video_data_in),
    .video_data_valid(video_data_valid),
    .anc_packet_data(anc_packet_data),
    .anc_packet_valid(anc_packet_valid),
    .in_hblank(in_hblank),
    .embed_enable(embed_enable),
    .sdi_data_out(sdi_data_out),
    .sdi_data_valid(sdi_data_valid)
);

// 状态监控
always @(posedge clk_74mhz or negedge rst_n) begin
    if (!rst_n) begin
        audio_embedded_status <= 4'b0000;
    end else begin
        audio_embedded_status <= audio_channel_enable & {4{embed_enable}};
    end
end

endmodule

2. 视频时序检测模块

module video_timing_detector (
    input wire clk,
    input wire rst_n,
    input wire [9:0] video_data,
    input wire data_valid,
    input wire [1:0] video_standard,
    
    output reg in_hblank,
    output reg [10:0] line_number,
    output reg [10:0] pixel_count,
    output reg hblank_start,
    output reg hblank_end
);

// 视频标准参数
localparam [10:0] 
    HD_ACTIVE_PIXELS = 11'd1920,
    HD_HBLANK_START  = 11'd1920,
    HD_HBLANK_END    = 11'd2200,
    HD_TOTAL_LINES   = 11'd1125;

reg [10:0] vcounter;
reg [9:0] prev_video_data;
wire sav_detected, eav_detected;

// SAV/EAV检测
assign sav_detected = (prev_video_data == 10'h3FF) && (video_data == 10'h000) && 
                     data_valid;
assign eav_detected = (prev_video_data == 10'h3FF) && (video_data == 10'h000) && 
                     data_valid;

// 像素计数器
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        pixel_count <= 11'd0;
        vcounter <= 11'd0;
        line_number <= 11'd0;
        in_hblank <= 1'b0;
        prev_video_data <= 10'd0;
    end else if (data_valid) begin
        prev_video_data <= video_data;
        
        if (sav_detected) begin
            pixel_count <= 11'd0;
            in_hblank <= 1'b0;
            hblank_start <= 1'b0;
            hblank_end <= 1'b1;
        end else if (eav_detected) begin
            pixel_count <= 11'd0;
            in_hblank <= 1'b1;
            hblank_start <= 1'b1;
            hblank_end <= 1'b0;
            vcounter <= vcounter + 11'd1;
            
            if (vcounter == HD_TOTAL_LINES - 11'd1) begin
                vcounter <= 11'd0;
            end
            
            line_number <= vcounter;
        end else begin
            pixel_count <= pixel_count + 11'd1;
            hblank_start <= 1'b0;
            hblank_end <= 1'b0;
            
            // 水平消隐期检测
            case (video_standard)
                2'b01: begin // HD
                    if (pixel_count == HD_HBLANK_START) begin
                        in_hblank <= 1'b1;
                    end else if (pixel_count == HD_HBLANK_END) begin
                        in_hblank <= 1'b0;
                    end
                end
                // 其他视频标准...
            endcase
        end
    end
end

endmodule

3. 音频数据处理模块

module audio_data_processor (
    input wire clk_audio,
    input wire clk_video,
    input wire rst_n,
    
    // 音频输入
    input wire [15:0] audio_ch1_data,
    input wire [15:0] audio_ch2_data,
    input wire [15:0] audio_ch3_data,
    input wire [15:0] audio_ch4_data,
    input wire audio_data_valid,
    input wire [3:0] audio_channel_enable,
    
    // 处理后的输出
    output reg [191:0] processed_audio_data, // 4通道×24-bit×2样本
    output reg processed_audio_valid,
    output reg [1:0] audio_group
);

// 音频FIFO
reg [67:0] audio_fifo_in; // 4×16-bit + 4-bit有效
wire [67:0] audio_fifo_out;
reg audio_wr_en, audio_rd_en;
wire audio_fifo_full, audio_fifo_empty;

// 音频样本缓冲区
reg [23:0] audio_samples[0:7]; // 4通道×2样本
reg [2:0] sample_count;
reg [7:0] audio_control_bits;

// 16-bit转24-bit扩展
function [23:0] extend_16_to_24;
    input [15:0] audio_16bit;
    begin
        extend_16_to_24 = {audio_16bit[15], audio_16bit[15:0], 7'b0};
    end
endfunction

// 音频FIFO写逻辑
always @(posedge clk_audio or negedge rst_n) begin
    if (!rst_n) begin
        audio_wr_en <= 1'b0;
        audio_fifo_in <= 68'd0;
    end else if (audio_data_valid) begin
        audio_fifo_in[15:0]   <= extend_16_to_24(audio_ch1_data);
        audio_fifo_in[39:16]  <= extend_16_to_24(audio_ch2_data);
        audio_fifo_in[63:40]  <= extend_16_to_24(audio_ch3_data);
        audio_fifo_in[87:64]  <= extend_16_to_24(audio_ch4_data);
        audio_fifo_in[91:88]  <= audio_channel_enable;
        audio_wr_en <= 1'b1;
    end else begin
        audio_wr_en <= 1'b0;
    end
end

// 异步FIFO实例
async_fifo #(
    .DATA_WIDTH(92),
    .FIFO_DEPTH(512)
) u_audio_fifo (
    .wr_clk(clk_audio),
    .rd_clk(clk_video),
    .rst_n(rst_n),
    .wr_en(audio_wr_en),
    .rd_en(audio_rd_en),
    .data_in(audio_fifo_in),
    .data_out(audio_fifo_out),
    .full(audio_fifo_full),
    .empty(audio_fifo_empty)
);

// 音频数据处理状态机
reg [2:0] audio_state;
localparam [2:0]
    AUDIO_IDLE = 3'd0,
    AUDIO_READ = 3'd1,
    AUDIO_PROCESS = 3'd2,
    AUDIO_OUTPUT = 3'd3;

always @(posedge clk_video or negedge rst_n) begin
    if (!rst_n) begin
        audio_state <= AUDIO_IDLE;
        processed_audio_valid <= 1'b0;
        sample_count <= 3'd0;
        audio_rd_en <= 1'b0;
    end else begin
        case (audio_state)
            AUDIO_IDLE: begin
                processed_audio_valid <= 1'b0;
                if (!audio_fifo_empty) begin
                    audio_rd_en <= 1'b1;
                    audio_state <= AUDIO_READ;
                end
            end
            
            AUDIO_READ: begin
                audio_rd_en <= 1'b0;
                // 存储音频样本
                audio_samples[0] <= audio_fifo_out[23:0];   // CH1
                audio_samples[1] <= audio_fifo_out[47:24];  // CH2  
                audio_samples[2] <= audio_fifo_out[71:48];  // CH3
                audio_samples[3] <= audio_fifo_out[95:72];  // CH4
                audio_state <= AUDIO_PROCESS;
            end
            
            AUDIO_PROCESS: begin
                // 生成控制位 (V, U, C, P)
                audio_control_bits <= 8'b11110000; // V=1, U=1, C=1, P=0
                
                // 打包音频数据
                processed_audio_data[23:0]   <= audio_samples[0];  // 样本1
                processed_audio_data[47:24]  <= audio_samples[1];  // 样本2
                processed_audio_data[71:48]  <= audio_samples[2];  // 样本3
                processed_audio_data[95:72]  <= audio_samples[3];  // 样本4
                processed_audio_data[119:96] <= audio_samples[4];  // 样本5 (如果有)
                processed_audio_data[143:120] <= audio_samples[5]; // 样本6
                processed_audio_data[167:144] <= audio_samples[6]; // 样本7
                processed_audio_data[191:168] <= audio_samples[7]; // 样本8
                
                audio_state <= AUDIO_OUTPUT;
            end
            
            AUDIO_OUTPUT: begin
                processed_audio_valid <= 1'b1;
                audio_state <= AUDIO_IDLE;
                audio_group <= audio_group + 2'd1; // 轮换音频组
            end
        endcase
    end
end

endmodule

4. ANC数据包生成器

module anc_packet_generator (
    input wire clk,
    input wire rst_n,
    input wire [191:0] audio_data,
    input wire audio_valid,
    input wire [1:0] audio_group,
    input wire [10:0] line_number,
    input wire [1:0] video_standard,
    
    output reg [9:0] anc_packet_data,
    output reg anc_packet_valid,
    output reg packet_ready
);

// ANC包状态机
reg [3:0] packet_state;
reg [7:0] data_counter;
reg [9:0] crc_register;
reg [191:0] audio_data_latched;

// ANC包定义
localparam [7:0] 
    AUDIO_DID = 8'h5F,        // 音频数据包DID
    AUDIO_SDID = 8'h60;       // 音频数据包SDID

localparam [9:0] 
    ANC_PREFIX = 10'h000,
    ANC_PREFIX_INV = 10'h3FF;

// CRC计算函数
function [9:0] compute_crc;
    input [9:0] data;
    input [9:0] current_crc;
    reg [9:0] new_crc;
    begin
        new_crc = current_crc;
        for (int i = 0; i < 10; i = i + 1) begin
            if (data[i] ^ new_crc[9]) begin
                new_crc = {new_crc[8:0], 1'b0} ^ 10'h23;
            end else begin
                new_crc = {new_crc[8:0], 1'b0};
            end
        end
        compute_crc = new_crc;
    end
endfunction

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        packet_state <= 4'd0;
        anc_packet_valid <= 1'b0;
        packet_ready <= 1'b1;
        crc_register <= 10'd0;
        data_counter <= 8'd0;
    end else begin
        anc_packet_valid <= 1'b0;
        
        case (packet_state)
            4'd0: begin // 等待音频数据
                if (audio_valid && packet_ready) begin
                    audio_data_latched <= audio_data;
                    packet_ready <= 1'b0;
                    packet_state <= 4'd1;
                    data_counter <= 8'd0;
                    crc_register <= 10'd0;
                end
            end
            
            4'd1: begin // ANC前缀
                anc_packet_data <= ANC_PREFIX;
                anc_packet_valid <= 1'b1;
                packet_state <= 4'd2;
            end
            
            4'd2: begin // ANC前缀取反
                anc_packet_data <= ANC_PREFIX_INV;
                anc_packet_valid <= 1'b1;
                packet_state <= 4'd3;
            end
            
            4'd3: begin // 数据ID (DID)
                anc_packet_data <= {2'b00, AUDIO_DID};
                crc_register <= compute_crc({2'b00, AUDIO_DID}, crc_register);
                anc_packet_valid <= 1'b1;
                packet_state <= 4'd4;
            end
            
            4'd4: begin // 数据块号 (DBN)
                anc_packet_data <= {2'b00, 8'h00}; // 数据块号
                crc_register <= compute_crc({2'b00, 8'h00}, crc_register);
                anc_packet_valid <= 1'b1;
                packet_state <= 4'd5;
            end
            
            4'd5: begin // 数据计数 (DC)
                anc_packet_data <= {2'b00, 8'd23}; // 23个数据字
                crc_register <= compute_crc({2'b00, 8'd23}, crc_register);
                anc_packet_valid <= 1'b1;
                packet_state <= 4'd6;
            end
            
            // 音频数据字段 (24个字)
            4'd6: begin
                if (data_counter < 8'd24) begin
                    anc_packet_data <= audio_data_latched[data_counter*8 +: 8];
                    crc_register <= compute_crc(audio_data_latched[data_counter*8 +: 8], crc_register);
                    anc_packet_valid <= 1'b1;
                    data_counter <= data_counter + 8'd1;
                end else begin
                    packet_state <= 4'd7;
                end
            end
            
            4'd7: begin // CRC校验和
                anc_packet_data <= crc_register;
                anc_packet_valid <= 1'b1;
                packet_state <= 4'd0;
                packet_ready <= 1'b1;
            end
        endcase
    end
end

endmodule

5. SDI数据混合器

module sdi_data_mixer (
    input wire clk,
    input wire rst_n,
    input wire [9:0] video_data_in,
    input wire video_data_valid,
    input wire [9:0] anc_packet_data,
    input wire anc_packet_valid,
    input wire in_hblank,
    input wire embed_enable,
    
    output reg [9:0] sdi_data_out,
    output reg sdi_data_valid
);

reg [9:0] video_pipeline[0:2];
reg packet_insert_active;
reg [4:0] packet_insert_counter;

// 视频数据流水线
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        video_pipeline[0] <= 10'd0;
        video_pipeline[1] <= 10'd0;
        video_pipeline[2] <= 10'd0;
        packet_insert_active <= 1'b0;
        packet_insert_counter <= 5'd0;
        sdi_data_valid <= 1'b0;
    end else if (video_data_valid) begin
        // 视频数据流水线
        video_pipeline[0] <= video_data_in;
        video_pipeline[1] <= video_pipeline[0];
        video_pipeline[2] <= video_pipeline[1];
        
        sdi_data_valid <= 1'b1;
        
        if (embed_enable && in_hblank) begin
            // 在消隐期插入ANC包
            if (anc_packet_valid && !packet_insert_active) begin
                packet_insert_active <= 1'b1;
                packet_insert_counter <= 5'd0;
                sdi_data_out <= anc_packet_data;
            end else if (packet_insert_active) begin
                sdi_data_out <= anc_packet_data;
                packet_insert_counter <= packet_insert_counter + 5'd1;
                
                // 假设ANC包长度为32个10-bit字
                if (packet_insert_counter == 5'd31) begin
                    packet_insert_active <= 1'b0;
                end
            end else begin
                sdi_data_out <= video_pipeline[2];
            end
        end else begin
            // 非消隐期或禁用加嵌,直接输出视频
            sdi_data_out <= video_pipeline[2];
            packet_insert_active <= 1'b0;
        end
    end else begin
        sdi_data_valid <= 1'b0;
    end
end

endmodule

6. 配置和控制寄存器

module sdi_audio_embed_registers (
    input wire clk,
    input wire rst_n,
    input wire [7:0] reg_addr,
    input wire [31:0] reg_data_in,
    input wire reg_write,
    
    output reg [31:0] reg_data_out,
    
    // 控制信号输出
    output reg [3:0] audio_channel_enable,
    output reg embed_enable,
    output reg [1:0] audio_sample_rate,
    output reg [7:0] audio_delay
);

// 寄存器定义
localparam [7:0]
    REG_CONTROL     = 8'h00,
    REG_CH_ENABLE   = 8'h04,
    REG_SAMPLE_RATE = 8'h08,
    REG_AUDIO_DELAY = 8'h0C;

// 控制寄存器
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        embed_enable <= 1'b0;
        audio_channel_enable <= 4'b0000;
        audio_sample_rate <= 2'b00; // 48kHz
        audio_delay <= 8'd0;
        reg_data_out <= 32'd0;
    end else if (reg_write) begin
        case (reg_addr)
            REG_CONTROL: begin
                embed_enable <= reg_data_in[0];
            end
            REG_CH_ENABLE: begin
                audio_channel_enable <= reg_data_in[3:0];
            end
            REG_SAMPLE_RATE: begin
                audio_sample_rate <= reg_data_in[1:0];
            end
            REG_AUDIO_DELAY: begin
                audio_delay <= reg_data_in[7:0];
            end
        endcase
    end
    
    // 寄存器读取
    case (reg_addr)
        REG_CONTROL:     reg_data_out <= {31'd0, embed_enable};
        REG_CH_ENABLE:   reg_data_out <= {28'd0, audio_channel_enable};
        REG_SAMPLE_RATE: reg_data_out <= {30'd0, audio_sample_rate};
        REG_AUDIO_DELAY: reg_data_out <= {24'd0, audio_delay};
        default:         reg_data_out <= 32'd0;
    endcase
end

endmodule

四、关键特性

1. 支持的音频格式

  • 4通道/8通道音频嵌入

  • 16-bit/24-bit音频精度

  • 48kHz采样率支持

  • 可配置的音频延迟

2. 视频标准支持

  • HD-SDI (1.5 Gbps)

  • 3G-SDI (2.97 Gbps)

  • 6G-SDI/12G-SDI (可选)

3. 性能特点

  • 低延迟音频处理

  • 精确的时序控制

  • 可配置的音频通道映射

  • 完整的错误检测和处理

这种SDI音频加嵌实现广泛应用于广播设备、视频切换台、音频嵌入器和专业视频制作系统中。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值