国产高云FPGA基于ov5640的以太网传输

本文章为笔者学习国产高云FPGA的学习记录,如有不妥请指正。

实验任务是使用开发板及 OV5640 摄像头实现640*480@30Hz 的图像采集,并通过以太网发送上位机并实时显示图像。(本实验参照其它开源学习资料进行的修改与调试,基于HDMI显示的进阶)

由系统总体框图可知,FPGA 顶层模块例化了以下6个模块,分别是工程顶层(ov5640_udp_rgmii)、时钟锁相环(pll)、以太网 PHY 芯片的寄存器配置模块(pyh_reg_config)、摄像头编号模块(Camera_ETH_Formator)、UDP 协议发送模块(UDP_Send)、gmii 接口到 rgmii转换模块(gmii_to_rgmii)

ov5640_udp_rgmii :工程顶层,例化了 UDP 发送和摄像头 DVP 接口图像数据捕获编码模块, 实现完整的图像采集传输功能。

PLL:锁相环,用于产生各个模块所需工作时钟。

phy_reg_config:以太网 PHY 芯片的寄存器配置模块,控制 mdio_bit_shift 模块对以太网 PHY 的指定寄存器进行读写操作以完成以太网 PHY 的工作模式设置。

mdio_bit_shift:MDIO底层传输协议实现,完成基于 MDIO 协议对 PHY 寄存器的一次 读或者写操作。

Camera_ETH_Formator:编号模块,对摄像头输出的数据以行为单位进行编号,以便于以太网 上位机正确接收图像。

UDP_Send :协议发送模块, 该模块将用户输入的需要发送的数据内容经过 UDP、 IP、 MAC 层协议层层打包后,通过 RGMII 接口输出给以太网 PHY 芯片, 以完成数据的发送。

async_fifo:UDP发送数据缓存 FIFO,用户将需要发送的数据写入该 FIFO,然后 由 UDP_Send 中的发送逻辑将数据读出并最终以 UDP 协议发送。

CRC32_D8:CRC32 校验逻辑, 计算经由 MAC 层发送的数据的 CRC 值并附加在 MAC 结尾发送。

gmii_to_rgmii:gmii 接口到 rgmii 接口转换模块,实现 gmii 到 rgmii 的转换。

由于代码部分过多,此处只附上顶层代码部分,如有需要可以私信联系。

