Advertisement

数字信号处理——多速率信号处理(3)

阅读量:

以下是关于该Verilog代码的总结:

Verilog代码总结
模块结构
TBFIRFILTER: 主要负责整个系统的初始化配置和时钟同步。
FIR_FILTER: 实现了主FIR滤波器的功能。

  • 使用多级加法器(如ADD1、“Add1”)和移存器(如MULRES1、“MULLEN1”)来完成乘法与累加操作。
  • 系统通过逐位抽取输入数据并进行累加以实现低通滤波功能。
    DATADCMMDL: 实现了下采样模块的功能。
  • 使用计数器控制数据抽取频率,并通过队列(FIFO)进行数据存储与输出。
    数据流处理
    输入数据经过主时钟(I_CLK)进入FIR滤波器模块。
    每个时钟周期对输入数据进行一次抽样,并通过下采样模块进一步减少抽样率。
    输出信号通过锁相环路(PLL)恢复主时钟频率(OTRDY),并在满足条件时触发(OTRDY)。
    关键组件功能
    多级加法器:用于逐位计算输入信号与滤波系数的乘积,并将结果累加到总和中。
  • 每一级加法器负责一个乘积项的计算,并将结果传递给下一级以完成累加操作。
    移存器:用于延迟输入信号并为下一阶段提供正确的位对齐。
  • 移存器的数量根据所需 taps的数量决定(例如8 taps需要4级移存器)。
    下采样模块:通过计数控制数据抽取频率,并使用队列确保输出符合主时钟频率的要求。
    总体工作流程
    初始化阶段:
  • I_RSTN置高使系统进入初始状态。
  • I_CLK开始工作以启动各模块。
    数据处理阶段:
  • 每个周期对输入数据进行一次抽样并进行相应的运算(包括乘法和累加)。
  • 抽样的次数由下采样模块控制以减少抽样率。
    输出阶段:
  • 当所有必要的计算完成并满足条件时(如所有 taps完成),触发输出信号(O_TRDY)。

仿真结果分析
仿真结果图显示了输入信号经过系统处理后的输出情况。虽然具体数值未给出,但可以通过以下几点验证设计的有效性:
输出信号应具有较低的频带内陷波带宽度(BWC),表明有效完成了低通滤波功能。
下采样过程应保持输出稳定且符合预期频率关系。
系统应在所有 taps完成后正确触发(O_TRDY)信号。

后续内容提示
接下来将详细介绍FIR滤波器的设计步骤:
FIR滤波器系数生成与存储的设计与仿真;
系数读取与分发的具体实现;
下采样模块的设计细节;
全系统的关键测试点及仿真配置;
请继续关注后续内容!



目录

引言

总体设计结构

设计说明

设计框图

设计详述

FIR滤波器模块

时钟 IP

下采样模块




引言

本文接续前面几篇:

数字信号处理技术——多速率信息处理(1)

数字信号的处理技术——多速率信号的处理方法(2)

本研究及其后续内容主要聚焦于各设计阶段的代码开发。随后将详细阐述整体架构,并提供关键模块的代码和仿真结果。


总体设计结构

设计说明

本例程将实现一种高效的抽取滤波器。

设计框图

例程的总体设计框图如上:主要分为如下几个部分:

1、时钟IP模块,板上时钟为50MHz单端时钟,所以需要用此产生100MHz时钟和25MHz时钟。

2、DDS IP模块,用100MHz时钟作为采样时钟,产生1MHz的正弦信号。

3、ROM IP 和RAM IP模块联合用于FIR 滤波器系数的存储和分配。具体逻辑后续会说明。

4、抽取器模块主要分为3部分:

  • FIR滤波器组:并行四路FIR滤波处理。
  • 数据抽取模块:三级延迟器和并行四路下采样处理。
  • 2级加法树模块:实现4路并行输出的求和。

设计详述

FIR滤波器模块

该模块的设计理念可借鉴参考我的过往文章中的直接型FIR滤波器设计。

数字信号处理技术——直接型有限冲激响应(FIR)数字滤波器的设计原理与实现方法(1)

此处也是在之前设计的基础上,对模块进行适当修改。具体源码:

