(旁支)1_串口传图显示
串口传图显示项目方案介绍
串口传图显示项目的功能需求分析和实现方案。
串口传图显示的项目是指通过串口把PC端准备好的图像数据发送给FPGA,然后FPGA驱动显示器把图像显示出来的项目。这个项目主要涉及到以下几个方面:
-
PC端:PC端需要准备好图像数据,然后通过串口发送给FPGA。
使用C语言编写,实现图像数据的转换和发送功能
- PC端需要确定以下几个问题:
- 图像大小:图像大小要和摄像头的图像尺寸一致,为了和后续的项目挂钩,这里选择1080P的图像大小,即1920x1080的分辨率。
- 数据格式:数据格式要从RGB888转换成RGB565,因为RGB888占用24位,而RGB565占用16位,可以减少数据量。RGB888是指每个像素点由红绿蓝三个分量组成,每个分量占8位;RGB565是指每个像素点由红绿蓝三个分量组成,红色占5位,绿色占6位,蓝色占5位。
- 发送顺序:发送顺序要按照行扫描的方式,即先发送第一行的第一个像素点,然后依次发送第一行的其他像素点,再发送第二行的第一个像素点,以此类推,直到最后一行的最后一个像素点。每个像素点占两个字节,先发送高字节,再发送低字节。
- PC端需要确定以下几个问题:
-
FPGA内部:FPGA内部需要完成以下三个功能:
- 串口接收:串口接收模块需要接收PC端发送过来的图像数据,并把数据缓存到FIFO中,因为串口接收速度比较慢。
- DDR3存储:DDR3存储模块需要把FIFO中缓存的图像数据写入到外部的DDR3芯片中,因为FPGA内部的存储资源不足以存储一幅1080P的图像。这里需要调用DDR3 IP核来操作DDR3芯片,并通过AXI接口来控制DDR3 IP核。
- 显示器驱动:显示器驱动模块需要从DDR3芯片中读出图像数据,并通过HDMI接口发送给显示器。这里也需要把数据缓存到FIFO中,因为HDMI驱动速度比较快。这里需要有一个HDMI驱动模块来产生HDMI所需的时序。
FPGA 内部模块设计
- 串口接收模块:使用Verilog HDL编写,实现对 PC 端发送的图像数据的接收和校验,将数据送入写 FIFO 中
- 写 FIFO 模块:实现对串口接收数据的缓存和跨时钟域处理,将数据送入 AXI 控制模块中
- AXI 控制模块:使用Verilog HDL编写,实现对 DDR3 IP 的 AXI 写操作时序控制,将数据写入 DDR3 芯片中
- 读 FIFO 模块:使用Xilinx提供的IP核,实现对 DDR3 IP 的 AXI 读操作时序控制,将数据从 DDR3 芯片中读出并缓存到 FIFO 中
- DDR3 IP:使用Xilinx提供的IP核,负责与外部DDR3芯片进行通信,完成图像数据的存储和读取
- HDMI 驱动模块:使用Verilog HDL编写,实现对 HDMI 接口的驱动时序控制,将数据从读 FIFO 中读出并显示到显示器上
-
显示器:显示器需要接收FPGA通过HDMI接口发送过来的图像数据,并把图像显示出来。
流程步骤
-
步骤一:PC 端软件将图像数据转换为 RGB565 格式,并按行扫描方式发送到 FPGA 的串口接口
-
步骤二:FPGA 内部的串口接收模块接收 PC 端发送的图像数据,并进行校验,将数据送入写 FIFO 模块
-
步骤三:写 FIFO 模块对串口接收的数据进行缓存和跨时钟域处理,将数据送入 AXI 控制模块
-
步骤四:AXI 控制模块根据 AXI 写操作时序,将数据写入 DDR3 IP 的写端口
-
步骤五:DDR3 IP 将数据写入 DDR3 芯片中,存储图像数据
-
步骤六:AXI 控制模块根据 AXI 读操作时序,从 DDR3 IP 的读端口读取数据,将数据送入读 FIFO 模块
-
步骤七:读 FIFO 模块对 DDR3 IP 读出的数据进行缓存和跨时钟域处理,将数据送入 HDMI 驱动模块
-
步骤八:HDMI 驱动模块根据 HDMI 驱动时序,将数据从读 FIFO 中读出,并通过 HDMI 接口显示到显示器上
举例
- 假设要发送一幅2x2的图像,每个像素用RGB888表示,如下:
(255,0,0) | (0,255,0) |
---|---|
(0,0,255) | (255,255,255) |
-
首先要把每个像素转换为RGB565格式,即用5位表示红色分量,6位表示绿色分量,5位表示蓝色分量。转换的方法是保留每个分量的最高位,然后右移相应的位数,例如255用8位表示为11111111,用5位表示为00011111,用6位表示为00111111。转换后得到如下结果:
(255,0,0)转换成RGB565格式的步骤如下:
- 255的二进制表示是11111111,保留最高位,右移3位,得到00011111
- 0的二进制表示是00000000,保留最高位,右移2位,得到00000000
- 0的二进制表示是00000000,保留最高位,右移3位,得到00000000
- 拼接成16位,得到0001111100000000
(00011,111000,00000) | (00000,111111,00000) |
---|---|
(00000,000000,11111) | (11111,111111,11111) |
- 然后按照行扫描的顺序发送每个像素的高字节和低字节,即先发送第一行第一个像素的高8位,再发送第一行第一个像素的低8位,然后发送第一行第二个像素的高8位,再发送第一行第二个像素的低8位,以此类推。发送的数据如下:
00011111 00000000 00000111 11100000
00000000 00111111 00000000 00000111
11111000 00111111 11111000 00111111
在FPGA内部,串口接收模块会接收这个序列,并校验是否有错误。如果没有错误,它会把这个序列发送给写FIFO模块。写FIFO模块会缓存这些数据,并处理跨时钟域问题,因为串口接收模块和AXI控制模块可能使用不同的时钟源。然后写FIFO模块会把这个序列送给AXI控制模块。AXI控制模块会根据AXI4协议,向DDR3 IP发送写入命令和数据。DDR3 IP会根据自己的配置和仲裁机制,向外部DDR3芯片发送信号,并将数据写入到DDR3芯片中的指定地址。
当要显示图像时,AXI控制模块会向DDR3 IP发送读取命令,并从DDR3 IP读出数据。DDR3 IP会根据自己的配置和仲裁机制,向外部DDR3芯片发送信号,并从DDR3芯片中的指定地址读出数据。然后AXI控制模块会将数据发送给读FIFO模块。读FIFO模块会缓存数据,并处理跨时钟域问题,因为AXI控制模块和HDMI驱动模块可能使用不同的时钟源。然后读FIFO模块会将数据发送给HDMI驱动模块。HDMI驱动模块会根据HDMI协议,产生时序信号,并将数据通过HDMI接口发送给显示器。HDMI显示器会根据接收到的数据,显示出对应的图像。