如何在FPGA之间实现实时视频和音频通信
发布时间:2026/9/21
介绍
新冠疫情爆发后,虚拟通信工具迅速普及,重塑了我们对教育和职业环境中团队合作的理解。旨在促进远程通信的数字工具已成为我们学术体验的重要组成部分。考虑到本学期课程的异步性质,自然而然地选择在期末项目中探索如何在FPGA之间实现实时视频和音频通信。使用美国国家电视标准委员会(NSTC)的摄像机和立体声麦克风进行视频和音频数据采集,设计并实现了一种协议,使两个开发板能够成功且同时地交换数据,从而通过GPIO创建了一个视频通话系统。
顶层设计
项目实现了两块 DE-1 SoC FPGA 板之间的双向音视频通信。主要使用 Verilog 语言,通过状态机对视频总线进行读写操作来处理数据采集和传输。此外,还使用 HPS 与 NSTC 摄像头通信。音频数据从麦克风输入端口读取,并通过线路输出端口播放。使用 EBAB 总线主控器来处理与麦克风音频采样和播放相关的复杂操作。EBAB 总线主控器也用于视频播放。视频和音频的工作原理基本相同。总线主控器分别用于处理读取和写入操作,需要注意的是,这两个操作不能同时进行。
当音频或视频播放仅在一个电路板上进行时,该过程相当简单。当准备写入数据时,写入的将是之前状态中读取的数据。本项目的主要难点在于设计一个多板同步方案,确保在双向通信期间,一旦一个电路板完成对其摄像头和麦克风的读取,另一个电路板就能在数据写入的时间间隔内通过 GPIO 接口提供正确的数据。然而,一些因素使得音频比视频更容易处理。首先,音频的可靠性要求并不高。某些数据可能会“丢失”,这意味着它没有成功写入接收器的输出端。假设这种情况不经常发生,偶尔的丢失对输出音频质量没有明显的影响。其次,视频不需要像视频那样进行寻址来将像素颜色映射到 VGA 显示器上的位置。
由于这些关键差异,可以采用不同的方法来创建音频和视频播放,并分别处理它们的通信。这种划分背后的逻辑是,如果音频和视频看似实时地传输,那么任何细微的音频和视频同步偏差对用户来说都不会很明显。这种选择能够创建两个独立的状态机,一个专门用于音频,另一个专门用于视频。这大大简化了设计,并最大限度地降低了通信协议中握手过程的复杂性。
选择使用GPIO端口是因为它们简单易用。可以使用跳线连接FPGA。这种方法确实存在一些局限性,最明显的是长度限制。两个板子需要相对靠近,这在原则上违背了虚拟通信的初衷。不过,项目的重点在于协议设计,该协议可以轻松转换为支持通过不同介质进行数据传输。GPIO方法的另一个主要局限性是不可忽略的时钟偏移和信号失真,尤其是在高频情况下。由于电路板在高速读写引脚方面的限制,许多初步方案都被证明是无效的。最终,这些挑战促使我们设计出一个能够克服硬件限制的系统。
程序/硬件设计
视频
NTSC 摄像机直接连接到 FPGA,可以通过硬件协议系统 (HPS) 与其通信。为了在 VGA 显示器上显示摄像机输入,使用外部总线到 Avalon 桥接接口来实现 FPGA 和显示器之间的通信。从 NTSC 摄像机读取数据时,默认分辨率为 320 x 240,这与 VGA 显示器的 640 x 480 分辨率不同。没有直接将 NTSC 摄像机的输入映射到 VGA 显示器并逐像素写入,而是将一个像素映射到四个像素,以充分利用整个显示屏。如果没有这种方法,视频只能占据显示屏的四分之一。使用这种映射方案增加视频尺寸并不会提高分辨率,但认为它可以改善用户体验。理论上,视频播放过程是先读取后写入,但实际上,为了生成缩放后的图像,每次读取后都会进行四次连续写入,每次写入对应一个像素。

图 1:从相机读取到 VGA 像素的映射

图 2:FPGA 之间的视频通信流程

图 3:FPGA 上的视频状态机
两个FPGA都采用上述相同的读写方案。为了使它们能够相互通信,在其中一个状态机中添加了两个握手状态,以确保它们在读取完成后,只有在确认读取已完成三个时钟周期后才会进入写入阶段。为写入操作实现了类似的逻辑,即两个FPGA只有在确认写入完成后才会读取新值。一旦达成一致(通过监控板间交换的标志位),负责跟踪握手的状态机就会进入下一步,并与另一个FPGA通信以执行相同的操作。这种握手方案的主要动机是视频状态机的完成时间并不稳定。实现了一个定时器来防止总线占用,这最终导致完成时间存在32个时钟周期的波动。理论上,如果我们能够合理地假设完成所需的时钟周期数相同,并且板上的时钟频率相同,那么两个状态机默认情况下将在某种程度上保持同步。因为情况并非如此,所以我们依靠握手来实现同步。

图 4:FPGA 之间的音频通信流程
由于音频能够容忍一些不一致性,因此其实现比视频要简单得多。音频状态机是课程网站“数字信号处理”页面上的音频环回配置的修改版本。音频通信协议不使用任何握手机制,因为通过实验发现它完全没有必要。它首先从麦克风输入端口读取数据,然后写入线路输出端口。由于它也使用 EBAB 总线主控器,因此其读写机制与上面解释的视频机制非常相似。audio_bus_addr被设置为读取 FIFO 地址,audio_bus_read被设置为高电平。然后它会返回一个确认信息,并在下一个时钟周期将数据放在audio_bus_read_data上。所需的数据被放入audio_bus_write_data,audio_bus_write被设置为足够高以写入线路输出端口。然后它会等待写入成功的确认信息,然后再开始新的读取操作。数据交换非常简单直接。读取完成后,数据会被放置在一组 GPIO 引脚上,供另一个 FPGA 使用。写入时,写入数据会从另一组 GPIO 引脚上读取,而另一个 FPGA 则将读取的数据放置在这组引脚上。需要注意的是,这里会执行两次读取和两次写入操作,分别对应左声道和右声道。由于两个状态机无需同步运行,因此无需进行额外的协调。即使出现数据丢失(即 GPIO 引脚上的可用数据在写入之前发生变化),或者出现重复写入(即由于数据变化不够快,导致某个值被写入两次),也不会对音频清晰度造成显著影响。在项目演示中,可以明显听到明显的失真,但这只是因为我们将音频从 32 位压缩到 6 位,以便为视频通信腾出足够的 GPIO 引脚。我们通过保留最高 6 位,然后在接收到该值后将其连接 24 位 0 来实现这一点,这样它就可以保持其 32 位状态。
以下是一些调试图片



结论
总之,实现了两个FPGA板之间的双向视频和音频通信。使用GPIO接口在板间距离、速度和数据完整性方面存在明显的局限性。然而,通过开发一种有效管理后两项的协议,构建了一个稳健的框架,可以轻松扩展以支持其他通信方式。未来,可以添加静音按钮和摄像头关闭等功能。此外,为了扩展功能和实用性,可以放弃GPIO接口,转而支持无线网络通信,从而无需将两个板连接在一起。


