以太网传输图片工程出现的问题总结(含源码)

  本文对以太网传输图片的工程曾经出现过的问题及解决思路进行整理,便于日后出现类似问题能够快速处理。也指出为什么前文在FIFO IP设计时为啥强调深度的重要性。

1、问题

  当工程综合完毕之后,下载到板子,连接以太网口,相关硬件如下所示:

在这里插入图片描述

图1 硬件平台

  PC向开发板发送ARP请求和回显请求,通过Wireshark软件都能抓取开发板的应答数据报文,证明以太网链路畅通。

在这里插入图片描述

图2 arp请求和回显请求

  之后通过网络调试助手向开发板传输图片数据,当图片传输完毕后,显示器上显示的界面如下图所示。

在这里插入图片描述

图3 显示器显示图片

  为了对比,下图是显示器需要显示的图片,上图中部分左侧的像素显示在了显示器的右边。

在这里插入图片描述

图4 显示器需要显示的图片

2、分析

  由于上位机是将一张图片的像素数据依次传输给开发板的,每行像素并没有其实标志,只能通过像素的个数来判断像素位于哪一行。上位机是别人开发一直在用的,应该不会出问题,那么应该就只会存在一种问题,会导致这种结果。

  在FPGA接收上位机的数据后,像素显示在显示器上之前,应该是丢失了部分像素,导致剩下第一行的像素数据不足以在显示器第一行显示,就取了第二行部分数据显示在第一行的后侧,然后第二行取了第三行的部分像素,最终导致最左侧的画面显示在了显示器最右侧。

  现在问题在于,确定那段程序出现问题,导致数据丢失。首先可以使用Wireshark软件抓取上位机传输的图像数据,然后通过ILA抓取开发板接收的上位机图像数据,对比数据是否一致。

  之后进一步使用ILA抓取从写FIFO存入DDR3的MIG IP的数据是否正确,以及MIG IP输出的读取DDR3的数据是否正确,如果前面均没有问题,那么就需要抓取读FIFO输出的数据是否与以太网接收的数据一致,进而排查每个阶段的数据正确性,从而定位到问题的具体位置。

3、实际调试

  首先将工程中的ila0和ila1注释打开,抓取以太网接收并且存入DDR3读写控制模块的写FIFO的相关信号,ila1抓取读、写MIG IP的相关信号,进而确认以太网接收和写DDR3、读DDR3过程中是否出现问题,之所以不将ila2注释打开是因为资源不够。

  然后打开wireshark软件,运行ila,网口调试助手发送数据,之后抓取开头数据进行分析即可。Wireshark为了方便查看发给开发板的数据报文,建议使用ip.addr == 192.168.1.10对报文进行筛选,结果如下:

在这里插入图片描述

图5 wireshark抓取报文

  由于采用巨型帧传输的UDP报文,长度为8192字节,每个报文是显示器4行的图像数据。开头数据为128’h4438_4438_3c38_33f6_2bb6_2bd6_33f7_33f6。

在这里插入图片描述

图6 Wireshark抓取数据

  然后查看第一帧最后的128位数据为128’h0294_0294_0294_0294_0294_0294_0274_0273,前文分析过,这个问题是因为后面的行最后几个数据用来下一行前几个数据导致的,如果程序出现问题,那么第四行的最后几个数据肯定不是上述这128位像素数据。

在这里插入图片描述

图7 Wireshark抓取数据

  下图是ILA0抓取的第一帧数据的开始部分,紫色信号是开发板以太网接收模块输出的数据,与图5的开始部分一致,没有问题。橙色信号是将以太网的8位数据拼接为16位数据存入DDR3的写FIFO中,依次存入的数据为16’h4438、16’h 4438、16’h 3c38、16’h 33f6、16’h 2bb6、16’h 2bd6、16’h 33f7、16’h 33f6,也没有问题。

在这里插入图片描述

图8 以太网接收模块第一帧开始数据

  下图是抓取的第一帧数据结束位置的时序,与图6发出的数据依旧一致,结尾最后128位数据依次是16’h 0294、16’h 0294、16’h 0294、16’h 0294、16’h 0294、16’h 029、16’h 0274、16’h 0273。证明以太网接收到存入DDR3写FIFO中的数据是没有问题的。

在这里插入图片描述

