quartus ii FFT核使用
导入自己程序自带的txt文件,写出控制模块
时序图
FFT核文件给出的时序图输入
仿真时序图
1024个采样点数,输入结束
fft数据输出
2、代码
`timescale 1ns/1ns module fft_ctrl #( parameter [9:0] fftpts_n = 10'd11, parameter [9:0] real_imag_wei = 10'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 - 1:0] sink_real ;//输入数据的实部 input [real_imag_wei - 1:0] sink_imag ;//输入数据的虚部 input inverse ;//0 - FFT 1 - IFFT input [fftpts_n - 1:0] 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 - 1: 0] source_real ;//变换后输出数据的实部 output [real_imag_wei - 1: 0] source_imag ;//变换后输出数据的虚部 output [5:0] 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 [1:0] sink_error; wire [1:0] source_error; localparam NUM_FRAMES_c = 4; //输入数据的次数 //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 [7:0] frames_in_index; //number of output frames reg [7:0] frames_out_index; // signal the end of the input data stream and output data stream. reg [fftpts_n - 1:0] cnt; /////////////////////////////////////////////////////////////////////////////////////////////// // Clock Generation /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// // Set FFT Direction // '0' => FFT // '1' => IFFT // assign inverse = 1'b0; //no input error assign sink_error = 2'b0; // for example purposes, the ready signal is always asserted. assign source_ready = 1'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 == 1'b0) cnt <= 'd0; else begin if (sink_valid == 1'b1 & sink_ready == 1'b1) begin if (cnt == fftpts_array_N - 1) cnt <= 'd0; else cnt <= cnt + 1'b1; end end end // count the input frames and increment the index always @(posedge clk or negedge reset_n) begin if (reset_n == 1'b0) frames_in_index <= 'd0; else begin if (sink_eop == 1'b1 & sink_valid == 1'b1 & sink_ready == 1'b1 & frames_in_index < NUM_FRAMES_c -1) frames_in_index <= frames_in_index + 1'b1; end end // count the output frames and increment the index always @(posedge clk or negedge reset_n) begin if (reset_n == 1'b0) frames_out_index <= 'd0; else begin if (source_eop == 1'b1 & source_valid == 1'b1 & source_ready == 1'b1 & frames_out_index < NUM_FRAMES_c -1) frames_out_index <= frames_out_index + 1'b1; end end // signal when all of the input data has been sent to the DUT assign end_input = (sink_eop == 1'b1 & sink_valid == 1'b1 & sink_ready == 1'b1 & frames_in_index == NUM_FRAMES_c - 1) ? 1'b1 : 1'b0; // signal when all of the output data has be received from the DUT assign end_output = (source_eop == 1'b1 & source_valid == 1'b1 & source_ready == 1'b1 & frames_out_index == NUM_FRAMES_c - 1) ? 1'b1 : 1'b0; // generate start and end of packet signals assign sink_sop = (cnt == 0) ? 1'b1 : 1'b0 ; assign sink_eop = ( cnt == fftpts_array_N - 1 ) ? 1'b1 : 1'b0; //halt the input when done always @(posedge clk or negedge reset_n) begin if (reset_n == 1'b0) end_test <= 1'b0; else begin if (end_input == 1'b1) end_test <= 1'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[16 - 1:0] sink_real; reg[16 - 1:0] sink_imag; reg [10:0] fftpts_array_N; reg inverse; wire sink_sop; wire sink_eop; wire sink_ready; wire source_sop; wire source_eop; wire source_valid; wire [5:0] source_exp; wire [16 - 1: 0] source_real; wire [16 - 1: 0] source_imag; parameter NUM_FRAMES_c = 4; parameter MAXVAL_c = 2**(16 -1); parameter OFFSET_c = 2**(16); parameter MAXVAL_EXP_c = 2**5; parameter OFFSET_EXP_c = 2**6; // 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"); #0 clk = 1'b0; inverse = 0; fftpts_array_N = 11'd1024; sink_valid = 0; inverse = 0; #0 reset_n = 1'b0; #92 reset_n = 1'b1; end /////////////////////////////////////////////////////////////////////////////////////////////// // Clock Generation /////////////////////////////////////////////////////////////////////////////////////////////// always begin if (end_test == 1'b1 & end_output == 1'b1) begin clk = 1'b0; $finish; end else begin #5 clk = 1'b1; #5 clk = 1'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 == 1'b0) start <= 1'b1; else begin if (sink_valid_r == 1'b1 & sink_ready == 1'b1) start <= 1'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 "; /////////////////////////////////////////////////////////////////////////////////////////////// integer rc_x; integer ic_x; always @ (posedge clk) begin if(reset_n==1'b0) begin sink_real<=16'b0; sink_imag<=16'b0; sink_valid_r <= 1'b0; end else begin // send in NUM_FRAMES_c of data or until the end of the file if((end_test == 1'b1) || (end_input == 1'b1)) begin sink_real<=16'b0; sink_imag<=16'b0; sink_valid_r <= 1'b0; end else begin if ((sink_valid_r == 1'b1 & sink_ready == 1'b1 ) || (start == 1'b1 & !(sink_valid_r == 1'b1 & sink_ready == 1'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 <= 1'b1; end else begin sink_real<=sink_real; sink_imag<=sink_imag; sink_valid_r <= 1'b0; end end end end ////////////////////////////////////////////////////////////////////////////////////////////// // Write Real and Imginary Data Components and Block Exponent to Disk ////////////////////////////////////////////////////////////////////////////////////////////// always @ (posedge clk) begin if((reset_n==1'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(10'd11), .real_imag_wei(10'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