您现在的位置是:首页 > 正文

FPGA:计算滑动求和----信号检测计算信号功率

2024-02-01 03:53:21阅读 1

FPGA:计算滑动求和----信号检测计算信号功率

在进行简单信号检测过程中,需要计算信号的能量,这时候需要用到滑动求和的计算过程。
这里记录如何利用Verilog编写滑动求和过程。

思路:滑动求和的过程需要按照滑动窗口的大小,依次向后进行滑动求和;

从任务出发:输入IQ两路信号的位宽为12位,然后计算K个值区间段的功率值大小;
(1) 首先对I,Q两路信号求平方计算,得到平方的结果,这时候位宽大小变为24位;
(2) 求I,Q两路信号平方和,定义变量sum_s,表示单一点的信号平方和值,位宽为25位;
(3) 计算一段时间的平方和大小,sum=sum+sum_s,做和累加,这里面K的个数可以取2的指数次,方便通过移位做除法,同时sum的位宽也容易定义,如K设置为512,sum位宽取35位;
(4) 通过fifo实现活动取数的过程,前512个数据单独累加求和,第513个数据通过fifo输出,利用总和减去第一个数,这里面利用fifo先进先出的特性,控制fifo存入K个数据之后,每次取出一个数据之后,再写入另一个数据,这样就可以滑动计算结果求和;
(5) 注意设置fifo输入位宽为sum_s位宽,fifo输出为sum_f,表示滑动求和的第一个数据,fifo深度大小大于K值。

以下为程序代码:

//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/24 19:48:05
// Design Name: 
// Module Name: D_energy
// Project Name: 
// Target Devices: 通过滑动求和计算求信号功率
// Tool Versions: 
//


module D_energy(
    input l_clk,
    input rst_n,        //低电平有效(复位)
    input [11:0] i_da,
    input [11:0] q_da,
    output[24:0] d_out,   // 输出求和平均 (平方和的平均)
    output valid);        // 输出信号有效


localparam K_LENGTH = 16'd512;  //设定滑动窗长度 这个值一定大于fifo的深度

// 求信号的平方项
wire [23:0]i_da2,q_da2;
mult12a12 u0 (
  .CLK(l_clk),  // input wire CLK
  .A(i_da),      // input wire [11 : 0] A
  .B(i_da),      // input wire [11 : 0] B
  .P(i_da2)      // output wire [23 : 0] P
);
mult12a12 u1 (
  .CLK(l_clk),  // input wire CLK
  .A(q_da),      // input wire [11 : 0] A
  .B(q_da),      // input wire [11 : 0] B
  .P(q_da2)      // output wire [23 : 0] P
);

reg [34:0]sum;   //用来计算累加和
wire [24:0] sum_s;  
wire [24:0] sum_f;  //fifo输出的结果,相当于第一个结果,需要在减法的过程中减去这个结果
assign sum_s = i_da2 + q_da2;  //单次求和

reg [15:0] cnt_sum;  //用来记录第一个累加环节
always@(posedge l_clk)begin
    if(!rst_n)begin
        cnt_sum <= 16'b0;
    end
    else begin
        cnt_sum <= cnt_sum + 16'b1;
    end
end
// 计算前K个数据的和的大小
reg valid_temp;

