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

2023-10-30

注:此版本没有添加ARP PING 等,未完待续。
注:项目采用Verilog开发,基于Vivado编译器。
注:本版本没有计算校验
与上一篇相同开发环境,采用三段式状态机。
同样,接收后将数据写入FIFO,相比于数据发送更为简单,只需在写入数据时同步拉高FIFO使能就可以。
对外接口如下:

	input 	      				clk_i, //RX_clk
	input						rst_n,
	/*eth interface*/
	input  						Rxer_i,  
	input  						Rxdv_i, 	
	input		[ 7:0] 			Rxd_o,     
	/*control interface*/
	input 		[ 3:0]			Eth_Command,
	/*fifo interface*/
	output reg	[ 7:0] 			Fifo_Data_i,
	output reg 					Fifo_Wr_en	

其中Rxdv_i为关键信号数据输入有效,只有当此信号为高,才证明这个数据是正确的。
Rxer_i 这个信号暂时没有用,具体在板上验证时做修改。
本模块状态划分如下:

localparam  idle        	=  8'b1111_1110; //fe
localparam  Rec_MAC_addr  	=  8'b1111_1101; //fd
localparam  Rec_IP_addr   	=  8'b1111_1011; //fb
localparam  Rec_ARP     	=  8'b1111_0111; //f7
localparam  Rec_Data     	=  8'b1110_1111; //ef
localparam  Rec_Over     	=  8'b1101_1111; //df
localparam  Rec_Zero		=  8'b1011_1111; //bf

