赞
踩
1.傅里叶变换FFT
傅立叶变换是一种分析信号的方法,它可分析信号的成分,也可用这些成分合成信号。许多波形可作为信号的成分,比如正弦波、方波、锯齿波等,傅立叶变换用正弦波作为信号的成分。
通过FFT将时域信号转换到频域,从而对一些在时域上难以分析的信号在频域上进行处理。
其中,根据奈奎斯特采样定理,采样频率需大于信号频率的两倍;
1.N为FFT采样点数,代表对信号在频域的采样数;
2.采样频率Fs和采样点数N决定了信号的频域分辨力,即分辨力=Fs/N,即N越大,频域分辨力越好,反之频域分辨力越差。
2.Vivado中IP核的配置
打开Vivado2018.3:
配置IP核:
如图所示,其中,S_AXIS_DATA为输入数据端口,FFT的数据通过S_AXIS_DATA输入给IP核;S_AXIS_CONFIG为输入配置端口,对数据进行配置,FFT还是IFFT、缩放因子、FFT变换点数等信息;FFT变换后的数据从M_AXIS_DATA端口输出。
其中包含了S_AXIS_DATA_TDATA、S_AXIS_CONFIG_TDATA以及M_AXIS_DATA_TDATA的数据格式:
S_AXIS_DATA_TDATA:共32位,其中低16位为输入数据的实部,高16位为输入数据的虚部。
S_AXIS_CONFIG_TDATA:最低位第0位,决定对数据进行FFT还是IFFT,置1时FFT,清零时IIFT。
M_AXIS_DATA_TDATA:48位数据输出,低24位为实部,高24位为虚部。
3.仿真:
I通过matlab对F(t) = 100 + 100cos(2pi30t) + 100cos(2pi70t) 这个信号以Fs = 100HZ进行采样,采样点数N = 128,采样完成后,将数据转换为16位二进制,并存入txt文件中。matlab程序如下:
(源:CSDN—傅外叶) clear Fs=100; N = 128; n = 1:N; t = n/Fs; % 生成测试信号 f1 = 30; f2 = 70; s1 = cos(2*pi*f1*t); s2 = cos(2*pi*f2*t); fft_signal = 1 + s1 + s2 ; data_before_fft = 100*fft_signal; %系数放大100倍 fp = fopen('C:\Users\lys\Desktop\fft\data_before_fft.txt','w'); for i = 1:N if(data_before_fft(i)>=0) temp= dec2bin(data_before_fft(i),16); else temp= dec2bin(data_before_fft(i)+2^16+1, 16); end for j=1:16 fprintf(fp,'%s',temp(j)); end fprintf(fp,'\r\n'); end fclose(fp); y = fft(data_before_fft,N); y = abs(y); f = n*Fs/N; plot(f,y);
MATLAB中的信号做傅里叶变换:
建立tb文件:
(源:CSDN—傅外叶) `timescale 1ns / 1ps module fft_tb; reg clk; reg rst_n; reg signed [15:0] Time_data_I[127:0]; reg data_finish_flag; wire fft_s_config_tready; reg signed [31:0] fft_s_data_tdata; reg fft_s_data_tvalid; wire fft_s_data_tready; reg fft_s_data_tlast; wire signed [47:0] fft_m_data_tdata; wire signed [7:0] fft_m_data_tuser; wire fft_m_data_tvalid; reg fft_m_data_tready; wire fft_m_data_tlast; wire fft_event_frame_started; wire fft_event_tlast_unexpected; wire fft_event_tlast_missing; wire fft_event_status_channel_halt; wire fft_event_data_in_channel_halt; wire fft_event_data_out_channel_halt; reg [7:0] count; reg signed [23:0] fft_i_out; reg signed [23:0] fft_q_out; reg signed [47:0] fft_abs; initial begin clk = 1'b1; rst_n = 1'b0; fft_m_data_tready = 1'b1; $readmemb("C:/Users/lys/Desktop/fft/data_before_fft.txt",Time_data_I); end always #5 clk = ~clk; always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin fft_s_data_tvalid <= 1'b0; fft_s_data_tdata <= 32'd0; fft_s_data_tlast <= 1'b0; data_finish_flag <= 1'b0; count <= 8'd0; rst_n = 1'b1; end else if (fft_s_data_tready) begin if(count == 8'd127) begin fft_s_data_tvalid <= 1'b1; fft_s_data_tlast <= 1'b1; fft_s_data_tdata <= {Time_data_I[count],16'd0}; count <= 8'd0; data_finish_flag <= 1'b1; end else begin fft_s_data_tvalid <= 1'b1; fft_s_data_tlast <= 1'b0; fft_s_data_tdata <= {Time_data_I[count],16'd0}; count <= count + 1'b1; end end else begin fft_s_data_tvalid <= 1'b0; fft_s_data_tlast <= 1'b0; fft_s_data_tdata <= fft_s_data_tdata; end end always @ (posedge clk) begin if(fft_m_data_tvalid) begin fft_i_out <= fft_m_data_tdata[23:0]; fft_q_out <= fft_m_data_tdata[47:24]; end end always @ (posedge clk) begin fft_abs <= $signed(fft_i_out)* $signed(fft_i_out)+ $signed(fft_q_out)* $signed(fft_q_out); end //fft ip核例化 xfft_0 u_fft( .aclk(clk), // 时钟信号(input) .aresetn(rst_n), // 复位信号,低有效(input) .s_axis_config_tdata(8'd1), // ip核设置参数内容,为1时做FFT运算,为0时做IFFT运算(input) .s_axis_config_tvalid(1'b1), // ip核配置输入有效,可直接设置为1(input) .s_axis_config_tready(fft_s_config_tready), // output wire s_axis_config_tready //作为接收时域数据时是从设备 .s_axis_data_tdata(fft_s_data_tdata), // 把时域信号往FFT IP核传输的数据通道,[31:16]为虚部,[15:0]为实部(input,主->从) .s_axis_data_tvalid(fft_s_data_tvalid), // 表示主设备正在驱动一个有效的传输(input,主->从) .s_axis_data_tready(fft_s_data_tready), // 表示从设备已经准备好接收一次数据传输(output,从->主),当tvalid和tready同时为高时,启动数据传输 .s_axis_data_tlast(fft_s_data_tlast), // 主设备向从设备发送传输结束信号(input,主->从,拉高为结束) //作为发送频谱数据时是主设备 .m_axis_data_tdata(fft_m_data_tdata), // FFT输出的频谱数据,[47:24]对应的是虚部数据,[23:0]对应的是实部数据(output,主->从)。 .m_axis_data_tuser(fft_m_data_tuser), // 输出频谱的索引(output,主->从),该值*fs/N即为对应频点; .m_axis_data_tvalid(fft_m_data_tvalid), // 表示主设备正在驱动一个有效的传输(output,主->从) .m_axis_data_tready(fft_m_data_tready), // 表示从设备已经准备好接收一次数据传输(input,从->主),当tvalid和tready同时为高时,启动数据传输 .m_axis_data_tlast(fft_m_data_tlast), // 主设备向从设备发送传输结束信号(output,主->从,拉高为结束) //其他输出数据 .event_frame_started(fft_event_frame_started), // output wire event_frame_started .event_tlast_unexpected(fft_event_tlast_unexpected), // output wire event_tlast_unexpected .event_tlast_missing(fft_event_tlast_missing), // output wire event_tlast_missing .event_status_channel_halt(fft_event_status_channel_halt), // output wire event_status_channel_halt .event_data_in_channel_halt(fft_event_data_in_channel_halt), // output wire event_data_in_channel_halt .event_data_out_channel_halt(fft_event_data_out_channel_halt) // output wire event_data_out_channel_halt ); endmodule
4.仿真结果:
首先判断fft_s_data_tready信号是否为高电平,即IP核是否准备好了接收数据,当检测到该信号有效后,将fft_s_data_tvalid信号拉高,准备向IP核写入数据,并开启count计数。在fft_s_data_tvalid有效期间内,读出指定txt文件中的数据,并在低16位进行补零处理后,按顺序写入到fft_s_data_tdata信号线中。当count计数到127,即最后一个数据时,将fft_s_data_tlast信号拉高,代表数据写入完成。可以看到,在数据写入完成后(fft_s_data_tlast出现脉冲),fft_s_data_tready变为低电平,则代表IP核此时变为忙状态,不能再继续写入数据。
延时一段时间后,fft_m_data_tvalid变为高电平,代表fft_m_data_tdata中将输出有效数据,即128点FFT的计算结果。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。