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

原文地址:https://www.cnblogs.com/Dinging006/p/9520913.html

时间: 2024-10-06 00:45:18

微弱信号二次谐波检测的FPGA的实现-总结的相关文章

硬件十万个为什么——运放篇(四)微弱信号放大技巧

如何实现微弱信号放大? 传感器+运算放大器+ADC+处理器是运算放大器的典型应用电路,在这种应用中,一个典型的问题是传感器提供的电流非常低,在这种情况下,如何完成信号放大? 大多数检测固定频率信号(调制信号),可以通过信号的相干性进行检测.但是大多数场景传感器的信号是非调制信号,无法通过相干性进行算法检测. 通过电路设计如何提高信号的信噪比 另有工程师朋友建议,在运放.电容.电阻的选择和布板时,要特别注意选择高阻抗.低噪声运算和低噪声电阻.设计注意事项如下: 要点一.防止干扰: 1)电路设计时注

ECG信号读取,检测QRS,P,T 波(基于小波去噪与检测),基于BP神经网络的身份识别

这学期选了神经网络的课程,最后作业是处理ECG信号,并利用神经网络进行识别. 1  ECG介绍与读取ECG信号 1)ECG介绍  具体ECG背景应用就不介绍了,大家可以参考百度 谷歌.只是简单说下ECG的结构: 一个完整周期的ECG信号有 QRS P T 波组成,不同的人对应不用的波形,同一个人在不同的阶段波形也不同.我们需要根据各个波形的特点,提取出相应的特征,对不同的人进行身份识别. 2)ECG信号读取 首先需要到MIT-BIH数据库中下载ECG信号,具体的下载地址与程序读取内容介绍可以参考

Linux环境编程之信号(二):不可靠信号、中断的系统调用、可重入函数

(一)不可靠信号 对前面说的信号,是不可靠的,不可靠指的是信号可能会丢失:一个信号发生了,但进程却可能一直不知道这一点.另外,进程对信号的控制能力有限,只能捕捉信号或忽略它.有时用户希望通知内核阻塞一个信号:不要忽略它,在其发生时记住它,然后在进程做好准备时再通知它.这种阻塞信号的能力并不具备. 之前的版本中村咋一个问题:在进程每次接到信号对其进行处理时,随即将该信号动作复位为默认值.另一个问题是,在进程不希望某种信号发生时,它不能关闭该信号.进程能做的一切就是忽略该信号. (二)中断的系统调用

ECG信号读出,检测QRS,P,T 波(小波去噪,并根据检测),基于BP辨识的神经网络

这学期的课程选择神经网络.最后的作业处理ECG信号,并利用神经网络识别. 1  ECG引进和阅读ECG信号 1)ECG介绍  详细ECG背景应用就不介绍了,大家能够參考百度 谷歌.仅仅是简单说下ECG的结构: 一个完整周期的ECG信号有 QRS P T 波组成,不同的人相应不用的波形,同一个人在不同的阶段波形也不同.我们须要依据各个波形的特点,提取出相应的特征,对不同的人进行身份识别. 2)ECG信号读取 首先须要到MIT-BIH数据库中下载ECG信号,具体的下载地址与程序读取内容介绍能够參考一

GTA5自动驾驶二 边沿检测

边沿检测采用Candy算法,比较经典,opencv自带 Candy算法的原理可以参见这篇博文:http://www.tuicool.com/articles/Y3q2Mf 整个流程是这样的: 读取图像 将图像转化为灰度图像 运行高斯滤波 运行Candy算子得到边沿 示例代码如下: #! usr/bin/python #coding=utf-8 #doing all the relevant imports import matplotlib.pyplot as plt import matplo

信号(二)---signal函数详解

前面提到了当进程收到了信号后,有三种处理信号的方法:忽略该信号:执行默认动作:捕捉该信号. 捕捉信号 的意思就是当进程收到一个信号时去执行我们指定的动作.signal 函数就是Linux系统提供用来捕捉信号的函数. ======================================================== 函数原型: 函数参数: signum:捕捉的信号 handler:收到信号后执行的动作,是个函数指针变量 返回值: 调用失败时返回 SIG_ERR 调用成功时返回 指向之

谈谈MySQL死锁之二 死锁检测和处理源码分析

这一篇主要是通过一个实验来进行描述,过程是比较枯燥的. 实验准备 create table test_lock(id int auto_increment primary key ,stock int) engine=innodb; insert into test_lock(id,stock) value(1,50); 这里我把堆栈信息尽可能的简化,25个主要函数的名称和入参 后面为了突出主题,我对事务相关的函数加上这个开头死锁检测函数列表,一共10个函数   死锁检测函数列表A row_se

Java反射(二):检测类的修饰符和类型

一个类可被若干个能影响其运行时行为的修饰符声明: 访问修饰符:public,protected,private 需要重载的修饰符:abstract 限制为只有一个实例的:static 阻止值修改:final 强制严格浮点行为:strictfp 注解 不是所有的修饰符能用在所有的类上.比如final不能修饰接口,枚举不能是abstract.java.lang.reflect.Modifier包含了所有可能修饰符的声明,它也包含用来编码由Class.getModifiers()返回的修饰符集合的方法

水下通信技术的分类、特征、应用及其最新研究进展

海洋覆盖着地球三分之二的表面积,它是人类探索和研究的最前沿的领域之一.海洋不仅在国际商业和渔业中扮演重要的角色,而且还包含了有关气候的信息,以及大量急待开发的资源. 水下无线通信是研制海洋观测系统的关键技术,借助海洋观测系统,可以采集有关海洋学的数据,监测环境污染,气候变化海底异常地震火山活动,探查海底目标,以及远距离图像传输.水下无线通信在军事中也起到至关重要的作用,而且水下无线通信也是水下传感器网络的关键技术. 水下无线通信主要可以分成三大类:水下电磁波通信.水声通信和水下量子通信,它们具有