问题排查
之前在b64_data_gen模块中出现的问题查明白了。之前的问题是,模块最后的fifo中,控制读出数据的信号read_b64_ready始终为低电平。
read_b64_ready信号是ad_data_blob_generator模块中的输出信号,用于反馈b64_data_gen模块的工作,需要ad_data_blob_generator模块中状态机正常工作才能有符合预期的输出。
config_request_succed和m_data_slice_axis_tready两个信号,控制了ad_data_blob_generator模块中状态机工作,实际只需要该信号持续高电平即可,但是这个信号是后面的udp数据传输模块反馈的输出信号,需要实际进行数据打包发送才可以获得,仿真时不好模拟出来。所以后面尝试直接给这两个信号输入高电平,再进行仿真,显示到的b64_data_gen模块和ad_data_blob_generator模块都可以正常工作了。
补:后续继续看了后面的模块,发现config_request_succed与m_data_slice_axis_tready,这两个信号和blob_fifo_udp_transmit模块有关,该模块需要使用到SFP+通信产生的156.25MHz时钟信号,该时钟信号通过UDP_NET_PHY产生。我的仿真中,该模块工作出现问题,没有产出156.25MHz时钟信号,因此包括blob_fifo_udp_transmit模块,后面所有用到该时钟信号的模块都无法正常工作。还需要再继续理解UDP_NET_PHY模块。

后续模块阅读
ad_data_blob_generator 模块功能
设置跳过ARP,在仿真文件中,观察到ad_data_blob_generator模块中的状态机跳转逻辑为STATE_GE_IDLE、STATE_GE_HEADER、STATE_GE_HEADER_LAST、STATE_GE_SLICE、STATE_GE_SLICE_LAST的顺序循环。各个模块工作流程:
- STATE_GE_IDLE:当config_request_succed信号就绪,如果接收到b64_data_gen模块中开始产出b64_data的start_ad信号,则在下一周期跳转到STATE_GE_HEADER状态;与此同时,通过slice计数器判断该slice是否为blob中最后一个,根据判断结果决定slice长度为最大slice长度data_slice_prev_sa_len,还是最后的slice长度data_slice_last_sa_len。
- STATE_GE_HEADER:通过m_data_slice_axis_tdata_int信号传输该slice的data_slice_cnt, data_blob_cnt , data_blob_sa_len,即slice编号,blob编号,本次采样点点数。
- STATE_GE_HEADER_LAST:通过信号传输该slice的job_id,sample_coef,channel_num, m_data_slice_sa_len_reg , data_blob_sa_cnt,即id号,降采样倍率,通道数,本次slice长度,该slice在本blob中的计数序号;之后跳转到STATE_GE_SLICE。
- STATE_GE_SLICE:在读取到b64_valid信号后,通过m_data_slice_axis_tdata_int更新4通道采样数据,此时掩码m_data_slice_axis_tkeep_int置{KEEP_WIDTH{1'b1}},其他时候掩码置{KEEP_WIDTH{1'b0}};每次采样的所有通道数据全部传输过来,sample_end信号到来后,slice采样点计数器data_slice_sa_cnt_next,和blob采样点计数器data_blob_sa_cnt_next自增。
- STATE_GE_SLICE_LAST:同样是通过m_data_slice_axis_tdata_int更新slice里面最后一个4通道采样数据,之后判断该数据是slice还是blob的最后一个数据,根据判断结果决定data_slice_ready和data_blob_ready信号状态。
通过上述流程可知,数据传输到ad_data_blob_generator模块后,每次先在STATE_GE_IDLE等待,之后发送完毕blob的配置信息后开始工作,两个周期发送slice的头部信息,然后每次发送4通道的采样数据,直到一个slice的数据发送完毕,然后回到IDLE状态开始新一轮循环。
blob_fifo_udp_transmit
该模块接收UDP传输时的相关信号,监测UDP传输的状态,通过状态机在不同状态反馈信号给采集数据处理打包相关模块,调节相关模块的工作。
在ARP中,有状态机控制工作:
- ARP_IDLE:如果使用静态MAC地址,即程序中设置USE_STATIC_MAC=1,则直接跳过ARP请求,拉高arp_request_succed并跳转到ARP_RESPONSE_SUCCED;否则使用的使能信号led_lite_sync到来后,跳转到ARP_REQUEST状态发送请求。
- ARP_REQUEST:拉高arp_request_send信号,等待ARP请求发送完毕,UDP_IP_MAC模块返回相关信号后,跳转到ARP_GET_RESPONSE状态。
- ARP_GET_RESPONSE:UDP_IP_MAC模块返回通信的接收端MAC地址,检查该MAC地址是否为设定的接收端设备MAC地址,根据检查结果决定跳转至ARP_RESPONSE_SUCCED还是ARP_RESPONSE_ERROR。
- ARP_RESPONSE_SUCCED:拉高arp_request_succed,反馈给b64_data_gen模块中的fifo,使其可以输出b64_data。当IP 层发送数据包时,因 ARP 协议无法解析目标的 MAC 地址,导致发送失败时,ip_tx_error_arp_failed信号拉高,状态机跳回IDLE状态。
- ARP_RESPONSE_ERROR:拉低arp_request_succed和arp_request_send信号后,跳回IDLE状态。
程序的实际应用中,如果使用静态MAC地址,跳过了ARP请求,因此可以认为在使能信号到来后,状态机始终处于ARP_RESPONSE_SUCCED状态,此时arp_request_succed信号保持高电平。
另外,本模块还有一个UDP数据发送状态机,用于控制UDP协议栈中数据的发送流程:
- UDP_IDLE:等待状态,接收到数据准备信号m_udp_tx_en后,跳转至UDP_SEND_HEADER状态,准备发送UDP 头部状态。
- UDP_SEND_HEADER:检测m_udp_hdr_ready信号,高电平时拉高m_udp_hdr_valid,通知 UDP 协议栈头部可发送,并从fifo中读出数据data_slice_fifo_axis_tdata等信号,跳转到UDP_SEND_PAYLOAD状态,开始发送数据;否则保持该状态准备发送头部。
- UDP_SEND_PAYLOAD:检测检测m_udp_payload_axis_tready信号,高电平时表明UDP协议栈的UDP数据接收端就绪,此时持续从fifo中读出数据,同时判断本次数据是否为slice的最后一个,是则跳转至UDP_SEND_PAYLOAD_LAST,否,则本状态下发送数据。
- UDP_SEND_PAYLOAD_LAST:拉低读使能信号,停止从fifo中读出数据,发送slice最后一个数据,同时slice计数器data_slice_cnt自减,调至UDP_SEND_END状态。
- UDP_SEND_END:根据slice计数器判断当前的slice是否为最后一个,是,则跳至UDP_IDLE状态,否,则调制UDP_SEND_HEADER状态,准备开始发送下一个slice。
初始程序运行测试
PL端的UDP输出传输原始程序尝试在win系统下运行了,通过wireshark抓包可以接收到传出的数据包。
  
本文章使用limfx的vscode插件快速发布