复制代码
>       1. `timescale 1ns / 1ps

>  
>       2. //  BY :Xu Y. B.( ID :在路上,正出发)
>  
>       3. // 备注:1、实现直接型 实数FIR滤波器
>  
>       4. //            2、数据随时钟上升沿移位送入
>  
>       5. //       3、加法部分采样加法树流水结构
>  
>       6. //            4、为方便加法计算,滤波器长度固定为2的整数次幂(此处以8为例)
>  
>       7. //            5、此为示例,仅供参考
>  
>       8.  
>  
>       9.  
>  
>       10. module FIR_FILTER #(
>  
>       11.     parameter       P_FILTER_LEN     =   8, //滤波器长度
>  
>       12.     parameter       P_FILTER_WIDTH   =   16, //滤波器系数位宽
>  
>       13.     parameter       P_DATA_IN_WIDTH  =   16, //输入数据位宽
>  
>       14.     parameter       P_DATA_OUT_WIDTH =   32  //输出数据位宽
>  
>       15.     )(
>  
>       16. // ----------------------------输入
>  
>       17.     input                                                   I_CLK,    //10MHz  
>  
>       18.     input                                                   I_RSTN,
>  
>       19.  
>  
>       20.     input                                                   I_DATA_VAL,
>  
>       21.     input [P_DATA_IN_WIDTH-1:0]     I_DATA,
>  
>       22.     input                                                   I_COEF_VAL,
>  
>       23.     input [P_FILTER_WIDTH-1:0]              I_COEF,
>  
>       24.  
>  
>       25. // ----------------------------输出
>  
>       26.     output                                                  O_RES_VAL,
>  
>       27.     output [P_DATA_OUT_WIDTH-1:0]   O_RES_DATA,
>  
>       28.     output                                                  O_TRDY
>  
>       29.     );
>  
>       30.  
>  
>       31. // ----------------------------内部信号
>  
>       32. // 乘加运算相关
>  
>       33. // 乘法
>  
>       34. reg [P_FILTER_WIDTH+P_DATA_IN_WIDTH-1:0]            R_MULT_RES[P_FILTER_LEN-1:0];    //32个乘积输出
>  
>       35. reg [P_FILTER_LEN-1:0]                                                      R_MULT_RES_VAL;//有效信号
>  
>       36. // 加法
>  
>       37. reg [P_FILTER_WIDTH+P_DATA_IN_WIDTH:0]                      R_ADD_1[P_FILTER_LEN/2-1:0];  //第一级加法树输出
>  
>       38. reg [P_FILTER_WIDTH+P_DATA_IN_WIDTH+1:0]            R_ADD_2[P_FILTER_LEN/4-1:0];  //第二级加法树输出
>  
>       39. reg [P_FILTER_WIDTH+P_DATA_IN_WIDTH+2:0]            R_ADD_3[P_FILTER_LEN/8-1:0];  //第三级加法树输出
>  
>       40.  
>  
>       41.  
>  
>       42. // 输入移存相关
>  
>       43. reg [P_DATA_IN_WIDTH-1:0]                                           R_IN_SHIFT[P_FILTER_LEN-1:0];    //输入数据
>  
>       44. reg [P_FILTER_LEN-1:0]                                              R_IN_VAL_SHIFT;                              //有效信号R_IN_VAL_SHIFT[P_FILTER_LEN]
>  
>       45.  
>  
>       46. // 系数移存相关
>  
>       47. reg [P_FILTER_WIDTH-1:0]                                            R_COEF_SHIFT[P_FILTER_LEN-1:0];    //系数  
>  
>       48. reg [P_FILTER_LEN-1:0]                                                      R_COEF_VAL_SHIFT;                  //有效信号
>  
>       49.  
>  
>       50. // 输出
>  
>       51. reg                         [4:0]                                                   R_RES_VAL;//输出有效信号
>  
>       52.  
>  
>       53. // -----------------------------实现
>  
>       54. // STEP1 :输入移存
>  
>       55. // 数据
>  
>       56.  
>  
>       57. always @ (posedge I_CLK)
>  
>       58. begin
>  
>       59.     if(I_RSTN == 1'b0)
>  
>       60.     begin
>  
>       61.             R_IN_SHIFT[0] <= 0;
>  
>       62.     end
>  
>       63.     else
>  
>       64.     begin
>  
>       65.             if(I_DATA_VAL == 1'b1)
>  
>       66.             begin
>  
>       67.                     R_IN_SHIFT[0] <= I_DATA;
>  
>       68.             end
>  
>       69.             else
>  
>       70.             begin
>  
>       71.                     R_IN_SHIFT[0] <= R_IN_SHIFT[0];
>  
>       72.             end
>  
>       73.     end
>  
>       74. end
>  
>       75.  
>  
>       76. genvar GV_DATA_IN_SHIFT;
>  
>       77. generate
>  
>       78.     for(GV_DATA_IN_SHIFT = 1;GV_DATA_IN_SHIFT < P_FILTER_LEN;GV_DATA_IN_SHIFT = GV_DATA_IN_SHIFT+1)
>  
>       79.     begin:DATA_IN_SHIFT
>  
>       80.             always @ (posedge I_CLK)
>  
>       81.             begin
>  
>       82.                     if(I_RSTN == 1'b0)
>  
>       83.                     begin
>  
>       84.                             R_IN_SHIFT[GV_DATA_IN_SHIFT] <= 0;
>  
>       85.                     end
>  
>       86.                     else
>  
>       87.                             if(I_DATA_VAL == 1)
>  
>       88.                             begin
>  
>       89.                                     R_IN_SHIFT[GV_DATA_IN_SHIFT] <= R_IN_SHIFT[GV_DATA_IN_SHIFT-1];
>  
>       90.                             end
>  
>       91.                             else
>  
>       92.                             begin
>  
>       93.                                     R_IN_SHIFT[GV_DATA_IN_SHIFT] <= R_IN_SHIFT[GV_DATA_IN_SHIFT];
>  
>       94.                             end
>  
>       95.             end
>  
>       96.     end
>  
>       97. endgenerate
>  
>       98.  
>  
>       99. // 有效信号
>  
>       100. always @ (posedge I_CLK)
>  
>       101. begin
>  
>       102.    if(I_RSTN == 1'b0)
>  
>       103.    begin
>  
>       104.            R_IN_VAL_SHIFT[0] <= 1'b0;
>  
>       105.    end
>  
>       106.    else
>  
>       107.    begin
>  
>       108.            if(I_DATA_VAL == 1'b1)
>  
>       109.            begin
>  
>       110.                    R_IN_VAL_SHIFT[0] <= I_DATA_VAL;
>  
>       111.            end
>  
>       112.            else
>  
>       113.            begin
>  
>       114.                    R_IN_VAL_SHIFT[0] <= R_IN_VAL_SHIFT[0];
>  
>       115.            end
>  
>       116.    end
>  
>       117. end
>  
>       118.  
>  
>       119. genvar GV_VAL_IN_SHIFT;
>  
>       120. generate
>  
>       121.    for(GV_VAL_IN_SHIFT = 1;GV_VAL_IN_SHIFT < P_FILTER_LEN;GV_VAL_IN_SHIFT = GV_VAL_IN_SHIFT+1)
>  
>       122.    begin:VAL_IN_SHIFT
>  
>       123.            always @ (posedge I_CLK)
>  
>       124.            begin
>  
>       125.                    if(I_RSTN == 1'b0)
>  
>       126.                    begin
>  
>       127.                            R_IN_VAL_SHIFT[GV_VAL_IN_SHIFT] <= 1'd0;
>  
>       128.                    end
>  
>       129.                    else
>  
>       130.                    begin
>  
>       131.                            if(I_DATA_VAL == 1)
>  
>       132.                            begin
>  
>       133.                                    R_IN_VAL_SHIFT[GV_VAL_IN_SHIFT] <= R_IN_VAL_SHIFT[GV_VAL_IN_SHIFT-1];
>  
>       134.                            end
>  
>       135.                            else
>  
>       136.                            begin
>  
>       137.                                    R_IN_VAL_SHIFT[GV_VAL_IN_SHIFT] <= R_IN_VAL_SHIFT[GV_VAL_IN_SHIFT];
>  
>       138.                            end
>  
>       139.                    end
>  
>       140.            end
>  
>       141.    end
>  
>       142. endgenerate
>  
>       143.  
>  
>       144.  
>  
>       145. // 滤波器系数左移
>  
>       146. always @ (posedge I_CLK)
>  
>       147. begin
>  
>       148.    if(I_RSTN == 1'b0)
>  
>       149.    begin
>  
>       150.            R_COEF_SHIFT[P_FILTER_LEN-1] <= 0;
>  
>       151.    end
>  
>       152.    else
>  
>       153.    begin
>  
>       154.            if(I_COEF_VAL == 1'b1)
>  
>       155.            begin
>  
>       156.                    R_COEF_SHIFT[P_FILTER_LEN-1] <= I_COEF;
>  
>       157.            end
>  
>       158.            else
>  
>       159.            begin
>  
>       160.                    R_COEF_SHIFT[P_FILTER_LEN-1] <= R_COEF_SHIFT[P_FILTER_LEN-1];
>  
>       161.            end
>  
>       162.    end
>  
>       163. end
>  
>       164.  
>  
>       165. genvar GV_COEF_LEFT_SHIFT;
>  
>       166. generate
>  
>       167.    for(GV_COEF_LEFT_SHIFT = P_FILTER_LEN-2;GV_COEF_LEFT_SHIFT >=0;GV_COEF_LEFT_SHIFT = GV_COEF_LEFT_SHIFT-1)
>  
>       168.    begin:COEF_LEFT_SHIFT
>  
>       169.            always @ (posedge I_CLK)
>  
>       170.            begin
>  
>       171.                    if(I_RSTN == 1'b0)
>  
>       172.                    begin
>  
>       173.                            R_COEF_SHIFT[GV_COEF_LEFT_SHIFT] <= 0;
>  
>       174.                    end
>  
>       175.                    else
>  
>       176.                    begin
>  
>       177.                            if(I_COEF_VAL == 1'b1)
>  
>       178.                            begin
>  
>       179.                                    R_COEF_SHIFT[GV_COEF_LEFT_SHIFT] <= R_COEF_SHIFT[GV_COEF_LEFT_SHIFT+1];
>  
>       180.                            end
>  
>       181.                            else
>  
>       182.                            begin
>  
>       183.                                    R_COEF_SHIFT[GV_COEF_LEFT_SHIFT] <= R_COEF_SHIFT[GV_COEF_LEFT_SHIFT];
>  
>       184.                            end
>  
>       185.                    end
>  
>       186.            end
>  
>       187.    end
>  
>       188. endgenerate
>  
>       189.  
>  
>       190. // 有效信号左移
>  
>       191. always @ (posedge I_CLK)
>  
>       192. begin
>  
>       193.    if(I_RSTN == 1'b0)
>  
>       194.    begin
>  
>       195.            R_COEF_VAL_SHIFT[P_FILTER_LEN-1] <= 1'b0;
>  
>       196.    end
>  
>       197.    else
>  
>       198.    begin
>  
>       199.            if(I_COEF_VAL == 1'b1)
>  
>       200.            begin
>  
>       201.                    R_COEF_VAL_SHIFT[P_FILTER_LEN-1] <= I_COEF_VAL;
>  
>       202.            end
>  
>       203.            else
>  
>       204.            begin
>  
>       205.                    R_COEF_VAL_SHIFT[P_FILTER_LEN-1] <= R_COEF_VAL_SHIFT[P_FILTER_LEN-1] ;
>  
>       206.            end
>  
>       207.    end
>  
>       208. end
>  
>       209.  
>  
>       210. genvar GV_COEF_VAL_LEFT_SHIFT;
>  
>       211. generate
>  
>       212.    for(GV_COEF_VAL_LEFT_SHIFT = P_FILTER_LEN-2;GV_COEF_VAL_LEFT_SHIFT >=0 ;GV_COEF_VAL_LEFT_SHIFT = GV_COEF_VAL_LEFT_SHIFT-1)
>  
>       213.    begin:COEF_VAL_LEFT_SHIFT
>  
>       214.            always @ (posedge I_CLK)
>  
>       215.            begin
>  
>       216.                    if(I_RSTN == 1'b0)
>  
>       217.                    begin
>  
>       218.                            R_COEF_VAL_SHIFT[GV_COEF_VAL_LEFT_SHIFT] <= 1'd0;
>  
>       219.                    end
>  
>       220.                    else
>  
>       221.                    begin
>  
>       222.                            if(I_COEF_VAL == 1'b1)
>  
>       223.                            begin
>  
>       224.                                    R_COEF_VAL_SHIFT[GV_COEF_VAL_LEFT_SHIFT] <= R_COEF_VAL_SHIFT[GV_COEF_VAL_LEFT_SHIFT+1];
>  
>       225.                            end
>  
>       226.                            else
>  
>       227.                            begin
>  
>       228.                                    R_COEF_VAL_SHIFT[GV_COEF_VAL_LEFT_SHIFT] <= R_COEF_VAL_SHIFT[GV_COEF_VAL_LEFT_SHIFT];
>  
>       229.                            end
>  
>       230.                    end
>  
>       231.            end
>  
>       232.    end
>  
>       233. endgenerate
>  
>       234.  
>  
>       235. // 系数相乘
>  
>       236. genvar GV_DATA_COEF_MULT;
>  
>       237. generate
>  
>       238.    for(GV_DATA_COEF_MULT = 0;GV_DATA_COEF_MULT < P_FILTER_LEN;GV_DATA_COEF_MULT = GV_DATA_COEF_MULT+1)
>  
>       239.    begin:DATA_COEF_MULT
>  
>       240.            always @ (posedge I_CLK)
>  
>       241.            begin
>  
>       242.                    if(I_RSTN == 1'b0)
>  
>       243.                    begin
>  
>       244.                            R_MULT_RES_VAL[GV_DATA_COEF_MULT] <= 1'b0;
>  
>       245.                            R_MULT_RES[GV_DATA_COEF_MULT]     <= 32'd0;
>  
>       246.                    end
>  
>       247.                    else if(R_COEF_VAL_SHIFT[GV_DATA_COEF_MULT] && R_IN_VAL_SHIFT[GV_DATA_COEF_MULT])
>  
>       248.                    begin
>  
>       249.                            R_MULT_RES_VAL[GV_DATA_COEF_MULT] <= 1'b1;
>  
>       250.                            R_MULT_RES[GV_DATA_COEF_MULT]     <= {{(P_DATA_IN_WIDTH){R_COEF_SHIFT[GV_DATA_COEF_MULT][P_FILTER_WIDTH-1]}},R_COEF_SHIFT[GV_DATA_COEF_MULT]}
>  
>       251.                                                                                                    *
>  
>       252.                                                                                                     {{(P_FILTER_WIDTH){R_IN_SHIFT[GV_DATA_COEF_MULT][P_DATA_IN_WIDTH-1]}},R_IN_SHIFT[GV_DATA_COEF_MULT]};
>  
>       253.                    end
>  
>       254.                    else
>  
>       255.                    begin
>  
>       256.                            R_MULT_RES_VAL[GV_DATA_COEF_MULT] <= R_MULT_RES_VAL[GV_DATA_COEF_MULT];
>  
>       257.                            R_MULT_RES[GV_DATA_COEF_MULT]     <= R_MULT_RES[GV_DATA_COEF_MULT];
>  
>       258.                    end
>  
>       259.            end
>  
>       260.    end
>  
>       261. endgenerate
>  
>       262.  
>  
>       263. // 加法树
>  
>       264. // 第一级
>  
>       265. genvar GV_ADD_1;
>  
>       266. generate
>  
>       267.    for(GV_ADD_1 = 0;GV_ADD_1 < P_FILTER_LEN/2;GV_ADD_1 = GV_ADD_1+1)
>  
>       268.    begin:ADD_1
>  
>       269.            always @ (posedge I_CLK)
>  
>       270.            begin
>  
>       271.                    if(I_RSTN == 1'b0)
>  
>       272.                    begin
>  
>       273.                            R_ADD_1[GV_ADD_1] <= 33'd0;
>  
>       274.                    end
>  
>       275.                    else
>  
>       276.                    begin
>  
>       277.                            if(|R_MULT_RES_VAL)//只有一路乘法输出有效就进行加法
>  
>       278.                            begin
>  
>       279.                                    R_ADD_1[GV_ADD_1] <= {R_MULT_RES[GV_ADD_1][P_FILTER_WIDTH+P_DATA_IN_WIDTH-1],R_MULT_RES[GV_ADD_1]}
>  
>       280.                                                                            +
>  
>       281.                                                                             {R_MULT_RES[P_FILTER_LEN-1-GV_ADD_1][P_FILTER_WIDTH+P_DATA_IN_WIDTH-1],R_MULT_RES[P_FILTER_LEN-1-GV_ADD_1]};
>  
>       282.                            end
>  
>       283.                    end
>  
>       284.            end
>  
>       285.    end
>  
>       286. endgenerate
>  
>       287.  
>  
>       288. // 第二级
>  
>       289. genvar GV_ADD_2;
>  
>       290. generate
>  
>       291.    for(GV_ADD_2 = 0;GV_ADD_2 < P_FILTER_LEN/4;GV_ADD_2 = GV_ADD_2+1)
>  
>       292.    begin:ADD_2
>  
>       293.            always @ (posedge I_CLK)
>  
>       294.            begin
>  
>       295.                    if(I_RSTN == 1'b0)
>  
>       296.                    begin
>  
>       297.                            R_ADD_2[GV_ADD_2] <= 34'd0;
>  
>       298.                    end
>  
>       299.                    else
>  
>       300.                    begin
>  
>       301.                            R_ADD_2[GV_ADD_2] <= {R_ADD_1[GV_ADD_2][P_FILTER_WIDTH+P_DATA_IN_WIDTH],R_ADD_1[GV_ADD_2]}
>  
>       302.                                                                    +
>  
>       303.                                                                     {R_ADD_1[P_FILTER_LEN/2-1-GV_ADD_2][P_FILTER_WIDTH+P_DATA_IN_WIDTH],R_ADD_1[P_FILTER_LEN/2-1-GV_ADD_2]};
>  
>       304.                    end
>  
>       305.            end
>  
>       306.    end
>  
>       307. endgenerate
>  
>       308.  
>  
>       309. // 第三级
>  
>       310. genvar GV_ADD_3;
>  
>       311. generate
>  
>       312.    for(GV_ADD_3 = 0;GV_ADD_3 < P_FILTER_LEN/8;GV_ADD_3 = GV_ADD_3+1)
>  
>       313.    begin:ADD_3
>  
>       314.            always @ (posedge I_CLK)
>  
>       315.            begin
>  
>       316.                    if(I_RSTN == 1'b0)
>  
>       317.                    begin
>  
>       318.                            R_ADD_3[GV_ADD_3] <= 35'd0;
>  
>       319.                    end
>  
>       320.                    else
>  
>       321.                    begin
>  
>       322.                            R_ADD_3[GV_ADD_3] <= {R_ADD_2[GV_ADD_3][P_FILTER_WIDTH+P_DATA_IN_WIDTH+1],R_ADD_2[GV_ADD_3]}
>  
>       323.                                                                    +
>  
>       324.                                                                     {R_ADD_2[P_FILTER_LEN/4-1-GV_ADD_3][P_FILTER_WIDTH+P_DATA_IN_WIDTH+1],R_ADD_2[P_FILTER_LEN/4-1-GV_ADD_3]};
>  
>       325.                    end
>  
>       326.            end
>  
>       327.    end
>  
>       328. endgenerate
>  
>       329.  
>  
>       330. // 输出
>  
>       331. assign O_RES_DATA = R_ADD_3[0][(P_FILTER_WIDTH+P_DATA_IN_WIDTH+2)-:P_DATA_OUT_WIDTH];
>  
>       332.  
>  
>       333.  
>  
>       334. always @ (posedge I_CLK)
>  
>       335. begin
>  
>       336.    if(I_RSTN == 1'b0)
>  
>       337.    begin
>  
>       338.            R_RES_VAL[0] <= 1'b0;
>  
>       339.    end
>  
>       340.    else
>  
>       341.    begin
>  
>       342.            if(I_DATA_VAL == 1 && &R_COEF_VAL_SHIFT == 1)
>  
>       343.            begin
>  
>       344.                    R_RES_VAL[0] <= I_DATA_VAL;
>  
>       345.            end
>  
>       346.            else
>  
>       347.            begin
>  
>       348.                    R_RES_VAL[0] <=R_RES_VAL[0] ;
>  
>       349.            end
>  
>       350.    end
>  
>       351. end
>  
>       352.  
>  
>       353. genvar GV_RES_VAL;
>  
>       354. generate
>  
>       355.    for(GV_RES_VAL = 1;GV_RES_VAL <= 4;GV_RES_VAL = GV_RES_VAL+1)
>  
>       356.    begin:RES_VAL
>  
>       357.            always @(posedge I_CLK)
>  
>       358.            begin
>  
>       359.                    if(I_RSTN == 1'b0)
>  
>       360.                    begin
>  
>       361.                            R_RES_VAL[GV_RES_VAL] <= 1'd0;
>  
>       362.                    end
>  
>       363.                    else
>  
>       364.                    begin
>  
>       365.                            if(I_DATA_VAL == 1 && &R_COEF_VAL_SHIFT == 1)
>  
>       366.                            begin
>  
>       367.                                    R_RES_VAL[GV_RES_VAL] <=  R_RES_VAL[GV_RES_VAL-1];
>  
>       368.                            end
>  
>       369.                            else
>  
>       370.                            begin
>  
>       371.                                    R_RES_VAL[GV_RES_VAL] <= R_RES_VAL[GV_RES_VAL];
>  
>       372.                            end
>  
>       373.                    end
>  
>       374.            end
>  
>       375.    end
>  
>       376. endgenerate
>  
>       377.  
>  
>       378. assign O_RES_VAL = R_RES_VAL[4];
>  
>       379. assign O_TRDY = &R_COEF_VAL_SHIFT;//FIR 系数 全部读出且有效后 表示FIR滤波器已做好准备 开始接收输入数据
>  
>       380.  
>  
>       381.  
>  
>       382. endmodule
>  
>  
>  
>  
>     AI助手

仿真代码:

复制代码
>       1. `timescale 1ns / 1ps

