項目簡述
前面我們已經講解過Xilinx中FFT IP的使用,但是使用的時候IP的配置接口我們沒有進行相應的講解,直接使用GUI配置好的接口,這在現實應用中很不方方便,會讓人感覺到還不如自己手寫一個FFT算法,當然博主也可完全手撕FFT、CORDIC代碼,但是把IP用好了絕對比我們手寫的代碼要好用的多。這篇博客主要講解FFT IP的重配置及其參數的意義,最後將給出Modelsim與MATLAB的兩盒驗證。
本次實驗所使用的軟硬件環境如下:
1、VIVADO 2019.1
2、Modelsim 10.7
3、MATLAB 2015b
這裏再多說一句,從博主之前的文章中可以發現MATLAB在信號處理中的正確性,所以絕對不要說MATLAB不重要。而且一般Xilinx的IP核都可以生成相應的m文件,也就是說我們可以實現MATLAB與Modelsim完全一致的驗證。 所以要想做信號處理或算法得FPGA實現一定要掌握MATLAB。
FFT進行重配置
我們在定製FFT IP核得時候就已經對FFT進行了配置,但是我們實際使用IP得時候經常可以碰見IP得重配置,這一塊內容直至一年前我進行PLL得重配置得時候還是無從下手,但是這篇文章我們主要講解FFT IP得重配置,可以讓大家學習到Xilinx IP重配置得設計技巧。這裏我們首先強調技術手冊得重要性,因爲市面上沒有這方面得資料,所以我們要學習相應IP得重配置必須學習技術手冊。我們首先看FFT IP得技術手冊如下:
總共不到100頁,是值得瀏覽一遍的,因爲其他得IP基本上也是這幾部分。C Model我們上篇博客已經進行了介紹,主要是爲了我們在MATLAB中驗證該模塊得正確性來使用的。
首先我們來看FFT IP核的接口引腳:
其中FFT的接口主要可以分爲6組如上圖:
1、FFT的重配置接口
2、FFT的數據輸入接口,遵循AXI-Stream協議
3、FFT的時鐘、時鐘使能、復位信號(注意復位信號要多給幾個時鐘)
4、FFT的數據輸出接口,遵循AXI-Stream協議
5、可以輸出FFT IP的當前的狀態(一般不常使用)
6、可以輸出一些FFT的錯誤信息,比如輸入的last未知不正確或沒有,數據溢出等等
上面是簡要介紹了FFT IP的接口描述。具體的功能引腳的定義還是需要我們查找技術手冊,我們這篇博客主要講解IP的重配置,不會對AXI-Stream進行過多的介紹。
從FFT IP技術手冊的首頁我們可以發現,FFT可以完成的功能:
上面也是我們進行重配置的主要內容:
1、FFT最大變換的點數
2、FFT正變換還是逆變換
3、每級蝶形運算縮放因子的輸入
4、CP_LEN的長度(這個具體的所用,我也不知道,知道的同學可以在評論裏討論一下)
要想配置上面的這些信息,我們就一定要進行配置數據的輸入,配置數據的不同位數代表不同的功能,如下:
上面爲什麼會有PAD,主要是因爲字節對齊,每個配置功能佔整數個字節。其中除了SCALE_SCH上面的位寬都是確定的,如下:
上面每位的取值情況如下:
上面的功能需要大家仔細讀,尤其是SCALE_SCH,這裏我給大家稍微解讀一下。
1、每兩個比特位構成的數字作爲一級蝶形運算的縮放比例。2位比特位構成了0,1,2,3,這三個數代表分別代表蝶形運算之後的結果移位的個數。
2、SCALE_SCH的位數對於基-4 FFT算法是,其中ceil是指向上取整;對於基-2 FFT算法是,相信熟悉FFT蝶形運算的同學很容易明白,其實這就是蝶形運算的個數然後乘以2。
關於FFT重配置的理論我們就講到這裏,下面我們給出相應的代碼供大家學習,並且將代碼與上篇博客中的MATLAB生成的結果相互驗證,從而使得MATLAB與VIVADO實現雙重驗證。
FPGA代碼
FPGA邏輯代碼
tx_ifft_op模塊:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : tx_ifft_op.v
// Create Time : 2020-06-04 16:33:48
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module tx_ifft_op(
input sclk ,
input rst_n ,
input cfg_vld ,
output reg p1_start ,
input s_config_tvalid ,
input [29:0] s_config_tdata ,
input s_data_tvalid ,
input [23:0] s_data_tdata ,
input s_data_tlast ,
output reg s_axis_config_tready ,
output reg s_axis_data_tready ,
output reg [31:0] m_axis_data_tdata ,
output [23:0] m_axis_data_tuser ,
output reg m_axis_data_tvalid ,
input m_axis_data_tready ,
output reg m_axis_data_tlast ,
output [ 7:0] m_axis_status_tdata ,
output m_axis_status_tvalid ,
input m_axis_status_tready ,
output event_frame_started ,
output event_tlast_unexpected ,
output event_tlast_missing ,
output event_fft_overflow ,
output event_status_channel_halt ,
output event_data_in_channel_halt ,
output event_data_out_channel_halt ,
output [ 9:0] NOFDM
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
reg [ 9:0] NOFDM_CNT ;
wire [39:0] s_axis_config_tdata ;
wire s_axis_config_tvalid ;
wire [31:0] s_axis_data_tdata ;
wire s_axis_data_tvalid ;
wire s_axis_data_tlast ;
wire [ 4:0] NFFT ;
wire [13:0] SCALE_SCH ;
wire [11:0] RE_DATA ;
wire [11:0] IM_DATA ;
wire DATA_LAST ;
wire DATA_EN ;
wire FWD_INV ;
wire fft_config_en ;
wire [31:0] m_axis_data_tdata_store ;
wire m_axis_data_tvalid_store;
wire m_axis_data_tlast_store ;
reg p1_start_D ;
wire [12:0] CP_LEN ;
reg last_delay ;
wire Neg_ifft_tlast ;
reg [ 4:0] rstn_cnt ;
wire s_axis_data_tready1 ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign Neg_ifft_tlast = last_delay&&(~m_axis_data_tlast_store);
always@(posedge sclk)
last_delay <= m_axis_data_tlast_store;
always @(posedge sclk)
if(rst_n == 1'b0)
NOFDM_CNT <= 10'd0;
else if(NOFDM_CNT == NOFDM+1'b1 && NOFDM != 10'd0)
NOFDM_CNT <= 10'd0;
else if(Neg_ifft_tlast == 1'b1)
NOFDM_CNT <= NOFDM_CNT + 1'b1;
always @(posedge sclk)
if(rst_n == 1'b0)
rstn_cnt <= 5'h1f;
else if(cfg_vld == 1'b1)
rstn_cnt <= 5'd0;
else if(rstn_cnt == 5'h1f)
rstn_cnt <= rstn_cnt;
else
rstn_cnt <= rstn_cnt + 1'b1;
always @(posedge sclk)
if(rst_n == 1'b0)
p1_start <= 1'b0;
else if(rstn_cnt == 5'h1e)
p1_start <= 1'b1;
else if(NOFDM_CNT == NOFDM+1'b1 && NOFDM != 10'd0)
p1_start <= 1'b1;
else
p1_start <= 1'b0;
always @(posedge sclk)
if(rst_n == 1'b0)
s_axis_data_tready <= 1'b1;
else if(Neg_ifft_tlast == 1'b1)
s_axis_data_tready <= 1'b1;
else if(s_data_tlast == 1'b1)
s_axis_data_tready <= 1'b0;
always @(posedge sclk)
p1_start_D <= p1_start;
always @(posedge sclk)
if(rst_n == 1'b0)
s_axis_config_tready <= 1'b0;
else if(p1_start_D == 1'b1)
s_axis_config_tready <= 1'b0;
else if(Neg_ifft_tlast == 1'b1)
s_axis_config_tready <= 1'b1;
always @(posedge sclk)
begin
m_axis_data_tdata <= m_axis_data_tdata_store;
m_axis_data_tvalid <= m_axis_data_tvalid_store && m_axis_data_tready;
m_axis_data_tlast <= m_axis_data_tlast_store;
end
ifft_op_map ifft_op_map
(
.sclk (sclk ),
.rst_n (rst_n ),
.s_config_tvalid (s_config_tvalid ),
.s_config_tdata (s_config_tdata ),
.s_data_tvalid (s_data_tvalid ),
.s_data_tdata (s_data_tdata ),
.s_data_tlast (s_data_tlast ),
.RE_DATA (RE_DATA ),
.IM_DATA (IM_DATA ),
.DATA_EN (DATA_EN ),
.DATA_LAST (DATA_LAST ),
.fft_config_en (fft_config_en ),
.NFFT (NFFT ),
.CP_LEN (CP_LEN ),
.SCALE_SCH (SCALE_SCH ),
.FWD_INV (FWD_INV ),
.NOFDM (NOFDM )
);
/*===================================================================
====================================================================*/
fft_sig_comp fft_sig_comp
(
.sclk (sclk ),
.rst_n (rst_n ),
.P1_EN (DATA_EN ),
.RE_P1_DATA (RE_DATA ),
.IM_P1_DATA (IM_DATA ),
.data_LAST (DATA_LAST ),
.fft_config_en (fft_config_en ),
.NFFT (NFFT ),
.CP_LEN (CP_LEN ),
.SCALE_SCH (SCALE_SCH ),
.FWD_INV (FWD_INV ),
.s_axis_config_tdata (s_axis_config_tdata ),
.s_axis_config_tvalid (s_axis_config_tvalid ),
.s_axis_data_tdata (s_axis_data_tdata ),
.s_axis_data_tvalid (s_axis_data_tvalid ),
.s_axis_data_tlast (s_axis_data_tlast )
);
tx_xfft_0 tx_xfft_0 (
.aclk (sclk ),
.aresetn (rst_n ),
.s_axis_config_tdata (s_axis_config_tdata ),
.s_axis_config_tvalid (s_axis_config_tvalid ),
.s_axis_config_tready (sim_config_tready ),
.s_axis_data_tdata (s_axis_data_tdata ),
.s_axis_data_tvalid (s_axis_data_tvalid ),
.s_axis_data_tready (s_axis_data_tready1 ),
.s_axis_data_tlast (s_axis_data_tlast ),
.m_axis_data_tdata (m_axis_data_tdata_store ),
.m_axis_data_tuser (m_axis_data_tuser ),
.m_axis_data_tvalid (m_axis_data_tvalid_store ),
.m_axis_data_tready (m_axis_data_tready ),
.m_axis_data_tlast (m_axis_data_tlast_store ),
.m_axis_status_tdata (m_axis_status_tdata ),
.m_axis_status_tvalid (m_axis_status_tvalid ),
.m_axis_status_tready (m_axis_status_tready ),
.event_frame_started (event_frame_started ),
.event_tlast_unexpected (event_tlast_unexpected ),
.event_tlast_missing (event_tlast_missing ),
.event_fft_overflow (event_fft_overflow ),
.event_status_channel_halt (event_status_channel_halt ),
.event_data_in_channel_halt (event_data_in_channel_halt ),
.event_data_out_channel_halt (event_data_out_channel_halt)
);
endmodule
ifft_op_map模塊:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : ifft_op_map.v
// Create Time : 2020-06-04 16:49:13
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module ifft_op_map
(
input sclk ,
input rst_n ,
input s_config_tvalid ,
input [29:0] s_config_tdata ,
input s_data_tvalid ,
input [23:0] s_data_tdata ,
input s_data_tlast ,
output reg [11:0] RE_DATA ,
output reg [11:0] IM_DATA ,
output reg DATA_EN ,
output reg DATA_LAST ,
output reg fft_config_en ,
output reg [ 4:0] NFFT ,
output reg [12:0] CP_LEN ,
output reg [13:0] SCALE_SCH ,
output reg FWD_INV ,
output reg [ 9:0] NOFDM
);
/*===================================================================
====================================================================*/
wire [ 1:0] fft_mode ;
wire [ 9:0] nofdm ;
wire [ 2:0] cp_pro ;
wire [13:0] scale ;
wire inv ;
reg [ 2:0] PRO ;
reg [ 1:0] MODE ;
reg [ 1:0] MODE1 ;
reg [ 9:0] NOFDM1 ;
reg [ 2:0] PRO1 ;
reg [13:0] SCALE_SCH1 ;
reg FWD_INV1 ;
reg fft_config_en1 ;
assign fft_mode = s_config_tdata[1:0];
assign nofdm = s_config_tdata[11:2];
assign cp_pro = s_config_tdata[14:12];
assign scale = s_config_tdata[28:15];
assign inv = s_config_tdata[29];
always @(posedge sclk)
begin
if(rst_n == 1'b0)begin
MODE1 <= 2'b00;
NOFDM1 <= 10'd0;
PRO1 <= 3'b000;
SCALE_SCH1 <= 14'd0;
FWD_INV1 <= 1'b0;
end else if(s_config_tvalid)begin
MODE1 <= fft_mode;
NOFDM1 <= nofdm;
PRO1 <= cp_pro;
SCALE_SCH1 <= scale;
FWD_INV1 <= inv;
end
end
always@(posedge sclk)begin
MODE <= MODE1;
NOFDM <= NOFDM1;
PRO <= PRO1;
SCALE_SCH <= SCALE_SCH1;
FWD_INV <= FWD_INV1;
end
always @(posedge sclk)begin
RE_DATA <= s_data_tdata[23:12];
IM_DATA <= s_data_tdata[11:0];
DATA_EN <= s_data_tvalid;
DATA_LAST <= s_data_tlast;
end
always@(posedge sclk)
begin
fft_config_en1 <= s_config_tvalid;
fft_config_en <= fft_config_en1;
end
always @(posedge sclk)
if(PRO1 == 3'd0)
CP_LEN <= 13'd0;
else if(PRO1 == 3'd1)//1/32
CP_LEN <= 13'd32;
else if(PRO1 == 3'd2)//1/16
CP_LEN <= 13'd64;
else if(PRO1 == 3'd3)//1/8;
CP_LEN <= 13'd128;
else if(PRO1 == 3'd4)//1/4;
CP_LEN <= 13'd256;
else
CP_LEN <= 13'd0;
always @(posedge sclk)
case(MODE1)
2'b00: NFFT <= 5'b01010;//1k
2'b01: NFFT <= 5'b01011;//2k
2'b10: NFFT <= 5'b01100;//4k
2'b11: NFFT <= 5'b01101;//8k
default:NFFT <= 5'b00000;
endcase
endmodule
fft_sig_comp模塊:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : fft_sig_comp.v
// Create Time : 2020-06-04 16:55:01
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module fft_sig_comp(
input sclk ,
input rst_n ,
input P1_EN ,
input [11:0] RE_P1_DATA ,
input [11:0] IM_P1_DATA ,
input data_LAST ,
input fft_config_en ,
input [ 4:0] NFFT ,
input [12:0] CP_LEN ,
input [13:0] SCALE_SCH ,
input FWD_INV ,
output [39:0] s_axis_config_tdata ,
output s_axis_config_tvalid,
output [31:0] s_axis_data_tdata ,
output s_axis_data_tvalid ,
output s_axis_data_tlast
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
reg [39:0] s_axis_config_tdata_reg ;
reg s_axis_config_tvalid_reg;
reg [31:0] s_axis_data_tdata_reg ;
reg s_axis_data_tvalid_reg ;
reg s_axis_data_tlast_reg ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign s_axis_config_tdata = s_axis_config_tdata_reg;
assign s_axis_config_tvalid = s_axis_config_tvalid_reg;
assign s_axis_data_tdata = s_axis_data_tdata_reg;
assign s_axis_data_tvalid = s_axis_data_tvalid_reg;
assign s_axis_data_tlast = s_axis_data_tlast_reg;
always @(posedge sclk)
s_axis_config_tdata_reg <= {1'b0,SCALE_SCH,FWD_INV,3'b000,CP_LEN,3'b000,NFFT};
always @(posedge sclk)
s_axis_config_tvalid_reg <= fft_config_en;
always @(posedge sclk)
s_axis_data_tdata_reg <= {4'b0000,IM_P1_DATA,4'b0000,RE_P1_DATA};
always @(posedge sclk)
s_axis_data_tvalid_reg <= P1_EN;
always @(posedge sclk)
s_axis_data_tlast_reg <= data_LAST;
endmodule
上面的代碼聯繫之前的理論部分,便可以學會FFT的重配置,包括經過這篇博客的學習要學會其他Xilinx常用IP的重配置,比如:DDS、FIR等等。
FPGA測試代碼
tb_tx_ifft_op模塊:
`timescale 1ns / 1ps
module tb_tx_ifft_op;
reg sclk ;
reg rst_n ;
reg cfg_vld ;
reg s_config_tvalid ;
reg [29:0] s_config_tdata ;
reg s_data_tvalid;
reg s_data_tvalid_delay,s_data_tvalid_delay1;
reg [23:0] s_data_tdata;
reg s_data_tlast;
reg m_axis_data_tready ;
reg m_axis_status_tready ;
wire s_axis_config_tready ;
wire s_axis_data_tready ;
wire [31:0]m_axis_data_tdata ;
wire [23:0]m_axis_data_tuser ;
wire m_axis_data_tvalid ;
wire m_axis_data_tlast ;
wire [7:0] m_axis_status_tdata ;
wire m_axis_status_tvalid ;
wire event_frame_started ;
wire event_tlast_unexpected ;
wire event_tlast_missing ;
wire event_fft_overflow ;
wire event_status_channel_halt ;
wire event_data_in_channel_halt ;
wire event_data_out_channel_halt ;
wire [9:0] NOFDM ;
wire p1_start ;
reg [1:0] fft_mode ;
reg [9:0] nofdm ;
reg [2:0] cp_pro ;
reg [13:0]scale ;
reg inv ;
reg [11:0]re_data ;
reg [11:0]im_data ;
always @(posedge sclk)
begin
s_data_tvalid_delay <= s_data_tvalid;
s_data_tvalid_delay1 <= s_data_tvalid_delay;
end
initial
begin
#0;
sclk =1'b0;
rst_n=1'b0;
cfg_vld = 1'b0;
m_axis_data_tready = 1'b1;
m_axis_status_tready = 1'b1;
s_config_tvalid = 1'b0;
s_config_tdata = 30'd0;
fft_mode=2'b01;
nofdm = 10'd1;
cp_pro = 3'b000;
scale = 14'b01_0110_1010_1010;
//scale = 14'd0;
inv = 1'b0;
s_data_tvalid = 1'b0;
s_data_tlast = 1'b0;
repeat(1) @(posedge sclk)#1;
cfg_vld = 1'b1;
repeat(1) @(posedge sclk)#1;
cfg_vld = 1'b0;
repeat(30) @(posedge sclk)#1;
rst_n =1'b1;
repeat(30) @(posedge sclk)#1;
s_config_tvalid = 1'b1;
s_config_tdata = {inv,scale,cp_pro,nofdm,fft_mode};
repeat(1) @(posedge sclk)#1;
s_config_tvalid = 1'b0;
repeat(300) @(posedge sclk)#1;
s_data_tvalid = 1'b1;
s_data_tlast = 1'b0;
repeat(1) @(posedge sclk)#1;
s_config_tvalid = 1'b0;
repeat(2047) @(posedge sclk)#1;
s_data_tlast = 1'b0;
s_data_tvalid = 1'b0;//mark for test
repeat(1) @(posedge sclk)#1;
s_data_tlast = 1'b1;
repeat(1) @(posedge sclk)#1;
s_data_tlast = 1'b0;
end
always #10 sclk = ~sclk;
//=========================================================================
// input
//=========================================================================
integer fid1;
integer fid2;
initial
begin
fid2 = $fopen("IM_DATA.txt","r");
fid1 = $fopen("RE_DATA.txt","r");
end
always@(posedge sclk)
begin
if(s_data_tvalid)begin
$fscanf(fid1,"%d",re_data);
$fscanf(fid2,"%d",im_data);
end
end
always @(posedge sclk)
begin
s_data_tdata <= {re_data,im_data};
end
//=========================================================================
// output
//=========================================================================
wire signed [11:0] re_out;
wire signed [11:0] im_out;
assign re_out = {m_axis_data_tdata[15],m_axis_data_tdata[10:0]};
assign im_out = {m_axis_data_tdata[31],m_axis_data_tdata[26:16]};
integer fid3;
initial
begin
fid3 = $fopen("re_fft_data.txt","w");
end
always@(posedge sclk)
begin
if(m_axis_data_tvalid)
$fwrite(fid3,"%d\n",re_out);
end
integer fid4;
initial
begin
fid4 = $fopen("im_fft_data.txt","w");
end
always@(posedge sclk)
begin
if(m_axis_data_tvalid)
$fwrite(fid4,"%d\n",im_out);
end
tx_ifft_op uut
(
.sclk (sclk ),
.rst_n (rst_n ),
.cfg_vld (cfg_vld ),
.p1_start (p1_start ),
.s_config_tvalid (s_config_tvalid ),
.s_config_tdata (s_config_tdata ),
.s_data_tvalid (s_data_tvalid_delay1 ),
.s_data_tdata (s_data_tdata ),
.s_data_tlast (s_data_tlast ),
.m_axis_data_tready (m_axis_data_tready ),
.m_axis_status_tready (m_axis_status_tready ),
.s_axis_config_tready (s_axis_config_tready ),
.s_axis_data_tready (s_axis_data_tready ),
.m_axis_data_tdata (m_axis_data_tdata ),
.m_axis_data_tuser (m_axis_data_tuser ),
.m_axis_data_tvalid (m_axis_data_tvalid ),
.m_axis_data_tlast (m_axis_data_tlast ),
.m_axis_status_tdata (m_axis_status_tdata ),
.m_axis_status_tvalid (m_axis_status_tvalid ),
.event_frame_started (event_frame_started ),
.event_tlast_unexpected (event_tlast_unexpected ),
.event_tlast_missing (event_tlast_missing ),
.event_fft_overflow (event_fft_overflow ),
.event_status_channel_halt (event_status_channel_halt ),
.event_data_in_channel_halt (event_data_in_channel_halt ),
.event_data_out_channel_halt(event_data_out_channel_halt),
.NOFDM (NOFDM )
);
endmodule
MATLAB驗證
有關MATLAB對FFT IP核調用的部分,我們上篇博客已經進行了詳細的講解,在這裏我們將給出MATLAB與Modelsim生成的數據相對比的代碼:
clc;
clear all;
load fft_data_com.mat
sim_options = struct(...
'MODE', '2k' ... %fft模式 1k 2k 4k 8k
);
tx_nFrame=1;
%------------------------------------------------------------------------------
% Parameters Definition
%------------------------------------------------------------------------------
switch sim_options.MODE
case '1k'
NFFT = 1024; % FFT number of points
case '2k'
NFFT = 2048; % FFT number of points
case '4k'
NFFT = 4096; % FFT number of points
case '8k'
NFFT = 8192; % FFT number of points
otherwise, error('sim_options UNKNOWN MODE');
end
fid1 = fopen('re_fft_data.txt','r');
real_data_sim = fscanf(fid1,'%d');
fid1 = fopen('im_fft_data.txt','r');
imag_data_sim = fscanf(fid1,'%d');
start_Idx = NFFT*(tx_nFrame - 1);
if(isempty(real_data_sim))
real_data_result = 0;
imag_data_result = 0;
else
real_data_result = sum(abs(real(fft_data_com(start_Idx+1:start_Idx+NFFT)) - real_data_sim(start_Idx+1:start_Idx+NFFT)));
imag_data_result = sum(abs(imag(fft_data_com(start_Idx+1:start_Idx+NFFT)) - imag_data_sim(start_Idx+1:start_Idx+NFFT)));
end
a = real_data_result + imag_data_result
運行結果如下:
從上面結果可以驗證我們實驗的正確性,從而說明MATLAB與VIVADO輸出的數據完全相同,兩者相互驗證了實驗的正確性。
參考文獻
[1]、電子發燒友學院
總結
創作不易,認爲文章有幫助的同學們可以關注、點贊、轉發支持。爲行業貢獻及其微小的一部分。或者對文章有什麼看法或者需要更近一步交流的同學,可以加入下面的羣: