十五、基于FPGA的SDI协议介绍(一)

1 ,概念  

      SDI接口是一种“数字分量串行接口”,而HD-SDI接口是一种广播级的高清数字输入和输出端口,其中HD表示高清信号。由于SDI接口不能直接传送压缩数字信号,数字录像机、硬盘等设备记录的压缩信号重放后,必须经解压并经SDI接口输出才能进入SDI系统。如果反复解压和压缩,必将引起图像质量下降和延时增加,为此各种不同格式的数字录像机和非线性编辑系统,规定了自己的用于直接传输压缩数字信号的接口

      按速率分为:标准清晰度SD-SDI、高清标准HD-SDI和3G-SDI,对应速率分别是270Mb/s、1.485Gb/s和2.97Gb/s。

     SD中主要介绍最常见的PAL标准和NTSC标准;BT655格式数据
     PAL电视标准,每秒25帧,电视扫描线为625线,奇场在前,偶场在后,标准的数字化PAL电视标准分辨率为720*576, 24比特的色彩位深,画面的宽高比为4:3, PAL电视标准用于中国、欧洲等国家和地区。
      NTSC电视标准,每秒29.97帧(简化为30帧),电视扫描线为525线,偶场在前,奇场在后,标准的数字化NTSC电视标准分辨率为720*486, 24比特的色彩位深,画面的宽高比为4:3。NTSC电视标准用于美、日等国家和地区
     BT656:ITU-R Recommendation BT.656,有时候也称为ITU656(前身CCIR 656),是一个简单的数字视频协议,用于将未压缩的 PAL 或 NTSC (525行或者625行)信号进行编码;

2,BT656、PAL、NTSC

    2.1  BT656

           BT.656支持不同位数和分辨率的视频,本文以标准分辨率为720*576i 8bit BT.656(4:2:2)YCbCr SDTV 数字视频信号格式讲解协议和解码方法;采集图像的时候使用隔行扫描,每一帧有2个场,一个叫顶场,一个叫底场(有时又称为偶场和奇场),那么顶场就包含其中所有的偶数行,而底场则包含其中所有的奇数行,传输时其完整的帧结构如图所示;奇场和偶场有效行都为288行,每行有1440个字节(包含720个Y亮度字节,360个Cb色度字节,360个Cr色度字节),Y的取值范围为16-235,色度为16-240; 水平消隐区间为280个字节;

每一行有如下几个部分组成,行 = 结束码(EAV) + 水平消隐(Horizontal Vertical Blanking) + 起始码(SAV) + 有效数据(Active Video),BT.656有效数据帧如图1所示,blankIng区间通常填充80h/10h;

十五、基于FPGA的SDI协议介绍(一)_第1张图片 图1 BT.656 576i有效数据帧格式

EAV和SAV为嵌入控制字,分别表示视频的终点和起点,均由四个字节构成,前三个字节为固定的帧头FF,00,00,而第4个字节(XY)是根据场、消隐信息而定的,其8个bit含义如下: 1 F V H  P3 P2 P1 P0;其中 P0~P3为保护比特,其值取决于F、H、V,起到校验的作用
    F:标记场信息,传输顶场时为0,传输底场时为1;
    V:标记消隐信息,传输消隐数据时为1,传输有效视频数据时为0;
    H:标记EAV还是SAV,SAV为0,EAV为1;
    P3=V XOR H
    P2=F XOR H
    P1=F XOR V
    P0=F XOR V XOR H;

   2.2 PAL和NTSC

      PAL   :720*576    25帧
      NTSC:720*480    29.97帧

     行数据区别:其中PAL消隐区为288个数据;NTSC消隐区为268个数据;
     

十五、基于FPGA的SDI协议介绍(一)_第2张图片

  场数据区别:PAL为567;NTSC为480

十五、基于FPGA的SDI协议介绍(一)_第3张图片

3, 基于adv7391实现 pal 发送:

   3.1 IIC配置寄存器

                实现YUV格式数据输入,输出YUV;

十五、基于FPGA的SDI协议介绍(一)_第4张图片

   3.2,数据格式

