在此之前,已经讲解过HDMI、UDP、DDR3等模块的使用,前文在使用HDMI显示图片时,由于没有讲解DDR3,使用FPGA内部的RAM存储图像数据,因为FPGA片上RAM的资源有限,导致最终显示放大的图片失真严重。
本文通过DDR3存储整张图片的数据,然后通过HDMI在显示器上进行显示,得到清晰的图片。
整体思路比较简单,首先UDP接收电脑从网口传输的数据,将接收的8位数据拼接成16位数据后输入DDR3控制模块的写FIFO中。当写入DDR3一帧图像数据后,从DDR3读出数据存入读FIFO中,HDMI刷新模块从读FIFO中读取16位数据,之后将16位转变成24位像素数据。然后传输给HDMI编码模块进行编码,之后将数据传输给显示器进行显示。
显示器的分辨率为1024*768,因此DDR3的起始地址为0,最大地址设置为1024*768=786432,每次读写一行图像数据,突发长度设置为1024,对应MIG IP读写数据的突发长度为128。
1、udp输出数据处理模块
前文讲解过UDP模块的设计,本工程直接使用即可,由于UDP模块中实现了ARP和ICMP协议,所以电脑不需要手动绑定开发板的MAC地址和IP地址,直接使用上位机传输数据即可。
下图是以太网接收和发送模块的内部示意图,想了解具体实现方式可以参考前文。
UDP接收的是8位数据,而DDR3读写数据为16位,需要把8位数据拼接为16位数据。由于软件生成像素数据时,先生成的高8位数据,所以接收时也是先接收的高8位数据。
因此该模块的参考代码如下所示:
module udp_data(
input clk ,//时钟信号;
input rst_n ,//复位信号,低电平有效;
input [7 : 0] din ,//输入数据;
input din_vld ,//输入数据有效指示信号;
output reg [15 : 0] dout ,//输出16为并行数据;
output reg dout_vld //输出数据有效指示信号,高电平有效;
);
reg din_vld_r ;//
//生成像素有效指示信号,以太网每次穿8位数据,传输两次合成一个像素数据;
always@(posedge clk)begin
if(rst_n==1'b0)begin//初始值为0;
din_vld_r <= 1'b0;
end
else if(din_vld)begin
din_vld_r <= ~din_vld_r;
end
end
//将输入的8位数据合成16位数据,先接收高8位数据;
always@(posedge clk)begin
if(rst_n==1'b0)begin//初始值为0;
dout <= 16'd0;
end
else if(din_vld)begin
if(din_vld_r)
dout[7 : 0] <= din;
else//先接收高8位数据;
dout[15 : 8] <= din;
end
end
//当输入数据有效且是低八位数据时,表示接收到完整十六位数据了,拉高输出有效指示信号;
always@(posedge clk)begin
if(rst_n==1'b0)begin//初始值为0;
dout_vld <= 1'b0;
end
else begin
dout_vld <= din_vld & din_vld_r;
end
end
endmodule
2、DDR3读写模块
DDR3的读写控制模块前文已经封装完成,本次使用只需要将读写FIFO的深度修改即可,将读、写FIFO的深度设置为4096,为什么是4096不是2048后文会有讲解,其余代码保持不变。
DDR3读写控制模块的RTL视图如下所示。
3、HDMI模块
前文虽然使用过HDMI模块,但是没有对该模块进行封装,把HDMI相关功能的模块封装成一部分,另外引入DDR3复位完成信号,整个模块只有在DDR3复位完成之后,才能进行工作,否则没有意义。
由于DDR3控制模块的读FIFO的读数据与读使能信号对齐,所以需要修改一下HDMI的数据请求信号产生的时机。
并且把场同步信号引出,作为DDR3控制模块的读复位信号,在读取下一帧数据之前,将读FIFO中的数据清空后,从DDR3的起始地址开始读取数据进行显示,保证上次刷新出现的错误,不会影响下一次读出数据的显示。
下图是HDMI模块封装完成后的RTL视图,想要了解具体实现方式以及TMDS编码原理及实现,可以参考前文。
因为开发板上HDMI的19号热插拔检测引脚默认下拉到低电平,即HDMI接口默认作为输出,因此在设计代码是没有添加HDMI输出使能信号,对应原理图如下所示。
4、锁相环模块
开发板外部晶振提供100MHz的时钟输入信号,DDR3控制模块需要输入1路频率为200MHz的时钟作为MIG IP的参考时钟和系统时钟。而分辨率为1024*768,如果想要刷新率达到60Hz,则需要给HDMI模块提供65MHz的时钟,并且OSERDES需要一路5倍频的时钟信号,即325MHz。
因此需要通过锁相环将输入100MHz时钟,输出200MHz、65MHz、325MHz三路时钟信号。
将外部复位直接连接到锁相环的复位信号,而锁相环输出的locked信号直接作为其余模块的复位信号,锁相环的RTL视图如下所示,注意锁相环的复位信号设置为低电平有效。
5、顶层模块
顶层模块就是将上述模块相应接口信号解析连接,不使用的输入接口全部置为无效电平,输出端口悬空。
本文不使用UDP发送功能,所以以太网关于UDP发送功能相关的输入信号均接低电平,不需要开发板主动发出ARP请求,因此把开发给用户的ARP请求信号拉低。由于需要ARP应答,所以以太网发送部分的模块并不能缺损,只能将不使用的信号置为无效。
将DDR3的初始化完成信号作为DDR3的写复位信号,在DDR3复位完成之后对写FIFO进行复位,确保进行写操作之前FIFO为空。
其余模块对应连接即可,DDR3读侧只用到了读数据和读使能及读复位,其余信号悬空即可。
顶层的RTL视图如下所示,由于包含模块较多,连线也比较多,导致整张图比较大,截图后可能看不清,可以打开工程后放大查看。
6、上板测试
由于本工程多数模块在前面的讲解过程中已经仿真和实现过,本文就不再对这些模块进行仿真,主要是上板测试,然后看实际效果。
注意HDMI相关引脚直接分配为LVDS电平类型,如下图所示。
综合工程,然后下载到开发板,连接网线,可以在CMD下输入arp -a和ping等指令,检测以太网链路是否畅通,相关检测方式在“基于FPGA的ICMP实现”中已经讲解过,有需要的可以查看,不再赘述。
测试结果如下所示,icmp请求全部应答,且开发板的MAC地址和IP地址也已经在PC端绑定,证明以太网的数据链路没有问题。
由于需要通过UDP传输大量数据,为了加快传输速率,设置巨型帧,UDP每包就可以发送8192字节数据,能够大大加快传输速率。
如下图所示,鼠标右键点击开始菜单,然后打开设备管理器,找到网络适配器,之后双击Realtek Gaming 2.5GbE Family Controller。
之后在高级选项卡下面找到巨型帧(Jumbo Frame),设置为9014 Bytes即可。如果找不到巨型帧,那应该是电脑的网络适配器驱动没有更新,进行更新即可。
然后就是准备需要发送图片的数据了,首先去网上找一张1024*768分辨率的图片(找不到这个分辨率图片也没关系),然后将图片用电脑自带的画图工具打开,如下图所示操作,将图片分辨率设置为1024*768分辨率即可。
然后把图片另存为BMP格式的图片,如下图所示。
注意本次我们需要这样处理两张分辨率相同,但内容不同的图片,作为后面的参考使用。
然后双击打开lmg2Lcd软件,如下图所示。
软件参数设置如下,输出二进制的bin文件,水平扫描的16位数据,输出图片的像素为1024*768,高位在前,与前文的UDP输出数据处理保持一致。
然后将图片保存,将两张不同的图片生成两个bin文件,如下所示,图片R-C生成了A.bin文件,图片R-D生成B.bin文件。
然后将网络调试助手打开,设置协议为UDP,本地主机地址为192.168.1.102(注意要设置电脑的IP,具体方法查看前文ARP的验证文章),UDP端口号为5678。之后打开网络调试助手,查看连接的远程主机IP和UDP端口号是否为开发板的IP和UDP端口号,不同则需要手动修改。
在发送数据之前,先把wireshark软件打开,方便查看电脑发送的数据报文,如下所示。
如下图所示,使用网络调试助手打开文件,选择A.bin文件,然后点击发送。
在wireshark中输入ip.addr == 192.168.1.10则可以只查看发给这个IP地址相关的数据报文,可以过滤掉其余报文。如下图所示,电脑一直在给FPGA传输数据,每个报文的数据长度均为8192字节数据。
但是你会发现电脑虽然在发送数据,但是显示器却没有显示数据。这是正常现象,因为我们规定在DDR3起止地址之间的空间没有被写满一次数据时,不会读取DDR3中的数据进行显示,因为电脑还在发数据,所以一张图片还没发完,也证明DDR3规定的地址还没写满数据,显示器自然不会显示图片。
至于千兆网为啥这么慢,感觉可能跟这个网络调试助手传输数据的速度有关,就像某些网盘一样,即使你网络速度可以达到很高,但是不给你有效数据,你下载文件的速度依旧很慢。
最后显示器显示的图片如下所示,其实时很清晰的,由于晚上屏幕反光,用手机拍出来感觉就模糊了。
然后可以使用网络调试助手以同样的方式传输图片B.bin的文件,结果你就会看到如下现象。整段视频比较长,中间有部分就删除了,这种情况就是因为读、写操作位于DDR3的同一段地址,而写入数据的速度比较慢,导致输出的画面上半部分(DDR3低地址部分)已经刷新,画面下半部分(DDR3高地址存储数据)还没刷新。
图21 刷新效果
解决方法其实很简单,就是采用乒乓操作,将读、写操作的地址段分开,始终读取完整画面的数据进行显示,将DDR3读写控制模块的乒乓使能信号拉高,重新综合工程,然后下载到开发板,之后再次使用网络调试助手传输两张图片。刷新效果如下所示,这就是为什么图像显示喜欢用乒乓操作的原因吧。
图22 刷新效果
至此,以太网传输图片的工程验证到此结束了,本文将前面讲解的HDMI、UDP、DDR3工程全部结合起来了,如果从头开始写还是需要一段时间的,下篇文章将对本次调试出现的一个bug进行讲解,这个工程本来很快就完成了,结果因为一个bug多耽误了一天,但是也解决了一些问题,不是很亏。
需要本工程在后台回复“以太网传输图片”(不包括引号)即可。
如果对文章内容理解有疑惑或者对代码不理解,可以在评论区或者后台留言,看到后均会回复!文章来源:https://www.toymoban.com/news/detail-843849.html
如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!您的支持是我更新的最大动力!将持续更新工程!文章来源地址https://www.toymoban.com/news/detail-843849.html
到了这里,关于基于FPGA的以太网传输图片通过HDMI显示(含源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!