当前位置:   article > 正文

【FPGA教程案例1】基于FPGA的串行FIR滤波器设计与实现_基于fpga的fir滤波器设计

基于fpga的fir滤波器设计

FPGA教程目录

MATLAB教程目录

---------------------------------------------------------------------------------------

目录

1.软件版本

2.本算法理论知识

3.核心代码

4.操作步骤与仿真结论

5.参考文献


0.完整源码获得方式

方式1:微信或者QQ联系博主

方式2:订阅MATLAB/FPGA教程,免费获得教程案例以及任意2份完整源码

1.软件版本

vivado2019.2、MATLAB2021a

2.本算法理论知识

        FIR(Finite Impulse Response)滤波器是一种有限长单位冲激响应滤波器,又称为非递归型滤波器。FIR 滤波器具有严格的线性相频特性,同时其单位响应是有限长的,因而是稳定的系统,在数字通信、图像处理等领域都有着广泛的应用。FIR 滤波器是有限长单位冲击响应滤波器。直接型结构如下:

FIR 滤波器本质上就是输入信号与单位冲击响应函数的卷积,表达式如下:

        我们可以看到,一个串行结构的FIR滤波器,其首先通过延迟模块得到延迟后的输入信号x,然后和对应的FIR系数相乘,然后再求和就可以输出滤波结果。

3.核心代码

       这里,我们设计一个低阶的滤波器,首先通过MATLAB来确定FIR滤波器的系数,运行如下的MATLAB程序:

  1. clc;
  2. clear;
  3. close all;
  4. warning off;
  5. h = hamming(7);
  6. figure;
  7. plot(h,'b-o')
  8. h2 = round(1023*h)

这里使用hamming汉明窗函数自动产生系数,7表示窗函数的长度。

运行这个程序,可以得到FIR汉明窗的系数:

可以看到,我们产生了7个点长度的汉明窗。

matlab中的最后一行h2 = round(1023*h),表示滤波器系数量化之后h变为h2:

h2 =

          82
         317
         788
        1023
         788
         317
          82

然后在vivado中,新建一个文件,命名为fir_tops.v,其代码如下:

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2022/03/26 23:06:35
  7. // Design Name:
  8. // Module Name: fir_tops
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module fir_tops(
  22. input i_clk,
  23. input i_rst,
  24. input signed[1:0]i_din,
  25. output signed[15:0]o_dout
  26. );
  27. //滤波器系数
  28. parameter b0 = 14'd82;
  29. parameter b1 = 14'd317;
  30. parameter b2 = 14'd788;
  31. parameter b3 = 14'd1023;
  32. parameter b4 = 14'd788;
  33. parameter b5 = 14'd317;
  34. parameter b6 = 14'd82;
  35. reg signed[1:0]x0;
  36. reg signed[1:0]x1;
  37. reg signed[1:0]x2;
  38. reg signed[1:0]x3;
  39. reg signed[1:0]x4;
  40. reg signed[1:0]x5;
  41. reg signed[1:0]x6;
  42. //xn延迟
  43. always @(posedge i_clk or posedge i_rst)
  44. begin
  45. if(i_rst)
  46. begin
  47. x0 <= 2'd0;
  48. x1 <= 2'd0;
  49. x2 <= 2'd0;
  50. x3 <= 2'd0;
  51. x4 <= 2'd0;
  52. x5 <= 2'd0;
  53. x6 <= 2'd0;
  54. end
  55. else begin
  56. x0 <= i_din;
  57. x1 <= x0;
  58. x2 <= x1;
  59. x3 <= x2;
  60. x4 <= x3;
  61. x5 <= x4;
  62. x6 <= x5;
  63. end
  64. end
  65. //使用乘法器IP核计算乘法
  66. wire signed[15:0]r0;
  67. multer multer_u0 (
  68. .CLK(i_clk), // input wire CLK
  69. .A(x0), // input wire [1 : 0] A
  70. .B(b0), // input wire [13 : 0] B
  71. .SCLR(i_rst), // input wire SCLR
  72. .P(r0) // output wire [15 : 0] P
  73. );
  74. wire signed[15:0]r1;
  75. multer multer_u1 (
  76. .CLK(i_clk), // input wire CLK
  77. .A(x1), // input wire [1 : 0] A
  78. .B(b1), // input wire [13 : 0] B
  79. .SCLR(i_rst), // input wire SCLR
  80. .P(r1) // output wire [15 : 0] P
  81. );
  82. wire signed[15:0]r2;
  83. multer multer_u2 (
  84. .CLK(i_clk), // input wire CLK
  85. .A(x2), // input wire [1 : 0] A
  86. .B(b2), // input wire [13 : 0] B
  87. .SCLR(i_rst), // input wire SCLR
  88. .P(r2) // output wire [15 : 0] P
  89. );
  90. wire signed[15:0]r3;
  91. multer multer_u3 (
  92. .CLK(i_clk), // input wire CLK
  93. .A(x3), // input wire [1 : 0] A
  94. .B(b3), // input wire [13 : 0] B
  95. .SCLR(i_rst), // input wire SCLR
  96. .P(r3) // output wire [15 : 0] P
  97. );
  98. wire signed[15:0]r4;
  99. multer multer_u4 (
  100. .CLK(i_clk), // input wire CLK
  101. .A(x4), // input wire [1 : 0] A
  102. .B(b4), // input wire [13 : 0] B
  103. .SCLR(i_rst), // input wire SCLR
  104. .P(r4) // output wire [15 : 0] P
  105. );
  106. wire signed[15:0]r5;
  107. multer multer_u5 (
  108. .CLK(i_clk), // input wire CLK
  109. .A(x5), // input wire [1 : 0] A
  110. .B(b5), // input wire [13 : 0] B
  111. .SCLR(i_rst), // input wire SCLR
  112. .P(r5) // output wire [15 : 0] P
  113. );
  114. wire signed[15:0]r6;
  115. multer multer_u6 (
  116. .CLK(i_clk), // input wire CLK
  117. .A(x6), // input wire [1 : 0] A
  118. .B(b6), // input wire [13 : 0] B
  119. .SCLR(i_rst), // input wire SCLR
  120. .P(r6) // output wire [15 : 0] P
  121. );
  122. assign o_dout = r0+r1+r2+r3+r4+r5+r6;
  123. endmodule

