Advertisement

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

阅读量:

本文主要介绍了多速率信号处理中FIR滤波器的设计与实现过程。文章从引言开始,详细描述了FIR滤波器的整体架构及其核心模块的设计思路。总体框图展示了FIR滤波器的基本组成:系数产生模块用于生成滤波器系数;Coefficient store模块负责将生成的系数存储到ROM中;Coefficient read module则负责从ROM中读取并分配到RAM中进行处理。
在“Coefficient produce”部分,使用了MATLAB工具生成并量化了FIR滤波器的系数,并通过Verilog HDL语言实现了Coefficient read module的设计与仿真验证。该模块采用分步读取的方式从ROM中获取数据,并将其转换为所需宽度(64位)进行处理。仿真结果表明该设计能够正确完成数据转换与分配任务。
此外,文章还对RAM和ROM的具体IP配置进行了说明,并通过时序图展示了整个系统的运行流程及各模块之间的协作关系。整体而言,文章系统地阐述了多速率信号处理中基于FIR滤波器的设计方法及其硬件实现技术。


目录

引言

总体框图

FIR 滤波器设计

系数产生

ROM IP配置

RAM IP配置

系数读取分配模块



引言

本文继续介绍 FIR 滤波器系数的产生、存储、读取和分配设计。

前文链接:

本文接续前面几篇:

本节主要介绍数字信号处理中的多速率信号处理技术及其应用

在本节中讨论了数字信号的多速率采样与重构技术(Second Part/Chapter)

本节主要介绍


总体框图

说明:该系统中滤波器系数采用16位量化精度,在处理阶段系统能够连续并行读取四个数据块,并将这些数据被分配至四条并行处理路径供滤波器组使用。其中RAM输出端的数据采用64位宽度以保证信号完整性,在完成四个数据块采集后直接进入下一处理阶段以实现高效运行。

FIR 滤波器设计

系数产生

利用MATLAB产生、存储系数的代码如下:

复制代码
>       1.  %% ----------------------- Anti aliasing filter design and store -----------------------

