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;
图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个数据;
场数据区别:PAL为567;NTSC为480
3, 基于adv7391实现 pal 发送:
3.1 IIC配置寄存器
实现YUV格式数据输入,输出YUV;
3.2,数据格式
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