状态1、空闲状态:当使能开启时,等待外部输入正确引导码启动
状态2、接收MAC地址,同时判断是否正确
状态3、同上接收正确IP地址
状态4、保留,上次还没有做ARP的发送
状态5、开始接收数据,从上面信息中提取数据数量,来判断需要读取多少数据
状态6、接收完成,写入本次数据的帧尾(包计数、数据量),用于判断是否丢包或丢数据
状态7、将各寄存器清零。如果不清,会在起始状态时寄存器内就有正确数据。
切换状态条件:

		idle:			nstate <= (	(Eth_Command[3] == 1'b1) && 
									(Identifiy_Data[63:0] == `Leading_code))
									? Rec_MAC_addr : idle;
		Rec_MAC_addr: begin
			if( State_turn 	== 1'b1 ) begin
				if(MAC_Data[ 63:16]  == `Destination_MAC && MAC_Data[111:64]  == `Source_MAC) begin
					if(MAC_Data[ 15: 0]  == `IP_TYPE) begin
						nstate <=  Rec_IP_addr;
					end
					else if(MAC_Data[ 15: 0]  == `IP_TYPE_ARP) begin
						nstate <=  Rec_ARP;
					end
					else begin
						nstate <= idle;
					end
				end
				else begin
					nstate <= idle;
				end
			end			
			else begin
				nstate <= Rec_MAC_addr;
			end		
		end
		Rec_IP_addr:   begin
			if( State_turn 	== 1'b1 )begin
				if(Header_Data[ 47:32] == `Destination_Port && 
				   Header_Data[ 63:48] == `Source_Port 		&& 
				   Header_Data[ 95:64] == `Destination_IP 	&& 
				   Header_Data[127:96] == `Source_IP ) begin
					nstate <= Rec_Data;
				end
				else begin
					nstate <= idle;
				end
			end
			else begin
				nstate <= Rec_IP_addr;
			end
		end
		Rec_Data: nstate <= (State_turn == 1'b1) ? Rec_Over : Rec_Data;
		Rec_Over: nstate <= (State_turn == 1'b1) ? Rec_Zero : Rec_Over;
		Rec_Zero: nstate <= idle;

当外部命令开启使能,就开始接收数据,接收到争取引导码后,跳入下一状态
Start_turn :与上一篇判断条件一样,接收正确数量的数据后,判断各地址是否正确,正确进入下一状态,不正确跳回idle。
数据管理代码

			idle: begin
				if(Rxdv_i)begin
					Identifiy_Data[63:0] <= {Identifiy_Data[55:0],Rxd_o[7:0]};
				end
				else begin
					Identifiy_Data[63:0] <= Identifiy_Data[63:0];
				end
			end
			Rec_MAC_addr: begin
				if(Rxdv_i)begin
					MAC_Data[111:0] <= {MAC_Data[104:0],Rxd_o[7:0]};
				end
				else begin
					MAC_Data[111:0] <= MAC_Data[111:0];
				end
			end
			Rec_IP_addr:  begin
				if(Rxdv_i)begin
					Header_Data[223:0] <= {Header_Data[216:0],Rxd_o[7:0]};
				end
				else begin
					Header_Data[223:0] <= Header_Data[223:0];
				end
			end
			Rec_Data,Rec_Over: begin
				Identifiy_Data[ 63:0] <= Identifiy_Data[ 63:0];
				MAC_Data	  [111:0] <= MAC_Data      [111:0];
				Header_Data   [223:0] <= Header_Data   [223:0];	
			end
			Rec_Zero:begin
				Identifiy_Data[ 63:0] <= { 8{8'h00}};
				MAC_Data	  [111:0] <= {14{8'h00}};
				Header_Data   [223:0] <= {28{8'h00}};			
			end

Rxdv_i拉高,就收取数据,做移位操作,写入寄存器,接收到正确数量后,进行判断实现状态跳转。
FIFO写入代码

			Rec_Data: begin
				if(Rxdv_i)begin
					Fifo_Data_i[7:0]<= Rxd_o[7:0];
					Fifo_Wr_en		<= 1'b1;
				end
				else begin
					Fifo_Data_i[7:0]<= Fifo_Data_i[7:0];
					Fifo_Wr_en		<= 1'b0;
				end
			end

能正确跳入这个状态后,就开始按照提取出的Data_length个数,开始写就行了。
接收整体代码不多,没加校验,具体等实际用的时候看情况需不需要。
本工程是用于记录以太网数据,并写入存储器内。
还在等板子中…先看看仿真叭,代码:

initial begin
	clk_o  = 1'b1;	
	forever begin
		#10ns clk_o = ~clk_o; //10Mhz
	end
	//#10200 RX_START = 1'b0;
end	
initial begin
	rst_n = 1'b0;
	Data_length = 16'd1500;
	#1000ns rst_n = 1'b1;
	
end

always @(posedge clk_o or negedge rst_n)
begin
	if(!rst_n) begin
		Fifo_Data_i <= 8'hFF;
	end
	else if (Fifo_Rd_en)begin
		Fifo_Data_i <= Fifo_Data_i + 1'b1;
	end
	else begin
		Fifo_Data_i <= Fifo_Data_i;
	end
end
always @(posedge clk_o or negedge rst_n)
begin
	if(!rst_n) begin
		Eth_Command = 4'h0;
		#500ns
		Eth_Command = 4'h0;
	end
	else begin
		if(Eth_Write_Busy) begin
			Eth_Command = 4'h0;
		end	
		else begin
			#1000ns
			Eth_Command = 4'hA;
		end
	end
end
endmodule

顶层连接关系:ETH_Send是上篇文章的代码

test test_u(
	.clk_o					(clk_i),
	.rst_n					(rst_n),
	.Eth_Command			(Eth_Command),
	.Data_length			(Data_length),
	.Eth_Write_Busy 		(Eth_Write_Busy),
	.Fifo_Data_i			(Fifo_Data_o),
	.Fifo_Rd_en				(Fifo_Rd_en)
	
);
	
ETH_Send ETH_Send_u(
	.clk_i					(clk_i),
	.rst_n					(rst_n),
	.Txen_o					(Txen_o),                     
	.Txer_o					(Txer_o),                     
	.Txd_o					(Txd_o),     
	.Eth_Command			(Eth_Command),
	.Data_length			(Data_length),
	.Eth_Write_Busy 		(Eth_Write_Busy),
	.Fifo_Data_o			(Fifo_Data_o),
	.Fifo_Rd_en				(Fifo_Rd_en)
	);
	
ETH_Receive ETH_Receive_u(
	.clk_i					(clk_i),
	.rst_n					(rst_n),
	.Rxer_i					(1'b0),                     
	.Rxdv_i					(Txen_o),                     
	.Rxd_o					(Txd_o),     
	.Eth_Command			(Eth_Command),
	.Fifo_Data_i			(Fifo_Data_i),
	.Fifo_Wr_en				(Fifo_Wr_en)
	);

在这里插入图片描述
问题不大,下面看看细节
在这里插入图片描述
正确提取引导码、MAC、IP、并提取出数据长度、包计数。
同时把发送读fifo的首个数据写入fifo中。
本项目还有个问题:读出数据后,会在下一个时钟发送出去,这样会时钟存在一个数据在线上,所以会首先发送出一个数据是上次读出来。这样就会在第一帧数据内多一个无效数,对后面没有任何影响,保证连续不丢。对我的应用没有影响…也就懒得改了。
暂时的想法是将读fifo的vaild信号与Txen_o强关联。具体上板验证时,再调叭。
对于接收,因为发送端fifo的问题,在接收过程中就是写入实际收到的数据。
在这里插入图片描述
可以看到把1500数据写入后写入我的帧尾 FF_FF+包计数+数据长度+FF_FF,然后将用于判断的寄存器清零。
简单收发已经实现,下一步准备添加其他模式。

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

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

  • 【华为OD统一考试A卷

    华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为OD统一考试 A卷 和OD统一考试 B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是
  • 关于Linux上面无法读取资源目录下文件的问题

    一开始我的代码是这样子的 读取本地子路径下的json文件 代码运行的时候 在window是可以正常的 Override public String getBannerStr String str try Resource resource
  • 计算机网络面试要点总结

    概述 带宽 网络可通过的最高数据率 即每秒多少比特 宽带 发送速率 宽带线路 每秒有更多的比特注入到线路中 依然是串行传输 电路交换 需要拨号建立连接 专线 浪费资源 分组交换 分组发送 接收组合 存储转发 根据路由表的下一条 协议 语法
  • Java基础(8)面向对象基础

    面向对象是Java最重要的特性 Java是彻底的 纯粹的面向对象语言 在Java中 一切都是对象 本章将介绍面向对象基础知识 1 面向对象概述 面向对象的编程思想 按照真实世界客观事物的自然规律进行分析 客观世界中存在什么样的实体 构建的软
  • FOC中的PARK变换_TI和ST电机控制库的源码实现

    FOC中的Clarke变换 TI和ST电机控制库的源码实现 FOC中的PARK变换 TI和ST电机控制库的源码实现 FOC中的反PARK变换 TI和ST电机控制库的源码实现 park变换 该变换将平衡两相正交平稳系统中的矢量变换为正交旋转坐
  • winows服务器的ftp密码如何修改,windows怎么修改服务器ftp密码

    windows怎么修改服务器ftp密码 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 只有运行中的云服务器才允许用户登录
  • 服务器虚拟架构解决方案

    服务器虚拟化的意义 如何才能最大限度的节约建设成本 降低系统管理成本 节约人力投入 在提高老业务系统的性能 还降低新系统的开发部署成本 诸如此类的问题 我想一直是我们所追求的目标 特别是在当前经济发展比较困难的时期 如何才能在有效实现政府
  • Python读取大文件与内存占用检测(常用的分步调试pdb)

    大文件读取问题 顺便记录一下vim的配置 https blog csdn net sinat 33741547 article details 74781591 https blog csdn net zwbill article deta
  • bp神经网络算法步流程_MATLAB BP神经网络的非线性系统建模非线性函数拟合

    点击上方蓝字关注 公众号 MATLAB BP神经网络的非线性系统建模 非线性函数拟合 在实际工程应用中会遇到一些复杂的非线性系统 这些系统方程复杂 难以用数学方法建模 在这种情况下 可以使用BP神经网络表达这些非线性系统 该方法把位置系统看
  • MATLAB利用FFT对信号进行频谱分析

    1 实验目的 1 进一步加深DFT算法原理和基本性质的理解 因为FFT只是DFT的一种快速算法 所以FFT的运算结果必然满足DFT的基本性质 2 熟悉FFT算法原理和FFT程序的应用 3 学习利用FFT对离散时间信号进行频谱分析的方法 了解
  • 最新golang语言面试题总结(一)

    1 go中make和new区别 new 分配内存 内存里存的值是对应类型的零值 只有一个参数 参数是分配的内存空间所存储的变量类型 Go语言里的任何类型都可以是new的参数 比如int 数组 结构体 甚至函数类型都可以 返回的是指针 mak
  • 【02】2022.11最新超详细Vuforia图片识别教程

    02 2022 11最新超详细Vuforia图片识别教程 文章目录 02 2022 11最新超详细Vuforia图片识别教程 1 Vuforia环境搭建 2 License Key获取及注册 3 AR Camera 4 图片选择条件与图片上
  • 热门面试题:v-show和v-if的区别

    v show 和 v if 都可以控制dom元素的显示和隐藏 那么具体区别是什么呢 话不多说 先来段代码对比一下 就会更容易明白 希望能对你有所帮助哦 1 先来看 v show div div
  • 34道C++面试问答(C++基础)

    C和C 有什么区别 C 是面向对象的语言 而C是面向过程的语言 C 引入new delete运算符 取代了C中的malloc free库函数 C 引入引用的概念 而C中没有 C 引入类的概念 而C中没有 C 引入函数重载的特性 而C中没有
  • php.exe f,PHP命令行执行程序php.exe使用及常用参数

    PHP命令行执行程序php exe参数说明 f 以命令行方式运行指定的PHP文件 只要指定具体的PHP文件 带绝对路径 php exe就可以执行PHP文件 所以这个参数单个使用其实有没有都无所谓 他有点类似于在游览器方式下显示PHP执行的结
  • XLSX纯前端导出(简单导出)

    npm install xlsx 安装插件 直接上代码 div a a div

随机推荐

  • 或的方式触发多个条件

    或的方式触发多个条件 include
  • Bat批处理生成带随机数的毫秒时间戳验证码

    second bat echo off set temp Spring gt Echo WScript Echo new Date getTime for f a in cscript nologo e jscript do set tim
  • POJ 1789, Truck History

    Time Limit 2000MS Memory Limit 65536KTotal Submissions 5256 Accepted 1851 DescriptionAdvanced Cargo Movement Ltd uses tr
  • 图像的频谱图简单理解

    https zhuanlan zhihu com p 99605178 utm source qq https blog csdn net dazhuan0429 article details 85774692 一维信号的傅里叶变换 将一
  • Keil 5报错identifier “KEY0“ is undefined怎末解决呀大侠们【哭】

    错误 HARDWARE EXTI exti c 42 error 20 identifier KEY0 is undefined key c include key h include delay h 按键初始化函数 PA0 15和PC5
  • 把一个对象的key全部换成大写/小写

    前言 把一个对象 他的key都是大写 或者小写的情况下给他转换类型 大写 小写 实现效果 实现方法 1 封装两个方法 大写转换 export function upperJSONKey jsonObj for var key in json
  • robot framework 使用五:CentOS上运行robot framework 并自动发送测试结果

    操作系统版本 centos 6 0 x86 64 想要在linux上运行robot framework的测试用例 需要安装以下工具和软件 1 安装python 2 7 6 首先python version 查看系统是否装有python 并且
  • Python编程:实现整数反转(含完整源代码)

    Python编程 实现整数反转 含完整源代码 在Python中 实现整数反转非常简单 我们只需要将整数转换为字符串 然后对字符串进行反转操作 最后再将反转后的字符串转换回整数即可完成整数反转 下面是实现整数反转的Python源代码 def
  • 深入浅出--梯度下降法及其实现

    转自 https www jianshu com p c7e642877b0e 深入浅出 梯度下降法及其实现 六尺帐篷 关注 2018 01 17 21 06 字数 3001 阅读 1210 评论 2 喜欢 23 赞赏 1 梯度下降的场景假
  • 常用文件的文件头(十六进制)

    JPEG jpg 文件头 FFD8FF PNG png 文件头 89504E47 GIF gif 文件头 47494638 TIFF tif 文件头 49492A00 Windows Bitmap bmp 文件头 424D CAD dwg
  • 嘀嗒出行再闯IPO:千军万马我无懈

    羽扇纶巾笑谈间 千军万马我无懈 在激烈竞争中再度冲刺港交所IPO的嘀嗒出行 闪露出一丝歌词里的气魄 交通运输部下属网约车监管信息交互系统的数据显示 截至2023年1月31日 全国共有300家网约车平台公司取得网约车平台经营许可 在2022年
  • 隐式声明函数‘raw_copy_to_user’的问题

    隐式声明函数 raw copy to user 的问题 其实一般来说都是隐式声明函数 copy to user 的问题 这类问题你就看看有没有引用正确的头文件 例如有些是
  • 一些常见面试OO design题目总结

    最近很多公司面试喜欢问一些OO design的题目 我总结了一些比较高频的题目 需求不一定准确 设计的也不一定好 欢迎提出建议 1 电梯设计 2 停车厂设计 3 通用卡牌游戏blackjack设计 4 1 电梯设计 需求 以面向对象的方式设
  • vue知识点总结

    vue知识点总结 1 vue是渐进式的javaScript框架 其作者是尤雨溪是以为华裔前google工程师 是一个动态构建用户界面 个人理解为可以在一个界面中动态展示其中某一部分的数据显示 运行 转换等功能 相比于jsp html页面有着
  • VRRP技术(详解)

    一 VRRP的概述 用户一般都是采用一个默认的网关来访问外部网络 如果此时默认网关设备发生故障 将中 断所有用户终端的网络访问 导致不可挽回的损失 VRRP可以实现多网关 并且可以解决多网关运行中冲突的错误 二 VRRP术语 VRRP路由器
  • jvm面试题,jvm常见高频面试题汇总,必知必会

    1 Java 类加载过程 Java 类加载需要经历一下 7 个过程 1 加载 加载是类加载的第一个过程 在这个阶段 将完成一下三件事情 通过一个类的全限定名获取该类的二进制流 将该二进制流中的静态存储结构转化为方法去运行时数据结 构 在内存
  • 线程安全性分类

    1 不可变 不可变的对象一定是线程安全的 并且永远也不需要额外的同步 因为一个不可变的对象只要构建正确 其外部可见状态永远也不会改变 永远也不会看到它处于不一致的状态 Java 类库中大多数基本数值类如Integer String和BigI
  • Mysql5.7 + 查询并解析json数据方法(后转)

    说明 本文是对 Mysql5 7 查询并解析json数据方法 的补充说明 具体请点击查看 当前 也可以认为就是水贴 对于某个属性的值未数组的时候 我们取某一条中某一条某个元素 大家应该都理解了 具体 如下 详情请看上一篇 Mysql5 7
  • HBase Java API使用IDEA开发----mapreduce读取hdfs文件写入hbase

    一 配置hadoop读取hbase的支持包 在hadoop env sh 添加export HADOOP CLASSPATH HBASE HOME lib 没有配置HBASE HOME的去 etc profile配置环境变量 路径根据你自己
  • Verilog 实现千兆网UDP协议 基于88E1111--数据接收

    注 此版本没有添加ARP PING 等 未完待续 注 项目采用Verilog开发 基于Vivado编译器 注 本版本没有计算校验 与上一篇相同开发环境 采用三段式状态机 同样 接收后将数据写入FIFO 相比于数据发送更为简单 只需在写入数据