// 用状态机实现活动辅助
wire fifo_full;
wire fifo_empty;
wire fifo_prog_full;
reg state;
reg rd_valid; //控制读数
always@(posedge l_clk)begin
    if(!rst_n)begin
        state <= 1'b0;
        sum <= 35'b0;
        valid_temp <= 1'b0;
        rd_valid <= 1'b0;
    end
    else begin
        case(state)
        1'b0: begin
            sum <= sum + {{10'b0},sum_s};
            if(cnt_sum >= (K_LENGTH-2))begin   //控制着循环累加的长度,k+2;
                state <= 1'b1;
            end         
        end
        default: begin
            sum <= sum + sum_s - {{10'b0},sum_f};  //加上最新的数据,减去最后的数据
            valid_temp <= 1'b1;
            rd_valid <= 1'b1;
        end
        endcase
    end
end

//滑动相关利用fifoIP 核实现滑动计算过程,
fifo_generator_0 fifo_u0 (
  .clk(l_clk),              // input wire clk
  .srst(!rst_n),            // input wire srst
  .din(sum_s),              // input wire [23 : 0] din
  .wr_en(1'b1),          // input wire wr_en
  .rd_en(rd_valid),          // input wire rd_en
  .dout(sum_f),            // output wire [23 : 0] dout
  .full(fifo_full),            // output wire full
  .empty(fifo_empty),          // output wire empty
  .prog_full(fifo_prog_full)  // output wire prog_full
);

//输出滑动求和取平均的结果
assign d_out = sum[34:10];
assign valid = valid_temp;

//利用fifo 进行
Endmodule

IP核配置简单如图

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

测试仿真代码如下


`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/25 10:02:58
// Design Name: 
// Module Name: top_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module top_tb();

reg l_clk;
reg rst_n;
reg [11:0]i_data,q_data;
wire [24:0] data_out;
wire dout_valid;

//生成输入到计算模块中的数据,
always@(posedge l_clk)begin
    if(!rst_n)begin
        i_data <= 12'b0;
        q_data <= 12'b0;
    end
    else begin
        i_data <= i_data + 12'b1;
        q_data <= q_data + 12'b1;
    end
end


D_energy D_en(
    .l_clk(l_clk),
    .rst_n(rst_n),
    .i_da(i_data),
    .q_da(q_data),
    .d_out(data_out),   // 输出求和平均
    .valid(dout_valid));  


initial l_clk = 1;
always #20 l_clk= !l_clk;  //15.625   
always #10 data_in = 16'b100; 
initial begin
    rst_n <= 0;
    #320;
    rst_n <= 1;

    //#50000000;
    #320;
    $stop;
end

endmodule

最终实验结果为

在这里插入图片描述
在测试验证的时候为了方便,把k值取为4其中的sum_s 每相邻的四个值加和结果为下一个时钟的sum值。

网站文章

  • docker安装oracle11g史上最全步骤(带图文) 热门推荐

    docker安装oracle11g史上最全步骤(带图文) 热门推荐

    因为在Linux中安装oracle非常麻烦,相信每个人也会遇到各种坑,为了一次装好,也方便将来直接可以导出镜像在各平台移植使用,所以选择用docker安装,并做详细记录,为以后需要之时拿来再看。 1、安装docker环境。 2、开始拉取oracle镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_...

    2024-02-01 03:52:50
  • iOS pickerView

    1.有几组 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView 2.每组有几行 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component 3.显示内容

    2024-02-01 03:52:34
  • 数据结构【ArrayLIst】

    数据结构【ArrayLIst】

    ArrayList 方法的使用和介绍

    2024-02-01 03:52:28
  • java 反射

    java 反射

    在代码运行之前,我们不确定将来会使用哪一种数据结构,只有在程序运行时才决定使用哪一个数据类,而反射可以在程序运行过程中动态获取类信息和调用类方法。通过反射构造类实例,代码最终会演变成下面这样。

    2024-02-01 03:52:02
  • QT POST/GET 发送/获取网页数据 热门推荐

    #include #include QNetworkAccessManager *m_accessManager;Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui-&gt;setupUi(this); m_acc

    2024-02-01 03:51:53
  • 火爆全网,接口测试总结汇总,全知识点扫描卷起来...

    火爆全网,接口测试总结汇总,全知识点扫描卷起来...

    第一部分:主要从问题出发,引入接口测试的相关内容并与前端测试进行简单对比,总结两者之前的区别与联系。但该部分只交代了怎么做和如何做?并没有解释为什么要做?第二部分:主要介绍为什么要做接口测试,并简单总...

    2024-02-01 03:51:45
  • php 自动切图,前端工程师技能之photoshop巧用系列扩展篇自动切图

    php 自动切图,前端工程师技能之photoshop巧用系列扩展篇自动切图

    ×目录[1]初始设置 [2]自动切图前面的话随着photoshop版本的不断升级,软件本身增加了很多新的功能,也为切图工作增加了很多的便利。photoshop最新的版本新增了自动切图功能,本文将详细介...

    2024-02-01 03:51:17
  • List,Queue和Set

    List,Queue和Set

    List,Queue和Set这三个接口的介绍,和实现这些接口的类的使用

    2024-02-01 03:51:08
  • 【Django】配置本地域名、解决前后端跨域问题

    由于开发需求,我们可能会需要使用特定域名访问项目,但是当前又不方便直接上线,所以我们可以使用本地域名的方式访问,我们只需要在hosts文件里添加域名和ip即可 1.Linux 如果使用的是Linux系...

    2024-02-01 03:51:00
  • Mysql date的大于某一个时间点 热门推荐

    直接使用类似下面的方法就可以了 select status,edate,cdate from cp_trade_master where pay=2300 and proxy_uid=139144 and edate&gt;&#39;2016-07-27 19:30:00&#39; order by edate desc;

    2024-02-01 03:50:54