FFT配置讲解
*
(1)表示几个通道,这里我采用1024个点不同频率的正弦波。采用一通道
(2)表示通道点的个数。
(3)给FFT作用的时钟频率
(4)从上到下。算法越来越简单。
*
(1)输入数据的格式,我选择的为定点,还有浮点数据格式。
(2)选择算法类似上一张图的第四点。来考虑数据溢出。
(3)类似四舍五入对数据进行截断,进行判断的。
(4)输入数据的位宽。
(5)低电平复位
(6)有正序和倒序输出。我选择的正序。
(7)这个就是non real time 更加浪费资源, real time 节约资源。但是好处是non real time 对于输入时序要求低。
ip口生成如下
```c
xfft_0 xfft_0_U0 (
.aclk (i_clk ), // input wire aclk
.aresetn (~i_rst ), // input wire aresetn
.s_axis_config_tdata (s_axis_config_tdata ), // input wire [7 : 0] s_axis_config_tdata
.s_axis_config_tvalid (s_axis_config_tvalid ), // input wire s_axis_config_tvalid
.s_axis_config_tready (s_axis_config_tready ), // output wire s_axis_config_tready
.s_axis_data_tdata ({16'd0,w_data} ), // input wire [31 : 0] s_axis_data_tdata
.s_axis_data_tvalid (w_valid ), // input wire s_axis_data_tvalid
.s_axis_data_tready (w_ready ), // output wire s_axis_data_tready 表示已经准备接收好数据
.s_axis_data_tlast (w_last ), // input wire s_axis_data_tlast
.m_axis_data_tdata (w_fft_result ), // output wire [63 : 0] m_axis_data_tdata
.m_axis_data_tvalid (w_fft_valid ), // output wire m_axis_data_tvalid
.m_axis_data_tready (1 ), // input wire m_axis_data_tready
.m_axis_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
);
>解释:**代码的3,4,5类似握手信号,说来了数据,是有效的,赶快输出一下高电平。**
>代码的6,7,8,9表示输入的数据,其中高16为没虚数输入的0。低位输出的数。表示数据来了一直有效,输出数据接收好了。w_last表示输入完的最后一位数据。
> 10 11 12结果。需要等待输入数据完成,等待fft计算完成才会显示。表示输出数据是有效的。1表示随时准备接收数据
>
**DDS模块**
module DDS_Gen#(
parameter P_NUMBER = 1024 ,
parameter P_WIDTH = 16
)(
input i_clk ,
input i_rst ,
output [P_WIDTH - 1:0] o_data ,
output o_valid ,
output o_last ,
input i_ready
);
reg [P_WIDTH - 1:0] ro_data ;
(* ram_style = "block" *)
reg [P_WIDTH - 1:0] r_ram[0 : P_NUMBER - 1] ;
reg [$clog2(P_NUMBER) -1 :0] r_ram_addr ;
reg ro_valid ;
reg ro_last ;
assign o_data = ro_data ;
assign o_valid = ro_valid ;
assign o_last = ro_last ;
initial begin
$readmemh("fft_data.dat",r_ram,0,P_NUMBER - 1);
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
ro_data <= 'd0;
else
ro_data <= r_ram[r_ram_addr];
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_ram_addr <= 'd0;
else if(ro_valid && r_ram_addr == P_NUMBER - 1)
r_ram_addr <= r_ram_addr;
else if((r_ram_addr == 0 && i_ready) || ro_valid)
r_ram_addr <= r_ram_addr + 1;
else
r_ram_addr <= r_ram_addr;
end
always@(posedge i_clk)
begin
if(i_rst)
ro_valid <= 'd0;
else if(ro_last && ro_valid && i_ready)
ro_valid <= 'd0;
else if(r_ram_addr == 0 && i_ready)
ro_valid <= 'd1;
else
ro_valid <= ro_valid;
end
always@(posedge i_clk)
begin
if(i_rst)
ro_last <= 'd0;
else if(ro_last && ro_valid && i_ready)
ro_last <= 'd0;
else if(ro_valid && r_ram_addr == P_NUMBER - 1)
ro_last <= 'd1;
else
ro_last <= ro_last;
end
代码先生成一个ram,然后写入数据,读出数据。假设 P_NUMBER 是 16。
clog2(16) 的结果是 4,因为 2^4 = 16。
[$clog2(16) - 1 : 0] 变成 [3 : 0],表示 r_ram_addr 的位宽是 4 位(从 3 到 0)。
这里就是算有多少二进制,比如16需要4位1111表示。类似十进制转换为二进制。
(* ram_style = “block” *) 调用了系统原语。
$readmemh(“fft_data.dat”,r_ram,0,P_NUMBER - 1);读取1024个数,数据由matlab生成。
下面的就是根据地址读取数据,读取数据的时候有一个有效信号,读取完了顺便有一个last标志信号。