日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Verilog功能模块——取滑动平均值(使用寄存器组)

發布時間:2025/3/13 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Verilog功能模块——取滑动平均值(使用寄存器组) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我的另一篇博客:Verilog功能模塊——取滑動平均值(使用FIFO)

兩者用不同的方式實現相同的功能,

  • 使用FIFO占用較少寄存器資源,適用于取值N較大的場合。

  • 使用寄存器組不需要額外的IP,更簡單,但消耗寄存器資源較多,適用于取值N較小(一般不大于1024)的場合。

一. 模塊功能與應用場景

模塊功能:對輸入信號取滑動平均值。

滑動平均值:又名移動平均值,在簡單平均值的基礎上,通過順序逐期增加新數據、減去舊數據求算移動平均值,借以消除偶然變動因素。

參考百度百科:滑動平均法

應用場景:

  • 對平均值會變化,但變化速度較慢的信號求平均值
  • 數字濾波中去除信號的直流偏置

二. 模塊框圖與使用說明

參數N表示求N個點的平均值,參數DIN_WIDTH控制輸入信號位寬。

注意:

  • din與din_valid應對齊
  • clk應就是din與din_valid產生的時鐘,這是為了保證一個有效數據din_valid只持續一個時鐘周期的高電平
  • N應為2的n次方,如:128(27),256(28),512(29),1024(210)等
  • 為使平均值計算正確,N至少應包含一個完整信號周期的點,一般要大于2~3個信號周期的點數,N也不易過大,否則會消耗較多FPGA的寄存器資源
  • 三. 模塊代碼

    /** @Author : Xu Dakang* @Email : XudaKang_up@qq.com* @Date : 2021-04-14 16:14:46* @LastEditors : Xu Dakang* @LastEditTime : 2021-05-06 21:32:36* @Filename : getMovingAvg.sv* @Description : 求N個有符號數的滑動平均值 *//* ! 模塊功能: 求N個有符號數的滑動平均值 * 思路:1.求N個數的和,再除以N即為N個數的平均值2.當第N+1個數到來后, 總和去除第1個數再加上第N+1個數, 再求平均值即為1~N+1個數的平均值, 以此類推 */module getMovingAvg #(parameter N = 1024, // 求N個數的平均值,N應等于2的n次方,如512,1024,2048等parameter DIN_WIDTH = 24 // 輸入數據的位寬 )(output logic signed [DIN_WIDTH-1 : 0] moving_avg,input logic signed [DIN_WIDTH-1 : 0] din,input logic din_valid,input logic clk,input logic rstn );//< 信號同步 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ logic signed [DIN_WIDTH-1 : 0] din_r1; logic signed [DIN_WIDTH-1 : 0] din_r2; always_ff @(posedge clk) begindin_r1 <= din;din_r2 <= din_r1; endlogic din_valid_r1; logic din_valid_r2; logic din_valid_r3; always_ff @(posedge clk) begindin_valid_r1 <= din_valid;din_valid_r2 <= din_valid_r1;din_valid_r3 <= din_valid_r2; end //< 信號同步 ------------------------------------------------------------//> 存儲N個數 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ logic [$clog2(N)-1 : 0] din_cnt; always_ff @(posedge clk, negedge rstn) beginif (~rstn)din_cnt <= '0;else if (din_valid_r2)din_cnt <= din_cnt + 1'b1;elsedin_cnt <= din_cnt; endlogic signed [DIN_WIDTH-1 : 0] din_array [N]; always_ff @(posedge clk, negedge rstn) begin // 存儲輸入數據if (~rstn)din_array <= '{default : '0};else if (din_valid_r2)din_array[din_cnt] <= din_r2;elsedin_array <= din_array; end //> 存儲N個數 ------------------------------------------------------------//< 求和 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ logic signed [$clog2(N)+DIN_WIDTH-1 : 0] sum; always_ff @(posedge clk, negedge rstn) beginif (~rstn)sum <= '0;else if (din_valid_r2)sum <= sum - din_array[din_cnt] + din_r2; // 先減再加,沒有位寬溢出的風險elsesum <= sum; end //< 求和 ------------------------------------------------------------//> 輸出平均值 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ always_ff @(posedge clk, negedge rstn) beginif (~rstn)moving_avg <= '0;else if (din_valid_r3)moving_avg <= sum[$clog2(N)+DIN_WIDTH-1 : $clog2(N)]; // 取高數據位elsemoving_avg <= moving_avg; end //> 輸出平均值 ------------------------------------------------------------endmodule

    四. testbench

    /** @Author : Xu Dakang* @Email : XudaKang_up@qq.com* @Date : 2021-04-21 14:29:04* @LastEditors : Xu Dakang* @LastEditTime : 2021-05-06 20:54:14* @Filename : getMovingAvg_tb.sv* @Description : testbench of getMovingAvg */module getMovingAvg_tb;timeunit 1ns; timeprecision 1ps;localparam N = 1024; localparam DIN_WIDTH = 24;logic signed [DIN_WIDTH-1 : 0] moving_avg;logic signed [DIN_WIDTH-1 : 0] din; logic din_valid;logic clk; logic rstn;getMovingAvg #(.N (N),.DIN_WIDTH (DIN_WIDTH) ) getMovingAvg_inst (.*);// 生成時鐘 localparam CLKT = 2; initial beginclk = 0;forever #(CLKT / 2) clk = ~clk; end// 導入輸入波形文件,無法使用相對路徑,注意修改!!! string din_path = "F:/OneDrive/VivadoPrj/getMovingAvg/getMovingAvg.srcs/sim_1/new/sin-1.0.txt"; // 可選 sin+0.5 sin-0.5 sin+1.0 sin-1.0localparam DATA_NUM = 10240; // 數據量, 也就是txt文件的行數, 如果此參數大于數據行數, 讀取到的內容為不定態 logic [DIN_WIDTH-1 : 0] din_wave_data [DATA_NUM]; // 讀取輸入波形數據initial begin$readmemb(din_path, din_wave_data, 0, DATA_NUM-1); // vivado讀取txt文件 endinitial beginrstn = 0;din_valid = 0;#(CLKT * 10) rstn = 1;for (int i = 0; i < DATA_NUM; i++) begindin = din_wave_data[i];din_valid = 1;#(CLKT);din_valid = 0;#(CLKT * ({$random} % 5));enddin_valid = 0;#(CLKT * 10) $stop; endendmodule

    五. 仿真驗證

    仿真工具:Vivado 2020.2 Simulator。

  • 輸入為(sinx + 0.5)信號:

  • 輸入為(sinx - 0.5)信號:

  • 輸入為(sinx + 1.0)信號:

  • 輸入為(sinx - 1.0)信號:

  • 六. 工程分享

    getMovingAvg 取滑動平均值模塊(使用寄存器組) vivado 2020.2工程.7z

    鏈接:https://pan.baidu.com/s/1YL0q2i2UfWdlCGSN7GOgnQ
    提取碼:uxxn

    總結

    以上是生活随笔為你收集整理的Verilog功能模块——取滑动平均值(使用寄存器组)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。