前言

我的另一篇博客:Verilog功能模块——取滑动平均值(使用寄存器组)

两者用不同的方式实现相同的功能,

  • 使用FIFO占用较少寄存器资源,适用于取值N较大的场合。
  • 使用寄存器组不需要额外的IP,更简单,但消耗寄存器资源较多,适用于取值N较小(一般不大于1024)的场合。

一. 模块功能与应用场景

模块功能:对输入信号取滑动平均值。

滑动平均值:又名移动平均值,在简单平均值的基础上,通过顺序逐期增加新数据、减去旧数据求算移动平均值,借以消除偶然变动因素。

参考百度百科:滑动平均法

应用场景:

  • 对平均值会变化,但变化速度较慢的信号求平均值
  • 数字滤波中去除信号的直流偏置

二. 模块框图与使用说明

参数N表示求N个点的平均值,参数DIN_WIDTH控制输入信号位宽。

注意:

  1. din与din_valid应对齐
  2. clk应就是din与din_valid产生的时钟,这是为了保证一个有效数据din_valid只持续一个时钟周期的高电平
  3. N应为2的n次方,如:128(27),256(28),512(29),1024(210)等
  4. 为使平均值计算正确,N至少应包含一个完整信号周期的点,一般要大于2~3个信号周期的点数
  5. 这里的ac_signal为din - moving_avg表示不带直流偏置的交流信号
  6. 此模块需要搭配一个首字直通的单时钟FIFO使用,此FIFO的时钟应与此模块时钟相同
  7. FIFO深度和位宽需要与模块参数N和DIN_WIDTH分别保持一致

模块封装为IP后的框图:

模块IP参数配置界面:


三. 模块代码

/** @Author       : Xu Dakang* @Email        : XudaKang_up@qq.com* @Date         : 2021-04-14 16:14:46* @LastEditors  : Xu Dakang* @LastEditTime : 2021-05-19 22:34:24* @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,output logic signed [DIN_WIDTH-1 : 0] ac_signal,output logic                          ac_signal_valid,input  logic signed [DIN_WIDTH-1 : 0] din,input  logic                          din_valid,input  logic signed [DIN_WIDTH-1 : 0] fwft_fifo_dout,output logic                          fwft_fifo_rd_en,input  logic                          fwft_fifo_empty,output logic signed [DIN_WIDTH-1 : 0] fwft_fifo_din,output logic                          fwft_fifo_wr_en,input  logic                          fwft_fifo_full,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;
always_ff @(posedge clk) begindin_valid_r1 <= din_valid;din_valid_r2 <= din_valid_r1;
end
//< 信号同步 ------------------------------------------------------------//> FWFT FIFO存储N个数 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
logic [$clog2(N) : 0] din_cnt;
always_ff @(posedge clk) begin  // FIFO写入计数if (~rstn)din_cnt <= '0;else if (din_valid_r2 && din_cnt[$clog2(N)] != 1)din_cnt <= din_cnt + 1'b1;elsedin_cnt <= din_cnt;
end// fwft FIFO输出
always_comb beginfwft_fifo_din = din_r2;fwft_fifo_wr_en = din_valid_r2;fwft_fifo_rd_en = din_cnt[$clog2(N)] == 1 && din_valid_r2;
end
//> FWFT FIFO存储N个数 ------------------------------------------------------------//< 求和 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
logic signed [$clog2(N)+DIN_WIDTH-1 : 0] sum;
always_ff @(posedge clk) beginif (~rstn)sum <= '0;else if (din_valid_r2)if (din_cnt[$clog2(N)] != 1)sum <= din_r2 + sum; // 先减再加,没有位宽溢出的风险elsesum <= (din_r2 - fwft_fifo_dout) + sum;elsesum <= sum;
end
//< 求和 ------------------------------------------------------------//> 输出平均值 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always_ff @(posedge clk) beginif (~rstn)moving_avg <= '0;elsemoving_avg <= sum[$clog2(N)+DIN_WIDTH-1 : $clog2(N)]; // 取高数据位
end
//> 输出平均值 ------------------------------------------------------------//< 求AC信号 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always_ff @(posedge clk) beginif (~rstn)ac_signal <= '0;else if (din_valid_r2)ac_signal <= din_r2 - moving_avg;elseac_signal <= ac_signal;
endalways_ff @(posedge clk) beginif (~rstn)ac_signal_valid <= '0;elseac_signal_valid <= din_valid_r2;
end
//< 求AC信号 ------------------------------------------------------------endmodule

四. testbench

/** @Author       : Xu Dakang* @Email        : XudaKang_up@qq.com* @Date         : 2021-04-21 14:29:04* @LastEditors  : Xu Dakang* @LastEditTime : 2021-05-20 00:32:15* @Filename     : getMovingAvg_tb.sv* @Description  : testbench of getMovingAvg
*/module getMovingAvg_tb;timeunit 1ns;
timeprecision 1ps;localparam DIN_WIDTH = 24;logic [DIN_WIDTH-1 : 0] ac_signal;
logic ac_signal_valid;logic [DIN_WIDTH-1 : 0] din;
logic din_valid;logic [DIN_WIDTH-1 : 0] moving_avg;logic clk;
logic rstn;getMovingAvg_system_wrapper  getMovingAvg_system_wrapper_inst (.*);// 生成时钟
localparam CLKT = 2;
initial beginclk = 0;forever #(CLKT / 2) clk = ~clk;
end// 导入输入波形文件 Vivado只能识别绝对路径 注意修改!!!
string din_path = "F:/OneDrive/VivadoPrj/getMovingAvg_useFIFO/getMovingAvg_useFIFO.srcs/sim_1/new/sin+0.5.txt"; // 可选 sin  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文件
endint cnt;
initial beginrstn = 0;din_valid = 0;#(CLKT * 10)  rstn = 1;for (int i = 0; i < DATA_NUM; i++) begindin = din_wave_data[i];cnt++;din_valid = 1;#(CLKT);// din_valid = 0;// #(CLKT * ({$random} % 12));enddin_valid = 0;#(CLKT * 10) $stop;
endendmodule