图9 以太网接收模块第一帧结束数据

  然后需要确认写入DDR3中和读出DDR3的数据是否有问题,首先ILA1抓取写入DDR3第一行图像数据的开始时序如下图所示,写入第一行的开始数据与图5最开始发送的128位数据一致,证明开始写入数据的位置没有问题。

在这里插入图片描述

图10 抓取写入DDR3的第一行开始数据

  由于wireshark发送一个报文,显示器需要显示4行,因此这里需要使用ILA抓取第4行的结尾128位数据与wireshark发送第一个报文的最后128位数据进行比较。

  下图蓝色方框的数据就是黄色光标处的数据,与图6最后发送的128位数据保持一致,存入地址为4088的DDR3中。由此证明写入到DDR3的数据也是没有问题的。

在这里插入图片描述

图11 抓取写入DDR3的第四行结束数据

  想要抓取从DDR3读出的数据,需要等待以太网发送完一帧数据,才会从DDR3中读出数据进行显示。之后需要利用一下读FIFO复位指示信号,抓取复位之后的一段数据,就可以抓取从DDR3中读出的第一行数据。

  如下图所示,当一帧图像开始显示时,会先复位读FIFO,读FIFO复位完成之后,从DDR3起始地址读出数据存入读FIFO中。DDR3读数据会滞后读指令一段时间,如下图蓝色方框所示,显示从DDR3地址0读出的数据,与图5上位机起始发送的128位数据一致。

在这里插入图片描述

图12 抓取读出DDR3的第一行开始数据

  由于DDR3输出数据会滞后读指令一段时间,就导致状态机在发送完读指令后,回到空闲状态,由于DDR3中一行数据还未全部数据,读FIFO中的数据小于一行数据个数,此时状态机会继续跳转到读状态,在从DDR3中读取一行数据,抓取的时序图会显示FIFO复位之后,会连续读取2行数据到FIFO中。

在这里插入图片描述

图13 读FIFO复位后连续两次读

  这个逻辑起始没法避免,这是因为DDR3本身硬件决定的,避免的方法可能有两种,一种把读FIFO中存储数据的阈值减小,另一种就是对读出的数据个数进行计数,直到读数据与读指令个数一致时,才判断读FIFO数据个数是否达到指定数据。但是这两种逻辑就会使程序复杂,另一种方式就是增加FIFO容量,使FIFO能够存下两行数据,这是为什么最开始将FIFO深度设置为2048的原因。

在这里插入图片描述

图14 状态机跳转

  然后通过调节HDMI刷新第2行数据时,查看DDR3输出的第四行结尾数据与上位机图6发送的结尾数据是否一致,如果一致,则说明读DDR3的时序也是没有问题的。

  下图蓝色方框的数据就是红色方框DDR3地址读出的数据,与图6结尾发送的128位数据一致,由此证明从以太网接收数据,然后将数据存入DDR3,最后读出DDR3数据的整个过程都是没有问题的。

在这里插入图片描述

图15 抓取读出DDR3的第四行结束数据

  之后将ila0和ila1注释掉,打开ila2的注释,抓取读FIFO读侧相关信号,查看读出的数据是否一致。

  首先第一行数据显示时的从FIFO读取数据的时序,如下图所示,开始读出的128位数据与图5上位机发送的128位数据还是一致的,证明刷新的起始位置并没有问题。

在这里插入图片描述

图16 刷新第零行从读FIFO读出8字节数据

  然后抓取第3行刷新时结尾的128位数据,如下图所示,明显红色方框的数据才是图6中上位机第一帧结尾的数据,而紫红色的8字节数据更像是一行数据的起始数据。

在这里插入图片描述

图17 刷新第三行从读FIFO读出8字节数据

  由此证明是读FIFO有问题,写入读FIFO的4行数据没有问题,但是读出的四行数据时,最后一行数据缺少了8字节数据,可能是FIFO溢出导致的。

  一行数据包含1024个像素点,而读FIFO深度设为2048,即使FIFO复位后会马上存入两行数据到读FIFO中,也不会导致FIFO溢出吧。

  然后回到图14,最开始读FIFO应该存入两行数据,但是图16开始时,读FIFO中却只有2038个数据,并不是2046个数据,因此确定是FIFO溢出了。

在这里插入图片描述

图18 开始读FIFO数据时FIFO中的数据

  在回到FIFO配置界面,发现将深度设置为2048时,该FIFO只能存储2040个数据,会丢失8个数据,这就与图15抓到缺少8字节数据的结果对上了。

