一、实验要求
验证udp传输过程中是否发生了如下问题:
- 数据包内数据损坏
- 丢包
- 数据包的顺序不正确
二、任务分析
在上述实验的基础上进行修改,利用FPGA设计计数器电路替换ADC采集模块,通过不断循环+1的数据,即可在接收端判断接收数据的连续性。生成的数据送入FIFO通过zynq读取,在数据包前添加udp包序号即可在上位机接收时验证是否丢包或错序。udp发送到主机,分析数据的连续性,验证udp传输的特性。
三、实验设计
3.1硬件环境搭建
大致设计与上述实验类似,不过需要将FPGA+DAC产生正弦波的部分删除,替换自定义IP核ad9280_sample,并删除其相关的端口。
因为涉及了PL-PS的数据交互,因此采用自定义 IP核的形式实现计数器电路,本IP核在上一实验的自定义 IP核ad9280_sample上修改,其中axis interface相关部分、状态机部分、xpm定义的fifo模块(注意修改写wr_clk、wr_en、din的例化实参)无需改动,计数器代码如下所示:
parameter cnt_max= 255;
//计数范围0-255
always @ (posedge cnt_clk or negedge cnt_rst_n) begin
if (!cnt_rst_n)begin
cnt_next<=8'd0;
end
else begin
if(cnt_next < cnt_max)begin// 未计数到最大值, 下一值加1
cnt_next<=cnt_next+1'b1;
end
else begin
cnt_next= 0;// 计数到最大值,下一计数值为0
end
end
end
// 时序逻辑 更新下一时钟周期的计数值
// CNTVAL 会被编译为D触发器
always @ (posedge cnt_clk or posedge cnt_rst_n) begin
if(!cnt_rst_n)
cnt <= 0;
else
cnt <= cnt_next;
end
由于保留了8位数据位宽的设定,因此技计数范围为0-255
.sample_len (slv_reg1 ),
.sample_start (slv_reg0[0]),
采样长度sample_len与开始采样标志sample_start同样例化为寄存器1与寄存器0
之后,在Pacnkage IP -Ports and Interfaces 时,为m00_axi_aclk添加参数如下
同样的,计数器时钟cnt_clk的ASSOCIATED_BUSIF值设置为计数值cnt。
硬件设计中其余IP核的设定基本与上一实验保持一致。
3.2软件设计
软件部分同样是在上一实验的vitis程序的基础上进行修改,首先修改IP的基地址及REG0与REG1地址,相关参数在xparameter.h文件中(此处参数名称保留了,没有影响)
#define AD9280_BASE XPAR_COUNT_IP_0_S00_AXI_BASEADDR
#define AD9280_START COUNT_IP_S00_AXI_SLV_REG0_OFFSET
#define AD9280_LENGTH COUNT_IP_S00_AXI_SLV_REG1_OFFSET
为了上位机能方便的分析数据的连续性,上一实验将数据转换为了有符号数,本次实验保持无符号数。
因为共发送1024个数据包,因此需要2字节来记录数据包的顺序,对上一实验中的udp协议中,获取数据的应答命令进行修改,如下
字节数 | 命令信息 |
1 | Header|0x01 |
2 | 0x0001 |
2 | udp包序号 |
1024 | ADC数据 |
其对应的为数据包部分添加序号的代码如下,
for(int i = 0 ; i < ADC_SAMPLE_NUM ; i++)
{
DmaBufferTmp[i] = (short)(DmaRxBuffer[i]) ; //保持无符号数,扩展为short类型
}
fg = 0;
/* Separate data into package */
for (int i = 0; i < FrameLengthCurr; i += 1024)
{
fg = fg +1 ;
char buf[2] = {0};
buf[0] = (fg >> 8 & 0xFF);
buf[1] = fg & 0xFF;
memcpy((unsigned char*)(TargetHeader + 3),&buf,2);
if ((i + 1024) > FrameLengthCurr)
udp_len = FrameLengthCurr - i;
else
udp_len = 1024;
send_adc_data((const char *) DmaBufferTmp + i, udp_len);//将ADC数据分包发送
}
四、 实验结果及分析验证
下载程序至开发板,通过matlab发送控制命令至开发板,将接受到的数据保存在adc中,本次读取了3090个字节,共三个数据包,matlab程序详情参考,以下是部分代码
%--------------------udp收发--------------------%
%data = ['28';'00';'01';'00';'01']; %询问命令
data = ['28';'00';'01';'00';'02';'00';'0A';'35';'00';'01';'02';'00';'00';'00';'00';'00';'08';'00';'00'];%控制命令
data = hex2dec(data);
%data = [0x28,0x00,0x01,0x00,0x01];
write(u,data,"uint8","192.168.1.10",8080);
%adc = read(u,27,"uint8");
adc = read(u,3090,"uint8");
flush(u,"output");%刷新输出缓冲区
clear u %断开并清除udp连接
首先是数据的连续性,保存的部分结果如图
经过分析得知,udp数据包中没有出现数据损坏的情况。
第一个数据包如上图,其序号为0001,其余两个数据包的序号分别如下图所示,分别为0002,0003
为了方便分析,通过wireshark观察抓取的udp包,观察第600个数据包的序号位
如图所示,为0x0258 ,换算为十进制为600,该数据包的序号正确。
经上述过程,即可验证udp包是否存在丢包及错序的现象。
五、问题与总结
问题1:一开始上位机接受到的序号为乱序,在请教了同学之后,明白了问题出在了主机字节序上,由于是小端字节序,高位数据存储于高位内存中,顺序发送,所以上位机接收到的序号被打乱,其主要的解决思路如下图所示:
问题2:当对板卡发送多次请求数据命令时,udp数据包内的序号字节出现错误,具体为第4个字节呈现00,04,08的累加状态,如下图所示,在分包发送的循环外部将fg初始化为0即可解决。
问题3:连接计数器IP核M_AXIS接口与axis_register_slice的S_AXIS接口,编译显示错误Port/Pin property FREQ_HZ does not match,经排查得知M_AXIS接口的CONFIG.FREQ_HZ为默认值100Mhz。
在Pacnkage IP中,为m00_axi_aclk的ASSOCIATED_BUSIF值设置为M_AXIS即可解决。