1 xilinx FFT IP 介紹
Xilinx 快速傅立葉變換(FFT IP)內(nèi)核實(shí)現(xiàn)了 Cooley-Tukey FFT 算法,這是一種計(jì)算有效的方法,用于計(jì)算離散傅立葉變換(DFT)。
1)正向和反向復(fù)數(shù) FFT,運(yùn)行時(shí)間可配置。
2)變換大小 N = 2m,m = 3 – 16
3)數(shù)據(jù)采樣精度 bx = 8 – 34
4)相位系數(shù)精度 bw = 8 – 34
5)算術(shù)類型:
°無標(biāo)度(全精度)定點(diǎn)
°定標(biāo)定點(diǎn)
°浮點(diǎn)數(shù)
6)定點(diǎn)或浮點(diǎn)接口
7)蝴蝶后舍入或截?cái)?/p>
8)Block RAM 或分布式 RAM,用于數(shù)據(jù)和相位因子存儲(chǔ)
9)可選的運(yùn)行時(shí)可配置轉(zhuǎn)換點(diǎn)大小
10)可擴(kuò)展的定點(diǎn)核心的運(yùn)行時(shí)可配置擴(kuò)展時(shí)間表
11)位 / 數(shù)字反轉(zhuǎn)或自然輸出順序
12)用于數(shù)字通信系統(tǒng)的可選循環(huán)前綴插入
13)四種架構(gòu)在內(nèi)核大小和轉(zhuǎn)換時(shí)間之間進(jìn)行權(quán)衡
14)位精確的 C 模型和用于系統(tǒng)建模的 MEX 功能可供下載
15)有四種運(yùn)算架構(gòu)可供選擇
.Pipelined Streaming I/O
.Radix-4 Burst I/O
.Radix-2 Burst I/O
.Radix-2 Lite Burst I/O
2 FFT IP 接口介紹
圖 1 xilinx FFT IP
1)AXI4-Stream 介紹
AXI4-Stream 接口帶來了標(biāo)準(zhǔn)化,并增強(qiáng)了 Xilinx IP LogiCORE 解決方案的互操作性。除了諸如 aclk,acclken 和 aresetn 之類的常規(guī)控制信號(hào)以及事件信號(hào)之外,到內(nèi)核的所有輸入和輸出都通過 AXI4-Stream 通道進(jìn)行傳輸。通道始終由 TVALID 和 TDATA 以及必填字段和可選字段(如 TREADY,TUSER 和 TLAST)組成。TVALID 和 TREADY 一起執(zhí)行握手以傳輸消息,其中有效負(fù)載為 TDATA,TUSER 和 TLAST。內(nèi)核對(duì)包含在 TDATA 字段中的操作數(shù)進(jìn)行運(yùn)算,并將結(jié)果輸出到輸出通道的 TDATA 字段中。
圖 2 AXI4-Stream 時(shí)序圖
圖 2 顯示了在 AXI4-Stream 通道中的數(shù)據(jù)傳輸。TVALID 由通道的源(主)端驅(qū)動(dòng),而 TREADY 由接收器(從屬)驅(qū)動(dòng)。TVALID 指示有效負(fù)載字段(TDATA,TUSER 和 TLAST)中的值有效。TREADY 表示從機(jī)已準(zhǔn)備好接收數(shù)據(jù)。當(dāng)一個(gè)周期中的 TVALID 和 TREADY 均為 TRUE 時(shí),將發(fā)生傳輸。主機(jī)和從機(jī)分別為下一次傳輸分別設(shè)置 TVALID 和 TREADY。
2)s_axis_config_tdata 接口介紹
s_axis_config_tdata 接口攜帶配置信息 CP_LEN,F(xiàn)WD / INV,NFFT 和 SCALE_SCH。
NFFT(變換的點(diǎn)大小):NFFT 可以是最大變換的大小或任何較小的點(diǎn)大小。例如,1024 點(diǎn) FFT 可以計(jì)算點(diǎn)大小 1024、512、256 等。NFFT 的值為 log2(點(diǎn)大?。T撟侄蝺H在運(yùn)行時(shí)可配置的轉(zhuǎn)換點(diǎn)大小時(shí)出現(xiàn)。
CP_LEN(循環(huán)前綴長(zhǎng)度):從轉(zhuǎn)換結(jié)束起,在輸出整個(gè)轉(zhuǎn)換之前,最初作為循環(huán)前綴輸出的樣本數(shù)。CP_LEN 可以是小于點(diǎn)大小的從零到一的任何數(shù)字。該字段僅在循環(huán)前綴插入時(shí)出現(xiàn)。
FWD_INV:指示是執(zhí)行前向 FFT 變換還是逆向 FFT 變換(IFFT)。當(dāng) FWD_INV = 1 時(shí),將計(jì)算前向變換。如果 FWD_INV = 0,則計(jì)算逆變換。
SCALE_SCH 伸縮時(shí)間表:對(duì)于突發(fā) I / O 架構(gòu),伸縮時(shí)間表由每個(gè)階段的兩位指定,第一階段的伸縮由兩個(gè) LSB 給出??s放比例可以指定為 3、2、1 或 0,代表要移位的位數(shù)。N = 1024,Radix-4 Burst I / O 的示例縮放計(jì)劃是[1 0 2 3 2](從最后階段到第一階段排序)。對(duì)于 N = 128,Radix-2 Burst I / O 或 Radix-2 Lite Burst I / O,一個(gè)可能的擴(kuò)展時(shí)間表是[1 1 1 1 0 1 2](從最后階段到第一階段排序)。對(duì)于流水線 I / O 架構(gòu),從兩個(gè) LSB 開始,每?jī)蓪?duì) Radix-2 級(jí)用兩位指定擴(kuò)展時(shí)間表。例如,N = 256 的縮放時(shí)間表可以是[2 2 2 3]。當(dāng) N 不是 4 的冪時(shí),最后一級(jí)的最大位增長(zhǎng)為一位。例如,對(duì)于 N = 512,[0 2 2 2 2]或[1 2 2 2 2]是有效的縮放時(shí)間表,但是[2 2 2 2 2]無效。對(duì)于此變換長(zhǎng)度,SCALE_SCH 的兩個(gè) MSB 只能為 00 或 01。此字段僅可用于縮放算法(非縮放,塊浮點(diǎn)或單精度浮點(diǎn))。
s_axis_config_tdata 接口格式:
1.(可選)NFFT 加填充
2.(可選)CP_LEN 加填充
3. 前轉(zhuǎn) / 后轉(zhuǎn)
4.(可選)SCALE_SCH
舉例:
內(nèi)核具有可配置的轉(zhuǎn)換大小,最大大小為 128 點(diǎn),具有循環(huán)前綴插入和 3 個(gè) FFT 通道。內(nèi)核需要配置為執(zhí)行 8 點(diǎn)變換,并在通道 0 和 1 上執(zhí)行逆變換,并在通道 2 上執(zhí)行前向變換。需要 4 點(diǎn)循環(huán)前綴。這些字段采用表中的值。
這給出了 19 位的向量長(zhǎng)度。由于所有 AXI 通道必須與字節(jié)邊界對(duì)齊,因此需要 5 個(gè)填充位,從而 s_axis_config_tdata 的長(zhǎng)度為 24 位。
3)相關(guān)標(biāo)志信號(hào)
3 xilinx FFT IP 的仿真測(cè)試
?FFT 的長(zhǎng)度選擇 8 點(diǎn),x 輸入序列為 x=[1,2,3,4,5,6,7,8];
Matlab 驗(yàn)證:
clear all
close all
clc
x = [1,2,3,4,5,6,7,8];
y =fft(x,8);
realy=real(y);
imagy=imag(y);
Y 的實(shí)部輸出為 realy=[36,-4,-4,-4,-4,-4,-4,-4];
Y 的虛部輸出為 imagy=[0,9.6569,4,1.6569,0,-1.6569,-4,-9.6569];
FPGA 仿真驗(yàn)證:
1)IP 的設(shè)置
2)仿真頂層
`timescale 1ns / 1ps
module tb_fft_top(
);
reg aclk;
reg [7 : 0] s_axis_config_tdata;
reg s_axis_config_tvalid;
wire s_axis_config_tready;
wire [31 : 0] s_axis_data_tdata;
reg s_axis_data_tvalid;
wire s_axis_data_tready;
reg s_axis_data_tlast;
wire [31 : 0] m_axis_data_tdata;
wire m_axis_data_tvalid;
reg m_axis_data_tready;
wire m_axis_data_tlast;
reg [15:0] real_data;
reg [15:0] imag_data;
wire [15:0] real_dataout;
wire [15:0] imag_dataout;
reg [9:0] cnt;
assign s_axis_data_tdata={real_data,imag_data};
assign real_dataout = m_axis_data_tdata[31:16];
assign imag_dataout = m_axis_data_tdata[15:0];
initial begin
aclk = 0;
s_axis_config_tdata=8'b0;
s_axis_config_tvalid=1'b0;
s_axis_data_tvalid=1'b0;
s_axis_data_tlast=1'b0;
real_data=16'd0;
imag_data=16'd0;
cnt = 0;
m_axis_data_tready=1'b1;
#1000;
s_axis_config_tdata=8'b0000_0001;
s_axis_config_tvalid=1'b1;
#10;
s_axis_config_tdata=8'b0000_0000;
s_axis_config_tvalid=1'b0;
#1000;
repeat(8)begin
s_axis_data_tvalid=1'b1;
real_data=real_data+16'd1;
cnt=cnt+1;
if(cnt==8) s_axis_data_tlast=1'b1;
#10;
end
s_axis_data_tvalid=1'b0;
s_axis_data_tlast=1'b0;
real_data=16'd0;
#1000;
$stop;
end
always #(5) aclk= ~aclk;
fft_top Ufft_top(
.aclk(aclk), // input wire aclk
.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(s_axis_data_tdata), // input wire [31 : 0] s_axis_data_tdata
.s_axis_data_tvalid(s_axis_data_tvalid), // input wire s_axis_data_tvalid
.s_axis_data_tready(s_axis_data_tready), // output wire s_axis_data_tready
.s_axis_data_tlast(s_axis_data_tlast), // input wire s_axis_data_tlast
.m_axis_data_tdata(m_axis_data_tdata), // output wire [31 : 0] m_axis_data_tdata
.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
.m_axis_data_tready(m_axis_data_tready), // input wire m_axis_data_tready
.m_axis_data_tlast(m_axis_data_tlast) // output wire m_axis_data_tlast
);
endmodule
3)仿真結(jié)果
Vivado 最終的仿真結(jié)果為
?Real=[36,-4,-4,-4,-4,-4,-4,-4];
?Imag=[0,-10,-4,-2,0,1,4,9];
與 matlab 的計(jì)算結(jié)果相比實(shí)部一樣,除虛部因?yàn)閿?shù)據(jù)位的取舍問題以外,正數(shù)和負(fù)數(shù)部分順序相反。