2. 视频图像数据流与接口基础
在 PolarFire 上做视频图像处理,第一件必须想清楚的事不是算法,而是“数据长什么样、按什么节奏流动、从哪个接口进、往哪个接口出”。同一帧图像,在传感器端可能是 RAW10 的 Bayer 数据,进入 FPGA 后要转成 RGB888 或 YCbCr 4:2:2,再经过行缓存、缩放或色彩处理,最后通过 HDMI 或 CSI-2 送出。如果像素格式、色彩空间和时序约定没有对齐,后面所有处理都会出现颜色错乱、图像撕裂或根本无同步信号的问题。
像素格式与色彩空间:先定义“一个像素由什么组成”
像素格式描述的是单个像素在存储和传输时的位排列方式。常见的有 RGB888(每像素 24 bit,R/G/B 各 8 bit)、RGB565(16 bit,红 5 位、绿 6 位、蓝 5 位)、YCbCr 4:4:4(亮度与两个色度分量等采样)、YCbCr 4:2:2(色度水平方向减半,每两个像素共享一组 Cb/Cr)、以及 Bayer RAW8/RAW10/RAW12。以 RAW10 为例,每个像素实际只有 10 bit 有效数据,但为了按字节对齐传输,通常把 4 个 10 bit 像素打包成 5 个字节,这就是 MIPI CSI-2 中常见的 RAW10 打包方式。
色彩空间则是“这些数值代表什么颜色”的定义。RGB 是设备相关空间,YCbCr 是亮度/色度分离空间,二者之间的转换有固定公式。以 8 bit 全范围(full range)为例,RGB 到 YCbCr 的常用近似为:
Y = 0.299R + 0.587G + 0.114B
Cb = -0.169R - 0.331G + 0.500B + 128
Cr = 0.500R - 0.419G - 0.081B + 128
在 PolarFire 的 SmartFusion2/Mi-V 视频流水线中,如果传感器输出的是 Bayer RAW,通常先做去马赛克(demosaic)得到 RGB,再按显示或编码需求转成 YCbCr。这里要特别注意“有限范围”(limited range,Y 取 16~235)与“全范围”(0~255)的区别:HDMI 通常按有限范围传输,而很多图像处理算法按全范围计算,二者混用会导致画面发灰或对比度异常。
行场同步与时序标准:让接收端知道“一行从哪开始、一帧从哪结束”
视频不是连续流,而是由“帧—行—像素”三级结构组成。行同步(HSYNC)标记一行的开始和结束,场同步(VSYNC)标记一帧的开始和结束,数据有效信号(DE)则指示当前像素是否有效。三者配合,接收端才能正确地把串行像素流还原成二维图像。以 1080p60 为例,一帧有 1125 行(其中 1080 行为有效行,45 行为消隐行),每行 2200 个像素时钟(其中 1920 个为有效像素,280 个为消隐区)。像素时钟约为 148.5 MHz,正好对应 1920×1080×60 的有效像素率。
PolarFire 的视频接口通常以 AXI4-Stream 或原生并行视频总线承载像素数据,配合 HSYNC/VSYNC/DE 三个控制信号。实现时最容易出错的地方是消隐区计数:如果行消隐或场消隐的计数值与发送端不一致,接收端就会把消隐数据当成有效像素,表现为图像偏移或出现黑边。建议在 FPGA 内部用一组可配置的时序参数(H_ACTIVE、H_FRONT_PORCH、H_SYNC、H_BACK_PORCH、V_ACTIVE、V_FRONT_PORCH、V_SYNC、V_BACK_PORCH)统一管理,所有模块共用同一套参数,避免各模块各自硬编码。
MIPI CSI-2 在 PolarFire 上的实现要点
MIPI CSI-2 是传感器侧最常用的高速串行接口,物理层为 D-PHY,包含 1 对时钟 Lane 和 1~4 对数据 Lane。在 PolarFire 上实现 CSI-2 接收,通常使用硬核或软核 D-PHY 接收器,再配合 CSI-2 协议解码模块。关键点有三个:第一,Lane 对齐与字节同步,接收端需要根据同步码(Sync Word)找到每个 Lane 的字节边界;第二,数据包解析,CSI-2 以短包(帧起始、帧结束、行起始、行结束)和长包(有效像素数据)交替传输,FPGA 需要正确区分包类型并提取有效载荷;第三,RAW10 解包,把 5 字节中的 4 个 10 bit 像素还原成 4 个 16 bit 对齐的像素值,便于后续处理。
实际调试时,建议先用 CSI-2 的帧起始和帧结束短包确认链路是否通,再检查长包中的像素计数是否与预期一致。如果帧起始能收到但像素数据错位,多半是 Lane 对齐或 RAW10 解包顺序有问题。
HDMI 接口在 PolarFire 上的实现要点
HDMI 发送端在 PolarFire 上通常由 TMDS 编码器、串行化器和时序生成器组成。TMDS 编码把 8 bit 像素数据转换成 10 bit 最小化跳变的码流,再通过高速 SerDes 以差分对形式送出。实现时要注意:HDMI 的像素时钟与 TMDS 时钟是 1:10 关系,PolarFire 的 SerDes 需要正确配置分频比;音频和控制数据通过数据岛(Data Island)插入到消隐区,如果只做视频可以暂时忽略;HDCP 加密在需要保护内容时才启用,普通教学链路可以跳过。
一个常见的工程做法是:在 FPGA 内部维护一套统一的视频时序参数,CSI-2 接收端按传感器时序写入行缓存,HDMI 发送端按显示时序从行缓存读出。两者通过 AXI4-Stream 的 TREADY/TVALID 握手进行背压,避免行缓存溢出。如果 HDMI 端时序参数与 CSI-2 端不一致,就会出现画面滚动或局部撕裂,此时应优先检查 VSYNC 和 HSYNC 的极性及消隐区长度是否匹配。
从数据流角度看整条链路
把上述内容串起来,PolarFire 上的视频链路可以概括为:传感器以 CSI-2 输出 RAW10 Bayer 数据 → FPGA 的 D-PHY 接收并解包 → 去马赛克得到 RGB888 → 色彩空间转换为 YCbCr 4:2:2 → 行缓存和时序重整 → HDMI TX 以 TMDS 送出。每一步都涉及格式、位宽和时序的转换,任何一处不一致都会在最终画面上暴露出来。理解这条链路中“数据是什么、按什么节奏走、在哪里转换”,是后续做图像算法加速和接口调试的基础。