五. 仿真验证

仿真工具:Vivado 2020.2 Simulator。

lock Design如下图,注意:

  1. 模块的参数N与FIFO深度保持一致
  2. 模块数据位宽与FIFO数据位宽保持一致
  3. FIFO必须是FWFT类型的

  1. 输入为(sinx + 0.5)信号:

  1. 输入为(sinx - 0.5)信号:

  1. 输入为(sinx + 1.0)信号:

  1. 输入为(sinx - 1.0)信号:


六. 工程分享

getMovingAvg_useFIFO 取滑动平均值模块(使用FIFO) vivado 2020.2工程.7z。

欢迎大家关注我的公众号:徐晓康的博客,回复以下代码获取。

1653

建议复制过去不会码错字!


徐晓康的博客持续分享高质量硬件、FPGA与嵌入式知识,软件,工具等内容,欢迎大家关注。

Verilog功能模块——取滑动平均值(使用FIFO)相关推荐

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

    我的另一篇博客:Verilog功能模块--取滑动平均值(使用FIFO) 两者用不同的方式实现相同的功能, 使用FIFO占用较少寄存器资源,适用于取值N较大的场合. 使用寄存器组不需要额外的IP,更简单 ...

  2. Verilog功能模块 —— 按键消抖

    一. 什么是按键消抖 按键消抖_百度百科 (baidu.com) 按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开.闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断 ...

  3. Verilog功能模块——AXI4-Lite协议主机-单次写-使用FIFO

    一. 模块功能与应用场景 模块功能:AXI4-Lite协议主机,从FWFT FIFO(首字直通FIFO)中读取地址和数据,实现将数据写入到设定的地址中的操作. 二. 模块框图与使用说明 2.1 模块框 ...

  4. Verilog功能模块——AXI4-Lite协议主机-连续区间写-使用FIFO

    一. 模块功能与应用场景 模块功能:AXI4-Lite协议主机,从FWFT FIFO(首字直通FIFO)中不断读取数据,写入到一段地址中. 应用场景:DDR读写,BRAM读写等AXI接口的存储器件读写 ...

  5. Verilog功能模块——符号位扩展

    一. 模块功能与应用场景 模块功能:符号位扩展 应用场景:DDR等存储器通常是32/64位的,数据需要转为合适的位数再存入. 二. 模块框图与使用说明 输入和输出都是二进制补码,补码的符号位扩展就是补 ...

  6. Verilog功能模块——降采样

    一. 模块功能与应用场景 模块功能:对输入信号进行降采样. 应用场景: 输入数据量太大,后级难以处理,需要减小信号量而不丢失关键信息 二. 模块框图与使用说明 参数DOWN_SAMPLING_TIME ...

  7. Verilog功能模块——串行数据转并行数据

    一. 模块功能与应用场景 模块功能:接收串行数据,转为并行数据. 应用场景:在SPI,Uart等串行协议接收侧均有应用. 二. 模块框图与使用说明 有两种模式(通过参数SDATA_IS_CONTINU ...

  8. Verilog功能模块——时钟分频

    一. 模块功能与应用场景 模块功能:对输入时钟进行任意倍数分频. 应用场景: 需要对时钟进行分频,而PLL不能满足要求或者使用起来不方便 需要固定倍数关系的时钟 二. 模块框图与使用说明 通过参数DI ...

  9. 避免重复造轮子,我们去哪找FPGA IP或是HDL功能模块?

    一. 各FPGA厂家IP库 对于一些常用的IP,通常各FPGA厂商的开发软件中会自带,并长期免费提供给用户使用或者允许申请IP评估免费使用一段时间.这些IP通常是不开源的,但使用起来很方便,有助于开发 ...

最新文章

  1. 启用tomcat debug模式
  2. 【spring boot2】第2篇:配置文件YAML语法
  3. 根据map中某一字段排序
  4. 汇编中的BP与SS组合时,BP里面放的到底是SS中的一个基地址的指针还是基地址本身?
  5. Hadoop中RPC机制详解之Server端
  6. cocos2d-x返回Android游戏黑屏解决办法
  7. sqlserver中在建立与服务器的连接时出错
  8. php pc_base,phpcms二次开发之base.php的桥梁作用_PHP教程
  9. NOI 题库 6264
  10. Shell命令-搜索文件或目录之which、find
  11. 【Unity笔记】UGUI的Image、RawImage控件
  12. eclipse中如何搜索带\的字串
  13. 利用WPS功能破解无线路由器PIN码
  14. uniapp小程序解压压缩包 (使用jszip)
  15. 视频拍摄和剪辑经验分享|南京
  16. 记大数据hbase集群天坑
  17. Windows10搭建EDK2环境
  18. “3D游戏之父”考古“诺基亚时代”手游,网友:求支持智能手机!
  19. JAVA中的各种引用
  20. 微信小程序判断手机系统

热门文章

  1. All Attention You Need
  2. RPA赋能与数据化运营
  3. 大数据系列sql基础知识(史上最全,收藏起来)
  4. Vijos P1881 闪烁的星星
  5. 记录前端常用代码规范
  6. Elasticsearch RestHighLevelClient操作
  7. 基于求导的快速exp()算法,exp()快速计算,exp导数算法,exp函数C语言实现
  8. 口红会染唇是什么意思_口红和唇釉有什么区别
  9. java程序员述职_java程序员述职报告
  10. 【Error】 Linux系统“检测到系统程序错误”