module ov5640_udp_rgmii(
	input 			clk,
	input 			rst_n,

	// eth interface
	output 			eth_gtxc,
	output [3:0]    eth_txd,
	output 			eth_txen,
	output 			eth_mdc,
	inout 			eth_mdio,
	output 			eth_rst_n,
	
	//cmos interface
	output			camera_sclk,
	inout		    camera_sdat,
	input			camera_vsync,
	input			camera_href,
	input			camera_pclk,
	output			camera_xclk,
    output          camera_rst_n,
    output          camera_pwdn,
	input 	[7:0]	camera_data
    );

	wire clk_125m;
	wire clk_50m;
	wire clk_24m;
	wire locked;
	wire global_rst_n = locked;
	assign camera_xclk = clk_24m;	
	
    assign clk_50m = clk;

    Gowin_rPLL Gowin_rPLL(
        .clkout(clk_125m), //output clkout
        .lock(locked), //output lock
        .reset(~rst_n), //input reset
        .clkin(clk) //input clkin
    );
	
    camera_rpll camera_rpll(
        .clkout(clk_24m), //output clkout
        .clkin(clk_50m) //input clkin
    );

	wire phy_init;
	phy_reg_config phy_reg_config_inst(
		.Clk(clk_50m),
		.Rst_n(global_rst_n),
		.Phy_rst_n(eth_rst_n),		
		.mdc(eth_mdc),
		.mdio(eth_mdio),
		.Phy_init_done(phy_init)
	);
	
	parameter IMAGE_WIDTH  = 640; //图片宽度
	parameter IMAGE_HEIGHT = 480; //图片高度

	//摄像头初始化配置
	wire Init_Done;
	
  camera_init
  #(
    .CAMERA_TYPE ( "ov5640"    ),//"ov5640" 
    .IMAGE_TYPE  ( 0            ),// 0: RGB; 1: JPEG
    .IMAGE_WIDTH ( IMAGE_WIDTH  ),// 图片宽度
    .IMAGE_HEIGHT( IMAGE_HEIGHT ),// 图片高度
    .IMAGE_FLIP_EN  ( 0            ),// 0: 不翻转,1: 上下翻转
    .IMAGE_MIRROR_EN( 0            ) // 0: 不镜像,1: 左右镜像
  )camera_init
  (
    .Clk         (clk_50m          ),
    .Rst_n       (locked           ),
    .Init_Done   (Init_Done        ),
    .camera_rst_n(camera_rst_n     ),
    .camera_pwdn (camera_pwdn      ),
    .i2c_sclk    (camera_sclk      ),
    .i2c_sdat    (camera_sdat      )
   );
   
  	wire fifo_wrreq;
  	wire fifo_aclr;
	wire [7:0] fifo_wrdata;
	
	//以太网图像行号编号逻辑
	Camera_ETH_Formator Camera_ETH_Formator(
	  .PCLK(camera_pclk),
	  .Rst_n(global_rst_n),
	  .Init_Done(Init_Done),
	  .HREF(camera_href),
	  .VSYNC(camera_vsync),
	  .DATA(camera_data),
	  .fifo_aclr(fifo_aclr),
	  .wrdata(fifo_wrdata),
	  .wrreq(fifo_wrreq)
	);
	
	wire [12:0] fifo_usedw;
	wire GMII_GTXC;
	assign GMII_GTXC = clk_125m;
	
	wire [7:0] GMII_TXD;
	wire GMII_TXEN;
	UDP_Send UDP_Send(
	  .Clk(),
	  .GMII_GTXC(GMII_GTXC),
	  .GMII_TXD(GMII_TXD),
	  .GMII_TXEN(GMII_TXEN),
	  .Rst_n(Init_Done),
	  .Tx_Done(),
	  .data_length(IMAGE_WIDTH*2+2	),//IMAGE_WIDTH*2+2
	  .des_ip(32'hc0_a8_00_03),//hc0_a8_00_03; 192.168.0.3
	  .des_mac(48'hFF_FF_FF_FF_FF_FF),
	  .des_port(16'd6102		),
	  .src_ip(32'hc0_a8_00_02),//hc0_a8_65_02; 192.168.0.2
	  .src_mac(48'h00_0a_35_01_fe_c0),
	  .src_port(16'd5000),
	  .wrclk(camera_pclk),
	  .wrdata(fifo_wrdata),
	  .wrreq(fifo_wrreq),
	  .aclr(fifo_aclr),
	  .wrusedw(fifo_usedw)
	);
	
	gmii_to_rgmii gmii_to_rgmii(
	  .reset_n(rst_n),
	  .gmii_tx_clk(GMII_GTXC),
	  .gmii_txd(GMII_TXD),
      .gmii_txen(GMII_TXEN),
	  .gmii_txer(0),
	  .rgmii_tx_clk(eth_gtxc),
      .rgmii_txd(eth_txd),
	  .rgmii_txen(eth_txen)
	);	
endmodule

调试记录:在调试过程中主要遇到两个问题,烧录程序后网口正常发送上位机图像不显示(此处使用小梅哥摄像头上位机软件)。

1.由于分辨率问题可能需要开启巨型帧进行传输,通常以太网一次可以传输的字节数<1500byte,开启巨型帧后可以提高至9000byte,但是也不是一定需要开启,根据实际情况进行判别,例如笔者使用640*480@30的图像其大小远小于标准以太网MTU的限制故可不开启。

2.最好使用固定座子的摄像头接口而非采用飞线的方式,杜邦线的长度和插槽的松动会引起图像数据的波动,导致图像出现闪频等现象。

<think>好的,我现在需要帮助用户解决如何使用FPGA实现以太网图像传输的问题。首先,我得回顾用户提供的引用资料,看看有哪些现有的方案和经验可以借鉴。用户提到了四个引用,其中涉及STM32与FPGA以太网功能尝试、Zynq FPGA实现SDI视频编解码并通过UDP传输高云FPGA以太网视频传输问题,以及基于FPGA的实时图像传输显示的具体步骤。 首先,用户的问题是如何使用FPGA实现以太网图像传输。根据引用内容,我需要整理出几个关键步骤和可能的方案。引用2中的Zynq方案使用了GTX接口和Tri Mode Ethernet MAC,这可能是Xilinx FPGA常用的方法。而引用4提到使用OV7670摄像头和UDP传输,涉及到设置IP地址和PC端软件,这可能是一个比较基础的实现方式。引用3提到高云FPGA中使用DDR3和BUFFER IP遇到的问题,说明在图像缓存和传输过程中需要注意色彩处理和FIFO的设计。 接下来,我需要考虑用户可能的背景。用户可能有一定的FPGA开发基础,但在以太网传输方面经验不足。他们可能希望了解从图像采集到传输的整个流程,包括硬件设计、协议栈实现、缓存处理以及调试步骤。同时,用户可能对现有的方案或参考设计感兴趣,以加快开发进程。 然后,我需要分解问题。FPGA实现以太网传输图像通常包括几个模块:图像采集、图像处理与缓存、以太网协议封装、物理层传输。每个模块都需要详细说明。例如,图像采集可能需要摄像头接口(如OV7670或SDI),图像缓存可能需要DDR3或片内RAM,以太网部分可能需要MAC和PHY的实现,或者使用现成的IP核。 根据引用2,使用Xilinx的Tri Mode Ethernet MAC和PCS/PMA IP核是一个可行的方案,尤其是结合Zynq的PS端处理能力。而引用4则提供了一个更简单的例子,使用UDP传输和特定的上位机软件。这可能适用于较低分辨率的图像传输。此外,引用3提到的高云FPGA案例中,使用DDR3作为缓存时需要注意FIFO的设计,避免色彩问题,这可能涉及到数据位宽和时序的匹配。 另外,用户可能需要了解不同的以太网协议选择,比如UDP和TCP的区别。UDP更适合实时视频传输,因为它的开销小,但可靠性较低。而TCP需要更复杂的握手和重传机制,可能不适合高实时性要求的场景。引用中的例子多采用UDP,这也是常见的做法。 在硬件连接方面,用户需要将FPGA以太网接口通过PHY芯片连接到RJ45,或者使用SFP光模块。引用2中的SFP光口可能用于更高速或长距离传输。同时,设置正确的IP地址和子网掩码是必要的,如引用4中的192.168.0.3。 关于图像处理,可能需要缩放(如引用2中的自研Verilog缩放模块)或色彩空间转换(比如从RGB到YUV),以减少数据量。缓存部分,使用DDR3配合FDMA(如引用2)或自定义FIFO(如引用3的建议)是关键,确保数据流的连续性和正确性。 调试步骤也很重要,用户可能需要逐步验证每个模块。例如,先测试以太网的连通性(如Ping命令),再传输测试图像,最后处理实时视频。引用1中提到的问题,如ARP应答缺失,可能导致网络层问题,因此需要确保协议栈的完整,或者使用静态ARP表来避免动态ARP查询的问题。 最后,用户可能需要参考现有的工程源码(如引用2和4),这些资源提供了实际的实现细节和架构参考。同时,需要注意不同FPGA厂商的IP核差异,比如Xilinx和高云的工具链和IP库可能不同,需要针对性调整。 总结下来,回答的结构应该包括:系统架构分解、关键模块实现、协议选择、硬件连接、调试步骤、常见问题及解决方案,以及参考案例。同时,生成的相关问题需要围绕这些方面展开,帮助用户深入理解各个部分。</think>### 如何使用FPGA实现以太网图像传输? #### 一、系统架构设计 FPGA以太网图像传输系统通常包含以下核心模块: 1. **图像采集模块**:通过摄像头接口(如MIPI、SDI或HDMI)或传感器(如OV7670)获取原始图像数据[^4]。 2. **图像处理与缓存**: - 使用DDR3或片内RAM缓存图像数据(例如通过FDMA技术实现高速缓存)[^2][^3]。 - 可选图像缩放(如从$1920 \times 1080$缩放到$1280 \times 720$)或色彩空间转换[^2]。 3. **以太网协议栈**: - 封装UDP/IP协议,支持1G/2.5G Ethernet(基于Xilinx的Tri Mode Ethernet MAC IP核)[^2]。 - 实现ARP协议应答,确保路由器能识别FPGA的MAC地址[^1]。 4. **物理层传输**:通过SGMII接口或SFP光模块实现数据发送[^2]。 #### 二、关键实现步骤 1. **硬件连接**: - FPGA通过PHY芯片(如88E1111)或光模块(SFP)连接至以太网。 - 摄像头输入通过并行接口或LVDS接入FPGA[^4]。 2. **协议栈开发**: - **UDP封装**:将图像数据打包为UDP报文,格式如下: $$ \text{帧结构} = \text{以太网头} + \text{IP头} + \text{UDP头} + \text{图像数据} $$ - **ARP应答**:静态配置IP与MAC地址映射,避免路由器无法识别的问题[^1]。 3. **图像缓存优化**: - 使用双FIFO或乒乓缓存结构实现DDR3连续读写,避免数据丢失[^3]。 - 注意位宽对齐(如32位RGB数据需匹配DDR3接口位宽)。 4. **调试与验证**: - **基础测试**:通过Ping命令验证FPGA网络连通性[^1]。 - **逐步验证**:先传输静态图片(如BMP格式),再测试视频流[^3]。 - **上位机配合**:使用QT或定制软件(如“小梅哥UDP摄像头V2.exe”)接收数据[^4]。 #### 三、典型方案对比 | 方案 | 优势 | 适用场景 | |---------------------|-----------------------------------------|-----------------------| | **Zynq PS+PL方案** | 利用ARM处理器简化协议栈开发,支持高清视频 | 复杂系统(如4K视频传输)[^2] | | **纯FPGA方案** | 低延迟,资源占用少 | 实时性要求高的场景(如工业检测)[^3] | | **软核CPU方案** | 灵活性高,可自定义协议栈 | 中等数据量传输(如1080P) | #### 四、常见问题与解决 1. **图像色彩异常**: - 检查DDR3缓存位宽与数据对齐,避免RGB分量错位[^3]。 - 验证色彩空间转换逻辑(如RGB转YUV)是否正确。 2. **网络丢包**: - 优化UDP报文长度(建议≤1400字节以避免分片)。 - 增加硬件流控或重传机制。 3. **低传输帧率**: - 提升时钟频率(如从100MHz升至200MHz)。 - 采用AXI Stream接口实现流水线处理[^2]。 #### 五、参考案例 - **Xilinx Zynq方案**:基于GTX接口实现SDI视频转以太网,工程源码包含FDMA缓存和图像缩放模块[^2]。 - **高云FPGA方案**:需自定义DDR3 FIFO控制器,避免官方IP的色彩异常问题[^3]。 - **基础实现方案**:OV7670摄像头+UDP传输,适合入门学习[^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值