十五、基于FPGA的SDI协议介绍(一)_第5张图片

 3.3,PAL实现代码如下

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/08/05 13:39:25
// Design Name: 
// Module Name: adv7931_pal
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module adv7931_pal(
	input   sys_clk,
	input   sys_rst,	
	input   iic_config_done,	
	
	output  ot_rd_fifo_en,
	output [7:0] ot_rd_fifo_data,
	output [15:0] ot_rd_fifo_cnt,
	output [15:0] ot_fval_cnt,
	output [15:0] ot_lval_cnt,
	
	output       tx_frame_lsync,
	output       tx_frame_ready,
	input        tx_frame_valid,
	input        tx_frame_last,
	input [15:0] tx_frame_data,
	
	//HD-SDI tx_data
	output  sdi_vs,
	output  sdi_hs,
	output [7:0] sdi_da
);
    
    localparam T_delays = 50_000_000 - 1;
	
	localparam F_num = 625 - 1;
	localparam L_num = 1440 + 288 - 1;
    
    reg axis_fifo_rstn = 0;
    wire axis_prog_full;
    wire wr_fifo_ready;
	wire wr_fifo_valid;
	wire wr_fifo_last;
	wire [7:0] wr_fifo_data;
	
	wire rd_fifo_valid;
	wire rd_fifo_ready;
	wire rd_fifo_last;
	wire [7:0] rd_fifo_data;
	
	reg [31:0] pal_tx_delays_cnt = 0;
	reg pal_tx_start_en = 0;

	reg f_reg = 0;
	reg v_reg = 0;
	reg [15:0] fval_cnt = 0;
	reg [15:0] lval_cnt = 0;
	reg [7:0]  data_reg = 0;
	wire [15:0] fval_cnt_data;
	
	reg tx_frame_lsync_reg = 0;
	reg rd_fifo_en = 0;
	reg [15:0] rd_fifo_cnt = 0;
		
	assign wr_fifo_valid = tx_frame_valid;
	assign wr_fifo_last  = tx_frame_last;
	assign wr_fifo_data  = tx_frame_data[13:6];
	assign rd_fifo_ready = rd_fifo_en;
	assign tx_frame_ready = wr_fifo_ready;
	assign fval_cnt_data = fval_cnt + 1;
	
    assign tx_frame_lsync = tx_frame_lsync_reg;
	assign sdi_vs = 1;
	assign sdi_hs = 1;
	assign sdi_da = data_reg;//rd_fifo_en ? rd_fifo_data : data_reg;
	
	assign ot_rd_fifo_en = rd_fifo_en;
	assign ot_rd_fifo_data = rd_fifo_data;
	assign ot_rd_fifo_cnt  = rd_fifo_cnt;
	assign ot_fval_cnt = fval_cnt;
	assign ot_lval_cnt = lval_cnt;

//--------------------------------------------------------------------------------------------	
    always @ (posedge sys_clk) begin 
	   if(sys_rst)
	       axis_fifo_rstn <= 0;
	   else if(fval_cnt == F_num && lval_cnt < 100)
            axis_fifo_rstn <= 0;
	   else 
            axis_fifo_rstn <= 1;	
	end   
	
    pal_tx_data_fifo pal_tx_data_fifo_inst(
		.wr_rst_busy   (              ),
		.rd_rst_busy   (              ),
		.s_aclk        (sys_clk       ),
		.s_aresetn     (axis_fifo_rstn),
		.s_axis_tvalid (wr_fifo_valid ),
		.s_axis_tready (wr_fifo_ready ),
		.s_axis_tlast  (wr_fifo_last  ),
		.s_axis_tdata  (wr_fifo_data  ),
		.m_axis_tvalid (rd_fifo_valid),
		.m_axis_tready (rd_fifo_ready),
		.m_axis_tlast  (rd_fifo_last ),
		.m_axis_tdata  (rd_fifo_data ),
		.axis_prog_full (axis_prog_full)
	);

    always @ (posedge sys_clk) begin 
	   if(sys_rst) begin 
	       pal_tx_delays_cnt <= 0;
	       pal_tx_start_en <= 0;
	       end 
	   else if(iic_config_done && pal_tx_delays_cnt >= T_delays) begin 
	       pal_tx_delays_cnt <= pal_tx_delays_cnt;
	       pal_tx_start_en <= 1;
	       end 
	   else if(iic_config_done) begin 
	       pal_tx_delays_cnt <= pal_tx_delays_cnt + 1;
	       pal_tx_start_en <= pal_tx_start_en;
	       end 
	   else  begin 
	       pal_tx_delays_cnt <= pal_tx_delays_cnt;
	       pal_tx_start_en <= 0;
	       end 
    end 
	
    always @ (posedge sys_clk) begin 
	   if(sys_rst) begin 
            fval_cnt <= 0;
            lval_cnt <= 0;
            end 
	   else if(pal_tx_start_en && fval_cnt >= F_num && lval_cnt >= L_num) begin 
            fval_cnt <= 0;
            lval_cnt <= 0;
	       end 
	   else  if(pal_tx_start_en && lval_cnt >= L_num) begin 
            fval_cnt <= fval_cnt + 1;
            lval_cnt <= 0;
            end 
	   else  if(pal_tx_start_en) begin 
            fval_cnt <= fval_cnt;
            lval_cnt <= lval_cnt + 1;
            end 
       else  begin 
            fval_cnt <= 0;
            lval_cnt <= 0;
	       end 
    end 	
    
    always @ (posedge sys_clk) begin 
        if(sys_rst)
            tx_frame_lsync_reg <= 0;
        else if(pal_tx_start_en && lval_cnt == 1 && (fval_cnt == 0 || fval_cnt == 310))
            tx_frame_lsync_reg <= 1;
        else 
            tx_frame_lsync_reg <= 0;
    end 
    
    always @ (posedge sys_clk) begin 
        if(sys_rst)
            rd_fifo_en <= 0;
