10G UDP协议栈 IP层设计-(6)IP TX模块

news2024/11/18 20:48:22

一、模块功能

1、上层数据封装IP报文头部

2、计算首部校验和

二、首部校验和计算方法 

在发送方,先把IP数据报首部划分为许多16位字的序列,并把检验和字段置零。用反码算术运算把所有16位字相加后,将得到的和的反码写入检验和字段。接收方收到数据报后,将首部的所有16位字再使用反码算术运算相加一次。将得到的和取反码,即得出接收方检验和的计算结果。若首部未发生任何变化,则此结果必为0,于是就保留这个数据报。否则即认为出差错。
原文链接:https://blog.csdn.net/weixin_44870077/article/details/118106364

 例如一包数据的首部:64‘h4500001400012000、64’h8017d0b9c0a86464、64‘hc0a8646300000000

版本号到片偏移:64‘h4500001400012000

生存时间:8’h80

协议号:8‘h17

计算出来的首部校验和:16’hd0b9

源IP地址:c0a86464

目的IP地址:c0a86463

划分为长度为16bit的字段:4500 0014 0001 2000 8017 首部校验和初始计算值0000 c0a8 6464 c0a8 6463

相加:4500 + 0014 +  0001 + 2000 + 8017 + 0000 + c0a8 + 6464 + c0a8 + 6463 = 3 2F43

进位的高位再次加到低16位:2F43 + 0003 = 2F46

按位取法之后得到:d0b9

三、程序设计

参考:奇哥FPGA

//将数据缓存到FIFO
FIFO_UDP_DATA_64X16 u_FIFO_UDP_DATA_64X16 (
  .clk          (i_clk              ), 
  .srst         (i_rst              ), 
  .din          (rs_axis_out_data   ), 
  .wr_en        (rs_axis_out_valid  ), 
  .rd_en        (r_fifo_rden        ), 
  .dout         (w_fifo_data_out    ), 
  .full         (), 
  .empty        (w_fifo_empty       )  
);


always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)begin
        rs_axis_out_data    <= 'd0; 
        rs_axis_out_user    <= 'd0;
        rs_axis_out_keep    <= 'd0;
        rs_axis_out_last    <= 'd0;
        rs_axis_out_valid   <= 'd0;
    end
    else begin
        rs_axis_out_data    <= s_axis_out_data  ;
        rs_axis_out_user    <= s_axis_out_user  ;
        rs_axis_out_keep    <= s_axis_out_keep  ;
        rs_axis_out_last    <= s_axis_out_last  ;
        rs_axis_out_valid   <= s_axis_out_valid ;
    end
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)begin
        r_fifo_rden_ff1 <= 'd0;
        r_fifo_rden_ff2 <= 'd0;
    end
    else begin
        r_fifo_rden_ff1 <= r_fifo_rden;
        r_fifo_rden_ff2 <= r_fifo_rden_ff1;
    end
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_fifo_data_out <= 'd0;
    else
        r_fifo_data_out <= w_fifo_data_out;
end


always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_last_user <= 'd0;
    else
        if(s_axis_out_last)
            r_last_user <= s_axis_out_user;
        else
            r_last_user <= r_last_user;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_last_keep <= 'd0;
    else
        if(s_axis_out_last)
            r_last_keep <= s_axis_out_keep;
        else
            r_last_keep <= r_last_keep;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        ri_set_source_ip <= P_SOURCE_IP;
    else
        if(i_set_source_valid)
            ri_set_source_ip <= i_set_source_ip;
        else
            ri_set_source_ip <= ri_set_source_ip;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        ri_set_target_ip <= P_TARGET_IP;
    else
        if(i_set_target_valid)
            ri_set_target_ip <= i_set_target_ip;
        else
            ri_set_target_ip <= ri_set_target_ip;
