quartus ii FFT核使用

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                                                                    \n";
   ///////////////////////////////////////////////////////////////////////////////////////////////
   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                                                                                                 

 

posted @ 2020-05-12 15:15  王林文思  阅读(2804)  评论(0编辑  收藏  举报