串行FIR滤波器

串行 FIR 滤波器设计

串行设计,就是在 16 个时钟周期内对 16 个延时数据分时依次进行乘法、加法运算,然后在时钟驱动下输出滤波值。考虑到 FIR 滤波器系数的对称性,计算一个滤波输出值的周期可以减少到 8 个。串行设计时每个周期只进行一次乘法运算,所以设计中只需一个乘法器即可。此时数据需要每 8 个时钟周期有效输入一次,但是为了保证输出信号频率的正确性,工作时钟需要为采样频率的 8 倍,即 400MHz。这种方法的优点是资源耗费少,但是工作频率要求高,数据不能持续输出。

串行设计

/**********************************************************
>> Description : fir study with serial tech
>>             : Fs:50Mhz, fstop:1-6Mhz, order:16, sys clk:400MHz
***********************************************************/
`define SAFE_DESIGNmodule fir_serial(input                rstn,input                clk,   // 系统工作时钟,400MHzinput                en ,   // 输入数据有效信号input        [11:0]  xin,   // 输入混合频率的信号数据output               valid, // 输出数据有效信号output       [28:0]  yout   // 输出数据);//delay of input data enablereg [11:0]            en_r ;always @(posedge clk or negedge rstn) beginif (!rstn) beginen_r[11:0]      <= 'b0 ;endelse beginen_r[11:0]      <= {en_r[10:0], en} ;endend//fir coeficientwire        [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 ;//(1) 输入数据移位部分reg [2:0]            cnt ;integer              i, j ;always @(posedge clk or negedge rstn) beginif (!rstn) begincnt <= 3'b0 ;endelse if (en || cnt != 0) begincnt <= cnt + 1'b1 ;    //8个周期计数endendreg [11:0]           xin_reg[15:0];always @(posedge clk or negedge rstn) beginif (!rstn) beginfor (i=0; i<16; i=i+1) beginxin_reg[i]  <= 12'b0;endendelse if (cnt == 3'd0 && en) begin    //每8个周期读入一次有效数据xin_reg[0] <= xin ;for (j=0; j<15; j=j+1) beginxin_reg[j+1] <= xin_reg[j] ; // 数据移位endendend//(2) 系数对称,16个移位寄存器数据进行首位相加reg  [11:0]          add_a, add_b ;reg  [11:0]          coe_s ;wire [12:0]          add_s ;wire [2:0]           xin_index = cnt>=1 ? cnt-1 : 3'd7 ;always @(posedge clk or negedge rstn) beginif (!rstn) beginadd_a  <= 13'b0 ;add_b  <= 13'b0 ;coe_s  <= 12'b0 ;endelse if (en_r[xin_index]) begin //from en_r[1]add_a  <= xin_reg[xin_index] ;add_b  <= xin_reg[15-xin_index] ;coe_s  <= coe[xin_index] ;endendassign add_s = {add_a} + {add_b} ;  //(3) 乘法运算,只用一个乘法wire        [24:0]    mout ;
`ifdef SAFE_DESIGNwire                 en_mult ;wire [3:0]           index_mult = cnt>=2 ? cnt-1 : 4'd7 + cnt[0] ;mult_man #(13, 12)   u_mult_single    //例化自己设计的流水线乘法器(.clk        (clk),.rstn       (rstn),.data_rdy   (en_r[index_mult]),  //注意数据时序对应.mult1      (add_s),.mult2      (coe_s),.res_rdy    (en_mult),  .res        (mout));`elsealways @(posedge clk or negedge rstn) beginif (!rstn) beginmout   <= 25'b0 ;endelse if (|en_r[8:1]) beginmout   <= coe_s * add_s ;  //直接乘endendwire                 en_mult = en_r[2];
`endif//(4) 积分累加,8组25bit数据 -> 1组 29bit 数据reg        [28:0]    sum ;reg                  valid_r ;//mult output en counterreg [4:0]            cnt_acc_r ;always @(posedge clk or negedge rstn) beginif (!rstn) begincnt_acc_r <= 'b0 ;endelse if (cnt_acc_r == 5'd7) begin  //计时8个周期cnt_acc_r <= 'b0 ;endelse if (en_mult || cnt_acc_r != 0) begin //只要en有效,计时不停cnt_acc_r <= cnt_acc_r + 1'b1 ;endendalways @(posedge clk or negedge rstn) beginif (!rstn) beginsum      <= 29'd0 ;valid_r  <= 1'b0 ;endelse if (cnt_acc_r == 5'd7) begin //在第8个累加周期输出滤波值sum      <= sum + mout;valid_r  <= 1'b1 ;endelse if (en_mult && cnt_acc_r == 0) begin //初始化sum      <= mout ;valid_r  <= 1'b0 ;endelse if (cnt_acc_r != 0) begin //acculating between cyclessum      <= sum + mout ;valid_r  <= 1'b0 ;endend//时钟锁存有效的输出数据,为了让输出信号不是那么频繁的变化reg [28:0]           yout_r ;always @(posedge clk or negedge rstn) beginif (!rstn) beginyout_r <= 'b0 ;endelse if (valid_r) beginyout_r <= sum ;endendassign yout = yout_r ;//(5) 输出数据有效延迟,即滤波数据丢掉前15个滤波值reg [4:0]    cnt_valid ;always @(posedge clk or negedge rstn) beginif (!rstn) begincnt_valid      <= 'b0 ;endelse if (valid_r && cnt_valid != 5'd16) begincnt_valid      <= cnt_valid + 1'b1 ;endendassign valid = (cnt_valid == 5'd16) & valid_r ;endmodule

testbench

module test ;//inputreg          clk ;reg          rst_n ;reg          en ;reg  [11:0]  xin ;//outputwire [28:0]  yout ;wire         valid ;parameter    SIMU_CYCLE   = 64'd1000 ;parameter    SIN_DATA_NUM = 200 ;//=====================================
// 8*50MHz clk generatinglocalparam   TCLK_HALF     = (10_000 >>3);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 * 8  * SIMU_CYCLE) ;$finish ;end//=======================================
// read cos data into registerreg          [11:0] stimulus [0: SIN_DATA_NUM-1] ;integer      i ;initial begin$readmemh("E:/appdata/SimulationTools/modelsim/demo/filter/FIR_filter/tb/cosx0p25m7p5m12bit.txt", stimulus) ;en = 0 ;i = 0 ;xin = 0 ;# 200 ;forever beginrepeat(7)  @(negedge clk) ; //空置7个周期,第8个周期给数据en          = 1 ;xin         = stimulus[i] ;@(negedge clk) ;en          = 0 ;         //输入数据有效信号只持续一个周期即可if (i == SIN_DATA_NUM-1)  i = 0 ;else  i = i + 1 ;endendfir_serial       u_fir_serial (.clk         (clk),.rstn        (rst_n),.en          (en),.xin         (xin),.valid       (valid),.yout        (yout));endmodule

仿真结果

在这里插入图片描述

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

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

相关文章

Linux重置ROOT密码(CentOS)

解释说明 在CentOS中重置root密码通常需要进入单用户模式&#xff0c;这是一个没有密码限制的特殊模式&#xff0c;允许您以root权限登录系统并更改密码。 重启系统 如果您无法登录到系统&#xff0c;可以通过重启系统来开始这个过程。您可以使用虚拟机控制台、物理服务器控制台…

新能源汽车技术的最新进展和未来趋势

文章目录 电池技术的进步智能驾驶与自动驾驶技术充电基础设施建设新能源汽车共享和智能交通未来趋势展望结论 &#x1f389;欢迎来到AIGC人工智能专栏~探索新能源汽车技术的最新进展和未来趋势 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客…

c刷题(三)

程序运行结果 int a, b, c; a 5; c a; b c, c, a, a; b a c; printf("a %d b %d c %d\n", a, b, c); line3&#xff1a;c6&#xff0c;a6&#xff1b; line4&#xff1a;(逗号表达式&#xff0c;从左向右计算&#xff0c;结果为最后一个表达式)c8&#xff…

DP读书:鲲鹏处理器 架构与编程(十一)鲲鹏生态软硬件构成

鲲鹏生态软硬件构成 鲲鹏软件构成硬件特定软件1. Boot Loader2. SBSA 与 SBBR3. UEFI4. ACPI 鲲鹏软件构成 鲲鹏处理器的软件生态是一个不断发展的软件生态&#xff0c;服务器本身也具有复杂度多样性&#xff0c;经过很长时间的发展服务器硬件有不同的操作系统方案&#xff0c…

如何向BertModel增加字符

这里写自定义目录标题 看起来add_special_tokens和add_tokens加入的新token都不会被切分。

基于ssm+vue德云社票务系统源码和论文

基于ssmvue德云社票务系统源码和论文063 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 1.选题的依据和意义 互联网时代&#xff0c;随着生活节奏的加快和不断上升的压力&#xff0c;人们急需寻找到情绪的宣泄…

redis缓存雪崩、穿透、击穿解决方案

redis缓存雪崩、穿透、击穿解决方案 背景缓存雪崩缓存击穿缓存穿透总结背景 关于缓存异常,我们常见的有三个问题:缓存雪崩、缓存击穿、缓存穿透。这三个问题一旦发生,会导致大量请求直接落到数据库层面。如果请求的并发量很大,会影响数据库的运行,严重的会导致数据库宕机…

Spring Cloud Nacos 和 Eureka区别,包含实战代码

目录 一、Spring Cloud Eureka详解二、Spring Cloud Nacos详解三、Spring Cloud Nacos和Eureka区别 Spring Cloud Nacos 和 Spring Cloud Eureka 都是 Spring Cloud 微服务框架中的服务注册和发现组件&#xff0c;用于帮助开发者轻松地构建和管理微服务应用。它们之间的主要区别…

Python工具箱系列(四十一)

使用zip批量压缩文件 前文的代码示例了使用gzip对单个文件进行压缩。本文示例使用更通用的zipfile来批量压缩文件。zipfile也是python内置的库&#xff0c;使用起来非常方便。废话不说&#xff0c;直接上代码示例。 import dbm import glob import zipfile# 保存压缩计划的库名…

电子价签如何让电信门店数字化事半功倍?

数字化转型&#xff0c;高效的工具首先跟上。早在2020年&#xff0c;深圳电信就与云里物里开展商业合作&#xff0c;在深圳所有电信营业厅安装云里物里的ESL电子标签&#xff0c;以替代传统纸质标签的显示。经过几年的效果认证&#xff0c;云里物里的数字化智显设备得到了深圳电…

网页接口导入postman进行接口请求

postman版本&#xff1a;v10.17.4 一、拷贝接口信息 网页打开开发者工具-networkk&#xff0c;在网页上请求一次接口&#xff0c;鼠标指在接口上&#xff0c;点击鼠标右键-copy-copy as cURL(bash) 二、导入postman 打开postman&#xff0c;点击import-Raw text&#xff0c;…

【MCU】SD NAND芯片之国产新选择

文章目录 前言传统SD卡和可贴片SD卡传统SD卡可贴片SD卡 实际使用总结 前言 随着目前时代的快速发展&#xff0c;即使是使用MCU的项目上也经常有大数据存储的需求。可以看到经常有小伙伴这样提问&#xff1a; 大家好&#xff0c;请问有没有SD卡芯片&#xff0c;可以直接焊接到P…