Menu Close

以太网UDP 实验(eth_udp_rx.v)

当以太网包数据被正确接收后, 解析出正确的IP地址后,送给UDP模块处理。 UDP模块需要检查源端口号,目的端口号,检查UDP的checksum是否正确,如果所有检查都是正确的,将数据送给应用层。

ethernet verilog code flowchart

图1

UDP rx interface

图2

状态机(udp_rx_st)逻辑的描述如下,状态流程图如图3(注意省略了状态转移条件不满足时,停留在当前状态的箭头)所示:

状态机处理过程:其中任何一步检查出错误,将状态机跳转到12。

状态0:初始化相应的寄存器,将A/B Buffer的子地址指向 1023, 跳转到状态1。注意这里udp_checksum被初始化成-20,因为在代码中计算了一次UDP包头长度,一次IP包头长度,实际上需要的是两次UDP包头长度,所以将差值(-20)先设置好。

状态1:等待1个时钟周期, 跳转到状态2。

状态2:两个时钟周期后,从子地址1023处读出标志,用来查看UDP_RX_DRAM中是否有数据包需要解析(A/B Buffer是否可以读数据),如果有, 跳转到状态3。设置A/B Buffer地址到IP长度处。

状态3:读取UDP_RX_DRAM中数据包的长度, 跳转到状态4。设置A/B Buffer地址到IP协议处。

状态4:计算IP长度的checksum, 跳转到状态5。设置A/B Buffer地址到源IP地址处。

状态5:计算IP协议 的checksum, 跳转到状态6。设置A/B Buffer地址到源IP地址处。

状态6:计算源IP地址, 目的IP地址, UDP源port, 目的port的checksum, 跳转到状态7。

状态7:计算UDP数据长度, 计算UDP长度的checksum, 跳转到状态8。验证UDP源port, 目的port是否正确,如果不正确,立起udp_rx_error。

状态8:计算UDP checksum (16-bit)的checksum, 跳转到状态9。注意这里判断了udp_rx_len[15]是否为1,如果为1,则表示在状态7中  udp_rx_len <= udp_rx_data[11:0] – 8;   的结果是负数,因此说明UDP的长度小于8(包头不完整),转到状态13,并立起udp_rx_error。这里也收集前面状态7的UDP源port或 目的port错误,转到状态13。如果没有错误,转到状态9。

状态9:根据UDP数据计算checksum,读出数据,如果剩余数据大于两个byte,转到状态10;如果剩余数据少于两个byte,转到状态12,注意要区分剩余1个byte数据,和数据偶数个被读完的情况(剩余0个byte数据)。

状态10:根据UDP数据计算checksum,读出数据,如果剩余数据大于两个byte,转到状态9;如果剩余数据少于两个byte,继续判断:如果剩余1个byte数据,转到状态11;如果是数据偶数个被读完的情况(剩余0个byte数据),转到状态12。

状态11:处理奇数长度的最后一个数据,同时计算checksum,跳转到状态12;

状态12:计算checksum的结果,如果计算的结果正确或者UDP包中checksum位置填写的是0,跳转到状态13; 如果checksum计算的结果不对,表示checksum 错误信息,跳转到状态13

状态13:清除UDP_RX_DRAM的封包字节, 跳转到状态14。

状态14:跳转到状态15。

状态15:UDP_RX_DRAM的A/B Buffer 位置加一, 跳转到状态0。

 

UDP rx state machine flowchart

图3 udp_rx_st流程图

 

eth_udp_rx.v 代码:


 

 

 

Posted in FPGA, FPGA 教材教案, RISC-V架构, Verilog, 教材与教案, 文章