如何使用xilinx的FFT ip

FFT解释

FFT(Fast Fourier Transform,快速傅立叶变换)是离散傅立叶变换的快速算法,也是我们在数字信号处理技术中经常会提到的一个概念。在大学的理工科课程中,在完成高等数学的课程后,数字信号处理一般会作为通信电子类专业的专业基础课程进行学习,原因是其中涉及了大量的高等数学的理论推导,同时又是各类应用技术的理论基础。

为什么需要FFT?

FFT(快速傅立叶变换)是离散傅立叶变换的快速算法.

傅立叶变换的物理意义在哪里?

傅立叶原理表明:任何连续测量的时序或信号,都可以表示为不同频率的正弦波信号的无限叠加。而根据该原理创立的傅立叶变换算法利用直接测量到的原始信号,以累加方式来计算该信号中不同正弦波信号的频率、振幅和相位。当然这是从数学的角度去看傅立叶变换。
那么从物理的角度去看待傅立叶变换,它其实是帮助我们改变传统的时间域分析信号的方法转到从频率域分析问题的思维,下面的一幅立体图形可以帮助我们更好得理解这种角度的转换:
时域和频域的相互转换
所以,最前面的时域信号在经过傅立叶变换的分解之后,变为了不同正弦波信号的叠加,我们再去分析这些正弦波的频率,可以将一个信号变换到频域。有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了。这就是很多信号分析采用FFT变换的原因。另外,FFT可以将一个信号的频谱提取出来,这在频谱分析方面也是经常用的。
傅立叶变换提供给我们这种换一个角度看问题的工具,看问题的角度不同了,问题也许就迎刃而解!

如何使用xilinx的FFT ip实现FFT过程

本篇文章我们主要讲解数据由fft再到ifft的过程,从而验证整个过程功能是否都具备;

matlab准备生成iq数据

clc;
clear all;
close all;

fs = 250e6;     % adc采样率
fout = 10e6;    % 生成信号频率
len = 1024;     % 生成信号长度
t = 0:1/fs:(len-1)/fs;  % 采样点的时间片
amp = 25000;    % adc信号幅度

adc_dat = exp(j*2*pi*fout*t); % adc数据
adc_dat = awgn(adc_dat, 40);% 对生成信号加入噪声

adc_dat_i = round(real(adc_dat)*amp);% 量化adc数据
adc_dat_q = round(imag(adc_dat)*amp);% 量化adc数据

% 画出信号的时域和频域图
subplot(211);
plot(adc_dat_i);hold on;
plot(adc_dat_q);
title('信号时域图');
xlabel('采样点');
ylabel('信号幅度');
subplot(212);
fft_adc_dat = adc_dat_i+j*adc_dat_q;
fft_data = abs(fft(fft_adc_dat, len));
fft_data = fftshift(fft_data);
fft_data = 20*log10(fft_data);
fft_data = fft_data - max(fft_data);
x = linspace(-fs/2,fs/2,len);
plot(x, fft_data);
title('信号频谱图');
xlabel('信号频率MHz');
ylabel('信号功率');
% 存储ADC数据
adc_dat = [adc_dat_q;adc_dat_i];
u_adc_dat = sign2com(adc_dat, 16);
fp = fopen('adc_dat.bin', 'w');
fprintf(fp, '%04x%04x\n',u_adc_dat);
fclose all;

xilinx的fft ip设置

fft ip设置
fft ip设置
输入输出数据格式

xilinx的ifft ip设置

ifft需要将该配置bit置为0,和更改下输入数据位宽,其他与fft配置一致;
ifft配置

verilog代码仿真