通过parameter语句,定义滤波器系数

然后通过多个乘法器,将延迟后的数据和滤波器系数相乘。 

其中,上述程序中multer乘法器模块,使用vivado的IP核实现,具体操作如下:

 点击IP calalog,然后点击multiplier

 乘法器的参数设置如下:

 

 点击ok,然后弹出

 点击generate

此时,在vivado中,可以看到:

 在vivado中,点击IP source

可以看到乘法器IP核的接口配置:

 双击multer.veo,就可以看到右侧的乘法器接口,将接口复制到verilog中,就有了上述程序

 调用方法和C语言中类似,()中为实际的信号名称,如上图,输入数据x0,系数b0,时钟i_clk,复位i_rst,输出乘积r0.。

FPGA的TB文件程序如下:

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2022/03/26 23:21:32
  7. // Design Name:
  8. // Module Name: test_fir
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module test_fir;
  22. reg i_clk;
  23. reg i_rst;
  24. reg signed[1:0]i_din;
  25. wire signed[15:0]o_dout;
  26. fir_tops fir_tops_u(
  27. .i_clk (i_clk),
  28. .i_rst (i_rst),
  29. .i_din (i_din),
  30. .o_dout (o_dout)
  31. );
  32. initial
  33. begin
  34. i_clk=1'b1;
  35. i_rst=1'b1;
  36. i_din=2'b00;
  37. #1000
  38. i_rst=1'b0;
  39. i_din=2'b01;
  40. #10
  41. i_din=2'b00;
  42. #30
  43. i_din=2'b01;
  44. #10
  45. i_din=2'b00;
  46. #30
  47. i_din=2'b01;
  48. #10
  49. i_din=2'b00;
  50. #30
  51. i_din=2'b01;
  52. #10
  53. i_din=2'b00;
  54. #30
  55. i_din=2'b11;
  56. #10
  57. i_din=2'b00;
  58. #30
  59. i_din=2'b01;
  60. #10
  61. i_din=2'b00;
  62. #30
  63. i_din=2'b11;
  64. #10
  65. i_din=2'b00;
  66. #30
  67. i_din=2'b11;
  68. #10
  69. i_din=2'b00;
  70. #30
  71. i_din=2'b11;
  72. #10
  73. i_din=2'b00;
  74. #30
  75. i_din=2'b01;
  76. #10
  77. i_din=2'b00;
  78. #30
  79. i_din=2'b01;
  80. #10
  81. i_din=2'b00;
  82. #30
  83. i_din=2'b01;
  84. #10
  85. i_din=2'b00;
  86. #30
  87. i_din=2'b01;
  88. #10
  89. i_din=2'b00;
  90. #30
  91. i_din=2'b11;
  92. #10
  93. i_din=2'b00;
  94. #30
  95. i_din=2'b01;
  96. #10
  97. i_din=2'b00;
  98. #30
  99. i_din=2'b11;
  100. #10
  101. i_din=2'b00;
  102. #30
  103. i_din=2'b11;
  104. #10
  105. i_din=2'b00;
  106. #30
  107. i_din=2'b11;
  108. #10
  109. i_din=2'b00;
  110. #30
  111. i_din=2'b01;
  112. #10
  113. i_din=2'b00;
  114. end
  115. always #5 i_clk=~i_clk;
  116. endmodule

4.操作步骤与仿真结论

 在vivado中,选择fir_tops这个顶层文件,右击,设置set as top

然后再选择test_fir,右击,设置set as top

然后点击run simulation,选择行为仿真

然后点击如下三角形,进行仿真

 仿真后将得到:

 同时选中右击,设置进制,选择有符号十进制

 

 然后 同时选中右击,选择波形显示

 

得到如下滤波效果 

上述案例,也可以直接和博主联系,获得完整工程文件。

5.参考文献

[1]郭继昌, 李香萍, 滕建辅. 基于位串行分布式算法和FPGA实现FIR电路的研究[J]. 电子测量与仪器学报, 2001, 15(2):7.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/470057
推荐阅读
相关标签
  

闽ICP备14008679号