【Verilog】7.2.1 Verilog 并行 FIR 滤波器设计

FIR(Finite Impulse Response)滤波器是一种有限长单位冲激响应滤波器,又称为非递归型滤波器。

FIR 滤波器具有严格的线性相频特性,同时其单位响应是有限长的,因而是稳定的系统,在数字通信、图像处理等领域都有着广泛的应用。

FIR 滤波器原理
FIR 滤波器是有限长单位冲击响应滤波器。直接型结构如下:
在这里插入图片描述
FIR 滤波器本质上就是输入信号与单位冲击响应函数的卷积,表达式如下:
在这里插入图片描述
FIR 滤波器有如下几个特性:

(1) 响应是有限长序列。
(2) 系统函数在 |z| > 0 处收敛,极点全部在 z=0 处,属于因果系统。
(3) 结构上是非递归的,没有输出到输入的反馈。
(4) 输入信号相位响应是线性的,因为响应函数 h(n) 系数是对称的。
(5) 输入信号的各频率之间,相对相位差也是固定不变的。
(6) 时域卷积等于频域相乘,因此该卷积相当于筛选频谱中各频率分量的增益倍数。某些频率分量保留,某些频率分量衰减,从而实现滤波的效果。
并行 FIR 滤波器设计
设计说明

输入频率为 7.5 MHz 和 250 KHz 的正弦波混合信号,经过 FIR 滤波器后,高频信号 7.5MHz 被滤除,只保留 250KHz 的信号。设计参数如下:

