zoukankan      html  css  js  c++  java
  • 微弱信号二次谐波检测的FPGA的实现-总结

    首先还是把握大的系统框架:

    我要实现的部分不包括DA以及AD的转换,主要是将SSP接收到的数据送入到FIFO中,然后经过FIR带通滤波器的处理后对该信号计算幅值并做PSD,然后处理的信号经过积分够一方面送入到FIFO一方面进行均值滤波(实际上就是在一定的积分门时间内做累加操作)。最后结果通过通信模块RS232 送入到上位机,此外信号源2经过缓冲放大然后AD转换后送入到FIFO,也是通过RS232送入到上位机。

    二次谐波幅值计算

    先计算二次谐波幅值。

    二次谐波的计算主要利用的是正余弦信号的周期性;信号经FIR带通滤波后主要含有8kHz的二次谐波,可用公式表示为

                                                  (4.5.1)

    其中,是二次谐波幅值,, 

    将各次采样的点编号为1,2,3,4,5,6,7,8,那么这8采样的表达式的相位之间满足相差90度

    A/D转换器的采样频率为64kHz而二次谐波频率为8kHz,即一个周期采样8个点,所以有

     A0^2+A2^2=A^2,而且A1^2+A3^2=A^2;

    通过40次定时中断采样40个点,32阶的FIR带通滤波器滤波后的最后8个点作为计算二次谐波幅值的数据点,因此可求得二次谐波幅值实际上就是这8次采样点的数据分别平方求和以后开根号,然后除以2(右移一位)来实现的

    检波与积分反馈

    在调试试验阶段预先调整好传感器输出信号与定时器匹配输出的8kHz检波信号同相(通过设置定时器计数器的初值),而设计的FIR带通滤波器不改变8kHz二次谐波的相位,在以后的测量中通过检波程序判断这两个信号是否还同相,就可知道所测信号的方向。

    具体检波过程:在二次谐波的一个周期8个点内,找出最大值x[count],如果对应的检波信号c[count]为1(同相)则信号为正,如果c[count]为0(反相)则信号为负。

    系统的积分是对每次计算出的二次谐波幅值进行累加求和。本系统反馈的是8K的幅值。假定幅值也是有正负的,当通过检波判断信号为正时幅值也为正,反之为负。每循环一次,计算一次二次谐波幅值,接着进行累加,然后把累加量通过D/A转换器反馈出去,直至使二次谐波幅值小于一个很小的预定值反馈才中止。此时,最后一次反馈的积分值可代表信号大小与方向。

    理想情况下,预定值为0,实际情况中预定值不可能设置为0,否则系统一直反馈下去。增大预定值可以减小每次测量的反馈次数,从而使系统的测量时间更短,但是预定值也不能太大,否则积分值不能真实反映实际大小。预定值大小可以在调试程序过程中根据系统要求进行选择。

    总结:这里边涉及到的主要的FPGA设计的关键部分主要有

    1)多个输入的平方和开根号的问题(cordic算法来实现开根号的处理)

    2)FIR带通滤波器的FPGA实现()

    3)SPI传输信号的FPGA实现(FPGA作为主机,往从机发送数据的过程)

    4)系统在门控时间内积分的实现(累加的过程实际上可以达到均值滤波的效果)

    5)FIFO做数据缓冲模块的实现。(主要用在AD转换以及DA转换的时候两个不同类型之间的数据的缓冲的问题)

    关于cordic实现求幅值的计算(开方根)

    module cordic
        (
         //input signals
         clk,
         rst,                  
         Data_i,
         Data_q,
         //output signals
         Z_valid,
         Magnitude,
         y,
         Phase
        );
        
    /*****************************************************/
    /*------- Input and Output Ports declaration --------*/
    /*****************************************************/
    input               clk; 
    input               rst;
    input   [15:0]      Data_i;
    input   [15:0]      Data_q;
                               
    output              Z_valid;
    output  [17:0]      Magnitude;
    output  [17:0]      Phase;
    output  [17:0]     y;
    /*****************************************************/
    /*-------  Ports Type declaration            --------*/
    /*****************************************************/ 
    reg                 Z_valid;
    reg     [17:0]      Magnitude;
    wire    [17:0]      Phase;                            
    reg  [17:0]     y;
    /*****************************************************/
    /*-------  Parameters declaration            --------*/
    /*****************************************************/ 
     
    parameter   Coef0  = 20'h20000;     //arctan(1/2^0 ) = 45       
    parameter   Coef1  = 20'h12e40;     //arctan(1/2^1 ) = 26.565051               
    parameter   Coef2  = 20'h09fb4;     //arctan(1/2^2 )       
    parameter   Coef3  = 20'h05111;     //arctan(1/2^3 )       
    parameter   Coef4  = 20'h028b1;     //arctan(1/2^4 )      
    parameter   Coef5  = 20'h0145d;     //arctan(1/2^5 )       
    parameter   Coef6  = 20'h00a2f;     //arctan(1/2^6 )
    parameter   Coef7  = 20'h00518;     //arctan(1/2^7 )
    parameter   Coef8  = 20'h0028c;     //arctan(1/2^8 )
    parameter   Coef9  = 20'h00146;     //arctan(1/2^9 )
    parameter   Coef10 = 20'h000a3;     //arctan(1/2^10)
    parameter   Coef11 = 20'h00051;     //arctan(1/2^11)
    parameter   Coef12 = 20'h00029;     //arctan(1/2^12)
    parameter   Coef13 = 20'h00014;     //arctan(1/2^13)
    parameter   Coef14 = 20'h0000a;     //arctan(1/2^14)
    parameter   Coef15 = 20'h00005;     //arctan(1/2^15)
    parameter   Coef16 = 20'h00003;     //arctan(1/2^16)
    parameter   Coef17 = 20'h00001;     //arctan(1/2^17)
    
    /*****************************************************
    ----       Variable declaration              
    *****************************************************/
    reg  [4:0]      Cnt;
    
    wire [15:0]     Data_i_inv;
    wire [15:0]     Data_q_inv;
    
    reg  [19:0]     X_in_reg;
    reg  [19:0]     Y_in_reg;
    
    reg  [19:0]     Data_in_reg;
    
    wire [19:0]     X_in[17:0];
    wire [19:0]     Y_in[17:0];
    wire [19:0]     Z_in[17:0];
    wire [19:0]     a_in[17:0];
                    
    wire [19:0]     X_out[17:0];
    wire [19:0]     Y_out[17:0];
    wire [19:0]     Z_out[17:0];                                
    
    reg  [20:0]     Phase_reg0;
    reg  [17:0]     Phase_reg1;
    wire [20:0]     Phase_carry;
    reg  [17:0]     Magnitude_reg;
    
    /*****************************************************/
    /*-------               Main Code            --------*/
    /*****************************************************/
    
    assign  a_in[0 ] = Coef0; 
    assign  a_in[1 ] = Coef1; 
    assign  a_in[2 ] = Coef2; 
    assign  a_in[3 ] = Coef3; 
    assign  a_in[4 ] = Coef4; 
    assign  a_in[5 ] = Coef5; 
    assign  a_in[6 ] = Coef6; 
    assign  a_in[7 ] = Coef7; 
    assign  a_in[8 ] = Coef8; 
    assign  a_in[9 ] = Coef9; 
    assign  a_in[10] = Coef10;
    assign  a_in[11] = Coef11;
    assign  a_in[12] = Coef12;
    assign  a_in[13] = Coef13;
    assign  a_in[14] = Coef14;
    assign  a_in[15] = Coef15;
    assign  a_in[16] = Coef16;
    assign  a_in[17] = Coef17;
    
    always @ ( posedge clk or posedge rst )
    begin
        if ( rst )
            Cnt <= 5'b0;
        else if ( Cnt < 5'd20 )
            Cnt <= Cnt + 1'b1;
        else
            ;    
    end
    
    always @ ( posedge clk or posedge rst )
    begin
        if ( rst )
            Z_valid <= 1'b0;
        else if ( Cnt >= 5'd20 )
            Z_valid <= 1'b1;
        else
            Z_valid <= 1'b0;    
    end
    
    genvar i;
    generate 
        for ( i = 0; i < 18; i = i + 1 )
            begin : U_Cordic_pipe
                cordic_pipe     cordic_pipe
                    (//input signals
                     .clk        ( clk     ),
                     .rst        ( rst     ),                  
                     .X_in       ( X_in[i] ),
                     .Y_in       ( Y_in[i] ),
                     .Z_in       ( Z_in[i] ),
                     .Iteration  ( a_in[i] ),
                     .Shiftbit   ( i       ),
                     //output signals  
                     .X_out      ( X_out[i]  ),
                     .Y_out      ( Y_out[i]  ),
                     .Z_out      ( Z_out[i]  )
                    );
            end                
    endgenerate            
    
    assign Data_i_inv = ~Data_i + 16'b01;
    assign Data_q_inv = ~Data_q + 16'b01;
    
    always @ ( posedge clk or posedge rst )
    begin
        if ( rst )
            begin
                X_in_reg <= 16'b0;
                Y_in_reg <= 16'b0;
            end     
        else if ( Data_q[15] == 1'b1 )
            begin
                X_in_reg <= { {4{Data_q_inv[15]}}, Data_q_inv };
                Y_in_reg <= { {4{Data_i[15]}}, Data_i };
            end     
        else
            begin                                          
                X_in_reg <= { {4{Data_q[15]}}, Data_q }; 
                Y_in_reg <= { {4{Data_i_inv[15]}}, Data_i_inv };         
            end                                                
    end     
    
    assign Z_in[0] = 20'b0;
    assign X_in[0] = X_in_reg;
    assign Y_in[0] = Y_in_reg;
          
    genvar j;
    generate 
        for ( j = 1; j < 18; j = j + 1 )
            begin : XYZ_IN
                assign X_in[j] = X_out[j-1];
                assign Y_in[j] = Y_out[j-1];
                assign Z_in[j] = Z_out[j-1];             
            end                
    endgenerate      
    
    always @ ( posedge clk or posedge rst )
    begin
        if ( rst  )
            Data_in_reg[0] = 1'b0;
        else
            Data_in_reg[0] = Data_q[15];
    end
    
    genvar k;
    generate 
        for ( k = 1; k < 20; k = k + 1 )
            begin : Rotate_back
                always @ ( posedge clk or posedge rst )
                    begin
                        if ( rst == 1'b1 )
                            Data_in_reg[k] <= 1'b0;
                        else
                            Data_in_reg[k] <= Data_in_reg[k-1];
                    end     
            end                
    endgenerate   
    
    always @ ( posedge clk or posedge rst )
    begin
        if ( rst )
            Phase_reg0 <= 21'b0;
        else if ( Data_in_reg[19] == 1'b0 )
            Phase_reg0 <= { Z_out[17][19], Z_out[17] } + 21'h40000;
        else    
            Phase_reg0 <= { Z_out[17][19], Z_out[17] } - 21'h40000;                   
    end
    
    assign Phase_carry = ( Phase_reg0[20] == 1'b0 ) ? ( Phase_reg0 + 21'b010 ) : ( Phase_reg0 + 21'b00001 );
    
    always @ ( posedge clk or posedge rst )
    begin
        if ( rst)
            Phase_reg1 <= 18'b0;
        else if ( ( Phase_carry[20:19] == 2'b00 ) || ( Phase_carry[20:19] == 2'b11 ) )
            Phase_reg1 <= Phase_carry[19:2];
        else if ( Phase_carry[20] == 1'b0 )  
            Phase_reg1 <= 18'h3ffff;
        else    
            Phase_reg1 <= 18'h20000;                   
    end
    
    assign Phase = ( Z_valid == 1'b1 ) ? Phase_reg1 : 18'b0;
    
    always @ ( posedge clk or posedge rst )
    begin
        if ( rst )
            Magnitude_reg <= 18'b0;
        else
        begin
            Magnitude_reg <= X_out[17][17:0]; 
            y <=Y_out[17][17:0];
            end
    end
    
    always @ ( posedge clk or posedge rst )
    begin
        if ( rst)
            Magnitude <= 18'b0;
        else
            Magnitude <= Magnitude_reg; 
    end
    
    endmodule    
    
    
    module cordic_pipe
        (
        //input signals
        clk,
        rst,                  
        X_in,
        Y_in,
        Z_in,
        Iteration,
        Shiftbit,
        //output signals  
        X_out,
        Y_out,
        Z_out
        );
        
    /*****************************************************/
    /*------- Input and Output Ports declaration --------*/
    /*****************************************************/
    input               clk; 
    input               rst;
    input   [19:0]      X_in;
    input   [19:0]      Y_in;
    input   [19:0]      Z_in;
    input   [19:0]      Iteration;
    input   [4:0]       Shiftbit;
                        
    output  [19:0]      X_out;
    output  [19:0]      Y_out;
    output  [19:0]      Z_out;
    
    /*****************************************************/
    /*-------  Ports Type declaration            --------*/
    /*****************************************************/  
    reg     [19:0]      X_out;
    reg     [19:0]      Y_out;
    reg     [19:0]      Z_out;
    
    wire    [19:0]      X_in_shift;
    wire    [19:0]      Y_in_shift;
    
    /*****************************************************
    ----       Variable declaration              
    *****************************************************/
    
    /*****************************************************/
    /*-------               Main Code            --------*/
    /*****************************************************/
    
    cordic_shift    U_cordic_shift     
        (        
        .X_in           ( X_in     ),
        .Y_in           ( Y_in     ),
        .Shiftbit       ( Shiftbit ),
        
        .X_in_shift     ( X_in_shift ),
        .Y_in_shift     ( Y_in_shift )
        );
    
    always @ ( posedge rst or posedge clk )
    begin
        if( rst )
            begin
                X_out <= 20'b0;
                Y_out <= 20'b0;
                Z_out <= 20'b0;
            end
        else if ( Y_in[19] == 1'b0 ) 
            begin
                X_out <= X_in + Y_in_shift;
                Y_out <= Y_in - X_in_shift;
                Z_out <= Z_in + Iteration;
            end    
        else
            begin
                X_out <= X_in - Y_in_shift;
                Y_out <= Y_in + X_in_shift;
                Z_out <= Z_in - Iteration;
            end    
    end
    
    endmodule    
    
    module cordic_shift
        (
        //input signals           
        X_in,
        Y_in,
        Shiftbit,
        //output signals  
        X_in_shift,
        Y_in_shift
        );
    
    /*****************************************************/
    /*------- Input and Output Ports declaration --------*/
    /*****************************************************/
    input   [19:0]      X_in;
    input   [19:0]      Y_in;
    input   [4:0]       Shiftbit;
                        
    output  [19:0]      X_in_shift;
    output  [19:0]      Y_in_shift;
    
    /*****************************************************/
    /*-------  Ports Type declaration            --------*/
    /*****************************************************/ 
    
    reg     [19:0]      X_in_shift;
    reg     [19:0]      Y_in_shift;
    
    always @ ( X_in or Shiftbit )
    begin
        case ( Shiftbit )
            5'b0  : X_in_shift = X_in;
            5'd1  : X_in_shift = {  {1{X_in[19]}}, X_in[19:1]  };
            5'd2  : X_in_shift = {  {2{X_in[19]}}, X_in[19:2]  };
            5'd3  : X_in_shift = {  {3{X_in[19]}}, X_in[19:3]  };
            5'd4  : X_in_shift = {  {4{X_in[19]}}, X_in[19:4]  };
            5'd5  : X_in_shift = {  {5{X_in[19]}}, X_in[19:5]  };
            5'd6  : X_in_shift = {  {6{X_in[19]}}, X_in[19:6]  };
            5'd7  : X_in_shift = {  {7{X_in[19]}}, X_in[19:7]  };
            5'd8  : X_in_shift = {  {8{X_in[19]}}, X_in[19:8]  };
            5'd9  : X_in_shift = {  {9{X_in[19]}}, X_in[19:9]  };
            5'd10 : X_in_shift = { {10{X_in[19]}}, X_in[19:10] };
            5'd11 : X_in_shift = { {11{X_in[19]}}, X_in[19:11] };
            5'd12 : X_in_shift = { {12{X_in[19]}}, X_in[19:12] };
            5'd13 : X_in_shift = { {13{X_in[19]}}, X_in[19:13] };
            5'd14 : X_in_shift = { {14{X_in[19]}}, X_in[19:14] };
            5'd15 : X_in_shift = { {15{X_in[19]}}, X_in[19:15] };
            5'd16 : X_in_shift = { {16{X_in[19]}}, X_in[19:16] };
            5'd17 : X_in_shift = { {17{X_in[19]}}, X_in[19:17] }; 
            default : X_in_shift = 20'b0;
        endcase        
    end
    
    always @ ( Y_in or Shiftbit )
    begin
        case ( Shiftbit )
            5'b0  : Y_in_shift = Y_in;
            5'd1  : Y_in_shift = {  {1{Y_in[19]}}, Y_in[19:1]  };
            5'd2  : Y_in_shift = {  {2{Y_in[19]}}, Y_in[19:2]  };
            5'd3  : Y_in_shift = {  {3{Y_in[19]}}, Y_in[19:3]  };
            5'd4  : Y_in_shift = {  {4{Y_in[19]}}, Y_in[19:4]  };
            5'd5  : Y_in_shift = {  {5{Y_in[19]}}, Y_in[19:5]  };
            5'd6  : Y_in_shift = {  {6{Y_in[19]}}, Y_in[19:6]  };
            5'd7  : Y_in_shift = {  {7{Y_in[19]}}, Y_in[19:7]  };
            5'd8  : Y_in_shift = {  {8{Y_in[19]}}, Y_in[19:8]  };
            5'd9  : Y_in_shift = {  {9{Y_in[19]}}, Y_in[19:9]  };
            5'd10 : Y_in_shift = { {10{Y_in[19]}}, Y_in[19:10] };
            5'd11 : Y_in_shift = { {11{Y_in[19]}}, Y_in[19:11] };
            5'd12 : Y_in_shift = { {12{Y_in[19]}}, Y_in[19:12] };
            5'd13 : Y_in_shift = { {13{Y_in[19]}}, Y_in[19:13] };
            5'd14 : Y_in_shift = { {14{Y_in[19]}}, Y_in[19:14] };
            5'd15 : Y_in_shift = { {15{Y_in[19]}}, Y_in[19:15] };
            5'd16 : Y_in_shift = { {16{Y_in[19]}}, Y_in[19:16] };
            5'd17 : Y_in_shift = { {17{Y_in[19]}}, Y_in[19:17] }; 
            default : Y_in_shift = 20'b0;
        endcase        
    end
    
    endmodule
  • 相关阅读:
    Coalesce (MS SQL Server)——取指定内容(列)中第一个不为空的值
    SQL 函数NULLIF、NULL、ISNULL、COALESCE、IIF
    oracle 分组后取每组第一条数据
    oracle判断是否包含字符串的方法
    Oracle 查询字段不包含多个字符串方法
    [oracle] to_date() 与 to_char() 日期和字符串转换
    Oracle中保留两位小数
    Oracle 树操作、递归查询(select…start with…connect by…prior)
    联合查询更新表数据
    WCF 之 生成元数据和代理
  • 原文地址:https://www.cnblogs.com/Dinging006/p/9520913.html
Copyright © 2011-2022 走看看