在这里插入图片描述

图19 FIFO实际深度

  之后将FIFO深度改为4096,然后将FIFO深度相关信号位宽进行修改,顶层位宽修改为9位,之后重新综合就解决问题了。再次传输图像数据进行显示的结果如下,问题得到解决。

在这里插入图片描述

图20 显示图片

4、总结

  结果就是因为FIFO深度设置问题,没有关注FIFO实际深度,最后导致这种问题的出现。但是整个调试思路没有任何问题,适用于所有的工程。

  遇到问题之后,首先应该仔细分析出现这种现象可能出现的原因,然后去通过上位机辅助软件和ILA等在线调试工具去抓取开发板的关键信号,从而排除或者确定猜想,最后定位到问题根本原因,解决并总结问题,避免下次设计时在出现类似问题就行了。

  最后需要本次工程文件在公众号后台回复“FIFO深度问题”(不包括引号),即可获取该工程文件,便于复现。


  如果对文章内容理解有疑惑或者对代码不理解,可以在评论区或者后台留言,看到后均会回复!

  如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!您的支持是我更新的最大动力!将持续更新工程!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/463601.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

0G联合创始人MICHAEL HEINRICH确认出席Hack.Summit() 2024区块链开发者大会

随着区块链技术的不断发展和应用,全球开发者瞩目的Hack.Summit() 2024区块链开发者大会即将于2024年4月9日至10日在香港数码港盛大举行。此次大会由Hack VC主办,并得到AltLayer和Berachain的协办,同时汇聚了Solana、The Graph、Blockchain Ac…

Vue | 使用 ECharts 绘制折线图

目录 一、安装和引入 ECharts 二、使用 ECharts 2.1 新增 div 盒子 2.2 编写画图函数 2.3 完整代码结构 三、各种小问题 3.1 函数调用问题 3.2 数据格式问题 3.3 坐标轴标签问题 3.4 间隔显示标签 参考博客:Vue —— ECharts实现折线图 本文是在上…

jvm 内存泄露、内存溢出、栈溢出区别

JVM(Java虚拟机)是负责执行Java程序的运行环境。以下是对内存泄露、内存溢出和栈溢出这几个概念的解释: 内存泄露(Memory Leak): 内存泄露指的是程序中分配的内存空间在不再被使用时没有被释放的情况。这可…

【DFS深度优先搜索专题】【蓝桥杯备考训练】:迷宫、奶牛选美、树的重心、大臣的旅费、扫雷【已更新完成】

目录 1、迷宫(《信息学奥赛一本通》) 2、奶牛选美(USACO 2011 November Contest Bronze Division) 3、树的重心(模板) 4、大臣的旅费(第四届蓝桥杯省赛Java & C A组) 5、扫…

git的下载与安装

下载 首先,打开您的浏览器,并输入Git的官方网站地址 点击图标进行下载 下载页面会列出不同操作系统和平台的Git安装包。根据您的操作系统(Windows、macOS、Linux等)和位数(32位或64位),选择适…

面试经典-33-反转链表 II

题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a…

【渗透测试】redis漏洞利用

redis安装及配置 wget http://download.redis.io/releases/redis-3.2.0.tar.gz tar xzf redis-3.2.0.tar.gz cd redis-3.2.0 make cp /root/redis-6.2.6/redis.conf /usr/local/redis/bin/ cd /usr/local/redis/bin/ vi redis.conf #修改内容如下&#xff1a; #protected-mode …

【消息队列开发】 实现MemoryDataCenter类——管理内存数据

文章目录 &#x1f343;前言&#x1f334;数据格式的准备&#x1f332;内存操作&#x1f6a9;对于交换机&#x1f6a9;对于队列&#x1f6a9;对于绑定&#x1f6a9;对于单个消息&#x1f6a9;对于队列与消息链表&#x1f6a9;对于未确认消息&#x1f6a9;从硬盘上读取数据 ⭕总…

【数据结构】栈与队列的“双向奔赴”

目录 前言 1.使用“栈”检查符号是否成对出现 2.使用“栈”实现字符串反转 3.使用“队列”实现“栈” 4.使用“栈”实现“队列” 前言 什么是栈&#xff1f; 栈&#xff08;stack&#xff09;是一种特殊的线性数据集合&#xff0c;只允许在栈顶按照后进先出LIFO&#xff…

搭建个人智能家居 3 -第一个设备“点灯”

