目录
一.概述
1.1IP协议
1.1.1IP协议简介
1.1.2IP协议首部报文格式
1.2ICMP协议
1.2.1ICMP协议简介
1.2.2ICMP报文格式
二.实验任务
三.模块设计
3.1总体模块设计
3.2ICMP模块设计
3.2.1icmp_rx 模块
3.2.2icmp_tx模块
四.modelsim仿真
4.1icmp_rx模块仿真
4.2icmp_tx模块仿真
五.板级验证
一.概述
1.1IP协议
1.1.1IP协议简介
IP 协议是 TCP/IP 协议簇中的核心协议,也是 TCP/IP 协议的载体,IP 协议规定了数据传输时的基本单元和格式。如下图所示,之所以先介绍IP协议,因为IP协议中包含ICMP协议。即ICMP协议位于IP层的数据段。所有的 TCP、UDP 及 ICMP 数据都以 IP 数据报格式传输。
1.1.2IP协议首部报文格式
IP首部一共20Byte,1个Byte=8bit,故一行4Byte(32bit),共有5行。
1.2ICMP协议
1.2.1ICMP协议简介
1.2.2ICMP报文格式
由1.1.1中的图可知ICMP首部一共8Byte,一行4Byte,故一共两行。
二.实验任务
三.模块设计
3.1总体模块设计
PLL模块:因为gmii_to_rgmii模块中的输入延时控制IDELAYCTRL中需要用到PLL倍频输出的200MHZ时钟。
FIFO模块:以太网单次会接收到大量数据,因此本次实验需要一个 FIFO 模块用来缓存数据,由于本次实验所使用的 GMII 接收时钟和 GMII 发送时钟实际上为同一个时钟,因此这里使用的是同步 FIFO。
arp模块:由于上位机应用程序只知道接收端的目的 IP 地址和端口号,却不知道接收端的 MAC 地址,因此这里需要通过 ARP 协议来获取接收端的 MAC 地址。
icmp模块:发送和解析icmp协议包,和arp模块功能类似,只不过协议时序数据不一样而已。
3.2ICMP模块设计
ICMP 接收模块按照 ICMP 的数据格式解析和发送数据。
3.2.1icmp_rx 模块
3.2.1.1整体模块图
clk:接收的icmp时钟信号
rst n:复位信号,低电平有效
gmii_rx_dv:GMII输入数据有效信号
gmii_rxd:GMII输入数据
icmp_id:ICMP标识符
icmp_seq:ICMP序列号
rec data:以太网接收的数据
rec en:以太网接收的数据使能信号
rec_pkt_done:以太网单包数据接收完成信号
rec_byte_num:以太网接收的有效字数
reply_checksum:接收数据校验
3.2.1.2波形图
gmii_rx_dv:gmii_rx_dv 为 GMII 输入数据有效信号,当 gmii_rx_dv 拉高则开始输入数据.
gmii_rxd[7:0]:为 GMII 输入数据信号,当 gmii_rx_dv 信号拉高,开始 ICMP 接收模块输入 GMII 数据信号。这里中间数据段标gmii_rxd是因为不确定接收来的以太网帧数据里是arp协议还是icmp协议。
icmp_id:当接收数据到gmii_rxd时,开始按照icmp协议逐步解析数据,icmp_id 为 ICMP 的标识符,共占用了 16bit 位,对于每一个发送的数据报进行标识。上图中的黄色部分。
icmp_seq:icmp_seq 信号(ICMP 序列号),同样占用了 16 bit 位,对于发送的每一个数据 报文进行编号。上图中的紫色部分
rec_data:为以太网接收的数据.上图中的肤色部分。
rec_pkt_done: 为以太网单包数据接收完成信号,当数据接收完成后 rec_pkt_done 信号拉高
rec_en:为以太网接收的数据使能信号,将GMII接收数据传递到rec_data,当开始接收数据时,GMII 输入数据有效信号为高,rec_en 信号拉高。
rec_byte_num 为以太网接收的有效字数,主要用于统计以太网接收的有效字数,在当数据接收完成后,将该信号的数据传递到发送模块。
reply_checksum 为接收数据校验信号,单包数据接收完成后,将该信号的数据通过输出信号进行数据反馈。
3.2.1.3解析以太网数据状态转换图
这与arp实验中的转换图意思大致一致,不解释。
3.12.1.4代码解析
状态机空闲时,GMII输入数据有效信号gmii_rx_dv为1时,并且第一个前导码来临。代表以太网帧数据来临,可以解析数据了 ,故skip_en=1,跳转至解析前导码+SFD状态。
前导码是7个8'h55+1个8'h05.因为空闲状态时已经解析出一个 8'h55,因此这里只用检测6个 8'h55。若两项均正确,则跳转至接收以太网帧头(目的MAC地址+源MAC地址+长度/类型)。只要其中一个接收有误则结束接收。
因为目的MAC地址6Byte(cnt=0~5),源MAC地址6Byte(cnt=6~11),长度/类型2Byte(cnt=12~13)。这里只用检查目的MAC是开发板MAC还是广播MAC,类型是否为IP协议,是则继续接收,否则立即终止接收。 0x0800 代表 IP 协议(网际协议)、0x0806 代表 ARP 协议(地址解析协议)。
由上图可以看出IP首部总共20Byte,因此cnt计数范围是(0~19),gmii_data在时序下按照以上表格顺序(首部长度—版本—服务类型—总长度—标识—。。)传递数据,整体的代码就是按照此顺序借助cnt索引依次解析。
注意,cnt=5时,ip_head_byte_num <= {gmii_rxd[3:0],2'd0}=5x4=20。因为将0101左移两位相当于010100=20,故左移两位相当于x4。
由上图可以看出ICMP首部总共8Byte,因此cnt计数范围是(0~7),gmii_data在时序下按照以上表格顺序(类型—代码—校验和—标识符—序列号)传递数据,整体的代码就是按照此顺序借助cnt索引依次解析。
将上图中的ICMP数据(上图肤色部分)进行16位拼接,累加。
1:当数据段没有接收完时,首先对接收的8位数据gmii_rxd进行打拍得到icmp_rx_data_d0,然后将上一时钟的8位gmii_rxd(icmp_rx_data_d0)与本时钟下的8位gmii_rxd进行拼接,拼接为16位数据,然后进行累加。如下图所示。
2:当数据接收到最后一个时,首先判断数据长度是不是奇数,如果是奇数,则最后一个8位数据落单,高八位需要拼接8个0.若长度是偶数,则两两8位数据拼接,不需要进行额外操作。
3.2.2icmp_tx模块
3.2.2.1整体模块图
clk:rxc时钟信号
rst n:复位信号,低电平有效
tx_start_en:以太网开始发送信号
icmp_id:ICMP标识符
icmp_seq:ICMP序列号
reply_checksum:ICMP数据部分校验和
des mac:发送的目标MAC地址
des_ip:发送的目标IP地址
tx data:以太网待发送数据
tx_byte_num:以太网发送的有效字节数
crc data:CRC校验数据
crc next:CRC下次校验完成数据
tx done:以太网发送完成信号
tx_req:读数据请求信号
gmii_tx en:GMII输出数据有效信号
gmii_txd:GMII输出数据
crc_en:CRC开始校验使能
crc_clr:CRC数据复位信号
3.2.2.2波形图
reply_checksum:由icmp_rx模块传来的ICMP数据部分校验和。
icmp_id:ICMP标识符
icmp_seq:ICMP序列号
tx_start_en:为以太网开始发送信号,当 tx_start_en 信号拉高之后,开始发送以太网数据。
tx_data:tx_data 为以太网待发送数据.
tx_byte_num:tx_byte_num为以太网发送的有效字节数.
crc_en:当发送数据段位于MAC帧头+IP首部+ICMP首部+ICMP数据段(填充数据除外)此时crc_en拉高,对数据进行校验。
gmii_tx_en:为 GMII 输出数据有效信号,gmii_txd 为 GMII 输出数据,当 gmii_tx_en 信号拉高,GMII 开始发送数据,当 gmii_tx_en 信号拉低表示数据发送完成.
3.2.2.3发送以太网数据状态转换图
3.2.2.4代码解析
tx_start_en为异步信号,捕捉上升沿因此这里打三拍处理。 得到发送使能信号pos_start_en信号,并将该信号暂存起来trig_tx_en。
tx_byte_num是以太网发送的有效字节数 ,相当于上图中的紫色部分。
由上图可知:total_num=28+8+(18~1472Byte)
该段代码是将紫色部分长度(以字节为单位)和绿色部分长度暂存起来。
空闲状态:当发送使能来临时, 按照上面表格,依次将每行数据赋值给ip_head。注意,ip_head是二维数据,位宽是32[0:31]因为一个ip_head代表上面表格的一行,数据深度是7[0:6],因为5行ip首部+2行icmp首部=7行数据。
赋值目的IP时注意,当目的ip更新时,ip_head[4]就赋值为刚更新的值,若没更新,则使用默认值。
同理,当目的MAC值更新时,则赋值更新值,若没更新则使用默认值。
该段作用是对IP首部的值进行校验。
该段作用是对icmp首部+数据段进行校验。
当前面校验无误时,开始发送以太网数据,同arp实验类似,先发送前导码+SFD,再发送MAC帧首部。
该段作用是发送IP首部还有ICMP首部,一共7行数据,但是一行数据32Bit,一个时钟周期只能发送8bit,因此一行数据要四个时钟周期才能发完。这里7行数据用cnt计数,四个时钟周期用tx_bit_sel计数。
注意,这里tx_req提前两个周期拉高,因为读FIFO里数据有两个clk延迟,故这里提前拉高。
data_cnt:发送数据个数计数器,技术范围(0~ 发送的有效数据字节总数-1)。
以上代码就是算出以太网数据实际多发的字节数,例如发送的有效数据字节总数是26,而以太网数据中的数据段最小18个字节,26-18=8,8就是以太网数据实际多发的字节数。
四.modelsim仿真
4.1icmp_rx模块仿真
4.1.1接收前导码
4.1.2接收以太网帧头
包含目的MAC、源MAC、长度/类型
4.1.3接收 IP首部
4.1.4接收ICMP首部
4.1.5接收数据段
4.2icmp_tx模块仿真
4.2.1校验IP首部
因为这里有进位,因此0002+889f=000088a1。后面没有进位,因此不用再累加。直接按位取反即可。
4.2.2校验icmp首部+数据
4.2.3发送数据段
五.板级验证
首先设置PC端的IP,如下所示。
然后以管理员身份打开命令符窗口,以arp-a命令查看MAC与IP映射表。
使用PING命令,PC端向开发板发送请求包。可以看出开发板很快回复报文。
再次使用arp -a命令查看MAC与IP的映射表,可以看出已经建立连接。