基于FPGA验证udp传输

一、实验要求

验证udp传输过程中是否发生了如下问题:

  • 数据包内数据损坏
  • 丢包
  • 数据包的顺序不正确

二、任务分析

基于 AN108 模块的ADC 采集以太网传输_Laid-back guy的博客-CSDN博客

在上述实验的基础上进行修改,利用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程序详情参考,以下是部分代码

基于Matlab的udp通信的简单实现_Laid-back guy的博客-CSDN博客

%--------------------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即可解决。

六、参考资料

[1]在Vivado中创建计数器IP核_抓紧爬起来不许摆烂的博客-CSDN博客_vivado添加ip核

[2]基于 AN108 模块的ADC 采集以太网传输_Laid-back guy的博客-CSDN博客

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值