>  
>       2. module TB_FIR_FILTER();
>  
>       3.  
>  
>       4. parameter    P_FILTER_LEN     =   8; //滤波器长度
>  
>       5. parameter    P_FILTER_WIDTH   =   16; //滤波器系数位宽
>  
>       6. parameter    P_DATA_IN_WIDTH  =   16; //输入数据位宽
>  
>       7. parameter    P_DATA_OUT_WIDTH =   32; //输出数据位宽
>  
>       8.
>  
>       9. // ----------------------------输入
>  
>       10. reg                                                         I_CLK;    //10MHz  
>  
>       11. reg                                                         I_RSTN;
>  
>       12. reg                                                         I_DATA_VAL;
>  
>       13. reg [P_DATA_IN_WIDTH-1:0]   I_DATA;
>  
>       14. reg                                                         I_COEF_VAL;
>  
>       15. reg [P_FILTER_WIDTH-1:0]            I_COEF;
>  
>       16.  
>  
>       17. // ----------------------------输出
>  
>       18. wire                                                        O_RES_VAL;
>  
>       19. wire [P_DATA_OUT_WIDTH-1:0]         O_RES_DATA;
>  
>       20. wire                                                        O_TRDY;
>  
>       21.  
>  
>       22. initial I_CLK = 0;
>  
>       23. always #20 I_CLK = ~I_CLK;
>  
>       24. initial
>  
>       25. begin
>  
>       26.     I_RSTN = 0;
>  
>       27.     #100;
>  
>       28.     I_RSTN = 1;
>  
>       29. end
>  
>       30.  
>  
>       31. reg [3:0] R_COUNT;
>  
>       32. always @ (posedge  I_CLK)
>  
>       33. begin
>  
>       34.     if(~I_RSTN)
>  
>       35.     begin
>  
>       36.             R_COUNT <= 0;
>  
>       37.             I_COEF_VAL <= 0;
>  
>       38.             I_COEF <= 0;
>  
>       39.     end
>  
>       40.     else
>  
>       41.     begin
>  
>       42.             if(R_COUNT == 8)
>  
>       43.             begin
>  
>       44.                     R_COUNT <= 8;
>  
>       45.                     I_COEF_VAL <= 0;
>  
>       46.                     I_COEF <= 0;
>  
>       47.             end
>  
>       48.             else
>  
>       49.             begin
>  
>       50.                     R_COUNT <= R_COUNT + 1;
>  
>       51.                     I_COEF_VAL <= 1;
>  
>       52.                     I_COEF <= I_COEF + 8;
>  
>       53.             end
>  
>       54.     end
>  
>       55. end
>  
>       56.  
>  
>       57. always @ (posedge I_CLK)
>  
>       58. begin
>  
>       59.     if(~I_RSTN)
>  
>       60.     begin
>  
>       61.             I_DATA <= 0;
>  
>       62.             I_DATA_VAL <= 0;
>  
>       63.     end
>  
>       64.     else
>  
>       65.     begin
>  
>       66.             if(O_TRDY)
>  
>       67.             begin
>  
>       68.                     I_DATA <= I_DATA + 1;
>  
>       69.                     I_DATA_VAL <= 1;
>  
>       70.             end
>  
>       71.             else
>  
>       72.             begin
>  
>       73.                     I_DATA <= 0;
>  
>       74.                     I_DATA_VAL <= 0;
>  
>       75.             end
>  
>       76.     end
>  
>       77. end
>  
>       78. FIR_FILTER #(
>  
>       79.             .P_FILTER_LEN(P_FILTER_LEN),
>  
>       80.             .P_FILTER_WIDTH(P_FILTER_WIDTH),
>  
>       81.             .P_DATA_IN_WIDTH(P_DATA_IN_WIDTH),
>  
>       82.             .P_DATA_OUT_WIDTH(P_DATA_OUT_WIDTH)
>  
>       83.     ) INST_FIR_FILTER (
>  
>       84.             .I_CLK      (I_CLK),
>  
>       85.             .I_RSTN     (I_RSTN),
>  
>       86.  
>  
>       87.             .I_DATA_VAL (I_DATA_VAL),
>  
>       88.             .I_DATA     (I_DATA),
>  
>       89.             .I_COEF_VAL (I_COEF_VAL),
>  
>       90.             .I_COEF     (I_COEF),
>  
>       91.  
>  
>       92.             .O_RES_VAL  (O_RES_VAL),
>  
>       93.             .O_RES_DATA (O_RES_DATA),
>  
>       94.             .O_TRDY     (O_TRDY)
>  
>       95.     );
>  
>       96.  
>  
>       97. endmodule
>  
>  
>  
>  
>     AI助手

