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

news2024/9/24 7:20:52

软件版本: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层

3.2.1 IP_ARP接收模块

3.2.2 IP_ARP发送模块


3.2 IP_ARP层

由于IP和ARP数据包送至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
    else if(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
        else if(I_mac_rdata_type == ARP_TYPE) begin//ARP包
            arp_rx_data_valid   <=  1'b1;
            arp_rx_data         <=  I_mac_rdata;
        end
        else begin
            ip_rx_data_valid    <=  1'b0;
            ip_rx_data          <=  8'd0;
            arp_rx_data_valid   <=  1'b0;
            arp_rx_data         <=  8'd0;
        end
    end
    else begin
        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_PACKET:I_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
    else begin
        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
                    else if(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
                    else begin
                        O_arp_tbusy             <= 1'b0;
                        O_ip_tbusy              <= 1'b0;                        
                        STATE                   <= IDLE;                        
                    end
                end
                else begin
                    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
                    else begin
                        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
                else begin
                    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
                    else begin
                        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
                else begin
                    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
                else begin
                    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
                else begin          
                    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
                else begin
                    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.coloradmin.cn/o/1981891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Golang实现Kubernetes边车模式

本文介绍了如何基于 Go 语言实现 Kubernetes Sidecar 模式&#xff0c;并通过实际示例演示创建 Golang 实现的微服务服务、Docker 容器化以及在 Kubernetes 上的部署和管理。原文: Sidecar Pattern with Kubernetes and Go[1] 在这篇文章中&#xff0c;我们会介绍 Sidecar 模式…

【分享】2022年291个城市的人均GDP数据,附带数据获取方式

2022年291个城市的人均GDP数据涉及全国地级及以上城市的经济发展水平。在这份详尽的数据中&#xff0c;包括了众多城市的经济表现&#xff0c;并依据国际标准对它们的经济状况进行了分类。具体如下&#xff1a; 人均GDP高值城市 鄂尔多斯&#xff1a;鄂尔多斯市位于内蒙古自治区…

单位企业邮箱有什么优势

单位企业邮箱成为了企业内外沟通的重要工具。单位企业邮箱的优势有什么呢&#xff1f;一、统一专业形象&#xff1b;二、高效沟通&#xff1b;三、安全保障&#xff1b;四、便捷管理&#xff1b;五、定制服务等。本文将深入探讨单位企业邮箱的独特优势&#xff0c;帮助您了解为…

格力美容仪售价9800元 董明珠:用一周发现变美了

近日&#xff0c;格力电器董事长兼总裁董明珠在格力冰洗生活电器战略发布会上透露&#xff0c;公司已研发了美容仪。 《时代周报》记者查询格力董明珠店官网发现&#xff0c;目前有一款名为“格力微电流美容仪”的产品在售卖&#xff0c;售价9800元&#xff0c;截至发稿已售出…

详解直铺防静电瓷砖的特点与优势

防静电地板分为架空防静电地板和直铺防静电地板&#xff0c;直铺式防静电地板是一种直接铺设在地面上的地板系统&#xff0c;防静电瓷砖就是常用的直铺防静电地板之一。防静电瓷砖是在瓷砖烧制过程中加入防静电功能粉体进行物理改性&#xff0c;规格为600*600*10mm&#xff0c;…

Windows使用wsl安装docker-desktop

一&#xff1a;修改Windows配置&#xff0c;启用相关功能。 1&#xff1a;启用硬件虚拟化VT-d 各品牌电脑的Bios设置都不一致&#xff0c;需要自行查找如何进入Bios开启VT-x功能&#xff0c;绝大部分电脑此功能默认情况下是直接开启的。 2&#xff1a;确定Windows系统的类别…

带动画特效、带音乐的仿真翻页电子相册制作教程

在当前数字化快速发展的时代&#xff0c;仿真翻页电子相册作为一种富有创意和互动性的表达形式&#xff0c;正受到越来越多用户的青睐。本教程将介绍如何利用带动画特效和音乐的功能&#xff0c;通过FLBOOK这款强大的电子相册制作工具&#xff0c;创作出令人印象深刻的作品。 第…

剪画小程序:录音转文字:告别会议烦恼,轻松整理文档!

在忙碌的工作中&#xff0c;开会是家常便饭。 每次会议上大家的讨论、决策和重要信息&#xff0c;都对工作的推进至关重要。 但您是否曾为会议录音的整理而感到头疼&#xff1f;冗长的会议录音&#xff0c;想要从中准确提取关键信息&#xff0c;费时又费力。 别担心&#xff…

文件系统 ---在硬盘中的文件

序言 在前两章的内容中&#xff0c;我们主要是介绍了一个文件被调度时&#xff0c;在内存中的存在形式以及相关的内核结构。在这一章中&#xff0c;我们主要介绍一磁盘是如何管理并存储文件的以及文件在磁盘上的存在形式。  大部分电脑采用硬盘驱动器&#xff08;HDD&#xff…

AWS域名注册:AWS 是否可以注册HK域名?

AWS&#xff08;Amazon Web Services&#xff09;本身并不直接提供域名注册服务&#xff0c;但它通过其服务Amazon Route 53提供域名注册功能&#xff0c;九河云来和你详细说说域名注册的一些事项吧。通过Amazon Route 53&#xff0c;你可以注册各种顶级域名&#xff08;TLD&am…

openai command not found (mac)

题意&#xff1a;mac 系统上无法识别 openai 的命令 问题背景&#xff1a; Im trying to follow the fine tuning guide for Openai here. 我正在尝试遵循 OpenAI 的微调指南 I ran: 我运行以下命令 pip install --upgrade openaiWhich install without any errors.…

本地安装Llama3.1与LobeChat可视化UI界面并实现远程访问大模型实战

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

著名数学教育家的精辟见解表明R有最小正数元

黄小宁 著名数学教育家余元希教授著《数的概念浅说》114页指出&#xff1a;数轴是连续的点集&#xff0c;它的元素是一个一个紧挨着的。这精辟见解说明R轴即x轴必有紧挨着原点x0的正数点xt&#xff0c;t显然是R的最小正数元&#xff0c;任何比t小的正数都是“更无理”的R外正数…

SD-WAN抢专线的饭碗?和传统WAN对比到底香在哪?

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 你们好&#xff0c;我的网工朋友。 广域网&#xff08;WAN, Wide Area Network&#xff09;是企业网络的核心组成部分之一&#xff0c;但是随着发…

测试GPT4o分析巴黎奥运会奖牌数据

使用GPT4o快速调用python代码&#xff0c;生成数据图表 测试GPT4o分析巴黎奥运会奖牌数据 测试GPT4o分析巴黎奥运会奖牌数据 1.首先我们让他给我们生成下当前奥运奖牌数 2.然后我们直接让GPT帮我们运行python代码&#xff0c;并生成奥运会奖牌图表 3.我们还可以让他帮我们…

初识云计算

随着科技的飞速发展&#xff0c;云计算作为一种新兴的信息技术架构&#xff0c;正在逐渐改变我们的工作方式和生活方式。 云计算是什么&#xff1f; 云计算是一种通过互联网提供计算资源和服务的计算模式。它通过互联网将计算和存储资源进行集中和共享&#xff0c;为用户提供…

mysql 各种锁归纳总结

文章目录 一、引言二、锁分类三、Mysql锁四、MyISAM表锁五、InnoDB锁六、间隙锁七、总结 一、引言 在现代应用程序中&#xff0c;数据库是不可或缺的组成部分之一。而MySQL作为一款开源的关系型数据库管理系统&#xff0c;广泛应用于各种规模的应用中。然而&#xff0c;在高并…

如何防止员工删除文件?10个操作让你随时找到重要文件

防止员工删除文件是确保企业数据安全的重要一环&#xff0c;有了这10个操作&#xff0c;让你不愁找不到重要的文件。 1.设置文件访问权限&#xff1a; 在文件服务器上或网络共享中&#xff0c;为不同用户或用户组设置适当的文件访问权限。确保员工只有必要的读、写权限&#…

polyglot,一个有趣的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个有趣的 Python 库 - polyglot。 Github地址&#xff1a;https://github.com/aboSamoor/polyglot 在处理多语言文本时&#xff0c;解析和翻译不同语言的文本数据是一个常见…

sql注入11、17、24关

sql注入第11关 查看源码后发现注入点。 $sql"SELECT username, password FROM users WHERE username$uname and password$passwd LIMIT 0,1";$resultmysqli_query($con1, $sql);$row mysqli_fetch_array($result, MYSQLI_BOTH); 在User Name输入框中输入注入语句&…