基于FPGA的以太网传输图片通过HDMI显示(含源码)

  基于FPGA的HDMI设计导航页面,点击跳转。

  基于FPGA的以太网相关文章导航,点击查看。

  在此之前,已经讲解过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地址,直接使用上位机传输数据即可。

  下图是以太网接收和发送模块的内部示意图,想了解具体实现方式可以参考前文。

图1 以太网传输模块

  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视图如下所示。

图2 DDR3控制模块RTL视图

3、HDMI模块

  前文虽然使用过HDMI模块,但是没有对该模块进行封装,把HDMI相关功能的模块封装成一部分,另外引入DDR3复位完成信号,整个模块只有在DDR3复位完成之后,才能进行工作,否则没有意义。

  由于DDR3控制模块的读FIFO的读数据与读使能信号对齐,所以需要修改一下HDMI的数据请求信号产生的时机。

  并且把场同步信号引出,作为DDR3控制模块的读复位信号,在读取下一帧数据之前,将读FIFO中的数据清空后,从DDR3的起始地址开始读取数据进行显示,保证上次刷新出现的错误,不会影响下一次读出数据的显示。

  下图是HDMI模块封装完成后的RTL视图,想要了解具体实现方式以及TMDS编码原理及实现,可以参考前文。

图3 HDMI模块RTL视图

  因为开发板上HDMI的19号热插拔检测引脚默认下拉到低电平,即HDMI接口默认作为输出,因此在设计代码是没有添加HDMI输出使能信号,对应原理图如下所示。

图4 HDMI接口原理图

4、锁相环模块

  开发板外部晶振提供100MHz的时钟输入信号,DDR3控制模块需要输入1路频率为200MHz的时钟作为MIG IP的参考时钟和系统时钟。而分辨率为1024*768,如果想要刷新率达到60Hz,则需要给HDMI模块提供65MHz的时钟,并且OSERDES需要一路5倍频的时钟信号,即325MHz。

  因此需要通过锁相环将输入100MHz时钟,输出200MHz、65MHz、325MHz三路时钟信号。

  将外部复位直接连接到锁相环的复位信号,而锁相环输出的locked信号直接作为其余模块的复位信号,锁相环的RTL视图如下所示,注意锁相环的复位信号设置为低电平有效。

图5 锁相环模块

5、顶层模块

  顶层模块就是将上述模块相应接口信号解析连接,不使用的输入接口全部置为无效电平,输出端口悬空。

  本文不使用UDP发送功能,所以以太网关于UDP发送功能相关的输入信号均接低电平,不需要开发板主动发出ARP请求,因此把开发给用户的ARP请求信号拉低。由于需要ARP应答,所以以太网发送部分的模块并不能缺损,只能将不使用的信号置为无效。

  将DDR3的初始化完成信号作为DDR3的写复位信号,在DDR3复位完成之后对写FIFO进行复位,确保进行写操作之前FIFO为空。

  其余模块对应连接即可,DDR3读侧只用到了读数据和读使能及读复位,其余信号悬空即可。

  顶层的RTL视图如下所示,由于包含模块较多,连线也比较多,导致整张图比较大,截图后可能看不清,可以打开工程后放大查看。

图6 顶层模块RTL视图

6、上板测试

  由于本工程多数模块在前面的讲解过程中已经仿真和实现过,本文就不再对这些模块进行仿真,主要是上板测试,然后看实际效果。

图7 硬件平台

  注意HDMI相关引脚直接分配为LVDS电平类型,如下图所示。

图8 分配管脚

  综合工程,然后下载到开发板,连接网线,可以在CMD下输入arp -a和ping等指令,检测以太网链路是否畅通,相关检测方式在“基于FPGA的ICMP实现”中已经讲解过,有需要的可以查看,不再赘述。

  测试结果如下所示,icmp请求全部应答,且开发板的MAC地址和IP地址也已经在PC端绑定,证明以太网的数据链路没有问题。

图9 数据链路测试

  由于需要通过UDP传输大量数据,为了加快传输速率,设置巨型帧,UDP每包就可以发送8192字节数据,能够大大加快传输速率。

  如下图所示,鼠标右键点击开始菜单,然后打开设备管理器,找到网络适配器,之后双击Realtek Gaming 2.5GbE Family Controller。

