BT656 Verilog实现720×576视频输出的技术实践
在工业相机、医疗成像设备和安防监控系统中,常常需要FPGA模拟标准视频信号与传统编解码芯片对接。而ITU-R BT.656作为广泛使用的并行数字视频接口,因其高兼容性和简洁的嵌入式同步机制,成为这类设计中的首选方案。
尤其当目标是生成符合PAL制式的720×576分辨率视频流时,如何用Verilog精确还原BT.656协议的行为,不仅考验对ITU标准的理解深度,也直接影响图像能否被下游处理器稳定锁定与显示。本文将从实际工程角度出发,拆解这一过程的核心逻辑,并提供可综合、易调试的代码框架。
BT656协议的本质:没有H/V Sync的同步艺术
传统TTL RGB接口依赖独立的HSYNC和VSYNC信号来标记帧和行边界,这种方式虽然直观,但占用大量IO资源且抗干扰能力弱。相比之下,BT656巧妙地把同步信息“隐藏”在数据流中,仅通过8位并行总线即可完成完整视频传输。
其核心思想是——
每行视频数据前后插入特殊的4字节包头
,即SAV(Start of Active Video)和EAV(End of Active Video)。这些包头不携带图像内容,而是以固定模式
FF FF 00 XY
编码控制标志,接收端据此判断当前是否处于有效区域、属于哪一场、以及是否为垂直消隐期。
例如:
-
XY = 0x00
:SAV,位于有效视频区
-
XY = 0x10
:EAV,位于有效视频区
-
XY = 0x20
:SAV,位于垂直消隐区
-
XY = 0x30
:EAV,位于垂直消隐区
其中
X
字节的三个关键位定义如下:
| 位 | 含义 |
|---|---|
| F (bit0) | 场标志:0=第一场,1=第二场(隔行扫描) |
| V (bit1) | 垂直同步标志:0=有效行,1=垂直消隐 |
| H (bit2) | 行类型:0=SAV,1=EAV |
这种设计使得整个系统无需额外引脚传递同步信号,极大简化了PCB布线,特别适合资源受限或高密度集成的应用场景。
720×576 PAL制式的关键时序参数
要让FPGA输出的视频能被标准设备识别,必须严格遵循ITU-R BT.601和BT.656规定的时序规范。对于PAL制式(576i),主要参数如下:
| 参数 | 数值 |
|---|---|
| 分辨率 | 720×576(有效像素) |
| 扫描方式 | 隔行(Field 0 / Field 1) |
| 帧率 | 25 fps(每秒50场) |
| 行频 | 15,625 Hz |
| 像素时钟 | 27 MHz(精确值通常为27.000或27.001 MHz) |
| 每行总周期 | 864像素时钟 |
| 每帧总行数 | 625行(含消隐) |
每一行由以下部分组成:
[Front Porch][HSYNC][Back Porch][Active Video][EAV][...]
12 64 68 720 4
注意:虽然有效像素是720个,但由于YCbCr 4:2:2采样下每个像素对应两个字节(Y + Cb/Cr交替),因此在一个像素时钟周期内只能传输一个字节。这意味着 720个像素需1440个PCLK周期才能传完 。
此外,每帧包含625行,分为两个场,各约312.5行。场标志(F)在每帧结束时翻转一次,用于区分奇偶场。若此标志出错,可能导致画面闪烁或撕裂。
Verilog实现:状态机驱动的数据流调度
下面是一个可综合的BT656输出模块实现,采用有限状态机(FSM)精确控制SAV/EAV插入时机和数据流向。
接口定义
module bt656_generator (
input clk_27m, // 27MHz 主时钟
input rst_n, // 复位信号(低有效)
input [7:0] video_y, // 当前Y分量输入
input [7:0] video_cbcr, // 当前Cb/Cr分量输入(交替)
input valid_pixel, // 当前像素有效标志
output reg [7:0] bt656_data, // BT656输出数据
output reg bt656_de, // 数据使能(辅助诊断)
output reg field_out // 当前场标识输出
);
bt656_de虽非标准要求,但在调试阶段非常有用,可用于ILA抓取有效数据区间。
内部计数器与状态定义
reg [9:0] pixel_counter; // 每行内的字节位置计数(最大864*2)
reg [9:0] line_counter; // 行计数(0~624)
reg field_flag; // 场标志(0/1)
localparam
ST_IDLE = 3'd0,
ST_SAV = 3'd1,
ST_ACTIVE = 3'd2,
ST_ACTIVE_YC= 3'd3, // 输出CbCr
ST_EAV = 3'd4,
ST_HBLANK = 3'd5;
reg [2:0] state;
核心状态机逻辑
always @(posedge clk_27m or negedge rst_n) begin
if (!rst_n) begin
state <= ST_IDLE;
pixel_counter <= 0;
line_counter <= 0;
field_flag <= 0;
bt656_de <= 0;
bt656_data <= 8'hFF;
field_out <= 0;
end else begin
case (state)
ST_IDLE: begin
bt656_data <= 8'hFF;
if (pixel_counter == 0) begin
state <= ST_SAV;
end else begin
pixel_counter <= pixel_counter + 1;
end
end
ST_SAV: begin
case (pixel_counter)
0,1: bt656_data <= 8'hFF;
2: bt656_data <= 8'h00;
3: begin
// 构造XY字节:F=field_flag, V=0(有效区), H=0(SAV)
bt656_data <= {1'b0, field_flag, 1'b0, 1'b0};
bt656_de <= 1;
state <= ST_ACTIVE;
end
default: ;
endcase
pixel_counter <= pixel_counter + 1;
if (pixel_counter == 3) begin
pixel_counter <= 0;
end
end
ST_ACTIVE: begin
if (valid_pixel) begin
bt656_data <= video_y;
state <= ST_ACTIVE_YC;
end else begin
state <= ST_EAV;
pixel_counter <= 0;
end
bt656_de <= 1;
end
ST_ACTIVE_YC: begin
bt656_data <= video_cbcr;
bt656_de <= 1;
state <= ST_ACTIVE;
// 注意:下一个时钟继续判断valid_pixel
end
ST_EAV: begin
case (pixel_counter)
0: bt656_data <= 8'hFF;
1: bt656_data <= 8'hFF;
2: bt656_data <= 8'h00;
3: begin
bt656_data <= {1'b0, field_flag, 1'b1, 1'b0}; // H=1 → EAV
bt656_de <= 0;
state <= ST_HBLANK;
pixel_counter <= 0;
end
default: ;
endcase
pixel_counter <= pixel_counter + 1;
end
ST_HBLANK: begin
bt656_data <= 8'hxx; // 可填充测试色或保留
if (pixel_counter >= (864 - 720 - 8)) begin // 消隐期剩余时间
if (line_counter == 624) begin
line_counter <= 0;
field_flag <= ~field_flag;
field_out <= ~field_flag;
end else begin
line_counter <= line_counter + 1;
end
pixel_counter <= 0;
state <= ST_SAV;
end else begin
pixel_counter <= pixel_counter + 1;
end
end
default: state <= ST_IDLE;
endcase
end
end
关键设计要点说明
-
双周期交替输出
:由于Y和CbCr分时复用同一数据线,每个像素需两个PCLK周期完成传输。状态
ST_ACTIVE与ST_ACTIVE_YC配对实现这一点。 - valid_pixel信号来源 :通常由地址发生器模块提供,指示当前地址是否落在720×576的有效范围内。
-
场切换时机
:必须在第624行结束后立即翻转
field_flag,否则会导致隔行错位。 -
EAV后消隐处理
:水平消隐期长度为
864 - 720 = 144像素时钟,减去SAV/EAV占用的8字节(等效于4像素周期),实际留空140个PCLK周期。
实际应用中的常见问题与对策
接收端无法锁定图像?
这是最常见的问题,原因多集中在同步码格式错误或时钟不稳定:
-
检查波形
:使用ILA工具捕获
bt656_data,确认是否存在连续的FF FF 00 XX序列。 -
验证XY字段
:确保SAV/EAV的
H、V、F位设置正确,特别是垂直消隐区应使用V=1。 - 时钟质量 :27MHz时钟建议通过PLL锁相环生成,并走专用全局时钟网络,避免抖动过大导致采样失败。
如何快速验证功能?
初期可接入彩条生成模块作为数据源:
// 简单彩条:每80像素切换一次颜色
assign color_bar = pixel_counter[9:6];
assign video_y = {color_bar, color_bar[2:0]};
assign video_cbcr = ~color_bar;
这样可在监视器上看到明显的竖条图案,便于判断是否同步成功。
能否支持NTSC或其他分辨率?
完全可以。只需调整以下参数:
- 每行总周期:NTSC为858像素时钟
- 有效行数:NTSC为480行
- 帧率:60Hz(场频59.94Hz)
- 场计数上限改为524或525
原有状态机结构无需改动,仅需修改计数阈值即可适配。
资源优化建议
- 若使用外部DDR存储图像,建议加入一行缓存(Line Buffer),避免频繁突发读取。
- 将状态机合并为两级(如SAV→ACTIVE→EAV→BLANK),减少状态分支。
- 在垂直消隐期间关闭不必要的逻辑模块以降低功耗。
典型系统架构与扩展方向
一个完整的视频生成系统通常包括以下几个模块:
+FPGA+
│
├─ PLL → 27MHz像素时钟
├─ Frame Buffer(SRAM/DDR) → 存储图像数据
├─ Address Generator → 扫描720×576地址空间
├─ Color Pattern Generator → 调试用彩条/棋盘格
└─ BT656 Generator → 输出至ADV7182、TVP5150等解码芯片
未来可拓展的方向包括:
- 双向BT656收发器 :既能输出也能解析BT656流,构建视频桥接器。
- 10-bit模式支持 :扩展至BT.656 10位格式,提升色彩精度。
- OSD叠加功能 :在原始画面上叠加时间戳、LOGO等信息。
- AXI-Stream集成 :适配Zynq平台,实现与PS端的高效数据交互。
掌握BT656协议的Verilog实现,不仅是理解数字视频底层机制的重要一步,更是通往专业级视频系统设计的必经之路。它教会我们如何在严格的时序约束下,精准调度每一个字节的传输,让看似简单的“数据流”承载起完整的视觉信息。
这种高度集成的设计思路,正引领着智能音视频设备向更可靠、更高效的方向演进。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
1592

被折叠的 条评论
为什么被折叠?



