原始的AD组blob的代码只有数据部分,即接收AD数据然后添加slice头部,后续跟ADC数据,现有修改如下:
接收UDP网络栈的ARP请求和回复状态。在ARP请求状态下,AD组blob会生成一个包含ADC运行参数和AD组blob参数的UDP包。
在ARP成功回复后,切换到正常的接收ADC数据然后组slice和blob状态。
原有的UDP发送代码为直接生成udp payload,现在修改如下:
在AD blob后连接到一个axis_async_fifo
模块,用于缓存blob数据和解决跨时钟域问题。因为AD组blob模块运行于100MHz
时钟域,UDP协议栈运行于156.25MHz
时钟域。
保留原有的ARP相关操作,即第一次运行时先进行ARP请求,同时发信号给AD组blob模块,生成相关的配置数据包。
使用ad_slice_ready
信号和ad_blob_ready
信号进行发送开始,同时可以指定使用哪一个信号作为发送开始信号。使用ad_slice_ready
作为发送开始信号时,每生成一个slice就发送一次;使用ad_blob_ready
作为发送开始信号时,每个slice会被缓存,当所有slice生成完成即一个blob生成完成后,开始发送该blob内的所有slice。
初步设计效果如下。SFP0_TXD上,2.57us时发送一个配置信息的udp包,触发5.9us一次ARP查询。ARP查询成功,即config_request_succed_tb
信号拉高。后续在7.145us时ad_data_blob_ready
信号拉高,表示一个bolb生成完毕,触发UDP传输。7.48us时UDP数据包的以太网帧出现在SFP0_TXD上,被传输出去。
由于涉及到axis_async_fifo
的读写,目前读取时发现多一个数据,需要解决读取状态机设计。
原始设计中需要根据AD组blob时设置参数,得到每个silce包含头部的长度信息,即本次待发送的udp数据包的长度。但在分析UDP代码后发现udp_64
模块中包含udp_checksum_gen_64
模块,默认启用。该模块的作用为:
64bits AXIS_FIFO
,深度2048
。缓冲来自UDP输入部分的数据。在使用udp_checksum_gen_64
模块后,关键数据数据路径上包含两个FIFO:
udp_checksum_gen_64
内部FIFO,用于缓冲UDP payload数据并计算UDP相关信息。
eth_mac_10g_fifo
内部FIFO,用于缓冲MAC数据并转换到XGMII
,与GTH
收发器对接。此外还用于计算CRC32使用。
以上两个FIFO的读写是主要的延时来源。下图中,第一次进行UDP发送在约7.6us时进行,而SFP0_TXD上第一次出现数据帧的时间是约9.72us,时延约为2.1us左右,约为2.2个UDP发送周期。
该时延可以通过去除udp_checksum_gen_64
进而减小一半,而eth_mac_10g_fifo
需要用于计算CRC32,必须保存。udp_checksum_gen_64
主要用于计算udp_checksum和udp_length
,udp_checksum可以在生成udp payload时进行计算,而udp_length可以在拿到udp_payload长度后加上8个字节长度即可。作者在设计udp_checksum_gen_64
模块也保留了CHECKSUM_GEN_ENABLE
参数,说明该模块可以不启用,由用户自行计算UDP相关信息。
本文章使用limfx的vscode插件快速发布