quartus ii FFT核使用

导入自己程序自带的txt文件,写出控制模块

时序图

quartus ii FFT核使用-LMLPHP

FFT核文件给出的时序图输入

quartus ii FFT核使用-LMLPHP

仿真时序图

quartus ii FFT核使用-LMLPHP

1024个采样点数,输入结束

quartus ii FFT核使用-LMLPHP

fft数据输出

quartus ii FFT核使用-LMLPHP

quartus ii FFT核使用-LMLPHP

quartus ii FFT核使用-LMLPHP

2、代码

`timescale 1ns/1ns
module fft_ctrl
#(
parameter [:] fftpts_n = 'd11,
parameter [:] real_imag_wei = 'd16
)
(
//inputs
clk ,
reset_n ,
sink_valid ,//拉高表示通知FFT即将有N个数据输入
sink_real ,//输入数据的实部
sink_imag ,//输入数据的虚部
inverse ,//0 - FFT 1 - IFFT
fftpts_array_N , //采样的点数 //output
source_sop , //输出数据起始标记
source_eop , //输出数据结束标记
source_valid , //置高,准备输出结果
//从时序看应该是sink_ready和sink_valid同步的
sink_ready ,//FFT模块准备就绪,可以接收数据 output
sink_sop ,//输入数据起始标记脉冲(维持一个时钟的高电平),与第一个数据同步
sink_eop ,//输入数据结束标记脉冲(维持一个时钟的高电平),与最后一个数据同步
source_real ,//变换后输出数据的实部
source_imag ,//变换后输出数据的虚部
source_exp , //结果数据缩放因子:这
end_input , //数据输入结束
end_test , //数据输入结束 置1
end_output //数据输出结束 ); //******************************* input and output *********************// //inputs
input clk ;
input reset_n ;
input sink_valid ;//拉高表示通知FFT即将有N个数据输入
input [real_imag_wei - :] sink_real ;//输入数据的实部
input [real_imag_wei - :] sink_imag ;//输入数据的虚部
input inverse ;//0 - FFT 1 - IFFT
input [fftpts_n - :] fftpts_array_N; //采样的点数 //output
output source_sop ; //输出数据起始标记
output source_eop ; //输出数据结束标记
output source_valid ; //置高,准备输出结果
//从时序看应该是sink_ready和sink_valid同步的
output sink_ready ;//FFT模块准备就绪,可以接收数据 output
output [real_imag_wei - : ] source_real ;//变换后输出数据的实部
output [real_imag_wei - : ] source_imag ;//变换后输出数据的虚部
output [:] source_exp ; //结果数据缩放因子:这
output end_input; //数据输入结束
output reg end_test; //输入的数据结束 置1
output end_output; //数据输出结束
output sink_sop;//输入数据起始标记脉冲(维持一个时钟的高电平),与第一个数据同步
output sink_eop;//输入数据结束标记脉冲(维持一个时钟的高电平),与最后一个数据同步 //***************************** parameter and interface *************************// wire source_ready;//表明downstream模块(理解为FFT的后续接收数据模块)可以接收数据 input
wire [:] sink_error;
wire [:] source_error; localparam NUM_FRAMES_c = ; //输入数据的次数
//parameter MAXVAL_c = 2**(16 -1);
//parameter OFFSET_c = 2**(16);
//parameter MAXVAL_EXP_c = 2**5;
//parameter OFFSET_EXP_c = 2**6; //reg start;
//number of input frames
reg [:] frames_in_index;
//number of output frames
reg [:] frames_out_index;
// signal the end of the input data stream and output data stream.
reg [fftpts_n - :] cnt; ///////////////////////////////////////////////////////////////////////////////////////////////
// Clock Generation
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
// Set FFT Direction
// '0' => FFT
// '1' => IFFT
// assign inverse = 1'b0; //no input error
assign sink_error = 'b0; // for example purposes, the ready signal is always asserted.
assign source_ready = 'b1; ///////////////////////////////////////////////////////////////////////////////////////////////
// All FFT MegaCore input signals are registered on the rising edge of the input clock, clk and
// all FFT MegaCore output signals are output on the rising edge of the input clock, clk.
////////////////////////////////////////////////////////////////////////////////////////////// // start valid for first cycle to indicate that the file reading should start.
/*
always @ (posedge clk or negedge reset_n)
begin
if (reset_n == 1'b0)
start <= 1'b1;
else
begin
if (sink_valid == 1'b1 & sink_ready == 1'b1)
start <= 1'b0;
end
end
*/
//sop and eop asserted in first and last sample of data
always @ (posedge clk or negedge reset_n)
begin
if (reset_n == 'b0)
cnt <= 'd0;
else
begin
if (sink_valid == 'b1 & sink_ready == 1'b1)
begin
if (cnt == fftpts_array_N - )
cnt <= 'd0;
else
cnt <= cnt + 'b1;
end
end
end // count the input frames and increment the index
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 'b0)
frames_in_index <= 'd0;
else
begin
if (sink_eop == 'b1 & sink_valid == 1'b1 & sink_ready == 'b1 & frames_in_index < NUM_FRAMES_c -1)
frames_in_index <= frames_in_index + 'b1;
end
end // count the output frames and increment the index
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 'b0)
frames_out_index <= 'd0;
else
begin
if (source_eop == 'b1 & source_valid == 1'b1 & source_ready == 'b1 & frames_out_index < NUM_FRAMES_c -1)
frames_out_index <= frames_out_index + 'b1;
end
end // signal when all of the input data has been sent to the DUT
assign end_input = (sink_eop == 'b1 & sink_valid == 1'b1 & sink_ready == 'b1 & frames_in_index == NUM_FRAMES_c - 1) ? 1'b1 : 'b0; // signal when all of the output data has be received from the DUT
assign end_output = (source_eop == 'b1 & source_valid == 1'b1 & source_ready == 'b1 & frames_out_index == NUM_FRAMES_c - 1) ? 1'b1 : 'b0; // generate start and end of packet signals
assign sink_sop = (cnt == ) ? 'b1 : 1'b0 ;
assign sink_eop = ( cnt == fftpts_array_N - ) ? 'b1 : 1'b0; //halt the input when done
always @(posedge clk or negedge reset_n)
begin
if (reset_n == 'b0)
end_test <= 'b0;
else
begin
if (end_input == 'b1)
end_test <= 'b1;
end
end ip_fft dut(
.clk (clk), //
.reset_n (reset_n), //
.inverse (inverse), //0 - FFT 1 - IFFT
.sink_real (sink_real), //输入数据的实部
.sink_imag (sink_imag), //输入数据的虚部
.sink_sop (sink_sop), //输入数据起始标记脉冲(维持一个时钟的高电平),与第一个数据同步
.sink_eop (sink_eop), //输入数据结束标记脉冲(维持一个时钟的高电平),与最后一个数据同步
.sink_valid (sink_valid), //拉高表示通知FFT即将有N个数据输入
.sink_error (sink_error), //指示数据流的错误信息:00——没有错误;01——丢失SOP;10——丢失EOP;11——多余的EOP;
.source_error (source_error), //表明upstream模块或者FFT模块出了问题,错误信息提示与sink_error一样 output
.source_ready (source_ready), //表明downstream模块(理解为FFT的后续接收数据模块)可以接收数据 input
.sink_ready (sink_ready), //FFT模块准备就绪,可以接收数据 output
.source_real (source_real), //变换后输出数据的实部
.source_imag (source_imag), //变换后输出数据的虚部
.source_exp (source_exp), //结果数据缩放因子:这个指数位的意思打个比方说吧,
//比如它是3,就是说这时输出的虚部和实部的数值要除以2的3次方,如果是10,就要除以2的10次方,
//如果对结果精度要求不高的话,可以直接截去相应的长度,
//比如指数是3,实部输出1011_0111_0111,那么此刻实际的值应该为1_0110_1110.111;取整就是101101110
.source_valid (source_valid), //置高,准备输出结果
.source_sop (source_sop), //输出数据起始标记
.source_eop (source_eop) //输出数据结束标记
); endmodule
// ================================================================================
// Legal Notice: Copyright (C) 1991-2008 Altera Corporation
// Any megafunction design, and related net list (encrypted or decrypted),
// support information, device programming or simulation file, and any other
// associated documentation or information provided by Altera or a partner
// under Altera's Megafunction Partnership Program may be used only to
// program PLD devices (but not masked PLD devices) from Altera. Any other
// use of such megafunction design, net list, support information, device
// programming or simulation file, or any other related documentation or
// information is prohibited for any other purpose, including, but not
// limited to modification, reverse engineering, de-compiling, or use with
// any other silicon devices, unless such use is explicitly licensed under
// a separate agreement with Altera or a megafunction partner. Title to
// the intellectual property, including patents, copyrights, trademarks,
// trade secrets, or maskworks, embodied in any such megafunction design,
// net list, support information, device programming or simulation file, or
// any other related documentation or information provided by Altera or a
// megafunction partner, remains with Altera, the megafunction partner, or
// their respective licensors. No other licenses, including any licenses
// needed under any third party's intellectual property, are provided herein.
// ================================================================================
// `timescale 1ns / 1ps
module ip_fft_ctrl_tb; //inputs
reg clk;
reg reset_n;
reg sink_valid;
reg[ - :] sink_real;
reg[ - :] sink_imag;
reg [:] fftpts_array_N;
reg inverse;
wire sink_sop;
wire sink_eop;
wire sink_ready; wire source_sop;
wire source_eop;
wire source_valid;
wire [:] source_exp;
wire [ - : ] source_real;
wire [ - : ] source_imag;
parameter NUM_FRAMES_c = ;
parameter MAXVAL_c = **( -);
parameter OFFSET_c = **();
parameter MAXVAL_EXP_c = **;
parameter OFFSET_EXP_c = **; // signal the end of the input data stream and output data stream.
wire end_test;
wire end_input;
wire end_output; integer fft_rf, fft_if;
integer expf;
integer data_rf,data_if;
integer data_real_in_int,data_imag_in_int;
integer fft_real_out_int,fft_imag_out_int;
integer exponent_out_int; initial
begin data_rf = $fopen("ip_fft_real_input.txt","r");
data_if = $fopen("ip_fft_imag_input.txt","r");
fft_rf = $fopen("ip_fft_real_output_ver.txt");
fft_if =$fopen("ip_fft_imag_output_ver.txt");
expf = $fopen("ip_fft_exponent_output_ver.txt");
# clk = 'b0;
inverse = ;
fftpts_array_N = 'd1024;
sink_valid = ;
inverse = ;
# reset_n = 'b0;
# reset_n = 'b1; end ///////////////////////////////////////////////////////////////////////////////////////////////
// Clock Generation
///////////////////////////////////////////////////////////////////////////////////////////////
always
begin
if (end_test == 'b1 & end_output == 1'b1)
begin
clk = 'b0;
$finish;
end
else
begin
# clk = 'b1;
# clk = 'b0;
end
end ///////////////////////////////////////////////////////////////////////////////////////////////
//采样的点数
//assign fftpts_array_N = 11'd1024; ///////////////////////////////////////////////////////////////////////////////////////////////
// All FFT MegaCore input signals are registered on the rising edge of the input clock, clk and
// all FFT MegaCore output signals are output on the rising edge of the input clock, clk.
////////////////////////////////////////////////////////////////////////////////////////////// // start valid for first cycle to indicate that the file reading should start.
reg start;
reg sink_valid_r;
always @ (posedge clk)
begin
if (reset_n == 'b0)
start <= 'b1;
else
begin
if (sink_valid_r == 'b1 & sink_ready == 1'b1)
start <= 'b0;
end
end ///////////////////////////////////////////////////////////////////////////////////////////////
// Read input data from files. Data is generated on the negative edge of the clock, clk, in the
// testbench and registered by the core on the positive edge of the clock \n";
///////////////////////////////////////////////////////////////////////////////////////////////
integer rc_x;
integer ic_x;
always @ (posedge clk)
begin
if(reset_n=='b0)
begin
sink_real<='b0;
sink_imag<='b0;
sink_valid_r <= 'b0;
end
else
begin
// send in NUM_FRAMES_c of data or until the end of the file
if((end_test == 'b1) || (end_input == 1'b1))
begin
sink_real<='b0;
sink_imag<='b0;
sink_valid_r <= 'b0;
end
else
begin
if ((sink_valid_r == 'b1 & sink_ready == 1'b1 ) ||
(start == 'b1 & !(sink_valid_r == 1'b1 & sink_ready == 'b0)))
begin
rc_x = $fscanf(data_rf,"%d",data_real_in_int);
sink_real <= data_real_in_int;
ic_x = $fscanf(data_if,"%d",data_imag_in_int);
sink_imag <= data_imag_in_int;
sink_valid_r <= 'b1;
end
else
begin
sink_real<=sink_real;
sink_imag<=sink_imag;
sink_valid_r <= 'b0;
end
end
end
end //////////////////////////////////////////////////////////////////////////////////////////////
// Write Real and Imginary Data Components and Block Exponent to Disk
//////////////////////////////////////////////////////////////////////////////////////////////
always @ (posedge clk)
begin
if((reset_n=='b1) & (source_valid == 1'b1))
begin
fft_real_out_int = source_real;
fft_imag_out_int = source_imag;
$fdisplay(fft_rf, "%d", (fft_real_out_int < MAXVAL_c) ? fft_real_out_int : fft_real_out_int - OFFSET_c);
$fdisplay(fft_if, "%d", (fft_imag_out_int < MAXVAL_c) ? fft_imag_out_int : fft_imag_out_int - OFFSET_c);
exponent_out_int = source_exp;
$fdisplay(expf, "%d", (exponent_out_int < MAXVAL_EXP_c) ? exponent_out_int : exponent_out_int - OFFSET_EXP_c);
end
end ///////////////////////////////////////////////////////////////////////////////////////////////
// FFT Module Instantiation
/////////////////////////////////////////////////////////////////////////////////////////////
fft_ctrl
#(
.fftpts_n('d11),
.real_imag_wei('d16)
) fft_ctrl
(
//inputs
.clk (clk ),
.reset_n (reset_n ),
.sink_valid (sink_valid_r ),//拉高表示通知FFT即将有N个数据输入
.sink_real (sink_real ),//输入数据的实部
.sink_imag (sink_imag ),//输入数据的虚部
.inverse (inverse ),//0 - FFT 1 - IFFT 0
.fftpts_array_N (fftpts_array_N ), //采样的点数 1024 //output
.source_sop (source_sop ), //输出数据起始标记
.source_eop (source_eop ), //输出数据结束标记
.source_valid (source_valid), //置高,准备输出结果
//从时序看应该是sink_ready和sink_valid同步的
.sink_ready (sink_ready ),//FFT模块准备就绪,可以接收数据 output
.sink_sop (sink_sop),//输入数据起始标记脉冲(维持一个时钟的高电平),与第一个数据同步
.sink_eop (sink_eop),//输入数据结束标记脉冲(维持一个时钟的高电平),与最后一个数据同步
.source_real (source_real),//变换后输出数据的实部
.source_imag (source_imag),//变换后输出数据的虚部
.source_exp (source_exp ), //结果数据缩放因子:这
.end_input (end_input ), //数据输入结束
.end_test (end_test ), //数据输入结束 置1
.end_output (end_output )//数据输出结束
); endmodule
05-11 13:18