//        else if(((fval_cnt > 21 && fval_cnt <= 277) || (fval_cnt > 334 && fval_cnt <= 591)) && lval_cnt >= 288 && lval_cnt < 1568)
        else if(((fval_cnt > 37 && fval_cnt <= 293) || (fval_cnt > 350 && fval_cnt <= 607)) && lval_cnt >= 358 && lval_cnt < 1638)
            rd_fifo_en <= !lval_cnt[0];
        else 
            rd_fifo_en <= 0;
    end 
    
    always @ (posedge sys_clk) begin 
        if(sys_rst)
            f_reg <= 0;
        else if(fval_cnt < 312)
            f_reg <= 0;
        else 
            f_reg <= 1;
    end 
    
    always @ (posedge sys_clk) begin 
        if(sys_rst)
            v_reg <= 0;
        else if((fval_cnt > 21  && fval_cnt <= 309) || (fval_cnt > 334  && fval_cnt <= 622))
            v_reg <= 0;
        else 
            v_reg <= 1;
    end 
    
    always @ (posedge sys_clk) begin 
	   if(sys_rst)
	       data_reg <= 0;
	   else if(rd_fifo_valid && rd_fifo_ready)
	       data_reg <= rd_fifo_data;
	   else if(pal_tx_start_en && (lval_cnt == 0 || lval_cnt == 284)) 
	       data_reg <= 8'hFF; 
	   else if(pal_tx_start_en && (lval_cnt == 1 || lval_cnt == 2 || lval_cnt == 285 || lval_cnt == 286 ))
	       data_reg <= 8'h00; 
       else if(pal_tx_start_en && lval_cnt == 3) 
	       data_reg <= {1'b1, f_reg, v_reg, 1'b1, v_reg^1'b1, f_reg^1'b1, f_reg^v_reg, f_reg^v_reg^1'b1};
	   else if(pal_tx_start_en && lval_cnt == 287) 
	       data_reg <= {1'b1, f_reg, v_reg, 1'b0, v_reg^1'b0, f_reg^1'b0, f_reg^v_reg, f_reg^v_reg^1'b0};
	   else if(pal_tx_start_en && (lval_cnt > 3 && lval_cnt < 284) && lval_cnt[0] == 0)
	       data_reg <= 8'h80; 
	   else if(pal_tx_start_en && (lval_cnt > 3 && lval_cnt < 284) && lval_cnt[0] == 1)
	       data_reg <= 8'h10; 
	   else 
	       data_reg <= 0;
    end 
//-----------------------------------------------------------------------------------------------------------
    always @ (posedge sys_clk) begin 
        if(sys_rst)
            rd_fifo_cnt <= 0;
        else if(rd_fifo_valid && rd_fifo_ready && rd_fifo_last)
            rd_fifo_cnt <= 0;
        else if(rd_fifo_valid && rd_fifo_ready)
            rd_fifo_cnt <= rd_fifo_cnt + 1;
        else 
            rd_fifo_cnt <= rd_fifo_cnt;
    end 

    
    
endmodule

你可能感兴趣的:(FPGA,fpga开发,sdi)