在医疗影像设备、工业检测系统等专业领域,许多传统设备仍采用BT.656标准传输标清视频。当FPGA工程师需要将这些视频源接入现代处理系统时,面临一个关键选择:使用现成的IP核还是自主实现解码器?本文将带您深入BT.656协议内核,通过Verilog构建一个可配置的解码器,并分享实际工程中的调试技巧。
BT.656协议作为ITU-R制定的数字视频接口标准,其精妙之处在于将时序信息与像素数据融合在单一数据流中。理解这个"自同步"机制是开发解码器的关键。
从物理层看,BT656数据流由连续的字节组成,每个时钟周期传输一个字节。但深入分析会发现三个逻辑层次:
text复制EAV + 水平消隐 + SAV + 有效视频数据
FF 00 00,第四个字节携带关键状态信息第四字节XY的每个比特都承载特定信息:
| 比特位 | 名称 | 含义 | 取值说明 |
|---|---|---|---|
| 7 | F | 场标识 | 0=顶场,1=底场 |
| 6 | V | 垂直消隐标识 | 1=消隐期,0=有效视频 |
| 5 | H | 水平消隐标识 | 0=SAV,1=EAV |
| 4-1 | P3-P0 | 保护比特 | 根据F/V/H计算得出的校验位 |
保护比特的计算公式为:
verilog复制P3 = V ^ H;
P2 = F ^ H;
P1 = F ^ V;
P0 = F ^ V ^ H;
在实际FPGA实现中,需要解决几个典型问题:
提示:在Xilinx FPGA中,建议使用IDDR原语处理字节数据,可显著改善时序
我们采用三级流水线结构实现解码器:
code复制 +---------------+
| 字节同步检测 |---> EAV/SAV识别
+-------|-------+
|
+-------v-------+
| 状态机控制器 |---> 场/行状态跟踪
+-------|-------+
|
+-------v-------+
| 数据分配器 |---> YCbCr数据输出
+---------------+
verilog复制module bt656_decoder #(
parameter DATA_WIDTH = 8,
parameter IMG_WIDTH = 720,
parameter IMG_HEIGHT = 576
)(
input wire clk,
input wire reset_n,
input wire [DATA_WIDTH-1:0] bt656_data,
output reg [DATA_WIDTH-1:0] y_data,
output reg [DATA_WIDTH-1:0] cb_data,
output reg [DATA_WIDTH-1:0] cr_data,
output reg video_valid,
output reg vsync,
output reg field
);
采用改进的Moore状态机,包含五个状态:
状态转移条件基于EAV/SAV检测:
verilog复制always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
state <= IDLE;
end else begin
case(state)
IDLE: if (eav_detected) state <= VBANK;
VBANK: if (sav_detected) state <= HBANK;
HBANK: if (eav_detected) state <= ACTIVE;
ACTIVE: if (eav_detected) state <= FIELD_END;
FIELD_END: if (sav_detected) state <= HBANK;
endcase
end
end
采用四级移位寄存器实现序列检测:
verilog复制reg [7:0] shift_reg[3:0];
always @(posedge clk) begin
shift_reg[0] <= bt656_data;
for (int i=1; i<4; i++) begin
shift_reg[i] <= shift_reg[i-1];
end
end
wire eav_detected = (shift_reg[3]==8'hFF) &&
(shift_reg[2]==8'h00) &&
(shift_reg[1]==8'h00) &&
((shift_reg[0] & 8'hF0) == 8'hA0);
wire sav_detected = (shift_reg[3]==8'hFF) &&
(shift_reg[2]==8'h00) &&
(shift_reg[1]==8'h00) &&
((shift_reg[0] & 8'hF0) == 8'h80);
BT.656采用YCbCr 4:2:2格式,需交替输出Y和CbCr分量:
verilog复制reg component_sel; // 0=Y, 1=Cb/Cr
always @(posedge clk) begin
if (video_valid) begin
component_sel <= ~component_sel;
if (!component_sel) begin
y_data <= bt656_data;
end else begin
{cb_data, cr_data} <= {bt656_data, cr_data};
end
end
end
精确的行计数需要结合场信息:
verilog复制reg [10:0] line_count;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
line_count <= 0;
end else if (vsync) begin
line_count <= 0;
end else if (eav_detected && !V) begin
line_count <= line_count + 1;
end
end
使用SystemVerilog构建自动化测试环境:
verilog复制module tb_bt656_decoder;
reg clk = 0;
always #18.519 clk = ~clk; // 27MHz时钟
task send_eav(input [7:0] xy);
{data[0], data[1], data[2], data[3]} = {8'hFF, 8'h00, 8'h00, xy};
endtask
initial begin
// 发送测试序列
send_eav(8'hAB); // EAV, 场1, 消隐
// ...更多测试用例
end
endmodule
调试时应重点关注以下信号:
问题1:SAV后第一个数据不是Y分量
问题2:场同步信号抖动
问题3:色度分量错位
注意:在Altera器件中,建议使用SignalTap II捕获实际硬件信号,比仿真更可靠
添加AXI-Lite接口实现运行时配置:
verilog复制module bt656_decoder_axi #(
parameter C_S_AXI_DATA_WIDTH = 32
)(
// AXI接口
input wire S_AXI_ACLK,
input wire S_AXI_ARESETN,
input wire [31:0] S_AXI_AWADDR,
// ...其他AXI信号
// 视频接口
input wire bt656_clk,
input wire [7:0] bt656_data
);
通过参数化设计支持相关标准:
verilog复制generate
if (STANDARD == "BT656") begin
// BT.656特定逻辑
end else if (STANDARD == "BT1120") begin
// BT.1120高清接口逻辑
end
endgenerate
在Xilinx Vivado中实现时,添加以下约束确保时序:
tcl复制create_clock -name vid_clk -period 37.037 [get_ports bt656_clk]
set_input_delay -clock vid_clk 2.0 [get_ports bt656_data]