end
//当FIFO有数据时就开始读FIFO
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_fifo_rden <= 'd0;
    else
        if(!w_fifo_empty && r_cnt == 0)
            r_fifo_rden <= 1'b1;
        else if(w_fifo_empty)
            r_fifo_rden <= 1'b0;
        else
            r_fifo_rden <= r_fifo_rden;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_cnt <= 'd0;
    else
        if(rm_axis_mac_last)
            r_cnt <= 'd0;
        else if((!w_fifo_empty && r_cnt == 0 && m_axis_mac_ready)|| r_cnt)
            r_cnt <= r_cnt + 1;
        else
            r_cnt <= r_cnt;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rs_axis_out_ready <= 'd1;
    else
        if(s_axis_out_last || !m_axis_mac_ready)
            rs_axis_out_ready <= 'd0;
        else if(rm_axis_mac_last || (!rm_axis_mac_valid && !m_axis_mac_ready))
            rs_axis_out_ready <= 'd1;
        else
            rs_axis_out_ready <= rs_axis_out_ready ;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_mac_data <= 'd0;
    else
        if(!w_fifo_empty && r_cnt == 0)
            rm_axis_mac_data <= {4'b0100,4'b0101,8'd0,(rs_axis_out_user[70:55] + 16'd20),
                                 rs_axis_out_user[15:0],{1'b0,rs_axis_out_user[54],~rs_axis_out_user[37]},rs_axis_out_user[28:16]};
        else if(r_cnt == 1)
            rm_axis_mac_data <= {8'd128,rs_axis_out_user[36:29],~r_header_check[15:0],ri_set_source_ip[31:0]};
        else if(r_cnt == 2)
            rm_axis_mac_data <= {ri_set_target_ip[31:0],w_fifo_data_out[63:32]};
        else
            rm_axis_mac_data <= {r_fifo_data_out[31:0],w_fifo_data_out[63:32]};
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_hd_check_cnt <= 'd0;
    else
        if(s_axis_out_valid)
            r_hd_check_cnt <= r_hd_check_cnt + 1;
        else
            r_hd_check_cnt <= 'd0;
end

//做首部校验和
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_header_check <= 'd0;
    else
        if(r_hd_check_cnt == 1)
            r_header_check <= 16'h4500 + (rs_axis_out_user[70:55] + 16'd20) + rs_axis_out_user[15:0] + 
                              ({{1'b0,rs_axis_out_user[54],~rs_axis_out_user[37]},rs_axis_out_user[28:16]})
                              + {8'd128,rs_axis_out_user[36:29]} ++ ri_set_source_ip[31:16] + ri_set_source_ip[15:0] 
                              + ri_set_target_ip[31:16] + ri_set_target_ip[15:0];
        else if(r_hd_check_cnt == 1)
            r_header_check <= r_header_check[31:16] + r_header_check[15:0]; //可能会产生进位
        else if(r_hd_check_cnt == 2)
            r_header_check <= r_header_check[31:16] + r_header_check[15:0]; //加进位之后,可能还会产生进位,所以要再加一次
        else
            r_header_check <= r_header_check;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_mac_user <= 'd0;
    else
        rm_axis_mac_user <= {((rs_axis_out_user[70:55] + 16'd19) >> 3) + 1,48'hFFFFFFFF_FFFF,16'h0800};
end
//字节对齐
always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_mac_keep <= 'd0;
    else
        if(w_fifo_rden_neg && r_last_keep <= 8'b1111_0000)
            case(r_last_keep)
                // 8'b1111_1111: rm_axis_mac_keep <= 8'b1111_1111
                // 8'b1111_1110: rm_axis_mac_keep <= 
                // 8'b1111_1100: rm_axis_mac_keep <=
                // 8'b1111_1000: rm_axis_mac_keep <=
                8'b1111_0000: rm_axis_mac_keep <= 8'b1111_1111;
                8'b1110_0000: rm_axis_mac_keep <= 8'b1111_1110;
                8'b1100_0000: rm_axis_mac_keep <= 8'b1111_1100;
                8'b1000_0000: rm_axis_mac_keep <= 8'b1111_1000;
                default     : rm_axis_mac_keep <= 8'b1111_1111;
            endcase
        else if(w_fifo_rden_neg_ff1 && r_last_keep >= 8'b1111_1000)
            case(r_last_keep)
                8'b1111_1111: rm_axis_mac_keep <= 8'b1111_0000;
                8'b1111_1110: rm_axis_mac_keep <= 8'b1110_0000;
                8'b1111_1100: rm_axis_mac_keep <= 8'b1100_0000;
                8'b1111_1000: rm_axis_mac_keep <= 8'b1000_0000;
                // 8'b1111_0000: rm_axis_mac_keep <= 8'b1111_1111;
                // 8'b1110_0000: rm_axis_mac_keep <= 8'b1111_1110;
                // 8'b1100_0000: rm_axis_mac_keep <= 8'b1111_1100;
                // 8'b1000_0000: rm_axis_mac_keep <= 8'b1111_1000;
                default     : rm_axis_mac_keep <= 8'b0000_0000;
            endcase   
        else
               rm_axis_mac_keep <= 8'b1111_1111;      
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_mac_last <= 'd0;
    else
        if(w_fifo_rden_neg && r_last_keep <= 8'b1111_0000)
            rm_axis_mac_last <= 1'b1;
        else if(w_fifo_rden_neg_ff1 && r_last_keep >= 8'b1111_1000)
            rm_axis_mac_last <= 1'b1;
        else
            rm_axis_mac_last <= 'd0;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_mac_valid <= 'd0;
    else
        if(!w_fifo_empty && r_cnt == 0)
            rm_axis_mac_valid <= 1'b1;
        else if(rm_axis_mac_last)
            rm_axis_mac_valid <= 'd0;
        else
            rm_axis_mac_valid <= rm_axis_mac_valid ;

end

四、仿真

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

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

相关文章

分布式系统的一致性与共识算法(二)

Consitency 背景 如买最后一张车票&#xff0c;两个售票处分别通过某种方式确认过这张票的存在。这时&#xff0c;两家售票处几乎同时分别来了一个乘客要买这张票&#xff0c;从各自"观察"看来&#xff0c;自己一方的乘客都是先到的&#xff0c;这种情况下&#xf…

【Shell脚本】Shell编程之数组

目录 一.数组 1.基本概念 2.定义数组的方法 2.1.方法一 2.2.方法二 2.3.方法三 2.4.方法四 2.5.查看数组长度 2.6.查看数组元素下标 3.数组分片 4.数组字符替换 4.1.临时替换 4.2.永久替换 5.数组删除 5.1.删除某个下标 5.2.删除整组 6.数组遍历和重新定义 7…

sql操作、发送http请求和邮件发送 全栈开发之路——后端篇(2)

全栈开发一条龙——前端篇 第一篇&#xff1a;框架确定、ide设置与项目创建 第二篇&#xff1a;介绍项目文件意义、组件结构与导入以及setup的引入。 第三篇&#xff1a;setup语法&#xff0c;设置响应式数据。 第四篇&#xff1a;数据绑定、计算属性和watch监视 第五篇 : 组件…

国内好用的测试用例管理工具有哪些?

目前市面上的测试用例管理工具有很多&#xff0c;但由于针对的项目、领域、目标用户&#xff0c;功能也并不一致&#xff0c;所以选择一款适合的测试管理平台并不轻松。做好这件事&#xff0c;首先要需求明确你用测试管理工具干什么&#xff1f;最终想要达到什么目标&#xff1…

基于UnetPlusPlus(Unet++)实现的医学图像分割

1、前言 unetPlusPlus 在unet 的基础上增添了密集连接的结构&#xff0c;有点像densenet网络 因为这种密集连接&#xff0c;unet可以实现剪枝的轻量化操作。由于本人的没有接触过这种剪枝、蒸馏之类的轻量化方法&#xff0c;所以不多赘述 本章仅仅根据unet模型实现医学图像分…

西门子博途WINCC精致触摸屏配方实用一例

我们现场有一台设备&#xff0c;是用来锯切钢坯的&#xff0c;里面有几个重要的参数&#xff0c;一开始投产的时候厂家没有做配方功能&#xff0c;需要操作人员每次换钢坯就需要手动计算然后输入&#xff0c;后来有时间我就做了个这个定尺管理的功能&#xff0c;方便了操作人员…

汇昌联信电商:拼多多网店好做吗?

在电子商务的海洋中&#xff0c;拼多多以其独特的团购模式和亲民策略迅速崛起&#xff0c;吸引了大批消费者和商家的目光。对于“拼多多网店好做吗?”这个问题&#xff0c;答案并非简单的是与否&#xff0c;而是需要从多个维度进行深入分析。 一、市场定位与竞争环境 拼多多定…

华为开源自研AI框架昇思MindSpore应用案例:在ResNet-50网络上应用二阶优化实践

常见的优化算法可分为一阶优化算法和二阶优化算法。经典的一阶优化算法如SGD等&#xff0c;计算量小、计算速度快&#xff0c;但是收敛的速度慢&#xff0c;所需的迭代次数多。而二阶优化算法使用目标函数的二阶导数来加速收敛&#xff0c;能更快地收敛到模型最优值&#xff0c…

TCP的滑动窗口机制和流量控制

目录 滑动窗口 流量控制 拥塞控制 滑动窗口 TCP除了保证可靠性之外&#xff0c;也希望能够尽可能高效的完成数据传输。滑动窗口就是一种提高效率的机制。以下是不引入滑动窗口的数据传输过程&#xff1a; 可以看到&#xff0c;主机A这边每次收到一个ACK才发送下一个数据。这…

接口、会话控制

文章目录 接口介绍RESTful APIjson-server接口测试工具apipost公共参数和文档功能 会话控制cookie介绍和使用运行流程浏览器中操作Cookieexpress中cookie操作 Sessionsession运行流程&#xff1a;session中间件配置session 和 cookie 的区别CSRF跨站请求伪造 tokenJWT介绍与演示…

数据新探:用Python挖掘互联网的隐藏宝藏

Hello&#xff0c;我是你们的阿佑&#xff0c;今天给大家上的菜是——数据存储&#xff01;听起来枯燥无味&#xff1f;错了&#xff01;阿佑将带你重新认识数据存储的艺术。就像为珍贵的艺术品寻找完美的展览馆&#xff0c;为你的数据选择合适的存储方式同样重要&#xff01; …

2022-1990年 各省碳排放Co2数据集(含数据及参考文献)

碳排放是指人类活动产生的二氧化碳&#xff08;CO2&#xff09;等温室气体释放到大气中的过程。通过划分排放源的范围以避免重复计算的思想&#xff0c;由世界资源研究所在关于企业温室气体排放清单编制的指南中首次提出。城市碳排放核算边界界定借鉴该思想&#xff0c;可分为3…

Web开发三层架构

##Controller Service Dao(mapper) 软件设计&#xff1a;高内聚 低耦合 Controller 调用Service&#xff0c; Service调用 DAO 模块之间耦合 如果要从EmpServiceA切换到EmpServiceB&#xff0c;Controller代码也要修改 new EmpServiceB 分层接耦 容器中放EmpServiceA&am…

(深度估计学习)Win11复现DepthFM

目录 1. 系统配置2. 拉取代码&#xff0c;配置环境3.开始深度预测4.运行结果 论文链接&#xff1a;https://depthfm.github.io/ 讲解链接&#xff1a;https://www.php.cn/faq/734404.html 1. 系统配置 本人系统&#xff1a;Win11 CUDA12.2 python3.11.5 这里附上几个CUDA安装链…

Linux第四节--常见的指令介绍集合(持续更新中)

点赞关注不迷路&#xff01;本节涉及初识Linux第四节&#xff0c;主要为常见的几条指令介绍。 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1f44d;&#x1f3fb; 收藏 ✨ 加关注&#x1f440; 期待与你共同进步! 1. more指令 语法&#xff1a;more [选项][文件]…

【数据可视化01】matplotlib实例介绍4之六边形分箱图

目录 一、引言二、实例介绍 一、引言 hexbin是一个二维直方图&#xff0c;其中箱子是六边形&#xff0c;颜色表示每个箱子内的数据点数。 二、实例介绍 import matplotlib.pyplot as plt import numpy as np# Fixing random state for reproducibility np.random.seed(19680…

umi搭建react项目

UMI 是一个基于 React 的可扩展企业级前端应用框架&#xff0c;提供路由、状态管理、构建和部署等功能&#xff0c;可以帮助开发者快速构建复杂的单页面应用&#xff08;SPA&#xff09;和多页面应用&#xff08;MPA&#xff09;。它与 React 的关系是&#xff0c;UMI 构建在 R…

draw.io 网页版二次开发(1):源码下载和环境搭建

目录 一 说明 二 源码地址以及下载 三 开发环境搭建 1. 前端工程地址 2. 配置开发环境 &#xff08;1&#xff09;安装 node.js &#xff08;2&#xff09;安装 serve 服务器 3. 运行 四 最后 一 说明 应公司项目要求&#xff0c;需要对draw.io进行二次开发&…

算法提高之加成序列

算法提高之加成序列 核心思想&#xff1a;迭代加深 dfs 从上往下逐渐增大depth 这样下面没有用的方案就不用遍历了 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 110;int n;int path[N];//当前求哪个位置…