zoukankan      html  css  js  c++  java
  • fft_cepin

      fft测频模块是整个工程的最后一个模块,该模块实现了频率和幅值的测量,先说一下缩放因子source_exp(有符号).我看网上的

    资料说如果缩放因子是负数则左移相应的位数,如果是整数则右移相应位数,实际测试发现缩放因子基本上围绕着固定的两个数变化,

    而实际的幅值跟fft变换出来的数据和缩放因子成线性关系。因为测量的是单一频率,并且fft在频域里面具有PI的对称性,所以只需要测

    前半段就可以了,通过比较大小,数据最大的值就是该频率所处在的位置。通过实测发现1hz,10Hz,100Hz是比较准确的,1KHZ测

    出的幅值有很大误差,我感觉是课本上说的栅栏效应,频率分辨率太低导致的。

    /*-----------------------------------------------------------------------
    
    Date                :        2017-XX-XX
    Description            :        Design for fft cepin.
    
    -----------------------------------------------------------------------*/
    
    module cepin
    (
        //global clock
        input                    clk,            //system clock
        input                    rst_n,             //sync reset
        
        //samclk  interface
        input            [1:0]    key_data,
        
        //sqrt        interface
        
        input            [12:0]    q_sig,
        
        //fft      interface
        input            [5:0]    source_exp,      
    //缩放因子,通过数据记录发现规律,如果source_exp = 53 则fuzhi(mv) = 4*source_exp
    //source_exp = 54 则fuzhi(mv) = 2*source_exp
        
        //ram  interface    
        input            [10:0]    wr_ram,
        
        //pinlv interface
    
        output    reg        [31:0]    f1,        //
        output    reg        [11:0]    a1
        
    ); 
    
    
    
    
    //--------------------------------
    //Funtion :  pinlv1分辨率
    reg            [15:0]        fp;
    
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            fp <= 16'd0;
        else
            case(key_data)
            2'b00 : fp <= 16'd1;
            2'b01 : fp <= 16'd10;
            2'b10 : fp <= 16'd100;
            2'b11 : fp <= 16'd1000;
            default : ;
            endcase
    end
    
    
    //--------------------------------
    //Funtion :  比较
    reg            [12:0]        temp1;
    reg            [12:0]        temp2;
    reg            [12:0]        temp3;
    
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
        begin
            temp1 <= 13'd0;
            temp2 <= 13'd0;
            temp3 <= 13'd0;
        end
        else
        begin
            temp1 <= q_sig;
            temp2 <= temp1;
            temp3 <= temp2;
        end
    end
    
    
    //--------------------------------
    //Funtion :  测频状态机
    
    reg            [1:0]        state_fft;
    reg            [12:0]        a_temp;
    reg            [31:0]        f_temp;
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
        begin
            state_fft <= 2'd0;
            a_temp    <= 12'd0;
            f_temp    <= 32'd0;
        end
        else
            case(state_fft)
        //因为FFT频域是对称分布的,所以只测正半周期即可
            
            3'd0 :
            begin
                if(wr_ram == 11'd1)
                begin
                    state_fft <= 1'd1;
                    f_temp    <= 32'd0;
                    a_temp      <= 12'd0;
                end
                else
                    state_fft <= 1'd0;
            end
            
            3'd1 :
            begin
                if(wr_ram < 11'd1024)
                begin
                    state_fft <= 3'd1;
                    if(temp2 - temp1 > 3'd2 && temp2 > temp3)
                    begin
                        if(temp2 > a_temp)
                        begin
                            f_temp <= wr_ram;
                            a_temp <= temp2;
                        end
                    end
                end
                else
                    state_fft <= 3'd2;
            end
            
            3'd2 :
            begin
                state_fft <= 3'd0;
            end
            
            default : ;
            endcase
    end
    
    
    //--------------------------------
    //Funtion :  0.5S稳定
    
    /* parameter        HALF_S = 32'd25_000_000;
    
    reg            [31:0]        cnt_s;
    
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            cnt_s <= 32'd0;
        else if(cnt_s == HALF_S - 1'b1)
            cnt_s <= 32'd0;
        else
            cnt_s <= cnt_s + 1'b1;
    end
    
    reg            [11:0]        a_temp1;
    reg            [31:0]        f_temp1;
    
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
        begin
            a_temp1 <= 12'd0;
            f_temp1 <= 32'd0;
        end
        else if(cnt_s == HALF_S - 1'b1)
        begin
            a_temp1 <= a_temp;
            f_temp1 <= f_temp;
        end
    end */
    
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            f1 <= 32'd0;
        else if(state_fft == 3'd2)
            f1 <= f_temp * fp;
    end
    
    
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            a1 <= 12'd0;
        else if(source_exp == 6'd53 && state_fft == 3'd2)
            a1 <= a_temp << 2'd2;
        else if(source_exp == 6'd54 && state_fft == 3'd2)
            a1 <= a_temp << 1'd1;
    end
    
    
    endmodule 
  • 相关阅读:
    C实现类封装、继承、多态
    运算符重载详解
    类定义 对象数组
    Install KVM Hypervisor on arrch64 Linux Server
    Failed to load package MonoAndroidDesignerPackage
    C# is和as操作符
    C#中out和ref之间的区别
    C#中 const 和 readonly 的区别
    C#版本和.NET版本以及VS版本的对应关系
    各类纤程/协程使用比较
  • 原文地址:https://www.cnblogs.com/bixiaopengblog/p/7265187.html
Copyright © 2011-2022 走看看