输入频率:    7.5MHz 和 250KHz
采样频率:    50MHz
阻带:           1MHz ~ 6MHz
阶数:           15(N-1=15

由 FIR 滤波器结构可知,阶数为 15 时,FIR 的实现需要 16 个乘法器,15 个加法器和 15 组延时寄存器。为了稳定第一拍的数据,可以再多用一组延时寄存器,即共用 16 组延时寄存器。由于 FIR 滤波器系数的对称性,乘法器可以少用一半,即共使用 8 个乘法器。

并行设计,就是在一个时钟周期内对 16 个延时数据同时进行乘法、加法运算,然后在时钟驱动下输出滤波值。这种方法的优点是滤波延时短,但是对时序要求比较高。

并行设计

设计中使用到的乘法器模块代码,可参考之前流水线式设计的乘法器。

为方便快速仿真,也可以直接使用乘号 * 完成乘法运算,设计中加入宏定义 SAFE_DESIGN 来选择使用哪种乘法器。

FIR 滤波器系数可由 matlab 生成,具体见附录。

/***********************************************************
>> V201001 : Fs:50Mhz, fstop:1Mhz-6Mhz, order: 15
************************************************************/
`define SAFE_DESIGNmodule fir_guide    (input                rstn,  //复位,低有效input                clk,   //工作频率,即采样频率input                en,    //输入数据有效信号input        [11:0]  xin,   //输入混合频率的信号数据output               valid, //输出数据有效信号output       [28:0]  yout   //输出数据,低频信号,即250KHz);//data en delay reg [3:0]            en_r ;always @(posedge clk or negedge rstn) beginif (!rstn) beginen_r[3:0]      <= 'b0 ;endelse beginen_r[3:0]      <= {en_r[2:0], en} ;endend//(1) 16 组移位寄存器reg        [11:0]    xin_reg[15:0];reg [3:0]            i, j ;always @(posedge clk or negedge rstn) beginif (!rstn) beginfor (i=0; i<15; i=i+1) beginxin_reg[i]  <= 12'b0;endendelse if (en) beginxin_reg[0] <= xin ;for (j=0; j<15; j=j+1) beginxin_reg[j+1] <= xin_reg[j] ; //周期性移位操作endendend//Only 8 multipliers needed because of the symmetry of FIR filter coefficient//(2) 系数对称,16个移位寄存器数据进行首位相加reg        [12:0]    add_reg[7:0];always @(posedge clk or negedge rstn) beginif (!rstn) beginfor (i=0; i<8; i=i+1) beginadd_reg[i] <= 13'd0 ;endendelse if (en_r[0]) beginfor (i=0; i<8; i=i+1) beginadd_reg[i] <= xin_reg[i] + xin_reg[15-i] ;endendend//(3) 8个乘法器// 滤波器系数,已经过一定倍数的放大wire        [11:0]   coe[7:0] ;assign coe[0]        = 12'd11 ;assign coe[1]        = 12'd31 ;assign coe[2]        = 12'd63 ;assign coe[3]        = 12'd104 ;assign coe[4]        = 12'd152 ;assign coe[5]        = 12'd198 ;assign coe[6]        = 12'd235 ;assign coe[7]        = 12'd255 ;reg        [24:0]   mout[7:0]; `ifdef SAFE_DESIGN//流水线式乘法器wire [7:0]          valid_mult ;genvar              k ;generatefor (k=0; k<8; k=k+1) beginmult_man #(13, 12)u_mult_paral          (.clk        (clk),.rstn       (rstn),.data_rdy   (en_r[1]),.mult1      (add_reg[k]),.mult2      (coe[k]),.res_rdy    (valid_mult[k]), //所有输出使能完全一致  .res        (mout[k]));endendgeneratewire valid_mult7     = valid_mult[7] ;`else//如果对时序要求不高,可以直接用乘号always @(posedge clk or negedge rstn) beginif (!rstn) beginfor (i=0 ; i<8; i=i+1) beginmout[i]     <= 25'b0 ;endendelse if (en_r[1]) beginfor (i=0 ; i<8; i=i+1) beginmout[i]     <= coe[i] * add_reg[i] ;endendendwire valid_mult7 = en_r[2];
`endif//(4) 积分累加,8组25bit数据 -> 1组 29bit 数据//数据有效延时reg [3:0]            valid_mult_r ;always @(posedge clk or negedge rstn) beginif (!rstn) beginvalid_mult_r[3:0]  <= 'b0 ;endelse beginvalid_mult_r[3:0]  <= {valid_mult_r[2:0], valid_mult7} ;endend`ifdef SAFE_DESIGN//加法运算时,分多个周期进行流水,优化时序reg        [28:0]    sum1 ;reg        [28:0]    sum2 ;reg        [28:0]    yout_t ;always @(posedge clk or negedge rstn) beginif (!rstn) beginsum1   <= 29'd0 ;sum2   <= 29'd0 ;yout_t <= 29'd0 ;endelse if(valid_mult7) beginsum1   <= mout[0] + mout[1] + mout[2] + mout[3] ;sum2   <= mout[4] + mout[5] + mout[6] + mout[7] ;yout_t <= sum1 + sum2 ;endend`else //一步计算累加结果,但是实际中时序非常危险reg signed [28:0]    sum ;reg signed [28:0]    yout_t ;always @(posedge clk or negedge rstn) beginif (!rstn) beginsum    <= 29'd0 ;yout_t <= 29'd0 ;endelse if (valid_mult7) beginsum    <= mout[0] + mout[1] + mout[2] + mout[3] + mout[4] + mout[5] + mout[6] + mout[7];yout_t <= sum ;endend 
`endifassign yout  = yout_t ;assign valid = valid_mult_r[0];endmodule

testbench

testbench 编写如下,主要功能就是不间断连续的输入 250KHz 与 7.5MHz 的正弦波混合信号数据。输入的混合信号数据也可由 matlab 生成,具体见附录。

`timescale 1ps/1psmodule test ;//inputreg          clk ;reg          rst_n ;reg          en ;reg [11:0]   xin ;//outputwire         valid ;wire [28:0]  yout ;parameter    SIMU_CYCLE   = 64'd2000 ;  //50MHz 采样频率parameter    SIN_DATA_NUM = 200 ;      //仿真周期//=====================================
// 50MHz clk generatinglocalparam   TCLK_HALF     = 10_000;initial beginclk = 1'b0 ;forever begin# TCLK_HALF ;clk = ~clk ;endend//============================
//  reset and finishinitial beginrst_n = 1'b0 ;# 30   rst_n = 1'b1 ;# (TCLK_HALF * 2 * SIMU_CYCLE) ;$finish ;end//=======================================
// read signal data into registerreg          [11:0] stimulus [0: SIN_DATA_NUM-1] ;integer      i ;initial begin$readmemh("../tb/cosx0p25m7p5m12bit.txt", stimulus) ;i = 0 ;en = 0 ;xin = 0 ;# 200 ;forever begin@(negedge clk) beginen          = 1'b1 ;xin         = stimulus[i] ;if (i == SIN_DATA_NUM-1) begin  //周期送入数据控制i = 0 ;endelse begini = i + 1 ;endendend end fir_guide u_fir_paral (.xin         (xin),.clk         (clk),.en          (en),.rstn        (rst_n),.valid       (valid),.yout        (yout));endmodule

仿真结果

由下图仿真结果可知,经过 FIR 滤波器后的信号只有一种低频率信号(250KHz),高频信号(7.5MHz)被滤除了。而且输出波形是连续的,能够持续输出。

但是,如红圈所示,波形起始部分呈不规则状态,对此进行放大。
在这里插入图片描述
波形起始端放大后如下图所示,可见不规则波形的时间段,即两根竖线之间的时间间隔是 16 个时钟周期。

因为数据是串行输入,设计中使用了 16 组延时寄存器,所以滤波后的第一个正常点应该较第一个滤波数据输出时刻延迟 16 个时钟周期。即数据输出有效信号 valid 应该再延迟 16 个时钟周期,则会使输出波形更加完美。
在这里插入图片描述

附录:matlab 使用
生成 FIR 滤波器系数

打开 matlab,在命令窗口输入命令: fdatool。

然后会打开如下窗口,按照 FIR 滤波器参数进行设置。

这里选择的 FIR 实现方法是最小二乘法(Least-squares),不同的实现方式滤波效果也不同。
在这里插入图片描述
点击 File -> Export

将滤波器参数输出,存到变量 coef 中,如下图所示。
在这里插入图片描述
此时 coef 变量应该是浮点型数据。对其进行一定倍数的相乘扩大,然后取其近似的定点型数据作为设计中的 FIR 滤波器参数。这里取扩大倍数为 2048,结果如下所示。
在这里插入图片描述
生成输入的混合信号

利用 matlab 生成混合的输入信号参考代码如下。
信号为无符号定点型数据,位宽宽度为 12bit,存于文件 cosx0p25m7p5m12bit.txt。

clear all;close all;clc;
%=======================================================
% generating a cos wave data with txt hex format
%=======================================================fc          = 0.25e6 ;      % 中心频率
fn          = 7.5e6 ;       % 杂波频率
Fs          = 50e6 ;        % 采样频率
T           = 1/fc ;        % 信号周期
Num         = Fs * T ;      % 周期内信号采样点数
t           = (0:Num-1)/Fs ;      % 离散时间
cosx        = cos(2*pi*fc*t) ;    % 中心频率正弦信号
cosn        = cos(2*pi*fn*t) ;    % 杂波信号
cosy        = mapminmax(cosx + cosn) ;     %幅值扩展到(-1,1) 之间
cosy_dig    = floor((2^11-1) * cosy + 2^11) ;     %幅值扩展到 0~4095
fid         = fopen('cosx0p25m7p5m12bit.txt', 'wt') ;  %写数据文件
fprintf(fid, '%x\n', cosy_dig) ;
fclose(fid) ;%时域波形
figure(1);
subplot(121);plot(t,cosx);hold on ;
plot(t,cosn) ;
subplot(122);plot(t,cosy_dig) ;%频域波形
fft_cosy    = fftshift(fft(cosy, Num)) ;
f_axis      = (-Num/2 : Num/2 - 1) * (Fs/Num) ;
figure(5) ;
plot(f_axis, abs(fft_cosy)) ;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/126754.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter框架实现登录注册功能,不连接数据库

要在Flutter框架中实现登录和注册功能&#xff0c;而不连接数据库&#xff0c;可以使用本地存储来存储用户信息。以下是一个简单的示例&#xff0c;演示如何使用本地存储来实现登录和注册功能。 首先&#xff0c;我们需要添加 shared_preferences 插件到 pubspec.yaml 文件中&…

nginx 转发数据流文件

1.问题描述 后端服务&#xff0c;从数据库中查询日志&#xff0c;并生成表格文件返回静态文件。当数据量几兆时&#xff0c;返回正常&#xff0c;但是超过几十兆&#xff0c;几百兆&#xff0c;就会超过网关的连接超时时间30秒。 时序图 这里面主要花费时间的地方在&#xff…

从零开始的目标检测和关键点检测(二):训练一个Glue的RTMDet模型

从零开始的目标检测和关键点检测&#xff08;二&#xff09;&#xff1a;训练一个Glue的RTMDet模型 一、config文件解读二、开始训练三、数据集分析四、ncnn部署 从零开始的目标检测和关键点检测&#xff08;一&#xff09;&#xff1a;用labelme标注数据集 从零开始的目标检测…

领先实践|IDEO 最佳设计思维和策略框架

设计思维是一种以人为本的创新方法&#xff0c;它从人类的角度出发&#xff0c;考虑技术上可行和经济上可行的内容。框架可以成为实现设计思维、策略和系统设计的有用工具。本文由此展开阐述 IDEO 的最佳设计思维和策略框架。 01. 设计思维框架 1.1 设计思维过程 设计思维?是…

python3 阿里云api进行巡检发送邮件

python3 脚本爬取阿里云进行巡检 不确定pip能不能安装上&#xff0c;使用时候可以百度一下&#xff0c;脚本是可以使用的&#xff0c;没有问题的 太长时间了&#xff0c;pip安装依赖忘记那些了&#xff0c;使用科大星火询问了下&#xff0c;给了下面的&#xff0c;看看能不能使…

一行代码搞定禁用web开发者工具

在如今的互联网时代&#xff0c;网页源码的保护显得尤为重要&#xff0c;特别是前端代码&#xff0c;几乎就是明文展示&#xff0c;很容易造成源码泄露&#xff0c;黑客和恶意用户往往会利用浏览器的开发者工具来窃取网站的敏感信息。为了有效防止用户打开浏览器的Web开发者工具…

X64(64位)汇编指令与机器码转换原理

X64&#xff08;64位&#xff09;汇编指令与机器码转换原理 1 64位寻址形式下的ModR/M字节1.1 寻址方式1.2 寄存器编号 2 汇编指令转机器码2.1 mov rcx, 1122334455667788h2.2 mov rcx,[r8]与mov [r8],rcx2.3 mov rcx,[r8r9*2] 本文属于《 X86指令基础系列教程》之一&#xff…

HPE Compute Scale-up Server 3200服务器来了!突破算力瓶颈,护航企业数字化转型

在全球数字化步入深水区的同时&#xff0c;伴随AIGC的迅速发展&#xff0c;对计算需求的迅速增长&#xff0c;如何高效灵活地使用算力资源成为开发者和企业发展的关注焦点。 服务器作为重要的算力基础设施之一&#xff0c;能快速处理大量数据&#xff0c;在AI时代其市场价值愈…

网络安全方向相关课题和材料

项目介绍 搜集大量网络安全行业开源项目 项目收集的思路: 一个是关注互联网企业/团队的安全开源项目,经企业内部实践,这些最佳实践值得借鉴。 一个是来自企业安全能力建设的需求,根据需求分类,如WAF、HIDS、Git监控等。 这个收集是一个长期的过程,我在GitHub创建了这…

9.MySQL索引的操作

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 索引操作 查询索引 创建主键索引 唯一索引的创建 普通索引的创建 全文索引的创建 删除索引 索引创建原则 索引操作 查询索引 第一种方法&#xff1a; show keys from 表名\G 我们了解其中几个就好。 第二种方法…

双目视觉检测 KX02-SY1000型测宽仪 有效修正和消除距离变化对测量的影响

双目视觉检测的基本原理 利用相机测量宽度时&#xff0c;由于单个相机在成像时存在“近大远小”的现象&#xff0c;并且单靠摄入的图像无法知道被测物的距离&#xff0c;所以由被测物的跳动导致的被测物到工业相机之间距离变化&#xff0c;使测量精度难以提高。 因此测宽仪需…

项目综合实训,vrrp+bfd,以及策略路由的应用

目录 一&#xff0e; 项目需求 二&#xff0e; Visio设备画图 三&#xff0e; 设备选型 三&#xff0e;vlan规划 四&#xff0e;Ip地址规划 五&#xff0e;实验拓扑图 六&#xff0e;配置过程及结果 项目需求 1.S1作为VLAN10的主网关和根桥&#xff0c;S2作为v…

【C语法学习】5 - fputc()函数

文章目录 1 函数原型2 参数3 返回值4 示例4.1 示例14.2 示例24.3 示例3 1 函数原型 fputc()&#xff1a;将一个字符发送至指定流stream&#xff0c;函数原型如下&#xff1a; int fputc(int c, FILE *stream);2 参数 fputc()函数有两个参数c和stream&#xff1a; 参数c是待…

【JAVA学习笔记】 56 - 开发中如何选择集合实现类,以及Collection工具类

项目代码 https://github.com/yinhai1114/Java_Learning_Code/blob/main/IDEA_Chapter14/src/com/yinhai/Collections_.java 在开发中&#xff0c;选择什么集合实现类&#xff0c;主要取决于业务操作特点&#xff0c;然后根据集合实现类特性进行 选择&#xff0c;分析如下: 0.…

npm工具使用方法介绍

npm 使用方法 文章目录 npm 使用方法安装 npm初始化项目安装依赖更新依赖卸载依赖发布包其他命令下载相关 npm 是 Node.js 的包管理工具&#xff0c;用于管理 Node.js 项目的依赖关系。npm 提供了丰富的命令和功能&#xff0c;可以帮助开发者快速构建和部署 Node.js 应用程序。…

Servlet

Servlet是运行在服务端的小型Java程序&#xff0c;是sun公司提供一套规范&#xff0c;用来处理客户端请求&#xff0c;响应给浏览器的动态资源。但servlet的实质就是Java代码&#xff0c;通过Java的API动态的向客户端输出内容&#xff08;HTML&#xff09; 一、使用servlet2.5实…

量化交易Copula建模应对市场低迷

一、简介 传统上,我们依靠相关矩阵来理解资产间的动态。然而,正如过去的市场崩盘所表明的那样,当风暴袭来时,许多模型都会陷入混乱。突然之间,相关性似乎趋于一致,而多样化这一经常被吹捧的风险管理口号似乎并没有提供什么庇护。 这种出乎意料的同步,即资产在经济低迷时…

虹科分享 | 太赫兹成像技术透视分层结构助力文物研究

文章来源&#xff1a;虹科光电Hophotonix 阅读链接&#xff1a;虹科分享 | 太赫兹成像技术透视分层结构助力文物研究 对于时间分辨成像方法来说&#xff0c;分层结构的无创检测具有挑战性&#xff0c;其中分辨率和对比度可能会因层间反射和色散的突出信号衰减而受到影响。在一…

【Java 进阶篇】Java Response 输出字符数据案例

在Java Web开发中&#xff0c;使用HTTP响应对象&#xff08;Response&#xff09;来向客户端发送数据是一项非常重要的任务。本篇博客将详细介绍如何使用Java中的Response对象来输出字符数据&#xff0c;并提供示例代码以帮助读者更好地理解和应用这一概念。不仅将讨论基础知识…

Redis 原理缓存过期、一致性hash、雪崩、穿透、并发、布隆、缓存更新策略、缓存数据库一致性

redis过期策略 redis的过期策略可以通过配置文件进行配置 一、定期删除 redis会把设置了过期时间的key放在单独的字典中&#xff0c;定时遍历来删除到期的key。 1&#xff09;.每100ms从过期字典中 随机挑选20个&#xff0c;把其中过期的key删除&#xff1b; 2&#xff09;.…