搭建个人智能家居 3 -第一个外设“点灯” 前言ESPHome点灯 HomeAssistant 前言 前面我们已经完成了搭建这个智能家居所需要的环境HomeAssistant和ESPHome&#xff0c;今天我们开始在这个智能家居中添加我们的第一个设备&#xff08;一颗LED灯&#xff09;&#xff0c;如果环境…

DIY小车神器 - 智能轮式驱动单元

为了便于做智能小车的朋友快速方便的构建自己的小车&#xff0c;我很早前设计过一个轮式驱动单元&#xff0c;将电机、驱动电路、轮子集成在一起&#xff0c;只需使用TTL电平的IO口即可驱动&#xff0c;即常见的核心板或开发板可以直接驱动&#xff0c;无需外加电路。&#xff…

Ubuntu Argoverse API安装

1. 创建并进入conda环境 conda create -n Argoverse python3.8 conda activate Argoverse2. 拉取argoverse-api源码 git clone https://github.com/argoai/argoverse-api.git3. 下载高精地图 Download hd_maps.tar.gz from Argoverse 4. 安装api cd argoverse-api pip in…

探索设计模式的魅力:探索发布-订阅模式的深度奥秘-实现高效、解耦的系统通信

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;并坚持默默的做事。 探索发布-订阅模式的深度奥秘&#xff1a;实现高效、解耦的系统通信 文章目录 一、案例场景&am…

如何在Ubuntu中查看编辑lvgl的demo和examples?

如何在Ubuntu中查看编辑lvgl的demo和examples&#xff1f; 如何在 Ubuntu系统中运行查看lvgl 1、拉取代码 在lvgl的github主页面有50多个仓库&#xff0c;找到lv_port_pc_eclipse这个仓库&#xff0c;点进去 拉取仓库代码和子仓库代码 仓库网址&#xff1a;https://github…

如何让intellij idea支持一个目录多个springtboot或maven项目

一、背景 有的时候&#xff0c;我们希望intellij idea 能像 eclipse 一样有workspace的概念&#xff0c;能在一个workspace目录里面引入多个项目&#xff0c;如&#xff1a; 我们有项目a、项目b&#xff0c;现在的项目几乎都是springboot项目&#xff08;即maven项目&#xf…

【机器学习300问】35、什么是随机森林?

〇、让我们准备一些训练数据 idx0x1x2x3x4y04.34.94.14.75.5013.96.15.95.55.9022.74.84.15.05.6036.64.44.53.95.9146.52.94.74.66.1152.76.74.25.34.81 表格中的x0到x4一共有5个特征&#xff0c;y是目标值只有0,1两个值说明是一个二分类问题。 关于决策树相关的前置知识&am…

Android分区存储到底是怎么回事

文章目录 一、Android存储结构二、什么是分区存储&#xff1f;三、私有目录和公有目录三、存储权限和分区存储有什么关系&#xff1f;四、我们应该该怎么做适配&#xff1f;4.1、利用File进行操作4.2、使用MediaStore操作数据库 一、Android存储结构 Android存储分为内部存储和…

STM32系列——F103C8T6 控制SG90舵机(HAL库)

文章目录 一、舵机控制原理二、.CubeMX配置配置RCC、SYS、时钟树配置RCC配置SYS配置时钟树配置定时器产生PWM波形 Keil5代码接线图及效果如果您发现文章有错误请与我留言&#xff0c;感谢 一、舵机控制原理 舵机的控制一般需要一个20ms左右的时基脉冲&#xff0c;该脉冲的高电平…

前端框架的发展史介绍框架特点

目录 1.前端框架的发展历程 2.官网、优缺点、使用场景 2.1 jQuery 2.2 AngularJS 2.3 React 2.4 Vue.js 2.5 Angular 1.前端框架的发展历程 jQuery&#xff08;2006年&#xff09;&#xff1a;jQuery是一个非常流行的JavaScript库&#xff0c;用于简化DOM操作和事件处理…

HTML5:七天学会基础动画网页13

看完前面很多人可能还不是很明白0%-100%那到底是怎么回事&#xff0c;到底该怎么用&#xff0c;这里我们做一个普遍的练习——心跳动画 想让心❤跳起来&#xff0c;我们先分析一波&#xff0c;这个心怎么写&#xff0c;我们先写一个正方形&#xff0c;再令一个圆形前移: 再来一…