[米联客-安路飞龙DR1-FPSOC] UDP通信篇连载-03 IP_ARP层程序设计

news/2024/11/17 5:57:09/文章来源:https://www.cnblogs.com/milianke/p/18351341

软件版本:Anlogic -TD5.9.1-DR1_ES1.1

操作系统:WIN10 64bit

硬件平台:适用安路(Anlogic)FPGA

实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板

板卡获取平台:https://milianke.tmall.com/

登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

 

3.2 IP_ARP

由于IPARP数据包送至MAC层要经过同一个通道,需要对发送的数据包类型进行判断和仲裁,这就需要额外增加一个IP_ARP层。

3.2.1 IP_ARP接收模块

该模块接收到MAC帧经过MAC层解包得到的数据包,通过类型字段判断该包是IP包还是ARP包,将其送入对应的模块中处理。

/*******************************uiip_arp_rx模块*********************

--以下是米联客设计的uiip_arp_rx模块

1.该模块1用于区分接收数据是IP包还是ARP

*********************************************************************/

`timescale 1ns/1ps

module  uiip_arp_rx

(

    input   wire                I_ip_arp_reset,     //复位

    input   wire                I_ip_arp_rclk,      //RX 接收时钟

    output  wire                O_ip_rvalid,        //接收的有效IP信号

    output  wire    [7:0]       O_ip_rdata,         //接收的IP数据

    output  wire                O_arp_rvalid,       //接收的有效ARP信号

    output  wire    [7:0]       O_arp_rdata,        //接收的有效ARP数据

 

    input   wire                I_mac_rvalid,       //MAC接收到的数据有效信号

    input   wire    [7:0]       I_mac_rdata,        //MAC接收的有效数据

    input   wire    [15:0]      I_mac_rdata_type    //MAC接收到的帧类型

 

);

reg                 ip_rx_data_valid;   //接收的有效IP信号

reg     [7:0]       ip_rx_data;         //接收的IP数据

reg                 arp_rx_data_valid;  //接收的有效ARP信号

reg     [7:0]       arp_rx_data;        //接收的有效ARP数据

 

assign  O_ip_rvalid     =   ip_rx_data_valid;

assign  O_ip_rdata      =   ip_rx_data;

assign  O_arp_rvalid    =   arp_rx_data_valid;

assign  O_arp_rdata     =   arp_rx_data;

 

localparam  ARP_TYPE    =   16'h0806;   //ARP包类型

localparam  IP_TYPE     =   16'h0800;   //IP 包类型

always@(posedge I_ip_arp_rclk or posedge I_ip_arp_reset) begin

    if(I_ip_arp_reset) begin

        ip_rx_data_valid    <=  1'b0;

        ip_rx_data          <=  8'd0;

        arp_rx_data_valid   <=  1'b0;

        arp_rx_data         <=  8'd0;

    end

    elseif(I_mac_rvalid) begin

        if(I_mac_rdata_type == IP_TYPE) begin//IP

            ip_rx_data_valid    <=  1'b1;

            ip_rx_data          <=  I_mac_rdata;

        end

        elseif(I_mac_rdata_type == ARP_TYPE) begin//ARP

            arp_rx_data_valid   <=  1'b1;

            arp_rx_data         <=  I_mac_rdata;

        end

        elsebegin

            ip_rx_data_valid    <=  1'b0;

            ip_rx_data          <=  8'd0;

            arp_rx_data_valid   <=  1'b0;

            arp_rx_data         <=  8'd0;

        end

    end

    elsebegin

        ip_rx_data_valid    <=  1'b0;

        ip_rx_data          <=  8'd0;

        arp_rx_data_valid   <=  1'b0;

        arp_rx_data         <=  8'd0;

    end

end

 

endmodule

3.2.2 IP_ARP发送模块

该模块接收IP层和ARP层传来的发送请求,通过busy信号与上层协议模块进行握手,来发送对应的数据。该模块的状态机转换图如图所示。

IDLE:如果是IP层发送的请求,且arp_req_pend信号没有挂起时,进入CHECK_MAC_CACHEE状态,进入ARP层查询mac_cache中缓存的MAC地址。如果是ARP层发送的请求,在MAC层非忙时,将arp_tbusy拉高,表示可以发送ARP包,进入WAIT_ARP_PACKET状态。

CHECK_MAC_CACHE:若没有查询到IP地址对应的MAC地址,则使能O_arp_treq_en信号,请求ARP层发送ARP广播包,并且将arp_req_pend挂起(该信号挂起时不能发送IP包),回到IDLE状态,等待ARP层发送请求信号。若查询到MAC地址,进入WAIT_IP_PACKET状态,等待IP层将有效数据发送过来。

WAIT_IP_PACKET:若I_ip_valid拉高,说明IP包有效数据开始传入,接收传来的数据并将其发送至MAC层,进入SEND_IP_PACKET状态。

SEND_IP_PACKET:等待一帧IP包数据全部发送完成时,回到IDLE状态。

WAIT_ARP_PACKETI_arp_valid拉高,说明ARP包有效数据开始传入,接收传来的数据并将其发送至MAC层,进入SEND_ARP_PACKET状态。

SEND_ARP_PACKET:如果发送的数据包是ARP应答包,数据全部发送完成时,回到IDLE状态。如果发送的数据包是ARP请求包,则要进入SEND_ARP_REPLY状态,等待接收到对方发送ARP应答包。

SEND_ARP_REPLY:接收到ARP应答包后,将arp_req_pend信号拉低,回到IDLE状态。若超时未收到应答,则回到IDLE状态,此时由于arp_req_pend信号一直为高,该模块会持续发送ARP请求直至收到应答。

always@(posedge I_ip_arp_clk or posedge I_ip_arp_reset)begin

    if(I_ip_arp_reset) begin

        O_mac_cache_ren         <=  1'b0;   //查询MAC cache

        O_mac_cache_rip_addr    <=  32'd0;  //查询MAC cache地址

        O_arp_tbusy             <=  1'b0;   //ip_arp_tx arp 发送准备好  

        O_arp_treq_en           <=  1'b0;   //ip_arp_tx arp请求发送ARP包(当发送IP包,没有找打cache中的MAC的时候发送)

        O_arp_treq_ip_addr      <=  32'd0;  //ARP可以发送模块通过发送带有目的IP地址的ARP请求,获取目的远程主机的MAC地址

         

        O_ip_tbusy              <=  1'b0;   //ip_arp_tx可以发送IP

 

        O_mac_tdata_type        <=  2'd0;   //MAC发送数据类型

        O_mac_tvalid            <=  1'b0;   //MAC发送数据有效

        O_mac_tdata             <=  8'd0;   //MAC发送数据

        O_mac_tdest_addr        <=  48'd0;  //MAC发送地址

 

        tmac_addr_temp          <=  48'd0;

        arp_req_pend            <=  1'b0;

        dst_ip_unreachable      <=  1'b0;

        arp_wait_time           <=  30'd0;

        STATE                   <=  IDLE;

    end

    elsebegin

        case(STATE)

            IDLE:begin

                O_arp_treq_en   <=  1'b0;

                if(!I_mac_tbusy) begin//MAC层不忙

                    if(I_arp_treq) begin//是否有ARP请求

                        O_arp_tbusy             <=  1'b1;           //可以发ARP

                        O_ip_tbusy              <=  1'b0;

                        STATE                   <=  WAIT_ARP_PACKET;//等待ARP响应

                    end

                    elseif(I_ip_treq && ~arp_req_pend) begin   //如果是IP请求,并且之前的ARP请求没有pend

                        O_arp_tbusy             <=  1'b0;

                        O_ip_tbusy              <=  1'b0;

                        O_mac_cache_ren         <=  1'b1;               //如果是IP请求,先从mac cache通过IP地址获取MAC地址

                        O_mac_cache_rip_addr    <=  I_ip_tdest_addr;    //通过IP地址查询MAC cache

                        STATE                   <=  CHECK_MAC_CACHE;    

                    end

                    elsebegin

                        O_arp_tbusy             <= 1'b0;

                        O_ip_tbusy              <= 1'b0;                        

                        STATE                   <= IDLE;                        

                    end

                end

                elsebegin

                    O_arp_tbusy             <= 1'b0;

                    O_ip_tbusy              <= 1'b0;

                    O_mac_cache_ren         <= 1'b0;

                    O_mac_cache_rip_addr    <= 48'd0;

                    STATE                   <= IDLE;

                end

            end

            CHECK_MAC_CACHE:begin//查询MAC cache,果没有查到MAC会请求ARP层发送ARP请求

                O_mac_cache_ren         <=  1'b0;

                if(I_mac_cache_rdone) begin                     //MAC cache查询完成

                    if(I_mac_cache_rdest_addr == 48'd0) begin   //如果没有查询到对应的MAC,请求ARP层发送ARP请求

                        O_arp_treq_en           <=  1'b1;       //请求ARP层发送ARP

                        O_ip_tbusy              <=  1'b0;

                        O_arp_treq_ip_addr      <=  O_mac_cache_rip_addr;   //如果没有查询到MAC需要根据提供的IP地址请求ARP层发送ARP包获取MAC

                        arp_req_pend            <=  1'b1;                   //arp请求Pend结束前不处理其他的arp请求

                        STATE                   <=  IDLE;                   //回到IDLE状态,等待ARP层发送ARP包

                    end

                    elsebegin

                        tmac_addr_temp          <=  I_mac_cache_rdest_addr; //从MAC cache查询到MAC地址

                        O_ip_tbusy              <=  1'b1;                   //返回IP层的ACK

                        O_arp_treq_en           <=  1'b0;

                        arp_req_pend            <=  1'b0;

                        STATE                   <=  WAIT_IP_PACKET;

                    end

                end

                    else

                        STATE                   <=  CHECK_MAC_CACHE;

            end

            WAIT_ARP_REPLY:begin//等待远程主机的ARP响应(ARP层的recieve模块会接收到ARP响应)

                if(I_arp_treply_done) begin//响应

                    arp_req_pend            <=  1'b0;

                    arp_wait_time           <=  30'd0;

                    dst_ip_unreachable      <=  1'b0;

                    STATE                   <=  IDLE;

                end

                elsebegin

                    if(arp_wait_time == ARP_TIMEOUT_VALUE) begin//超时,未收到响应

                        arp_req_pend            <=  1'b1;

                        O_arp_tbusy             <=  1'b0;

                        O_arp_treq_en           <=  1'b1;

                        O_arp_treq_ip_addr      <=  I_ip_tdest_addr;

                        dst_ip_unreachable      <=  1'b1;

                        arp_wait_time           <=  30'd0;

                        STATE                   <=  IDLE;                      

                    end

                    elsebegin

                        arp_req_pend            <=  1'b1;

                        O_arp_tbusy             <=  1'b1;

                        dst_ip_unreachable      <=  1'b0;

                        arp_wait_time           <=  arp_wait_time + 1'b1;

                        STATE                   <=  WAIT_ARP_REPLY;

                    end

                end

            end

            WAIT_ARP_PACKET:begin//ARP包有效,打拍后直接输出给MAC层  

                if(I_arp_tvalid) begin

                    O_mac_tdata_type        <=  {1'b1,I_arp_tdata_type};//2'b10:arp reply; 2'b11:arp request ;2'b01 ip

                    O_mac_tvalid            <=  1'b1;

                    O_mac_tdata             <=  I_arp_tdata;

                    O_mac_tdest_addr        <=  I_arp_tdest_mac_addr;

                    STATE                   <=  SEND_ARP_PACKET;

                end

                elsebegin

                    O_mac_tdata_type        <=  2'd0;

                    O_mac_tvalid            <=  1'b0;

                    O_mac_tdata             <=  8'd0;

                    O_mac_tdest_addr        <=  48'd0;

                    STATE                   <=  WAIT_ARP_PACKET;                    

                end

            end

            SEND_ARP_PACKET:begin       //继续打拍后输出给MAC层

                if(I_arp_tvalid) begin  //如果ARP包有效

                    O_mac_tvalid            <=  1'b1;

                    O_mac_tdata             <=  I_arp_tdata;

                    STATE                   <=  SEND_ARP_PACKET;                    

                end

                elsebegin

                    O_arp_tbusy             <=  1'b0;

                    O_mac_tdata_type        <=  2'd0;

                    O_mac_tvalid            <=  1'b0;

                    O_mac_tdata             <=  8'd0;

                    O_mac_tdest_addr        <=  48'd0;

                    if(arp_req_pend)    //如果该信号有效,代表IP层发送IP包的时候没有从本地cache查询到MAC地址,而发送的ARP请求包,因此下一步等待远程主机发送ARP响应

                        STATE               <=  WAIT_ARP_REPLY;

                    else

                        STATE               <=  IDLE;   //如果是单纯的ARP层发送的包,到此结束          

                end

            end

            WAIT_IP_PACKET:begin    //IP包的传输    

                if(I_ip_tvalid) begin

                    O_mac_tdata_type        <=  2'b01;

                    O_mac_tvalid            <=  1'b1;

                    O_mac_tdata             <=  I_ip_tdata;

                    O_mac_tdest_addr        <=  tmac_addr_temp;

                    STATE                   <=  SEND_IP_PACKET;

                end

                elsebegin          

                    O_mac_tdata_type        <=  2'd0;

                    O_mac_tvalid            <=  1'b0;

                    O_mac_tdata             <=  8'd0;

                    O_mac_tdest_addr        <=  48'd0;

                    STATE                   <=  WAIT_IP_PACKET;

                end

            end

            SEND_IP_PACKET:begin    //IP包的传输

                if(I_ip_tvalid) begin

                    O_mac_tvalid            <=  1'b1;

                    O_mac_tdata             <=  I_ip_tdata;

                    STATE                   <=  SEND_IP_PACKET;

                end

                elsebegin

                    O_ip_tbusy              <= 1'b0;

                    O_mac_tdata_type        <= 2'd0;

                    O_mac_tvalid            <= 1'b0;

                    O_mac_tdata             <= 8'd0;

                    O_mac_tdest_addr        <= 48'd0;

                    STATE                   <= IDLE;                    

                end

            end

        endcase

    end

end

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉树的非递归后序遍历如何实现?

背景 面试时考了这道题,之前一直都会递归遍历,非递归遍历倒是从来没有实际理解过它的具体过程,包括使用什么数据结构,具体的过程是怎样的?满脑子都是二叉树的层序遍历, 但是这里后序遍历和层序遍历还不太一样。 在仔细梳理并讲出自己的思路的时候,还是觉得并非易事。那就…

[米联客-安路飞龙DR1-FPSOC] UDP通信篇连载-01 以太网协议介绍

软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台:https://milianke.tmall.com/ 登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑! ​1 概述…

manim边学边做--点

几何图形是manim中最重要的一类模块,manim内置了丰富的各类几何图形,本篇从最简单的点开始,逐个介绍manim中的几何模块。 manim中点相关的模块主要有3个:Dot:通用的点 LabeledDot:在点的中间可以加一些说明文字 AnnotationDot:使用在注释场景中的点Dot系列在manim各个模…

给定一个10GB大小的文件,存储的都是数字,如何对文件中的数字进行排序,并输出新文件?限制内存只有1GB

背景 这是一道面试题,可考察的点也不少。总结几个关键词去解决这个问题,1,文件拆分;2、排序算法;3、缓冲buffer性能优化。 啊,乍一看,这绝对不是一个初级程序员能够答出来,且能答得很好的问题,这个题目可以考察到我们的算法能力,性能优化经验。可万万不能马虎对待!开…

从「数据资产入表」到「数据资产运营管理」,成功的关键在于找到合适的数资服务提供商

璞华科技在数据服务领域深耕细作,不断突破创新,近来荣膺多项重要认证与荣誉。 璞华易表数据资产运营管理平台正式获得国家计算机软件著作登记证书。这一殊荣不仅是对璞华科技研发团队技术实力的肯定,更是对璞华易表产品原创性和创新性的高度认可。它标志着璞华易表在软件开发…

基于米尔芯驰MY-YD9360商显板的神经网络推理库测试

本篇测评由优秀测评者“短笛君”提供。 本文将介绍基于米尔电子MYD-YD9360商显板(米尔基于芯驰D9360国产开发板)的TinyMaxi轻量级的神经网络推理库方案测试。 算力测试 TinyMaix 是面向单片机的超轻量级的神经网络推理库,即 TinyML 推理库,可以让你在任意单片机上运行轻量级…

Qwen2-Math 开源 AI 模型发布;阿里云推出首个域名 AI 大模型应用丨 RTE 开发者日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内…

ssh连接失败,排错经验

一、场景描述 ssh连接服务器,发现连接失败,但是对应服务器的ip能够ping通。 场景:[root@yl-web ~]# ssh root@10.1.101.35 ssh_exchange_identification: read: Connection reset by peer [root@yl-web ~]# ping 10.1.101.35 PING 10.1.101.35 (10.1.101.35) 56(84) bytes o…

面向忙碌的-Java-开发者的-Python-教程-全-

面向忙碌的 Java 开发者的 Python 教程(全)原文:Python for the Busy Java Developer 协议:CC BY-NC-SA 4.0一、语言 让我们从了解 Python 与 Java 的不同之处开始我们的 Python 之旅。在下一章深入研究 Python 的语法之前,我将帮助你设置 Python。 Python 是什么? Pytho…

maven搭建的springboot项目,引用了其他moudle的类,明明有这个类,install的时候确报错找不到这个类

其实这个问题是maven打包插件引起的,正常配置,install后包内首层会出现BOOT-INF这个目录,导致别的moudle打包install引用时找不到正确的目录 正常配置 打包后看引用的jar包就会有一层BOOT-INF目录包括着。 修改配置为下图,重新打包就没有了BOOT-INF目录了。再次引用并insta…

vue+iview-table点击展开展示内容,表格嵌套

实现如下效果的表格嵌套: 点击展开,展示tabs。 table的columns里设置展示的属性,然后属性里设置返回一个组件,然后在组件里写嵌套的内容。 <Table :columns="tableColumns" :data="tableData" style="width:100%" @on-selection-change=&…

Python-和-PowerShell-协作教程-全-

Python 和 PowerShell 协作教程(全)原文:PowerShell and Python Together 协议:CC BY-NC-SA 4.0一、面向调查人员的 PowerShell 简介 PowerShell 提供了一个强大的获取引擎,可以从实时系统、服务器、外围设备、移动设备和数据驱动的应用程序(如 Active Directory)中获取大…