微弱信号二次谐波检测的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

 

posted on 2018-08-22 22:46  super_star123  阅读(1396)  评论(0编辑  收藏  举报

导航