`timescale 1ns/1ps

module testbench;

reg										clk						;
reg										rst						;
reg		[11:0]							dat_cnt					;
reg		[31:0]							s_data_tdata			;
reg										s_data_tvalid			;
reg		[31:0]							adc_dat[1023:0]			;

wire									s_data_tlast			;
wire									s_data_tready			;
wire	[63:0]							m_data_tdata			;
wire	[15:0]							m_data_tuser			;
wire									m_data_tvalid			;
wire									m_data_tready			;
wire									m_data_tlast			;
wire	[79:0]							m_ifft_data_tdata		;
wire	[15:0]							m_ifft_data_tuser		;
wire									m_ifft_data_tvalid		;
wire									m_ifft_data_tready		;
wire									m_ifft_data_tlast		;

always #5.00	clk = ~clk	;

initial	begin
	clk=0;
	rst=1;
	#200
	rst=0;
end

localparam					LEN	=	1024			;

initial	begin
	$readmemh("./matlab/adc_dat.bin", adc_dat, 0, LEN-1);
end

always@(posedge clk)
begin
	if(rst)	begin
		s_data_tdata	<=0;
		s_data_tvalid	<=0;
		dat_cnt			<=0;
	end
	else	begin
		if(dat_cnt<LEN)	begin
			if(s_data_tready)	begin
				dat_cnt			<=dat_cnt+1;
				s_data_tdata	<=adc_dat[dat_cnt];
				s_data_tvalid	<=1;
			end
			else	begin
				s_data_tvalid	<=0;
			end
		end
		else if(s_data_tready)	begin
			s_data_tvalid	<=0;
		end
	end
end

assign	s_data_tlast = ((dat_cnt==1024)&&s_data_tvalid)? 1 : 0;

xfft_0 u_xfft_0 (
	.aclk								(clk						), // input wire aclk
	.aresetn							(~rst						), // input wire aresetn
	.s_axis_config_tdata				(8'd1						), // input wire [7 : 0] s_axis_config_tdata
	.s_axis_config_tvalid				(1'b1						), // input wire s_axis_config_tvalid
	.s_axis_config_tready				(							), // output wire s_axis_config_tready
	.s_axis_data_tdata					(s_data_tdata				), // input wire [31 : 0] s_axis_data_tdata
	.s_axis_data_tvalid					(s_data_tvalid				), // input wire s_axis_data_tvalid
	.s_axis_data_tready					(s_data_tready				), // output wire s_axis_data_tready
	.s_axis_data_tlast					(s_data_tlast				), // input wire s_axis_data_tlast
	.m_axis_data_tdata					(m_data_tdata				), // output wire [63 : 0] m_axis_data_tdata
	.m_axis_data_tuser					(m_data_tuser				), // output wire [15 : 0] m_axis_data_tuser
	.m_axis_data_tvalid					(m_data_tvalid				), // output wire m_axis_data_tvalid
	.m_axis_data_tready					(m_data_tready				), // input wire m_axis_data_tready
	.m_axis_data_tlast					(m_data_tlast				), // output wire m_axis_data_tlast
	.event_frame_started				(							), // output wire event_frame_started
	.event_tlast_unexpected				(							), // output wire event_tlast_unexpected
	.event_tlast_missing				(							), // output wire event_tlast_missing
	.event_status_channel_halt			(							), // output wire event_status_channel_halt
	.event_data_in_channel_halt			(							), // output wire event_data_in_channel_halt
	.event_data_out_channel_halt		(							) // output wire event_data_out_channel_halt
);

xifft_0 u_xifft_0 (
	.aclk								(clk						), // input wire aclk
	.aresetn							(~rst						), // input wire aresetn
	.s_axis_config_tdata				(8'd0						), // input wire [7 : 0] s_axis_config_tdata
	.s_axis_config_tvalid				(1'b1						), // input wire s_axis_config_tvalid
	.s_axis_config_tready				(							), // output wire s_axis_config_tready
	.s_axis_data_tdata					(m_data_tdata				), // input wire [63 : 0] s_axis_data_tdata
	.s_axis_data_tvalid					(m_data_tvalid				), // input wire s_axis_data_tvalid
	.s_axis_data_tready					(m_data_tready				), // output wire s_axis_data_tready
	.s_axis_data_tlast					(m_data_tlast				), // input wire s_axis_data_tlast
	.m_axis_data_tdata					(m_ifft_data_tdata			), // output wire [79 : 0] m_axis_data_tdata
	.m_axis_data_tuser					(m_ifft_data_tuser			), // output wire [15 : 0] m_axis_data_tuser
	.m_axis_data_tvalid					(m_ifft_data_tvalid			), // output wire m_axis_data_tvalid
	.m_axis_data_tready					(1'b1						), // input wire m_axis_data_tready
	.m_axis_data_tlast					(m_ifft_data_tlast			), // output wire m_axis_data_tlast
	.event_frame_started				(							), // output wire event_frame_started
	.event_tlast_unexpected				(							), // output wire event_tlast_unexpected
	.event_tlast_missing				(							), // output wire event_tlast_missing
	.event_status_channel_halt			(							), // output wire event_status_channel_halt
	.event_data_in_channel_halt			(							), // output wire event_data_in_channel_halt
	.event_data_out_channel_halt		(							)  // output wire event_data_out_channel_halt
);

endmodule

仿真结果

仿真结果

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值