图10 设置步骤

  之后在高级选项卡下面找到巨型帧(Jumbo Frame),设置为9014 Bytes即可。如果找不到巨型帧,那应该是电脑的网络适配器驱动没有更新,进行更新即可。

图11 巨型帧设置

  然后就是准备需要发送图片的数据了,首先去网上找一张1024*768分辨率的图片(找不到这个分辨率图片也没关系),然后将图片用电脑自带的画图工具打开,如下图所示操作,将图片分辨率设置为1024*768分辨率即可。

图12 图片分辨率调节

  然后把图片另存为BMP格式的图片,如下图所示。

图13 存储图片

  注意本次我们需要这样处理两张分辨率相同,但内容不同的图片,作为后面的参考使用。

  然后双击打开lmg2Lcd软件,如下图所示。

图14 打开lmg2Lcd

  软件参数设置如下,输出二进制的bin文件,水平扫描的16位数据,输出图片的像素为1024*768,高位在前,与前文的UDP输出数据处理保持一致。

图15 图片设置

  然后将图片保存,将两张不同的图片生成两个bin文件,如下所示,图片R-C生成了A.bin文件,图片R-D生成B.bin文件。

图16 生成两个不同文件

  然后将网络调试助手打开,设置协议为UDP,本地主机地址为192.168.1.102(注意要设置电脑的IP,具体方法查看前文ARP的验证文章),UDP端口号为5678。之后打开网络调试助手,查看连接的远程主机IP和UDP端口号是否为开发板的IP和UDP端口号,不同则需要手动修改。

图17 设置网络调试助手

  在发送数据之前,先把wireshark软件打开,方便查看电脑发送的数据报文,如下所示。

  如下图所示,使用网络调试助手打开文件,选择A.bin文件,然后点击发送。

图18 发送文件数据

  在wireshark中输入ip.addr == 192.168.1.10则可以只查看发给这个IP地址相关的数据报文,可以过滤掉其余报文。如下图所示,电脑一直在给FPGA传输数据,每个报文的数据长度均为8192字节数据。

图19 过滤无关IP地址报文

  但是你会发现电脑虽然在发送数据,但是显示器却没有显示数据。这是正常现象,因为我们规定在DDR3起止地址之间的空间没有被写满一次数据时,不会读取DDR3中的数据进行显示,因为电脑还在发数据,所以一张图片还没发完,也证明DDR3规定的地址还没写满数据,显示器自然不会显示图片。

  至于千兆网为啥这么慢,感觉可能跟这个网络调试助手传输数据的速度有关,就像某些网盘一样,即使你网络速度可以达到很高,但是不给你有效数据,你下载文件的速度依旧很慢。

  最后显示器显示的图片如下所示,其实时很清晰的,由于晚上屏幕反光,用手机拍出来感觉就模糊了。

图20 显示器显示图片

  然后可以使用网络调试助手以同样的方式传输图片B.bin的文件,结果你就会看到如下现象。整段视频比较长,中间有部分就删除了,这种情况就是因为读、写操作位于DDR3的同一段地址,而写入数据的速度比较慢,导致输出的画面上半部分(DDR3低地址部分)已经刷新,画面下半部分(DDR3高地址存储数据)还没刷新。

图21 刷新效果

  解决方法其实很简单,就是采用乒乓操作,将读、写操作的地址段分开,始终读取完整画面的数据进行显示,将DDR3读写控制模块的乒乓使能信号拉高,重新综合工程,然后下载到开发板,之后再次使用网络调试助手传输两张图片。刷新效果如下所示,这就是为什么图像显示喜欢用乒乓操作的原因吧。

图22 乒乓操作刷新效果

  至此,以太网传输图片的工程验证到此结束了,本文将前面讲解的HDMI、UDP、DDR3工程全部结合起来了,如果从头开始写还是需要一段时间的,下篇文章将对本次调试出现的一个bug进行讲解,这个工程本来很快就完成了,结果因为一个bug多耽误了一天,但是也解决了一些问题,不是很亏。

  需要本工程在后台回复“以太网传输图片”(不包括引号)即可。

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

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

版权声明:本文为博主作者:电路_fpga原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/weixin_50810761/article/details/136401921

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2024年4月10日
下一篇 2024年4月10日

相关推荐