Verilog 实现千兆网UDP协议 基于88E1111--数据发送

2023-11-08

Verilog 实现千兆网UDP协议 基于88E1111–数据发送

注:此版本没有添加ARP PING 等,未完待续。
注:项目采用Verilog开发,基于Vivado编译器。
UDP(User Datagram Protocol)一种基本的,低延迟的数据报。本章简单的实现了UDP数据包的发送。
首先UDP协议通讯信息中包含:MAC地址,IP地址,端口地址等。这些信息在没有提供ARP模式时,需要提前数据,所以采用Verilog Head 文件,提前输入,方便修改,适配时,只需更改头文件。

`define   Leading_code   					64'h55_55_55_55_55_55_55_D5 
`define   Source_MAC      					48'h11_22_33_44_55_01
`define   Destination_MAC 					48'h11_22_33_44_55_02
`define   IP_TYPE		 					16'h08_00
`define   IP_TYPE_ARP		 				16'h08_06
`define   Source_IP      					32'hC0_0A_00_02  //192.168.0.2
`define   Destination_IP 					32'hC0_0A_00_03  //192.168.0.3
`define   Source_Port      					16'h80_00
`define   Destination_Port 					16'h80_00 

模块接口如下:架构为从外部FIFO提取数据写入,读取外部FIFO内数据量,设置阈值,当数据量大于阈值,将命令Eth_Command和数据长度Data_length同步写入模块,模块跳出idle状态,开始进行数据写入。
模块对外接口Eth_Write_Busy:拉高的时候,外部就等待,不要在写入命令。拉低时就可以再次对模块进行操作。
现在还没有完善为有数据就开始写入。所以Txen_o会在每包数据写入时持续拉高,Txer_o就没有用。
Txd_o就是数据写入接口。其他如字面意思。

	input 	      				clk_i,
	input						rst_n,
	/*eth interface*/
	output reg 					Txen_o,                      //GMII数据使能信号
	output  					Txer_o,                      //GMII发送错误信号
	output reg 	[ 7:0] 			Txd_o,     
	/*control interface*/
	input 		[ 3:0]			Eth_Command,
	input		[15:0]			Data_length,
	output reg					Eth_Write_Busy,
	/*fifo interface*/
	input 		[ 7:0] 			Fifo_Data_i,
	output reg 					Fifo_en

采用三段式状态机开发,将各部分独立,方便单独信号维护,主要是习惯…

localparam  idle        	=  8'b1111_1110; //fe
localparam  Cal_Head_Crc	=  8'b1111_1101; //fd
localparam  Write_Leading  	=  8'b1111_1011; //fb
localparam  Write_Header   	=  8'b1111_0111; //f7
localparam  Write_Data     	=  8'b1110_1111; //ef
localparam  Write_Crc     	=  8'b1101_1111; //df
localparam  Write_Over     	=  8'b1011_1111; //bf

本模块将发送程序划分为6个状态机,
如命名所示:
状态1、准备数据
状态2、计算校验
状态3、写引导符:下面代码中的Leading_Code
状态4、写入头:有些固定写入就可以,具体代表什么见注释…下面代码中的Header_Code
状态5、写入数据:从FIFO中提取需要发送的数据。
状态6、写入校验和:具体见校验和计算部分
状态7、写完成:这个状态就对包计数加个1
状态跳转:三段式状态机中关键部分,判断Flag来实现状态切换

		idle:			nstate <= (Eth_Command == 4'hA )? Cal_Head_Crc  : idle;
		Cal_Head_Crc :  nstate <= (State_turn)			? Write_Leading : Cal_Head_Crc;
		Write_Leading:  nstate <= (State_turn)			? Write_Header  : Write_Leading;
		Write_Header :  nstate <= (State_turn)			? Write_Data    : Write_Header;
		Write_Data   :  nstate <= (State_turn)			? Write_Crc     : Write_Data;
		Write_Crc    :  nstate <= (State_turn)			? Write_Over    : Write_Crc;
		Write_Over   :  nstate <= idle;
		default: 		nstate <= idle;

写入数据代码:就是在给Txd_o ,使能信号Txen_o单独维护,这也是三段式状态机的好处。

idle: begin				
				Leading_Code <= {`Leading_code,`Source_MAC,`Destination_MAC,`IP_TYPE};   // 
				Header_Code  <= {16'h45_00	  ,Total_length,							 //	|	版本号4	|	头长度4	|	服务类型8		|	总长度16		|
								 Package_count,16'h40_00,                                //	|          标识16     						|  标志3|片偏移13	|
								 16'h80_11	  ,16'h00_00,                             	 //	|     生存时间TTL8    	|上层协议标识8		|   头部校验和16	|
								 `Source_IP	  ,                                          //	|                        源IP地址32    							|
								 `Destination_IP,                                        //	|                        目标IP地址32   						|
								 `Source_Port ,`Destination_Port,                        //	|                            选项                               |
								 Data_length  ,16'h00_00                                 //	|                                                               |
								 };                                                      //	
				Total_length <=	Data_length + 16'd20;
				Txd_o 		 <= 8'hZZ;
			end
			Cal_Head_Crc: begin
				if(Send_count == 16'd0)		begin
					Crc_Sum_Head_r <=  Header_Code[223:192] + Header_Code[191:160] + Header_Code[159:128] 
									+  Header_Code[127:96]  + Header_Code[ 95: 64] ;
				end
				else if(Send_count == 16'd1)		begin
					Crc_Sum_Head   <= Crc_Sum_Head_r[31:16] + Crc_Sum_Head_r[15:0];
				end
				else if(Send_count == 16'd2)		begin
					Header_Code[143:128] <=  Crc_Sum_Head;
				end
				else begin
					Crc_Sum_Head_r <= Crc_Sum_Head_r;
					Crc_Sum_Head   <= Crc_Sum_Head;
					Header_Code    <= Header_Code;
				end
			end
			Write_Leading: begin
				Txd_o		 <=  Leading_Code[175:168];
				Leading_Code <= {Leading_Code[167:	0],Leading_Code[175:168]};
			end
			Write_Header:  begin	
				Txd_o		 <=  Header_Code[223:216];
				Header_Code  <= {Header_Code[215:  0],Header_Code[223:216]};
			end
			Write_Data: begin
				Txd_o		 <= Fifo_Data_o;
			end
			Write_Crc: begin
				if(Send_count == 16'd0)		begin
					Txd_o <= {~Crc_Sum_Rec[24],~Crc_Sum_Rec[25],~Crc_Sum_Rec[26],~Crc_Sum_Rec[27],
							  ~Crc_Sum_Rec[28],~Crc_Sum_Rec[29],~Crc_Sum_Rec[30],~Crc_Sum_Rec[31]};
				end
				else if(Send_count == 16'd1)begin
					Txd_o <= {~Crc_Sum_Rec[16],~Crc_Sum_Rec[17],~Crc_Sum_Rec[18],~Crc_Sum_Rec[19],
							  ~Crc_Sum_Rec[20],~Crc_Sum_Rec[21],~Crc_Sum_Rec[22],~Crc_Sum_Rec[23]};
				end
				else if(Send_count == 16'd2)begin
					Txd_o <= {~Crc_Sum_Rec[ 8],~Crc_Sum_Rec[ 9],~Crc_Sum_Rec[10],~Crc_Sum_Rec[11],
							  ~Crc_Sum_Rec[12],~Crc_Sum_Rec[13],~Crc_Sum_Rec[14],~Crc_Sum_Rec[15]};
				end
				else if(Send_count == 16'd3)begin
					Txd_o <= {~Crc_Sum_Rec[ 7],~Crc_Sum_Rec[ 6],~Crc_Sum_Rec[ 5],~Crc_Sum_Rec[ 4],
							  ~Crc_Sum_Rec[ 3],~Crc_Sum_Rec[ 2],~Crc_Sum_Rec[ 1],~Crc_Sum_Rec[ 0]};
				end
				else Txd_o <= 8'hZZ;
			end	
			Write_Over: begin
				Txd_o <= 8'hZZ;
			end

因为本模块是持续写入,不中断,所以状态跳转切换就比较简单,单纯的计数就可以。每个状态就是把该发的数据发送出去
达到计数值得时候同步拉高State_turn 状态跳转,实现状态切换。

			idle: 			begin
				Send_count   <= 16'd0;
				State_turn   <=  1'b0;
			end
			Cal_Head_Crc:		begin
				if (Send_count == 16'd2)  				begin
					Send_count 	<=16'd0;
					State_turn  <= 1'b1;
				end
				else 									begin			 
					Send_count	<= Send_count + 1'b1;
					State_turn  <= 1'b0;				
				end
			end
			Write_Leading: 	begin
				if (Send_count == 16'd21) 				begin
					Send_count  <= 16'd0;
					State_turn  <=  1'b1;
				end
				else 									begin
					Send_count  <= Send_count + 1'b1;
					State_turn  <= 1'b0;
				end
			end
			Write_Header:  	begin
				if (Send_count == 16'd27) 				begin
					Send_count  <=16'd0;
					State_turn  <= 1'b1;
				end
				else 									begin					 
					Send_count  <= Send_count + 1'b1;
					State_turn  <= 1'b0;					
				end
			end
			Write_Data:    	begin
				if (Send_count == Data_length - 1'b1) 	begin
					Send_count  <= 16'd0;
					State_turn  <=  1'b1;
				end
				else 									begin
					Send_count 	<= Send_count + 1'b1;	
					State_turn  <= 1'b0;
				end
			end
			Write_Crc :		begin
				if (Send_count == 16'd3)  				begin
					Send_count 	<=16'd0;
					State_turn  <= 1'b1;
				end
				else 									begin			 
					Send_count	<= Send_count + 1'b1;
					State_turn  <= 1'b0;				
				end
			end
			Write_Over: 	begin
				Send_count <= Send_count;
				State_turn   <= 1'b0;
			end

Txen_o信号的维护:在写入数据的状态拉高就可以了

			idle,Cal_Head_Crc,Write_Over: begin
				Txen_o	<= 1'b0;
			end
			Write_Header,Write_Data,Write_Leading,Write_Crc: begin
				Txen_o	<= 1'b1;
			end

以上,就简单实现了UDP数据包的连续发送。
仿真:画个波形看看情况,代码如下

module test(
	output reg	      			clk_o,
	output reg					rst_n,
	
	output reg	[ 3:0]			Eth_Command,
	output reg	[15:0]			Data_length,
	input 						Eth_Write_Busy,	
	
	output reg  [ 7:0] 			Fifo_Data_i,
	input 						Fifo_en	
    );
initial begin
	clk_o  = 1'b1;	
	forever begin
		#10ns clk_o = ~clk_o; //10Mhz
	end
end	
initial begin
	rst_n = 1'b0;
	#1000ns rst_n = 1'b1;	
end
initial begin
	Eth_Command = 4'hf;
	Data_length = 16'd1500;
	#1500ns
	if(Eth_Write_Busy) Eth_Command = 4'hf;
	else begin
		#1000ns
		Eth_Command = 4'hA;
	end
end
always @(posedge clk_o or negedge rst_n)
begin
	if(!rst_n) begin
		Fifo_Data_i <= 8'hFF;
	end
	else if (Fifo_en)begin
		Fifo_Data_i <= Fifo_Data_i + 1'b1;
	end
	else begin
		Fifo_Data_i <= Fifo_Data_i;
	end
end
endmodule

仿真截图:
连续发送
开始写,提前一个时钟读FIFO
提前一个时钟结束读FIFO,写入校验和
还有没有上电路板验证,秀一下刚画完的板子
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Verilog 实现千兆网UDP协议 基于88E1111--数据发送 的相关文章

  • 学习ORACLE-物化视图(MATERIALIZED VIEW)总结

    数据仓库项目中使用物化视图推送数据 现记录一下相关方面的知识 物化视图需要有基表 基表可以在本地库 也可以在远程库 可以在本地通过数据库链接访问远程库的基表 基表 hr departments orcl 物化视图 scott departm
  • google可视化编程工具blockly介绍

    1 什么是blockly blockly是google发布的可视化编程工具 是一个可用于Web Android iOS的可视化代码编辑器库 blockly有几个特点 它是纯粹的javascript库 它是100 面对客户端的 没有任何服务端
  • Cesium中文教程-空间数据可视化Visualizing Spatial Data(一)

    目录 3 空间数据可视化 Visualizing Spatial Data 1 实体API What is the Entity API 2 第一个实体 Our First Entity 3 图形和容器 Shapes and Volumes
  • 30. PyQuery: 基于HTML的CSS选择器

    目录 前言 导包 基本用法 按标签选择 标签链式操作 简便链式 后代选择器 类选择器 id 选择器 属性 文本选择器 重点 改进多标签拿属性方法 快速总结 PyQuery的强大功能 修改源代码 添加代码块 修改 添加属性 删除属性 标签等
  • 我写CSS的常用套路(附demo的效果实现与源码)

    作者 alphardex https juejin im post 5e070cd9f265da33f8653f0 前言 本文是笔者写CSS时常用的套路 不论效果再怎么华丽 万变不离其宗 1 交错动画 有时候 我们需要给多个元素添加同一个动
  • celery 简要概述

    文章目录 1 celery 简要概述 1 1 celery 可以做什么 2 celery 的核心模块 2 1 celery 的5个角色 3 celery 和flask 如何结合起来 3 1项目结构 3 2 项目入口 文件 routes py
  • SQLRecoverableException: Closed Connection

    目录 问题描述 解决过程 问题描述 事情是这样子的 公司线上oracle数据库因为等保评估突然设置了idle time 设置成10分钟了 如果不设置idle time 默认是 UNLIMITED 则连接始终不会被断开 这就占用了连接数资源
  • flutter使用坑点记录

    container点击失效 一般container点击 可能会在container外包一层 GestureDetector 有时候你会发现点击事件无效或是只有点击了文字或图片之后才会触发点击事件 解决办法 1 为Container设置背景颜
  • 免费微信小程序商城源代码,基于Uni-App,实现一码多端

    微信商城功能介绍 购物流程 符合大众习惯的首页 分类 商品展示 下单流程 智能搜索商品 会员体系 手机号登录 微信登录 用户积分 商品收藏 商品评论 足迹 营销工具 满额包邮 优惠券 满减和满折扣 定向发放 积分抵扣 10级定价 订单管理
  • 2.2.4 读取EXCEL数据与Error: ‘\U‘ used without hex digits in character string starting ““C:\U“报错

    当我们需要用R读取EXCEL数据时我们应首先在R程序中输入以下命令 install packages xlsx repos https mirrors ustc edu cn CRAN 来安装读写 Excel 文件需要安装扩展包 当安装完成
  • ps景观平面图转鸟瞰图_ps如何制作鸟瞰图 ps制作鸟瞰图教程

    ps如何制作鸟瞰图 大家都知道ps是一款强大的制图绘图工具 而在我们制作规划图的时候 鸟瞰图是最好的展示图 那么ps就派上用场了 使用ps制作的鸟瞰图可以杜绝凭空想象的随意性 让整个图变得更加的精确 那么下面我们就一起来看看吧 1 拿相机拍
  • 正则 去掉括号内的内容

    前言 刚开始以为 就是括号内任意字符了 试了不行 错误点 1 括号需要转移 是正则表达式关键字 2 不是任意字符 而是 除了右括号的任意字符 String content i want to thank you thank very dfl
  • 嵌入式Linux人脸检测libfacedetection

    人脸检测 此库依赖Opencv 所以首先要移植Opencv到板子上 笔者使用LVGL搭建了一个界面 界面有些卡顿 主要原因是文件存取较慢 演示效果如下 OpenCV 首先要交叉编译Opencv 参考 https blog csdn net
  • 统计学——简单理解方差分析

    方差分析 方差分析 analysis of variance 简写为ANOVA 指的是利用对多个样本的方差的分析 得出总体均值是否相等的判定 它是一种分析调查或试验结果是否有差异的统计分析方法 也就是检验各组别间是否有差异 方差分析按照以下
  • linux 网卡队列深度,linux 磁盘队列深度nr_requests 和 queue_depth

    nr requests 和 queue depth 修改配置值 nr requests 和 queue depth 区别 iostat 的avgqu sz lsscsi l 的队列大小 iostat nr requests 和 queue
  • MOEA/D 算法详解

    MOEA D 笔记 1 聚合方法 1 1 权重求和法 Weighted Sum Approach 1 2 切比雪夫聚合法 Tchebycheff Approach 1 3 边界交叉法 Boundary Intersection Approa

随机推荐

  • JS:MessageChannel

    MessageChannel API MessageChannel 为通信管道对象 使用 MessageChannel 构造函数将返回一个 MessageChannel 对象 返回的对象中包含两个 MessagePort 对象 可以实现双端
  • 关于numpy中seed随机数种子的使用

    numpy random seed 随机种子生成器 使下一次生成的随机数为由种子数决定的 特定 的随机数 如果seed中参数为空 则生成的随机数 完全 随机 gt gt gt import numpy as np gt gt gt np r
  • 电脑查询域名对应IP的过程

    1 浏览器缓存 当用户通过浏览器访问某域名时 浏览器首先会在自己的缓存中查找是否有该域名对应的IP地址 若曾经访问过该域名且没有清空缓存 便存在 2 系统缓存 当浏览器缓存中无域名对应IP则会自动检查用户计算机系统Hosts文件DNS缓存是
  • 4键电子手表说明书_电子手表怎么调(电子手表的四个键的功能各是什么)

    展开全部 四个功能键分别是 左上角按键e68a84e8a2ad62616964757a686964616f31333433643062LIGHT 右上角按键ST SP 左下角按键MODE 右下角按键RESET 具体操作步骤如下 1 首先 在
  • (干货)微信小程序组件封装

    概述 自己封装的一个比较简单微信弹窗小组件 主要就是教会大家对微信小组件的用法和理解 因为微信小程序对组件介绍特别少 所以我就把自己的理解分享给大家 一前言 相信大家在开发小程序时会遇到某个功能多次使用的情况 比如弹出框 这个时候大家首先想
  • 自动化测试之RobotFramework框架

    自动化测试之RobotFramework框架 很久没更新 因为我跳槽了 之前学习了入门级别性能测试的Jmeter 发现自由度真的差 又想着找一个上限比较高的python测开的工作 所以换到了现在的工作 我们公司使用的是wxpython基于r
  • 学习日记——基于MDK的智慧物流案例开发(2020.2.19)

    准备阶段 开发板 小熊派开发板 提前组装 将 NB卡 NB35 A通信扩展板 E53 ST1GPS模块 IDE LiteOS Stiudio 小熊派的编译环境 平台 华为云账号 开通开发中心的权限 若使用软件开发服务进行应用开发 还需要开通
  • QT drawPixmap和drawImage处理图片模糊问题

    drawPixmap和drawImage显示图片时 如果图片存在缩放时 会出现模糊现象 例如将一个100x100 的图片显示到30x30的区域 这个时候就会出现模糊 如下 实际图片 这个问题就是大图显示成小图造成的像素失真 当我们在1080
  • ctf.show_web12

    f12提示 传参 cmd hightlight file index php 得到源码
  • 【抽五分钟】使用VuePress创建在线文档中心

    文章目录 安装初始化 核心配置 导航栏配置 侧边栏配置 静态资源配置 nginx部署 typora编写 安装初始化 全局安装 npm install g vuepress 创建目录 mkdir vurepress blog 项目初始化 cd
  • 使用 pair 做 unordered_map 的键值

    背景 标准库中 unordered map 是使用哈希表实现的 对于内置类型标准库通过 std hash 提供了哈希函数的实现 因此若采用非内置类型做键值 则需要程序员自己提供其哈希函数的实现 用 pair 做键值 自定义哈希函数 stru
  • Spring-Boot-Admin--快速学习--按应用实例添加标签--08

    代码地址 https gitee com DanShenGuiZu learnDemo tree master springboot admin learn 一 按应用实例添加标签 Tags 是我们区别同一应用的不同实例的方法 1 1 举例
  • 如何用电路区分 OC门与TTL

    这是两个概念 oc门是输出驱动方式 指集电极开路驱动 在电路中如果输出有一个电源到输出端的上拉电阻通常就是OC门 OC门只能灌电流 你说的TTL可能是指没注明的图腾拄驱动 即用不同极性的两个管子推拉驱动 不需要外接电源 高电平时可给负载提供
  • Vue第二篇:概念深度剖析

    参考链接 https www bilibili com video BV1oj411D7jk spm id from 333 788 recommend more video 0 vd source 3969f30b089463e19db0
  • 人生如一趟旅行

    http www putclub com html download life prose 2011 0311 27595 html Life is like a train ride We get on We ride We get of
  • HikariPool一直报连接不可用

    前言 一开始发现测试环境报错 原先配置6现在配置20依然还是很频繁的报错 想看下底层到底如何处理的导致这个问题 到底什么情况 排查 看了下日志连接数大量的空闲 看日志活跃的却是满的疑惑 2023 07 18 13 17 15 258 xxl
  • Java EnumMap putAll()方法具有什么功能呢?

    转自 Java EnumMap putAll 方法具有什么功能呢 下文笔者讲述EnumMap中putAll 方法的功能简介说明 如下所示 EnumMap中putAll 方法的功能 向map中批量添加一个map元素 EnumMap中putAl
  • MSBuild入门(续)

    MSBuild基本概念 续 在上一篇简单的介绍了下MSBuild中的四个基本块 每块介绍比较单薄 在这里对在大多数的项目模版生成的 proj文件中比较常见一些用法和概念做些补充 主要有一下几方面 MSBuild特殊字符 MSBuild保留的
  • 狄利克雷卷积 && 莫比乌斯反演

    狄利克雷卷积 莫比乌斯反演 狄利克雷卷积 数论函数及其运算 数论函数是指定义域是正整数 值域是一个数集的函数 加法 逐项相加 即 f h n f n h n 数乘 这个数和每一项都相乘 即 xf n x f n 狄利克雷卷积 定义两个数论函
  • Verilog 实现千兆网UDP协议 基于88E1111--数据发送

    Verilog 实现千兆网UDP协议 基于88E1111 数据发送 注 此版本没有添加ARP PING 等 未完待续 注 项目采用Verilog开发 基于Vivado编译器 UDP User Datagram Protocol 一种基本的