十四、基于FPGA的SDI协议解析与实战:从BT.656到高清视频发送

张开发
2026/5/6 11:07:12 15 分钟阅读
十四、基于FPGA的SDI协议解析与实战:从BT.656到高清视频发送
1. SDI协议与BT.656标准入门第一次接触SDI协议时我被它复杂的时序控制搞得一头雾水。直到在项目里实际用ADV7391芯片发送PAL视频信号才真正理解BT.656协议的精妙之处。SDISerial Digital Interface本质上是一种数字分量串行接口就像高速公路上的快递车道专门用来传输未经压缩的视频数据。与常见的HDMI不同SDI更擅长长距离稳定传输在广电领域几乎一统天下。BT.656协议可以看作SDI的包装规范。我常跟新手比喻如果把视频数据比作货物BT.656就是规定如何装箱、贴标签和安排发货时间的标准。它定义了三个关键要素EAV/SAV嵌入字相当于快递单上的起始和终止标签消隐区间类似货车之间的安全距离有效视频数据就是真正的货物内容实际项目中遇到过最典型的配置是720x576i 8bit 4:2:2格式。这里的i代表隔行扫描就像老式电视的显示方式——先传偶数行顶场再传奇数行底场。每个像素用YUV颜色空间表示其中Y是亮度信号16-235Cb/Cr是色度信号16-240。这种设计让视频在传输过程中能保持更好的色彩一致性。2. BT.656协议深度解析2.1 数据行结构解剖真正让我踩坑的是BT.656的行数据结构。记得第一次用逻辑分析仪抓取信号时看到那一串十六进制数完全懵了。后来发现每行数据其实像火车车厢一样有固定编组[EAV] [水平消隐] [SAV] [有效视频数据]EAV/SAV这两个4字节的标记就像书签。它们的结构特别有意思前三个字节固定是0xFF,0x00,0x00第四个字节的8个bit藏着重要信息F位标记场序0顶场1底场V位指示是否消隐期1消隐H位区分EAV/SAV1EAVP0-P3校验位用异或运算生成在Verilog实现时我常用位运算来生成这个控制字assign P3 V ^ H; assign P2 F ^ H; assign P1 F ^ V; assign P0 F ^ V ^ H;2.2 PAL与NTSC的实战差异调试跨国项目时我深刻体会到PAL和NTSC标准的区别。不只是帧率不同25fps vs 30fps消隐区设置才是真正的坑参数PALNTSC有效行576行480行水平消隐288字节268字节场消隐行数567行480行最要命的是场序——PAL是奇场在前NTSC却是偶场在前。有次在FPGA里搞反了场序输出的视频就像老式电视机信号不良时的鬼影效果。后来我在代码里加了状态机来明确区分always (posedge clk) begin if(fval_cnt 312) f_reg 0; // PAL顶场 else f_reg 1; // PAL底场 end3. FPGA实现关键设计3.1 视频时序发生器在Xilinx Artix-7上实现时时序控制是核心难点。我的方案是用两个计数器构建坐标系fval_cnt垂直方向的行计数器0-624lval_cnt水平方向的字节计数器0-1727always (posedge clk) begin if(reset) begin fval_cnt 0; lval_cnt 0; end else if(lval_cnt L_NUM) begin // 行结束 lval_cnt 0; fval_cnt (fval_cnt F_NUM) ? 0 : fval_cnt 1; end else lval_cnt lval_cnt 1; end这里有个细节优化消隐区填充0x80和0x10交替值能帮助接收端时钟恢复。我最初偷懒全填0x00结果传输距离超过50米就出现同步丢失。3.2 ADV7391配置要点通过I2C配置ADV7391时这几个寄存器最易出错0x00输入格式设置YUV422对应0x400x01输出使能PAL模式需设0x060x82色度增益默认0x10效果最佳实测发现芯片上电需要至少50ms稳定时间。我的做法是在FPGA里添加延时计数器always (posedge clk) begin if(config_done delay_cnt 5_000_000) delay_cnt delay_cnt 1; else if(config_done) tx_enable 1; end4. 完整Verilog架构设计4.1 数据流管道整个系统像条流水线我的设计分为三级AXIS FIFO缓冲解决跨时钟域问题时序生成模块产生EAV/SAV标记数据选择器在有效数据和消隐数据间切换关键代码段实现数据选择always (posedge clk) begin if(lval_cnt 0) data_out 8hFF; // SAV起始 else if(lval_cnt 1 || lval_cnt 2) data_out 8h00; else if(lval_cnt 3) data_out {1b1,f,v,1b1,P3,P2,P1,P0}; else if(in_active_region) data_out video_data; else data_out (lval_cnt[0]) ? 8h10 : 8h80; // 消隐填充 end4.2 调试技巧用ILA抓取信号时建议设置这些触发条件EAV/SAV的FF0000序列场同步信号上升沿FIFO空满状态有次发现图像顶部扭曲最终定位是FIFO复位信号与场同步不同步。解决方法是在每场开始时复位FIFOalways (posedge clk) begin if(fval_cnt 0 lval_cnt 10) fifo_rst 0; else fifo_rst 1; end经过三个版本迭代现在的设计能稳定支持100米电缆传输。最关键的是理解BT.656协议就像掌握一门语言只有清楚每个字节的含义才能在FPGA世界里自如地对话。

更多文章