赞
踩
输出频率字的计算公式:deta_theta=f_out*(2^B)/f_clk
B:相位位宽,这里为32
f_clk :250M。注意,例化DDS IP时,外部模块例化端口的输入信号频率也必须为250M。
第一页配置(Configuration):
(1)Number of Channels:多通道输入。FFT转换通道的个数,这里为1。
(2)Transform Length :FFT的处理点数
(3)Architecture Configuration:
Target Clock Frequency:工作时钟;
Architecture choice:选择一种FFT结构。包括自动匹配、流水线Streaming、基4 Burst、基2 Burst和轻量级基2 Burst,它们的计算速度和消耗的资源依次减少,可根据工程实际进行选择。
(4)Run Time Configurable Transform Length:实时更改FFT的点数。
第二页配置(Implementation):
(1)Data Format:设置FFT的数据格式为定点Fixed Point或浮点Float Point;
(2)Scaling Option:输出截位方式选择。不截位(Unscaled),截位(Scaled),块浮点(Block Floating Point);
(3)Precision Option:设置输入数据的位宽和相位因子位宽;
(4)Control Signals:时钟使能(ACLKEN),复位信号(ARESETn,低有效);
(5)Output Ordering Option:用以选择FFT计算结果以自然顺序(Nature Order)或位倒序(Bit/Digit Reversed Order)输出。
第三页配置(Detailed Implementation):
可设置优化方式、存储的类型。
存储类型分为两种:Block RAM(块RAM)和Distributed RAM(分布式RAM)
优化方式可选择资源最优或者速度最优。
`timescale 1ns / 1ps
/*
幅度结果说明:
1、估计出来的信号幅度估计值是正弦波的有效幅度,所以是正弦波最大值的1/sqrt(2)
由于信号只有实部,所以信号幅度还要减少一半
所以幅度估计值=正弦波的峰值/(2*sqrt(2))
频率估计结果说明:
计算公式:m_axis_data_tuser* fs/COUNT=82*250M/1024= 20.0195MHz
易错点:
1、如果连续估计信号幅度时,每次出来的幅度结果不一样,检查IP 的信号频率是否和clk相等
2、tdata_i_valid 必须是一个脉冲信号
3、FFT IP核里面设置的信号频率必须和外部信号频率一致
*/
// I:实部 Q:虚部
// fft_m_data_tuser) 输出频谱的索引该值* fs/N,即为输入信号的频点
//fs(200M)和N(Transform Length)的值见FFT IP 设置
/*
3、NFFT:可选,本次设计没有使用
位宽为5
Point size of the transform,NFFT can be the size of the maximum transform or any smaller point size.
For example, a 1024-point FFT can compute point sizes 1024, 512, 256, and so on.
The value of NFFT is log2 (point size). 如果是2048个采样点 NFFT=log2(2048)=11=01011
The transform point size can be set through the NFFT field in the Configuration channel if
the run time configurable transform length option is selected.
只有选中run time configurable transform length这个选项,NFFT才可以配置。
2、CP_LEN:(Cyclic prefix length) 可选,本次设计没有使用
位宽为log2(采样点数)
The number of samples from the end of the transform that are initially output as a cyclic prefix,
before the whole transform is output. CP_LEN can be any number from zero to one less than
the point size.
This field is only present with cyclic prefix insertion.
只有选中 cyclic prefix insertion这个选项时,CP_LEN才可以配置。。
1、FWD_INV: 必须
位宽为:1 bit per FFT data channel
Indicates if a forward FFT transform or an inverse FFT transform is performed.
FWD_INV = 1, a forward transform is computed. FFT变换
FWD_INV = 0, an inverse transform is computed. IFFT变换
Each FFT data channel has an assigned FWD_INV field
0、SCALE_SCH: 可选,本次设计没有使用
for Pipelined Streaming I/O and Radix-4 Burst I/O architectures,位宽为:2*ceil(NFFT/2)
for Radix-2, Burst I/O and Radix-2 Lite Burst I/O architectures 位宽为:2*NFFT
This field is only available with scaled arithmetic
(not unscaled, block floating-point or singleprecision floating-point).
只有选中scalingOption的 scaled 这个选项时,SCALE_SCH才可以配置。
All fields with padding should be extended to the next 8-bit boundary
if they do not already finish on an 8-bit boundary.
*/
//模块功能:1024个点的FFT变换,并得到幅度谱
module Use_FFT_SignalAmp(
input clk ,// 工作时钟信号
input rst_n ,// 复位信号
input tdata_i_valid ,// 输入数据有效信号 // 是一个脉冲信号(上升沿有效)
input [31:0] tdata_i ,// 待估计信号幅度的数据 32bit
output [15:0] data_max ,//信号幅度
output DataMax_Vaild //信号幅度有效信号 //是一个脉冲信号(上升沿有效)
);
/*
step 1: 保证 tdata_i_valid 是一个脉冲信号
为了避免它不是脉冲信号,所以我们用 tdata_i_valid 的上升沿来作为整个模块的触发信号
*/
reg tdata_i_valid_delay;
reg tdata_i_valid_syn;
always@(posedge clk)
begin
tdata_i_valid_delay<=tdata_i_valid;
if(tdata_i_valid_delay==1'b0 && tdata_i_valid==1'b1)//抓取信号的上升沿
tdata_i_valid_syn<=1'b1;
else
tdata_i_valid_syn<=1'b0;
end
/*
step 2: FFT IP从端的输入数据和valid信号控制
控制什么时候给FFT IP给输入数据以及输入给FFT IP的数据是否有效
*/
reg fft_s_data_tvalid;
reg [31:0] fft_s_data_tdata;
reg fft_s_data_tlast;
reg [10:0] count;
reg [3:0] ST_FFT;
always @(posedge clk)
begin
if(!rst_n)
begin
ST_FFT<=4'd0;
fft_s_data_tvalid<=1'b0;
fft_s_data_tdata<=32'dx;
fft_s_data_tlast<=1'b0;
count<=11'd0;
end
case(ST_FFT)
0:
begin
fft_s_data_tvalid<=1'b0; // FFT IP的从端数据无效
fft_s_data_tdata<=32'dx; //数据保持,不给新数据
fft_s_data_tlast<=1'b0;
count<=11'd0;
if (tdata_i_valid_syn)// 输入数据有效 是一个脉冲信号(上升沿有效)
begin
ST_FFT<=4'd1;
end
else//外界数据无效或者且FFT IP没有准备好接收数据,握手不成功
begin
ST_FFT<=4'd0;
end
end
1:
begin
fft_s_data_tvalid<=1'b1; //输入给FFT IP的数据有效
fft_s_data_tdata<=tdata_i; //给FFT IP灌数据
if(count==11'd1023) //最后一个数据
begin
fft_s_data_tlast<=1'b1; //last信号拉高
count<=11'd0; //计数器清零
ST_FFT<=4'd2;
end
else
begin
fft_s_data_tlast<=1'b0;//last信号为低
count<=count+1; //计数器的值+1
ST_FFT<=4'd1;
end
end
2:
begin
// fft_s_data_tdata<=tdata_i; //给FFT IP灌数据
fft_s_data_tdata<=32'dx;
fft_s_data_tlast<=1'b0; //last信号拉低
fft_s_data_tvalid<=1'b0; // FFT IP的从端数据无效
count <=11'd0; //计数器清零
ST_FFT<=4'd0;
end
default :
ST_FFT<= 4'd0;
endcase
end
/*
step 3:例化FFT IP
*/
// output
wire fft_s_data_tready ;// 表示FFT IP核准备好接受数据
wire [63:0] fft_m_data_tdata ;// FFT 变换后的结果(频域信号)
wire fft_m_data_valid ;
wire fft_m_data_tlast ;
wire [15:0] fft_m_data_tuser ;
xfft_1 Inst_xfft_1(
//FFT的时钟、时钟使能、复位信号(注意复位信号要多给几个时钟)
.aclk(clk), // input wire aclk
.aresetn(rst_n), // input wire aresetn
// FFT的重配置接口
.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
//FFT的数据输入接口,遵循AXI-Stream协议
.s_axis_data_tdata(fft_s_data_tdata), // input wire [31 : 0] s_axis_data_tdata
.s_axis_data_tvalid(fft_s_data_tvalid), // input wire s_axis_data_tvalid
.s_axis_data_tready(fft_s_data_tready), // output wire s_axis_data_tready
.s_axis_data_tlast(fft_s_data_tlast), // input wire s_axis_data_tlast
//FFT的数据输出接口,遵循AXI-Stream协议
.m_axis_data_tdata(fft_m_data_tdata), // output wire [63 : 0] m_axis_data_tdata
.m_axis_data_tuser(fft_m_data_tuser), // output wire [15 : 0] m_axis_data_tuser
.m_axis_data_tvalid(fft_m_data_valid), // output wire m_axis_data_tvalid
.m_axis_data_tready(1'b1), // input wire m_axis_data_tready
.m_axis_data_tlast(fft_m_data_tlast), // output wire m_axis_data_tlast
//可以输出一些FFT的错误信息,比如输入的last未知不正确或没有,数据溢出等等
.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
);
wire [26:0] dati_out;//27bit
wire [26:0] datq_out;
assign datq_out=fft_m_data_tdata[58:32];//虚部 结果只有[26:0]的数据才是有效的
assign dati_out=fft_m_data_tdata[26:0];//实部 ---IP总结表明需要这样截位
/*
step 3:得到信号的幅度谱
*/
//step 3.1 :得到信号的功率
wire [31:0] dati_out_32bit;
wire [31:0] datq_out_32bit;
assign dati_out_32bit={dati_out[26],dati_out[26],dati_out[26],
dati_out[26],dati_out[26],dati_out};
assign datq_out_32bit={datq_out[26],datq_out[26],datq_out[26],
datq_out[26],datq_out[26],datq_out};
wire [127 : 0] fft_m_axis_dout_tdata;
wire fft_P_Vaild;
wire [63:0] fft_P;// 信号的频谱(幅度值的平方)
cpMult32x32 Inst_cpMult32x32 (
.aclk(clk), // input wire aclk
.s_axis_a_tvalid(fft_m_data_valid), // input wire s_axis_a_tvalid
.s_axis_a_tdata({datq_out_32bit,dati_out_32bit}), // input wire [63 : 0] s_axis_a_tdata
.s_axis_b_tvalid(fft_m_data_valid), // input wire s_axis_b_tvalid
.s_axis_b_tdata({~datq_out_32bit+1,dati_out_32bit}), // input wire [63 : 0] s_axis_b_tdata
.m_axis_dout_tvalid(fft_P_Vaild), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata(fft_m_axis_dout_tdata) // output wire [127 : 0] m_axis_dout_tdata
);
assign fft_P=fft_m_axis_dout_tdata[63:0]; // 幅度谱的实部---IP总结表明需要这样截位
/*
step 3.2 :得到信号的幅度 Amp
Amp的计算方法
Amp = abs(fft_P)/L
= sqrt(实部的平方+虚部的平方)/L % 即表示先求模值,再除以采样点数
= sqrt(实部的平方+虚部的平方)/sqrt(L^2)
= sqrt( (实部的平方+虚部的平方)/L^2 )
= sqrt( fft_P /L^2 )
*/
wire [34 : 0] fft_P_44bit;
wire [47 : 0] fft_P_48bit;
assign fft_P_44bit=fft_P[63:20];// [19:0]= 缩小2^20倍= L^2 =(2^10)^2
assign fft_P_48bit={fft_P_44bit[44],fft_P_44bit[44],fft_P_44bit[44],fft_P_44bit[44],fft_P_44bit };
wire [31:0] fft_Amp ; // 开方结果,得到信号的幅度谱
wire fft_Amp_vaild;
CORDICROOT Inst_CORDICROOT (
.aclk(clk), // input wire aclk
.s_axis_cartesian_tvalid(fft_P_Vaild), // input wire s_axis_cartesian_tvalid
.s_axis_cartesian_tdata(fft_P_48bit), // input wire [47 : 0] s_axis_cartesian_tdata
.m_axis_dout_tvalid(fft_Amp_vaild), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata(fft_Amp) // output wire [31 : 0] m_axis_dout_tdata
);
wire [24:0] fft_Amp_25bit;
assign fft_Amp_25bit=fft_Amp[24 : 0] ;//--IP总结表明需要这样截位
/*
step 5:找到一组数据的最大值,得到信号的幅度
*/
wire [24:0] data_max_25bit;
Max_Get Inst_Max_Get(
//input
.clk (clk ),
.reset (!rst_n ),
.En (fft_Amp_vaild ), //是一个脉冲信号(上升沿有效)
.data_in (fft_Amp_25bit ),//信号的幅度谱 [24:0]
//output
.data_max (data_max_25bit) ,//[24:0] 幅度谱的最大值,即为时域信号的幅度
.DataMax_Vaild (DataMax_Vaild ) // 信号幅度有效信号 //是一个脉冲信号(上升沿有效)
);
assign data_max=data_max_25bit[15:0];
endmodule
`timescale 1ns / 1ps
// 找一串序列(深度为1024)的最大值
module Max_Get(
input clk ,
input reset ,
input En ,//模块开始工作的使能信号 是一个脉冲信号(上升沿有效)
input [24:0] data_in ,// 输入数据
output reg [24:0] data_max ,//搜索得到的最大值
output reg DataMax_Vaild //是一个脉冲信号(上升沿有效)
);
reg [24:0] data_max_temp;
reg [3:0] ST_max_search;
reg [15:0] count;
always@(posedge clk)
begin
if(reset)
begin
data_max_temp<=25'd0;
ST_max_search<=4'd0;
count<=16'd0;
DataMax_Vaild<=1'b0;
end
else
begin
case(ST_max_search)
0:
begin
if(En==1'b1) //是一个脉冲信号(上升沿有效)
begin
ST_max_search<=4'd1;
data_max_temp<=25'd0;//数据归零,避免影响下一次寻求最大值
count<=16'd0;//计数器清零
end
else
begin
ST_max_search<=4'd0;
end
end
1:
begin
if(count<16'd1024)
begin
count<=count+1'd1;
ST_max_search<=4'd1;
if(data_in>data_max_temp)
data_max_temp<=data_in;
else
data_max_temp<=data_max_temp;
end
else//if(count==16'd1024)
begin
data_max<= data_max_temp;//输出最大值
DataMax_Vaild<=1'b1; //是一个脉冲信号(上升沿有效)
ST_max_search<=4'd2;
end
end
2:
begin
ST_max_search<=4'd0;
data_max_temp<=25'd0;//数据归零,避免影响下一次寻求最大值
count<=16'd0;
DataMax_Vaild<=1'b0;
end
default:
ST_max_search<= 4'd0;//跳到状态0
endcase
end
end
endmodule
`timescale 1ns / 1ps
/*
1、出一次结果需要40us,整个仿真需要250us
2、信号幅度是32767,估计出来的结果是有效信号幅度 即23767/sqrt(2)=22925
易错点:1、tdata_i_valid必须是一个脉冲信号
2、FFT IP核里面设置的信号频率必须和外部信号频率一致
*/
module sim_Use_FFT_SignalAmp;
reg clk_250M;
reg reset;
// step 1:DDS产生参考信号 RtI,RtQ
wire [31:0] Calib_Freq;//频率字
wire Calib_Freq_vaild;//频率字有效信号
assign Calib_Freq=32'h147AE148;//20M dec2hex(round(20/250*2^32))
assign Calib_Freq_vaild=1'b1;
wire [31:0] m_axis_data_PINC;
wire m_axis_data_PINC_vaild;
wire [15:0] RtI;
wire [15:0] RtQ ;
dds_data Inst_dds_data (
.aclk(clk_250M), // input wire aclk
.s_axis_config_tvalid(Calib_Freq_vaild), // input wire s_axis_config_tvalid
.s_axis_config_tdata(Calib_Freq), // input wire [31 : 0] s_axis_config_tdata
.m_axis_data_tvalid(m_axis_data_PINC_vaild), // output wire m_axis_data_tvalid
.m_axis_data_tdata(m_axis_data_PINC), // output wire [31 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata() // output wire [31 : 0] m_axis_phase_tdata
);
assign RtI=m_axis_data_PINC[15:0]; //I:实部 Q:虚部
assign RtQ=m_axis_data_PINC[31:16];
wire [15:0] Beam1_Amp ;//子波束1的接收信号的幅度
wire Beam1_Amp_Vaild ;
reg tdata_i_valid;
reg [15:0] tdata_i_I;
reg [15:0] tdata_i_Q ;
reg [1:0] Signal_num;
always @(posedge clk_250M )
begin
if(Signal_num==2'd0)//第一种信号
begin
tdata_i_I<=RtI;
tdata_i_Q<=RtQ;
end
else if(Signal_num==2'd1)//第二种信号
begin
tdata_i_I<={RtI[15],RtI[15:1]};
tdata_i_Q<={RtQ[15],RtQ[15:1]};
end
end
Use_FFT_SignalAmp Inst_Use_FFT_SignalAmp(
//input
.clk (clk_250M ), // 工作时钟信号
.rst_n (~reset ), // 复位信号
.tdata_i_valid (tdata_i_valid ), // 必须是一个脉冲信号(上升沿有效)
.tdata_i ({tdata_i_Q,tdata_i_I}), // 复信号 32bit
// .tdata_i ({tdata_i_Q,16'd0}), // 只有实部信号 16bit
//output
.data_max (Beam1_Amp ),//子波束1的信号幅度
.DataMax_Vaild (Beam1_Amp_Vaild ) //子波束的信号幅度有效信号
);
initial
begin
clk_250M<=1'b0;
reset<=1'b1;
tdata_i_valid<=1'b0;
Signal_num<=2'dx;
#30
reset<=1'b0;
// 第一次循环:第1种目标信号数据有效
#100
tdata_i_valid<=1'b1;
Signal_num<=2'd0;
#10
tdata_i_valid<=1'b0;
// 第2个目标信号数据有效
#40_000
tdata_i_valid<=1'b1;
Signal_num<=2'd1;
#10
tdata_i_valid<=1'b0;
// 第2次循环: 第1个目标信号数据有效
#40_000
tdata_i_valid<=1'b1;
Signal_num<=2'd0;
#10
tdata_i_valid<=1'b0;
// 第2个目标信号数据有效
#40_000
tdata_i_valid<=1'b1;
Signal_num<=2'd1;
#10
tdata_i_valid<=1'b0;
// 第3次循环: 第1个目标信号数据有效
#40_000
tdata_i_valid<=1'b1;
Signal_num<=2'd0;
#10
tdata_i_valid<=1'b0;
// 第2个目标信号数据有效
#40_000
tdata_i_valid<=1'b1;
Signal_num<=2'd1;
#10
tdata_i_valid<=1'b0;
end
always #2 clk_250M = ~ clk_250M;
endmodule
DDS产生的信号频率为20M,T=50ns
FFT IP的信号频率估计值:
计算公式:m_axis_data_tuser* fs/COUNT=82*250M/1024= 20.0195MHz
频率估计值和真实值很接近;且任意时刻的频率估计值是一致的。
分析:
1、信号幅度是31736,理论上的幅度有效值为31736/sqrt(2)=22441;FFT IP估计出来的信号幅度有效值为22925 ,误差较小。
2、同一个目标信号,多次调用FFT IP,理论上幅度估计值应该是一致的。上图也证明了这一点,如第一次、第三次和第五次的幅度估计值。
1、频率估计:计算公式:m_axis_data_tuser* fs/COUNT=82*250M/1024= 20.0195MHz
2、幅度估计:如果输入的是复信号,最后输出的值是信号幅度的有效值。如果输入的是实信号,最后输出的值是信号幅度的有效值的一半。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。