仿真结果:

时钟 IP

IP核配置

此处的相位无所谓,随便设置。默认都为0即可。

下采样模块

设计源码:

复制代码
>       1. // |------------------------------------------------------------------------------

>  
>       2. // |------------------------------ DATA DECIMATE DESIGN --------------------------
>  
>       3. // |------------------------------------------------------------------------------
>  
>       4. // |
>  
>       5. // |********* Basic Information Specify *********
>  
>       6. // |Author                    : Xu Y.B. ( 昵称:在路上,正出发)
>  
>       7. // |Abstract          :
>  
>       8. // |                            -1- Configurable Parameter.
>  
>       9. // |                            -2- Dual clock ports.
>  
>       10. // |  
>  
>       11. // |FPGA Chirp Model : xc7a35tfgg484-2
>  
>       12. // |Vivado Version   : 2018.3
>  
>       13. // |File Create Time : 2022-10-07
>  
>       14. // |Advice                   : This is a example design source.
>  
>       15. // |                                   It is better to understand and improve the source code!
>  
>       16. // |
>  
>       17. // |********* Version Change History *********
>  
>       18. // |
>  
>       19. // |
>  
>       20.  
>  
>       21. `timescale 1ns / 1ps
>  
>       22. module DATA_DCM_MDL #(
>  
>       23. // --------------------------- Module Parameter -------------------------
>  
>       24. parameter                   P_DCM_FACTOR            =               4,
>  
>       25. parameter                   P_DATA_WIDTH            =               8,
>  
>       26. parameter                   P_PHASE_OFFSET          =               0
>  
>       27. )(
>  
>       28. // ------------------------- Input/Output Ports -------------------------
>  
>       29. // Initial Sample Clock Domain
>  
>       30. input                                                                                       I_INT_CLK,
>  
>       31. input                                                                                       I_RSTN,
>  
>       32. input                                                                                       I_DATA_IN_VAL,
>  
>       33. input                               [P_DATA_WIDTH-1:0]                      I_DATA_IN,
>  
>       34. // Decimator Clock Domain
>  
>       35. input                                                                                       I_DCM_CLK,
>  
>       36. output                                                                                      O_DATA_OUT_VAL,
>  
>       37. output                              [P_DATA_WIDTH-1:0]                      O_DATA_OUT
>  
>       38. );
>  
>       39. // -------------------------- Local Parameters ---------------------------
>  
>       40. localparam                  LP_COUNT_WIDTH          =               $clog2(P_DCM_FACTOR); // Counter Width
>  
>       41.  
>  
>       42. // ---------------------- Module Internal Signals ------------------------
>  
>       43. reg                                 [LP_COUNT_WIDTH-1:0]            R_COUNT;                                 // Counter
>  
>       44. wire                                [P_DATA_WIDTH-1:0]                      W_DATA_DCM_OUT_INTCD;    // Decimate Out Data In Initial Clock Domain
>  
>       45. wire                                                                                        W_DATA_DCM_OUT_VAL_INTCD;// Decimate Out Data Valid In Initial Clock Domain
>  
>       46.  
>  
>       47. // FIFO
>  
>       48. reg                                                                                         R_FIFO_RD_EN;
>  
>       49. wire                                                                                        W_FIFO_FULL;
>  
>       50. wire                                                                                        W_FIFO_EMPTY;
>  
>       51. wire                                                                                        W_FIFO_ALMOST_FULL;
>  
>       52. wire                                                                                        W_FIFO_ALMOST_EMPTY;
>  
>       53. wire                                [P_DATA_WIDTH-1:0]                      W_FIFO_RD_OUT;
>  
>       54. wire                                                                                        W_FIFO_OUT_VLD;
>  
>       55.  
>  
>       56. // ------------------------ Module Logic Design --------------------------
>  
>       57. // Initial Clock Domain Decimate Logic
>  
>       58. always @ (posedge I_INT_CLK)
>  
>       59. begin
>  
>       60.     if(~I_RSTN)
>  
>       61.     begin
>  
>       62.             R_COUNT <= 0;
>  
>       63.     end
>  
>       64.     else if(I_DATA_IN_VAL)
>  
>       65.     begin
>  
>       66.             if(R_COUNT == P_DCM_FACTOR-1)
>  
>       67.             begin
>  
>       68.                     R_COUNT <= 0;
>  
>       69.             end
>  
>       70.             else
>  
>       71.             begin
>  
>       72.                     R_COUNT <= R_COUNT + 1;
>  
>       73.             end
>  
>       74.     end
>  
>       75.     else
>  
>       76.     begin
>  
>       77.             R_COUNT <= 0;
>  
>       78.     end
>  
>       79. end
>  
>       80. assign W_DATA_DCM_OUT_INTCD = (R_COUNT == P_PHASE_OFFSET) ? I_DATA_IN : {(P_DATA_WIDTH){1'b1}};
>  
>       81. assign W_DATA_DCM_OUT_VAL_INTCD = ((R_COUNT == P_PHASE_OFFSET) &&(I_DATA_IN_VAL)) ? 1'b1 : 1'b0;
>  
>       82.  
>  
>       83.  
>  
>       84. assign O_DATA_OUT_VAL = W_FIFO_OUT_VLD;
>  
>       85. assign O_DATA_OUT = W_FIFO_RD_OUT;
>  
>       86.  
>  
>       87. always @ (posedge I_DCM_CLK)
>  
>       88. begin
>  
>       89.     if(~I_RSTN)
>  
>       90.     begin
>  
>       91.             R_FIFO_RD_EN <= 0;
>  
>       92.     end
>  
>       93.     else
>  
>       94.     begin
>  
>       95.             if(W_FIFO_ALMOST_EMPTY)
>  
>       96.             begin
>  
>       97.                     R_FIFO_RD_EN <= 0;
>  
>       98.             end
>  
>       99.             else
>  
>       100.            begin
>  
>       101.                    R_FIFO_RD_EN <= 1;
>  
>       102.            end
>  
>       103.    end
>  
>       104. end
>  
>       105.   106. FIFO_DATA_CDC INST_FIFO_DATA_CDC (
>  
>       107.   .rst(1'b0),                    // input wire rst
>  
>       108.   .wr_clk(I_INT_CLK),              // input wire wr_clk
>  
>       109.   .rd_clk(I_DCM_CLK),              // input wire rd_clk
>  
>       110.   .din(W_DATA_DCM_OUT_INTCD),                    // input wire [7 : 0] din
>  
>       111.   .wr_en(W_DATA_DCM_OUT_VAL_INTCD),                // input wire wr_en
>  
>       112.   .rd_en(R_FIFO_RD_EN),                // input wire rd_en
>  
>       113.   .dout(W_FIFO_RD_OUT),                  // output wire [7 : 0] dout
>  
>       114.   .full(W_FIFO_FULL),                  // output wire full
>  
>       115.   .almost_full(W_FIFO_ALMOST_FULL),    // output wire almost_full
>  
>       116.   .empty(W_FIFO_EMPTY),                // output wire empty
>  
>       117.   .almost_empty(W_FIFO_ALMOST_EMPTY),  // output wire almost_empty
>  
>       118.   .valid(W_FIFO_OUT_VLD)                 // output wire valid
>  
>       119. );
>  
>       120.  
>  
>       121.  
>  
>       122. endmodule
>  
>  
>  
>  
>     AI助手

FIFO IP核的配置:

仿真源码:

复制代码
>       1.  
>  
>       2.  
>  
>       3. `timescale 1ns / 1ps
>  
>       4. module TB_DATA_DCM_MDL();
>  
>       5. // --------------------------- Module Parameter -------------------------
>  
>       6. parameter                    P_DCM_FACTOR            =               4;
>  
>       7. parameter                    P_DATA_WIDTH            =               16;
>  
>       8. parameter                    P_PHASE_OFFSET          =               3;
>  
>       9.  
>  
>       10. // ------------------------- Input/Output Ports -------------------------
>  
>       11. // Initial Sample Clock Domain
>  
>       12. wire                                                                                        I_INT_CLK;
>  
>       13. wire                                                                                        I_RSTN;
>  
>       14. reg                                                                                         I_DATA_IN_VAL;
>  
>       15. reg                                 [P_DATA_WIDTH-1:0]                      I_DATA_IN;
>  
>       16. // Decimator Clock Domain
>  
>       17. wire                                                                                        I_DCM_CLK;
>  
>       18. wire                                                                                        O_DATA_OUT_VAL;
>  
>       19. wire                                [P_DATA_WIDTH-1:0]                      O_DATA_OUT;
>  
>       20.  
>  
>       21. reg                                                                                         CLK_IN_50M;
>  
>       22.  
>  
>       23. initial CLK_IN_50M = 0;
>  
>       24. always #10 CLK_IN_50M = ~CLK_IN_50M;
>  
>       25.  
>  
>       26.  
>  
>       27. always @ (posedge I_INT_CLK)
>  
>       28. begin
>  
>       29.     if(~I_RSTN)
>  
>       30.     begin
>  
>       31.             I_DATA_IN <= 0;
>  
>       32.             I_DATA_IN_VAL <= 0;
>  
>       33.     end
>  
>       34.     else
>  
>       35.     begin
>  
>       36.             I_DATA_IN <= I_DATA_IN + 1;
>  
>       37.             I_DATA_IN_VAL <= 1;
>  
>       38.     end
>  
>       39. end
>  
>       40.  
>  
>       41. DATA_DCM_MDL #(
>  
>       42.             .P_DCM_FACTOR(P_DCM_FACTOR),
>  
>       43.             .P_DATA_WIDTH(P_DATA_WIDTH),
>  
>       44.             .P_PHASE_OFFSET(P_PHASE_OFFSET)
>  
>       45.     ) inst_DATA_DCM_MDL (
>  
>       46.             .I_INT_CLK      (I_INT_CLK),
>  
>       47.             .I_RSTN         (I_RSTN),
>  
>       48.             .I_DATA_IN_VAL  (I_DATA_IN_VAL),
>  
>       49.             .I_DATA_IN      (I_DATA_IN),
>  
>       50.             .I_DCM_CLK      (I_DCM_CLK),
>  
>       51.             .O_DATA_OUT_VAL (O_DATA_OUT_VAL),
>  
>       52.             .O_DATA_OUT     (O_DATA_OUT)
>  
>       53.     );
>  
>       54.  
>  
>       55.  SYS_MMCM SYS_MMCM_INST
>  
>       56.    (
>  
>       57.     // Clock out ports
>  
>       58.     .CLK_100M(I_INT_CLK),     // output CLK_100M
>  
>       59.     .CLK_25M(I_DCM_CLK),     // output CLK_25M
>  
>       60.     // Status and control signals
>  
>       61.     .reset(1'b0), // input reset
>  
>       62.     .locked(I_RSTN),       // output locked
>  
>       63.    // Clock in ports
>  
>       64.     .CLK_IN_50M(CLK_IN_50M));      // input CLK_IN_50M
>  
>       65. endmodule
>  
>  
>  
>  
>     AI助手

仿真结果:


在后续文章中进一步阐述FIR滤波器系数的具体设计内容及其实现流程,在这一过程中将详细说明包括生成、存储、读取和分发等关键步骤,并提供相应的设计方法和仿真源代码。

全部评论 (0)

还没有任何评论哟~