操作系统 Window10Vivado2018.2目的采用FPGA实现24为无符号数的互相关运算并输出对应峰值在我学习使用FPGA实现互相关运算的时候想在网上寻找相应的实现思路和相关例程参考但大部分都是分享一个笼统的概念不利于理解也没有对应的软件实现思路偶尔有分享源码的还需会员等条件因此我收集学习网上资料自己琢磨实现采用FPGA实现互相关运算互相关运算的核心是通过滑动匹配两个信号的相似性利用峰值位置获取时延信息在工程领域有非常多落地应用主要体现在以下五个方面1、时延估计与定位在声源定位中通过多麦克风采集同源信号利用互相关计算到达时差结合声速反演目标方位是TDOA定位的基础。在管道泄漏检测中通过在管道两端部署声学传感器互相关分析泄漏噪声时延可实现厘米级漏点定位。在声呐或者雷达探测时通过对发射与回波信号进行互相关处理可在强噪声背景下提取微弱回波准确计算目标距离。在地震震源反演中可以利用地震波在不同台站的波形互相关提取微小时延进而反演震源位置。2、速度测量利用固定间距传感器采集同一运动目标产生的随机特征信号通过互相关峰值获取传输时延结合间距计算出运动速度。广泛应用于热轧钢带测速、管道流体流速测量及车辆滑移速度检测等场景。3、噪声抑制与特征提取互相关可保留与参考信号同频相关的分量有效滤除非相关噪声。例如在机械振动分析中可以 对设备施加已知频率的激振信号将其与含噪响应作互相关可精准提取由激振引发的有效响应排除背景干扰。在通信同步中可以在低信噪比接收信号中通过本地同步序列做互相关实现信号捕获与定时同步。4、图像处理将预设模板与图像进行二维互相关滑动匹配相关峰值位置即模板在图像中的最佳匹配坐标广泛用于图像配准、目标识别与追踪。5、系统特性分析通过计算系统输入输出信号的互相关峰值时延即为信号通过系统的传输滞后时间。该技术可用于识别复杂系统的信号传递路径如汽车座舱振动溯源判断振动源来自后桥或发动机或者隔离与识别多通道耦合系统中的振动或声学传递通道。互相关运算具体实现分为时域互相关、频域互相关、离散信号的互相关、连续信号的互相关、有限长序列互相关和无限长序列互相关。1、连续信号互相关时域能量有限2、 离散信号互相关时域能量有限3、有限长连续信号互相关4、有限长离散序列互相关5、频域互相关连续、分别为和的频谱6、频域互相关离散DFT设X[k],Y[k] 分别为离散序列x[n],y[n]的 DFT长度为N则循环互相关的DFT为若使用线性互相关则需补零后再做 DFT 避免循环卷绕。7、无限长离散互相关功率信号对于功率信号如周期信号互相关采用时间平均定义8、无限长连续互相关功率信号本文中我主要实现FPGA中有限长离散序列的互相关运算。即假设要对长度为Na为整数但由于实际数组没有负索引计算会引起数组越界若舍去越界部分只计算x与y重合的部分则会引起计算结果的数组大小随着值的变化而变化即计算结果不是一个定长结果则会对后续模块的数值计算带来困难即计算时要实时匹配数组长度。为了实现两个定长序列N互相关运算并的到定长的结果数组我将参考序列x的零点索引偏移a个单位即采用x[a]作为抽象零点x[0]则y[n-a]即为y[0]则参与运算的序列总长度为N2a1计算时参考序列固定为x[a]~x[aN-1]滑动序列y随着值变化在y[0]~y[N2a]之间固定为N个单位滑动即可保证数组不越界的同时维持计算结果长度恒定为2a1。运算采用状态机实现IDLE为空闲状态、MULT为乘法运算、SUM为求和运算、PEAK为查找峰值。具体实现和详细注释如下timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2026/07/02 11:12:37 // Design Name: // Module Name: TD_cross_correlation_operation // Project Name: // Target Devices: // Tool Versions: // Description: 实现两个定长为N的序列的互相关运算当τ 0时y滞后 求和范围 -τ N - 1 //当τ 0时y超前 求和范围 0 N - τ - 1使用x[n]作为参考序列y[n]为滑动序列 // 实现计算定长序列的互相关运算并实现互相关函数的峰值输出 // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module TD_cross_correlation_operation( input clk,//系统时钟 input reset_n,//系统复位低电平有效 input [23:0] data_x,//数据x输入 input data_x_valid,//数据x输入有效高电平脉冲 input [23:0] data_y,//数据y输入 input data_y_valid,//数据y输入有效高电平脉冲 output reg [47:0] data_max//互相关运算的峰值输出 ); //状态机状态定义 reg [1:0]state; localparam IDLE 2b00;//空闲状态 localparam MULT 2b01;//乘法 localparam SUM 2b10;//求和 localparam PEAK 2b11;//峰值 //互相关计算实现 //移位寄存器 localparam N 9d12;//移位寄存器的大小,N N_SUM 2*TAO reg [11:0] cnt_mult;//乘法计数 reg [47:0] shift_mult[N-1:0];//x[n]*y[nτ]乘积寄存器 reg [5:0] tao;//τ值 //计算基线 localparam TAO 3d3;//此时抽象为n0,即τ 0即当τ∈[-3,3]时基线为3 localparam TAO_CNT 2*TAO 1b1;//表示τ∈[-3,3] localparam N_SUM N - 2*TAO;//参考序列x[n]的长度 reg [23:0]shift_data_x[N-1:0]; reg [23:0]shift_data_y[N-1:0]; reg [47:0] sum[2*TAO:0];//存储R(τ)值数组大小为TAO_CNT //峰值比较变量 reg [6:0] cnt;//用于遍历索引sum数组中的所有值 //状态机实现 always(posedge clk or negedge reset_n)begin if(!reset_n)begin tao 4d0;//基线为3此时的x[3]表示x[0],则y[0]表示y[-3] sum[0] 48b0; state 2b0; cnt_mult 10b0; shift_data_x[0] 24d1;// shift_data_x[1] 24d1;// shift_data_x[2] 24d2;// shift_data_x[3] 24d2; shift_data_x[4] 24d3; shift_data_x[5] 24d4; shift_data_x[6] 24d55; shift_data_x[7] 24d7; shift_data_x[8] 24d1; shift_data_x[9] 24d1;// shift_data_x[10] 24d2;// shift_data_x[11] 24d2;// shift_data_y[0] 24d7;// shift_data_y[1] 24d1;// shift_data_y[2] 24d2;// shift_data_y[3] 24d4; shift_data_y[4] 24d3; shift_data_y[5] 24d48; shift_data_y[6] 24d5; shift_data_y[7] 24d7; shift_data_y[8] 24d7; shift_data_y[9] 24d1;// shift_data_y[10] 24d2;// shift_data_y[11] 24d4;// end else begin case(state) IDLE : begin cnt_mult 10b0; state MULT; tao 4b0; cnt 7b0; data_max 48b0; end MULT : begin//相乘 if(tao TAO_CNT)begin//遍历tao sum[tao] 48b0;//sum赋初始值 if(tao TAO)begin//τ 0y超前 if( (cnt_mult TAO) (N_SUM TAO - 1b1))begin//τ0时有效计算点数0~N-1 shift_mult[cnt_mult TAO] shift_data_x[cnt_mult TAO]*shift_data_y[cnt_mult tao];//x[n]*y[nτ]; cnt_mult cnt_mult 1b1; end else begin cnt_mult 10b0; state SUM; end end else begin//τ 0y滞后 if( (cnt_mult TAO) (N_SUM TAO - 1b1) )begin//τ 0时有效计算点数为-τ~N-1 shift_mult[cnt_mult TAO] shift_data_x[cnt_mult TAO]*shift_data_y[cnt_mult tao]; cnt_mult cnt_mult 1b1; end else begin cnt_mult 10b0; state SUM; end end end else begin//tao TAO_CNTtao遍历完毕开始比较峰值 state PEAK; end end SUM : begin//求和 if(tao TAO_CNT)begin//遍历tao if(tao TAO)begin if( (cnt_mult TAO) (N_SUM TAO - 1b1) )begin//τ0时有效计算点数0~N-τ-1 sum[tao] sum[tao] shift_mult[cnt_mult TAO];//x[n]*y[nτ]求和 cnt_mult cnt_mult 1b1; end else begin cnt_mult 10b0; state MULT;//计算下一个tao值 tao tao 1b1; end end else begin//τ 0 if( (cnt_mult TAO) (N_SUM TAO - 1b1) )begin//τ 0时有效计算点数为-τ~N-1 sum[tao] sum[tao] shift_mult[cnt_mult TAO];//x[n]*y[nτ]求和 cnt_mult cnt_mult 1b1; end else begin cnt_mult 10b0; state MULT;//计算下一个tao值 tao tao 1b1; end end end end PEAK : begin if(cnt TAO_CNT)begin if(sum[cnt] data_max)begin//将sum数组中的最大值赋给data_max data_max sum[cnt]; cnt cnt 1b1; end else begin cnt cnt 1b1; end end else begin//遍历sum完成返回空闲状态 state IDLE; end end endcase end end endmodule仿真测试代码timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2026/07/02 15:22:57 // Design Name: // Module Name: tb_TD // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module tb_TD(); reg clk,reset_n; TD_cross_correlation_operation TD_cross_correlation_operation( .clk(clk),//系统时钟 .reset_n(reset_n),//系统复位低电平有效 .data_x(),//数据x输入 .data_x_valid(),//数据x输入有效高电平脉冲 .data_y(),//数据y输入 .data_y_valid(),//数据y输入有效高电平脉冲 . data_max()//互相关运算的峰值输出 ); initial begin clk 1b0; forever begin #10 clk ~clk; end end initial begin reset_n 1b0; #100 reset_n 1b1; end endmodule测试结果对代码中的数据进行互相关运算输出的结果为sum[0] 314sum[1] 530sum[2] 2710sum[3] 540sum[4] 605sum[5] 533sum[6] 132最大峰值为data_max 2710。根据仿真波形图对比验证输出结果可见正确实现无符号数离散有限长序列的互相关运算。但该代码仅对互相关的乘积求和过程进行直观探索并不具备工程实现要求。1、当前代码中无缓冲区保持数据稳定而进行互相关运算时需要在值变化时保持数据稳定即在这期间序列x与y中的数值保持不变才能计算出峰值对应的值。2、此外代码中将乘积与求和分开采用[47:0] shift_mult[N-1:0]寄存x[n]y[nτ]的值当N的值很小时并没有太大影响但当N较大时FPGA综合时就会消耗大量的LUT与FF去寄存N48个数据从而造成宝贵的逻辑资源浪费。3、未对峰值索引进行输出外部调用时无法确定峰值对应值。4、采用内部定义的数据未使用外部数据进行实时处理不具备处理实时数据流的能力。后续将围绕这几点不足持续完善代码使其具备能采用最少的逻辑资源实现实时数据流的互相关运算。