本文介绍了Vidado中FFT IP核的使用,具体内容为:调用IP核>>配置界面介绍>>IP核端口介绍>>MATLAB生成测试数据>>测试verilogHDL>>TestBench仿真>>结果验证>>FFT运算。
1、调用IP核
该IP核对应手册pg109_xfft.pdf,首先按照图片找到IP核:
2、配置界面介绍
本小节主要介绍Fast Fourier Transform9.1这个IP核配置界面的一些选项:
第1页:Configuration
图1
表1 Configuration界面介绍
第2页:Implementation
图2
表2 Implementation界面介绍
图3
表3 Detailed Implementation
3、IP核端口配置
根据上述配置界面的介绍,下面以64点IFFT为例子,总结了使用IP核时所需的端口配置,如表4所示,需要注意的是表4中没有涉及的部分按照IP核的默认配置即可:
表4 64点IFFT运算IP核的设置表汇总
配置完成之后IP核的端口图如下:
图4 64点IFFT核端口图
按照下面图找到例化原语:
图5
打开.veo后缀的文件找到例化原语:
图6
对例化语句的介绍见表5,其中L表示IFFT/FFT的点数。
表5 例化原语介绍
需要说明的是,需要配置的端口有,1)aclk;2)aclken;3)s_axis_config_tdata ;4)s_axis_config_tvalid ;5)s_axis_config_tready;6)s_axis_data_tdata;7)s_axis_data_tvalid;8)s_axis_data_tready;9)m_axis_data_tdata;10)m_axis_data_tuser;11)m_axis_data_tready;12)m_axis_data_tlast
4、MATLAB生成测试数据
本次测试只需要使用TestBench验证即可,需要生成.txt后缀的文件,产生IFFT核的输入数据,主要程序为:
%%该.m文件用来生成介绍IFFT核的数据,具体为64点的IFFT16QAM clear closeall clc rngdefault%产生固定数值的随机数据 %%基于符号算法的目标距离和速度探测 %%定义基本参数 Ns=1;%符号数 Nc=64;%子载波数 M=16;%调制方式 bit_num=log2(M);%一个码组中的码元个数 bit=randi([01],Nc*Ns*bit_num,1);%产生比特 norm=1/sqrt(10);%16qam归一化因子 %%16qam bit_convert=(reshape(bit,bit_num,length(bit)/bit_num))';%二进制数据流按照调制的方式分成不同码元 data_2_to_10=bi2de(bit_convert,'left-msb');%将每四位数据转换为十进制数 maxtix=reshape(data_2_to_10,Nc,Ns); bit_mo=norm*qammod(data_2_to_10,M); a_nm=reshape(bit_mo,Nc,Ns); %%发送端IFFT调制 IFFT_OUT=ifft(a_nm,64); %%数据保存为.txt文件 echo_real=real(a_nm); echo_imag=imag(a_nm); echo1_real=quantizer([1611]); echo1_imag=quantizer([1611]); fid_echo=fopen('C:Users15865DesktopFFT_IP_core_64pointIFFT_IP_core_64point_exam.txt','wt'); forj=1:Ns echo2_real=num2bin(echo1_real,echo_real(:,j)); echo2_imag=num2bin(echo1_imag,echo_imag(:,j)); fori=1:Nc imag_real_echo=[echo2_imag(i,:),echo2_real(i,:)]; fwrite(fid_echo,imag_real_echo); fprintf(fid_echo,' '); end end fclose(fid_echo);
图中程序功能是生成了一段包含64个复数数据的数组,并将每个复数数据用16表示实部16位表示虚部共生成32位二进制数,最后将这组数据保存为.txt后缀文件。
5、测试verilog HDL
根据前文的配置编写一个简单的测试.v文件测试64点数据的IFFT运行结果,主要程序如下:
`timescale1ns/1ps moduleIFFT_introduction( inputclk, inputrst_n, inputifft_valid, input[31:0]data_in, //inputlast, outputs_config_tready, output[31:0]m_data_tdata, outputs_data_tready, output[7:0]m_data_tuser, outputm_data_tvalid, outputm_data_tlast ); FFT_IP_core_64pointifft_u0( .aclk(clk),//inputwireaclk .aclken(rst_n),//inputwireaclken .s_axis_config_tdata(8'd0),//inputwire[7:0]s_axis_config_tdata .s_axis_config_tvalid(1'b1),//inputwires_axis_config_tvalid .s_axis_config_tready(s_config_tready),//outputwires_axis_config_tready .s_axis_data_tdata(data_in),//inputwire[31:0]s_axis_data_tdata .s_axis_data_tvalid(ifft_valid),//inputwires_axis_data_tvalid .s_axis_data_tready(s_data_tready),//outputwires_axis_data_tready //.s_axis_data_tlast(s_axis_data_tlast),//inputwires_axis_data_tlast .m_axis_data_tdata(m_data_tdata),//outputwire[31:0]m_axis_data_tdata .m_axis_data_tuser(m_data_tuser),//outputwire[7:0]m_axis_data_tuser .m_axis_data_tvalid(m_data_tvalid),//outputwirem_axis_data_tvalid .m_axis_data_tready(1'b1),//inputwirem_axis_data_tready .m_axis_data_tlast(m_data_tlast)//outputwirem_axis_data_tlast ); wire[15:0]ifft_64point_out_RE,ifft_64point_out_IM; //assignRE={{4{m_data_tdata[15]}},m_data_tdata[15:4]};//IFFT归一化处理,除Nfft //assignIM={{4{m_data_tdata[39]}},m_data_tdata[39:28]}; assignifft_64point_out_IM=m_data_tdata[31:16];//虚部 assignifft_64point_out_RE=m_data_tdata[15:0];//实部 endmodule
这段程序调用了FFT IP核的例化原语,并将部分接口作为函数的输入和输出,方便TestBench调用。
6、TestBench仿真
主要程序如下:
`timescale1ns/1ps moduleifft_tb(); regclk;//系统时钟 regrst_n;//复位信号,低有效 regifft_valid;//数据有效位,指示输入数据有效 reg[31:0]data_in;//输入数据 wires_config_tready; wire[31:0]m_data_tdata; wires_data_tready; wire[7:0]m_data_tuser; wirem_data_tvalid; wirem_data_tlast; IFFT_introductionu0(//例化.v文件 .clk(clk), .rst_n(rst_n), .ifft_valid(ifft_valid), .data_in(data_in), .s_config_tready(s_config_tready), .m_data_tdata(m_data_tdata), .s_data_tready(s_data_tready), .m_data_tuser(m_data_tuser), .m_data_tvalid(m_data_tvalid), .m_data_tlast(m_data_tlast) ); reg[31:0]mem[63:0]; initialbegin//$readmembVivado内置函数调用.txt文件 $readmemb("C:/Users/15865/Desktop/FFT_IP_core_64point/IFFT_IP_core_64point_exam.txt",mem); clk=0; rst_n=0; #1000; rst_n=1; #10_000; $stop; end always#10clk<=~clk; //50MHz reg [6:0] count; //计数 always@(posedge clk or negedge rst_n) begin if(!rst_n) count<='d0; else if(count<='d63) count<=count+1'b1; else count<='dz; end // 产生信号和数据 always@(posedge clk or negedge rst_n) begin if(!rst_n) begin ifft_valid<='d0; data_in<='d0; end else if(count>='d0&&count<='d63) begin ifft_valid<=1; data_in<=mem[count]; end else begin ifft_valid<=1'b0; data_in<='d0; end end endmodule
7、Modelsim结果与MATLAB输出结果验证
本节将验证Modelsim和MATLAB输出结果的一致性,并简单介绍Modelsim输出结果向MATLAB数据的转换。
Modelsim 输出结果如下图:
图10
由于数据有64个而这里验证前三个中间三个和后三个的方式验证Modelsim数据和MATLAB数据正确性:
表6数据验证
需要注意的是,Modelsim输出的结果并不是小数,而是忽略了小数点的整数,要想获得和MATLAB类似的浮点数,需要我们将输出结果变换,这里以Modelsim输出的最后一个数为例(即表6中序号64),可见图11。
图11
对于该结果需要我们将输出结果除以2^(a+ b),a为用以表示小数的位宽数,本文中为11,b为FFT点数的2次幂幂值,本文为6,因此对于每一个Modelsim的输出结果都需要除以2^17,这里实部-15302/2^17=-0.1167,虚部-23234/2^17=-0.1773。
从表6中数据可以看出,IFFT 核执行的运算和MATLAB的运算结果十分接近,验证成功。
8、FFT运算
与IFFT运算类似,配置不用更改只需将第5小节程序中,s_axis_config_tdata端口配置改为8’d1即可,其他无需变动。
-
FFT
+关注
关注
15文章
434浏览量
59390 -
仿真
+关注
关注
50文章
4085浏览量
133636 -
端口
+关注
关注
4文章
966浏览量
32084 -
IP核
+关注
关注
4文章
327浏览量
49501 -
Vivado
+关注
关注
19文章
812浏览量
66571
原文标题:Vivado中的FFT IP核使用
文章出处:【微信号:Hack电子,微信公众号:Hack电子】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论