>  
>       2. % | Author          :Xu Y. B.( NICK NAME:在路上,正出发)
>  
>       3. % | Time            :2022 10 09
>  
>       4. % | Store File Type :.coe(Vivado ROM Initialize File)
>  
>       5. % | Filter Parameter:Changeable
>  
>       6. % -----------------------------------------------------------------------------------------
>  
>       7.  
>  
>       8. %% Preparation For Start
>  
>       9. clc;            % Clear Screen
>  
>       10. clearvars;      % Clear All Variables
>  
>       11. close all;      % Close All
>  
>       12.  
>  
>       13. %% Parameter Settings
>  
>       14. fs_int = 100e6;% Initial Sample Rate ;Unit:Hz
>  
>       15. fs_dcm = 25e6; % Decimate Sample Rate ;Unit:Hz
>  
>       16. dcm_factor = 4;% Decimator factor
>  
>       17.  
>  
>       18. filter_length = 32;
>  
>       19. coef_width = 16;
>  
>       20.  
>  
>       21. %% Filter Design
>  
>       22. H = fir1(filter_length-1,1/dcm_factor,"low");
>  
>       23. figure;
>  
>       24. freqz(H,1)
>  
>       25.  
>  
>       26. %% Coefficient Store
>  
>       27. H_QUAN = (round(H/(max(abs(H)))*(2^(coef_width-1)-1))).';
>  
>       28. FILE_NAME = ['D:\VIVADO_WORK_SPACE\Multirate_SP\Multirate_SP.srcs\COEF_FILE\','FIR_COEF.coe'];
>  
>       29. fid_coe=fopen(FILE_NAME,'w+');                                  % Get file id
>  
>       30. fprintf(fid_coe,'memory_initialization_radix=10;\n');           % Write the first line
>  
>       31. fprintf(fid_coe,'memory_initialization_vector=\n');             % Write the second line
>  
>       32. fprintf(fid_coe,'%d,\n',H_QUAN((1:end-1),1));                   % Write data
>  
>       33. fprintf(fid_coe,'%d;',H_QUAN(end,1));                           % Write last data
>  
>       34.   35. % Close Files
>  
>       36. fclose(fid_coe);
>  
>  
>  
>  
>     AI助手

注意:

抗混叠滤波器的截止频率为 1/D。(对于fir1函数而言)

ROM IP配置

RAM IP配置

系数读取分配模块

Verilog HDL 设计源码

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

>  
>       2. // |------------------- FIR Filter Coefficient Read Module -----------------------
>  
>       3. // |------------------------------------------------------------------------------
>  
>       4. // |
>  
>       5. // |********* Basic Information Specify *********
>  
>       6. // |Author                    : Xu Y.B. ( 昵称:在路上,正出发)
>  
>       7. // |Abstract          :
>  
>       8. // |                            -1- FIR Filter Coefficient Width is 16 .
>  
>       9. // |                            -2- FIR Filter Length is 32.(Per Channel has 32/4=8 Coefficients)
>  
>       10. // |                                   -3- RAM is Read After ALL the Coefficients is Stored In RAM.
>  
>       11. // |FPGA Chirp Model : xc7a35tfgg484-2
>  
>       12. // |Vivado Version   : 2018.3
>  
>       13. // |File Create Time : 2022-09-25
>  
>       14. // |Advice                   : This is a example design source.You can also use shift register to design this module,not using IP cores
>  
>       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 COEF_READ_MDL(
>  
>       23. // ------------------------- Input/Output Ports -------------------------
>  
>       24. input                                                                                       I_OPR_CLK,
>  
>       25. input                                                                                       I_OPR_RSTN,
>  
>       26.   27. output                                                                                        O_COEF_VAL,
>  
>       28. output                                              [63:0]                          O_COEF_DATA
>  
>       29.     );
>  
>       30. // ---------------------- Module Internal Signals ------------------------
>  
>       31. reg                                                                                         R_ROM_RD_EN;
>  
>       32. reg                                                                                         R_ROM_RD_EN_R1;
>  
>       33. reg                                                 [4:0]                           R_ROM_RD_ADDRA;
>  
>       34. wire                                                [15:0]                          W_ROM_OUT_DATA;
>  
>       35. reg                                                                                         R_ROM_OUT_VAL;
>  
>       36. reg                                                                                         R_ROM_OUT_VAL_R1;
>  
>       37.  
>  
>       38. reg                                                 [4:0]                           R_RAM_WR_ADDRA;// Read write shared address line
>  
>       39. wire                                                [63:0]                          W_RAM_OUT_DATA;
>  
>       40. reg                                                                                         R_RAM_OUT_VAL;
>  
>       41. reg                                                                                         R_RAM_OUT_VAL_R1;
>  
>       42.  
>  
>       43. // ------------------------ Module Logic Design --------------------------
>  
>       44. // ROM Read
>  
>       45. always @ (posedge I_OPR_CLK)
>  
>       46. begin
>  
>       47.     if(~I_OPR_RSTN)
>  
>       48.     begin
>  
>       49.             R_ROM_RD_ADDRA <= 0;
>  
>       50.             R_ROM_RD_EN <= 1;
>  
>       51.     end
>  
>       52.     else
>  
>       53.     begin
>  
>       54.             if(R_ROM_RD_ADDRA == 31)
>  
>       55.             begin
>  
>       56.                     R_ROM_RD_ADDRA <= 31;
>  
>       57.                     R_ROM_RD_EN <= 0;
>  
>       58.             end
>  
>       59.             else
>  
>       60.             begin
>  
>       61.                     R_ROM_RD_EN <= 1;
>  
>       62.                     R_ROM_RD_ADDRA <= R_ROM_RD_ADDRA + 1;
>  
>       63.             end
>  
>       64.     end
>  
>       65. end
>  
>       66. always @ (posedge I_OPR_CLK)
>  
>       67. begin
>  
>       68.     if(~I_OPR_RSTN)
>  
>       69.     begin
>  
>       70.             R_ROM_RD_EN_R1 <= 0;
>  
>       71.             R_ROM_OUT_VAL <= 0;
>  
>       72.             R_ROM_OUT_VAL_R1 <= 0;
>  
>       73.     end
>  
>       74.     else
>  
>       75.     begin
>  
>       76.             R_ROM_RD_EN_R1 <= R_ROM_RD_EN;
>  
>       77.             R_ROM_OUT_VAL <= R_ROM_RD_EN_R1;
>  
>       78.             R_ROM_OUT_VAL_R1 <= R_ROM_OUT_VAL;
>  
>       79.     end
>  
>       80. end
>  
>       81.  
>  
>       82.  
>  
>       83. // RAM Write
>  
>       84. always @ (posedge I_OPR_CLK)
>  
>       85. begin
>  
>       86.     if(~I_OPR_RSTN)
>  
>       87.     begin
>  
>       88.             R_RAM_WR_ADDRA <= 0;
>  
>       89.     end
>  
>       90.     else
>  
>       91.     begin
>  
>       92.             if(R_ROM_RD_EN_R1)
>  
>       93.             begin
>  
>       94.                     if(R_ROM_RD_EN_R1 & (~R_ROM_OUT_VAL))
>  
>       95.                     begin
>  
>       96.                             R_RAM_WR_ADDRA <= 0;
>  
>       97.                     end
>  
>       98.                     else
>  
>       99.                     begin
>  
>       100.                            R_RAM_WR_ADDRA <= R_RAM_WR_ADDRA + 1;
>  
>       101.                    end
>  
>       102.            end
>  
>       103.            else
>  
>       104.            begin
>  
>       105.                    R_RAM_WR_ADDRA <= 0;
>  
>       106.            end
>  
>       107.    end
>  
>       108. end
>  
>       109.  
>  
>       110. always @ (posedge I_OPR_CLK)
>  
>       111. begin
>  
>       112.    if(~I_OPR_RSTN)
>  
>       113.    begin
>  
>       114.            R_RAM_OUT_VAL <= 0;
>  
>       115.    end
>  
>       116.    else
>  
>       117.    begin
>  
>       118.            if(R_RAM_WR_ADDRA % 4 == 3)
>  
>       119.            begin
>  
>       120.                    R_RAM_OUT_VAL <= 1;
>  
>       121.            end
>  
>       122.            else
>  
>       123.            begin
>  
>       124.                    R_RAM_OUT_VAL <= 0;
>  
>       125.            end
>  
>       126.    end
>  
>       127. end
>  
>       128.  
>  
>       129. always @ (posedge I_OPR_CLK)
>  
>       130. begin
>  
>       131.    if(~I_OPR_RSTN)
>  
>       132.    begin
>  
>       133.            R_RAM_OUT_VAL_R1 <= 0;
>  
>       134.    end
>  
>       135.    else
>  
>       136.    begin
>  
>       137.            R_RAM_OUT_VAL_R1 <= R_RAM_OUT_VAL;
>  
>       138.    end
>  
>       139. end
>  
>       140.   141. ROM_32X16_COEF ROM_32X16_COEF_INST (
>  
>       142.   .clka(I_OPR_CLK),    // input wire clka
>  
>       143.   .ena(R_ROM_RD_EN|R_ROM_RD_EN_R1),      // input wire ena
>  
>       144.   .addra(R_ROM_RD_ADDRA),  // input wire [4 : 0] addra
>  
>       145.   .douta(W_ROM_OUT_DATA)  // output wire [15 : 0] douta
>  
>       146. );
>  
>       147.  
>  
>       148. RAM_COEF_READ RAM_COEF_READ_INST (
>  
>       149.   .clka(I_OPR_CLK),    // input wire clka
>  
>       150.   .ena(1'b1),                 // input wire ena
>  
>       151.   .wea(R_ROM_OUT_VAL),   // input wire [0 : 0] wea
>  
>       152.   .addra(R_RAM_WR_ADDRA),  // input wire [4 : 0] addra
>  
>       153.   .dina(W_ROM_OUT_DATA),   // input wire [15 : 0] dina
>  
>       154.   .douta(W_RAM_OUT_DATA)              // output wire [63 : 0] douta
>  
>       155. );
>  
>       156.  
>  
>       157. assign O_COEF_DATA = W_RAM_OUT_DATA;
>  
>       158. assign O_COEF_VAL = R_RAM_OUT_VAL_R1;
>  
>       159. endmodule
>  
>  
>  
>  
>     AI助手

仿真源码:

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

>  
>       2.   3. module TB_COEF_READ_MDL();
>  
>       4. // ------------------------- Input/Output Ports -------------------------
>  
>       5. reg                                                                                  I_OPR_CLK;
>  
>       6. reg                                                                                  I_OPR_RSTN;
>  
>       7.  
>  
>       8. wire                                                                                         O_COEF_VAL;
>  
>       9. wire                                                 [63:0]                          O_COEF_DATA;
>  
>       10.  
>  
>       11. initial I_OPR_CLK = 0;
>  
>       12. always #20 I_OPR_CLK = ~I_OPR_CLK;
>  
>       13. initial
>  
>       14. begin
>  
>       15.     I_OPR_RSTN = 0;
>  
>       16.     #1002;
>  
>       17.     I_OPR_RSTN = 1;
>  
>       18.     @(negedge O_COEF_VAL);
>  
>       19.     #1000;
>  
>       20.     $stop;
>  
>       21. end
>  
>       22.     COEF_READ_MDL INST_COEF_READ_MDL
>  
>       23.             (
>  
>       24.                     .I_OPR_CLK   (I_OPR_CLK),
>  
>       25.                     .I_OPR_RSTN  (I_OPR_RSTN),
>  
>       26.                     .O_COEF_VAL  (O_COEF_VAL),
>  
>       27.                     .O_COEF_DATA (O_COEF_DATA)
>  
>       28.             );
>  
>       29.  
>  
>       30. endmodule
>  
>  
>  
>  
>     AI助手

仿真时序:

说明:

RAM模块完成位宽转换无需依赖IP核来实现功能。
可以通过移位寄存器来实现。
具体建议参考本人下面的文章:
数据位宽转换(任意整数倍)设计——思路和源码

全部评论 (0)

还没有任何评论哟~