芯路恒电子技术论坛

 找回密码
 立即注册
热搜: 活动
查看: 217|回复: 0

串行结构FIR滤波器设计

[复制链接]
  • TA的每日心情
    萌哒
    昨天 07:48
  • 3

    主题

    3

    帖子

    56

    积分

    初级会员

    Rank: 3Rank: 3

    积分
    56
    发表于 2019-8-25 13:16:45 | 显示全部楼层 |阅读模式
    本帖最后由 cyy13623649348 于 2019-8-25 13:15 编辑

    1.  FIR滤波器原理
        FIR滤波器是线性时不变系统,分析FIR、IIR系统的方法都是以线性时不变系统为基础的。
        滤波器的出可以表示为输入序列和单位取样响应的卷积。
    输出y.jpg
    系统函数为
    单位取样响应.jpg
        FIR滤波器单位取样响应满足对称条件时具有线性相位特性。
        FIR滤波器的结构有直接型、级联型、频率取样型和快速卷积型。FPGA实现时最常用的是最简单的直接型结构。FPGA实现直接型结构的FIR滤波器可以采用串行结构、并行结构、分布式结构和IP核等。
        FIR滤波器直接型结构
    直接型结构.jpg
    图 1 FIR直接型结构
    2.FIR滤波器设计
        之前设计了一个数字混频程序,载频为1MHz,信号频率为625kHz。相乘后的信号包含和频1.625MH,差频375kHz两个频率分量。本次设计一个31阶(长度为32)的低通滤波器,截止频率为375KHz,采样频率10M。将混频后的信号通过滤波器,就可以得到375kHz的信号。

    数字信号处理学习——混频器
    http://www.corecourse.cn/forum.php?mod=viewthread&tid=27994
    (出处: 芯路恒电子技术论坛)

      
    (1)通过MATLAB设计出滤波器系数;
    1. N=32;      %滤波器长度
    2. fs=10000000;%采样频率10M
    3. fc=375000;    %低通滤波器的截止频率375kHz
    4. B=12;      %量化位数

    5. %生成各种窗函数
    6. % w_rect=rectwin(N)';
    7. % w_hann=hann(N)';
    8. % w_hamm=hamming(N)';
    9. w_kais=blackman(N)';
    10. % w_kais=kaiser(N,7.856)';

    11. %采用fir1函数设计FIR滤波器
    12. % b_rect=fir1(N-1,fc*2/fs,w_rect);
    13. % b_hann=fir1(N-1,fc*2/fs,w_hann);
    14. % b_hamm=fir1(N-1,fc*2/fs,w_hamm);
    15. % b_blac=fir1(N-1,fc*2/fs,w_blac);
    16. b_kais=fir1(N-1,fc*2/fs,w_kais);
    17. %量化滤波器系数
    18. Q1=max(abs(b_kais))
    19. Q2=b_kais/Q1
    20. Q3=Q2*(2^(B-1)-1)
    21. Q_kais=round(b_kais/max(abs(b_kais))*(2^(B-1)-1))
    22. hn=Q_kais;
    23. %转化成16进制数补码
    24. Q_h=dec2hex(Q_kais+2^B*(Q_kais<0))


    25. %求滤波器的幅频响应
    26. % m_rect=20*log(abs(fft(b_rect,512)))/log(10);
    27. % m_hann=20*log(abs(fft(b_hann,512)))/log(10);
    28. % m_hamm=20*log(abs(fft(b_hamm,512)))/log(10);
    29. % m_blac=20*log(abs(fft(b_blac,512)))/log(10);
    30. m_kais=20*log(abs(fft(b_kais,1024)))/log(10); m_kais=m_kais-max(m_kais);
    31. Q_kais=20*log(abs(fft(Q_kais,1024)))/log(10); Q_kais=Q_kais-max(Q_kais);


    32. %设置幅频响应的横坐标单位为Hz
    33. x_f=[0:(fs/length(m_kais)):fs/2];
    34. %只显示正频率部分的幅频响应
    35. % m1=m_rect(1:length(x_f));
    36. % m2=m_hann(1:length(x_f));
    37. % m3=m_hamm(1:length(x_f));
    38. % m4=m_blac(1:length(x_f));
    39. m5=m_kais(1:length(x_f));
    40. m6=Q_kais(1:length(x_f));


    41. %绘制幅频响应曲线
    42. % plot(x_f,m1,'-',x_f,m2,'*',x_f,m3,'+',x_f,m4,'--',x_f,m5,'-.');
    43. plot(x_f,m5,'-',x_f,m6,'--');
    44. xlabel('频率(Hz)');ylabel('幅度(dB)');
    45. legend('未量化','12bit量化');
    46. grid;</font>
    复制代码

      (2)使用Varilog设计串行FIR程序;

        根据FIR直接型结构,滤波器是一个乘累加运算,乘累加的次数由滤波器的阶数决定,前面提到FIR滤波器具有线性相位特性,其系数具有对称性,因此可以减少运算次数。
    串行结构框图.jpg

    图 2 FIR串行结构

        由于设定的采样时钟为10MHz,而两次采样间隔内要完成16次加法运算,因此系统时钟必须高于采样时钟16倍以上。这里使用PLL产生一个160M系统时钟。
        根据图2,串行结构只需要一个乘法器和一个加法器即可,这里通过IP核来实现
    1. /*实例化有符号数加法器IP核,对输入数据进行1位符号位扩展,输出结果为13比特数据*/
    2.         reg signed [12:0] add_a;
    3.         reg signed [12:0] add_b;
    4.         wire signed [12:0] add_s; //输入为12比特量化数据,两个对称系数相加需要13比特存储
    5.         adder adder (
    6.                 .dataa (add_a),
    7.                 .datab (add_b),
    8.                 .result(add_s)
    9.         );
    10.         
    11. /*例化有符号数乘法器*/
    12.         reg signed [11:0]coe;        //滤波器12bit量化数据
    13.         wire signed [24:0]Mout;  
    14.         mult mult (
    15.                 .clock (clk),
    16.                 .dataa (coe),
    17.                 .datab (add_s),
    18.                 .result (Mout)
    19.         );
    复制代码
       在两次采样间隔中完成16个滤波器系数与数据的乘法运算。一个加法器顺序完成16次加法运算
    1.         always@(posedge clk or negedge rst_n)
    2.         if(!rst_n) begin
    3.                 add_a <= 13'd0;
    4.                 add_b <= 13'd0;
    5.                 coe <= 12'd0;
    6.         end
    7.         else begin
    8.                 case(simple_cnt)
    9.                         0:begin
    10.                                 add_a <= {in_reg[0][11],in_reg[0]};
    11.                                 add_b <= {in_reg[31][11],in_reg[31]};
    12.                                 coe <= 12'h000;//c0
    13.                         end
    14.                         1:begin
    15.                                 add_a <= {in_reg[1][11],in_reg[1]};
    16.                                 add_b <= {in_reg[30][11],in_reg[30]};
    17.                                 coe <= 12'hfff; //c1
    18.                         end
    19.                         2:begin
    20.                                 add_a <= {in_reg[2][11],in_reg[2]};
    21.                                 add_b <= {in_reg[29][11],in_reg[29]};
    22.                                 coe <= 12'h000; //c2
    23.                         end
    24.                         3:begin
    25.                                 add_a <= {in_reg[3][11],in_reg[3]};
    26.                                 add_b <= {in_reg[28][11],in_reg[28]};
    27.                                 coe <= 12'h005; //c3
    28.                         end
    29.                         4:begin
    30.                                 add_a <= {in_reg[4][11],in_reg[4]};
    31.                                 add_b <= {in_reg[27][11],in_reg[27]};
    32.                                 coe <= 12'h017; //c4
    33.                         end
    34.                         5:begin
    35.                                 add_a <= {in_reg[5][11],in_reg[5]};
    36.                                 add_b <= {in_reg[26][11],in_reg[26]};
    37.                                 coe <= 12'h03e; //c5
    38.                         end
    39.                         6:begin
    40.                                 add_a <= {in_reg[6][11],in_reg[6]};
    41.                                 add_b <= {in_reg[25][11],in_reg[25]};
    42.                                 coe <= 12'h086; //c6
    43.                         end
    44.                         7:begin
    45.                                 add_a <= {in_reg[7][11],in_reg[7]};
    46.                                 add_b <= {in_reg[24][11],in_reg[24]};
    47.                                 coe <= 12'h0fa; //c7
    48.                         end
    49.                         8:begin
    50.                                 add_a <= {in_reg[8][11],in_reg[8]};
    51.                                 add_b <= {in_reg[23][11],in_reg[23]};
    52.                                 coe <= 12'h1a2; //c8
    53.                         end
    54.                         9:begin
    55.                                 add_a <= {in_reg[9][11],in_reg[9]};
    56.                                 add_b <= {in_reg[22][11],in_reg[22]};
    57.                                 coe <= 12'h27f; //c9
    58.                         end
    59.                         10:begin
    60.                                 add_a <= {in_reg[10][11],in_reg[10]};
    61.                                 add_b <= {in_reg[21][11],in_reg[21]};
    62.                                 coe <= 12'h389; //c10
    63.                         end
    64.                         11:begin
    65.                                 add_a <= {in_reg[11][11],in_reg[11]};
    66.                                 add_b <= {in_reg[20][11],in_reg[20]};
    67.                                 coe <= 12'h4ad; //c11
    68.                         end
    69.                         12:begin
    70.                                 add_a <= {in_reg[12][11],in_reg[12]};
    71.                                 add_b <= {in_reg[19][11],in_reg[19]};
    72.                                 coe <= 12'h5d1; //c12
    73.                         end
    74.                         13:begin
    75.                                 add_a <= {in_reg[13][11],in_reg[13]};
    76.                                 add_b <= {in_reg[18][11],in_reg[18]};
    77.                                 coe <= 12'h6d4; //c13
    78.                         end
    79.                         14:begin
    80.                                 add_a <= {in_reg[14][11],in_reg[14]};
    81.                                 add_b <= {in_reg[17][11],in_reg[17]};
    82.                                 coe <= 12'h797; //c14
    83.                         end
    84.                         15:begin
    85.                                 add_a <= {in_reg[15][11],in_reg[15]};
    86.                                 add_b <= {in_reg[16][11],in_reg[16]};
    87.                                 coe <= 12'h7ff; //c15
    88.                         end
    89.                 endcase
    90.         end
    复制代码
        最后对滤波器系数与输入数据的乘法结果进行累加,并输出滤波后的数据。考虑到乘法器及累加器的延时,需要计数器为2时对累加器清零,同时输出滤波器结果数据。
    1. reg signed [28:0] sum;
    2.         reg signed [28:0] yout;
    3.         always @(posedge clk or negedge rst_n)
    4.                 if(!rst_n) begin
    5.                         sum = 29'd0;
    6.                         yout <= 29'd0;
    7.                 end
    8.                 else begin
    9.                         if(simple_cnt==2) begin
    10.                                 yout <= sum;
    11.                                 sum = 29'd0;
    12.                                 sum =sum + Mout;
    13.                         end
    14.                         else
    15.                                 sum = sum + Mout;
    16.                 end
    17.         
    18.         assign Signal_out = yout;
    复制代码

      (3)仿真验证
        将数字混频后的输出接到滤波器的输入

    1. module Fir_test(
    2.         rst_n,
    3.         clk,
    4.         Signal_out
    5. );
    6.         
    7.         input rst_n;
    8.         input clk;
    9.         output [28:0]Signal_out;
    10.         
    11.         wire [23:0]Mixer_out;
    12.         wire clk_PLL;
    13.         
    14.         PLL PLL(
    15.                 .inclk0(clk),
    16.                 .c0(clk_PLL)
    17.         );

    18.         Mixer Mixer(
    19.                 .rst_n(rst_n),
    20.                 .clk(clk),
    21.                 .dout(Mixer_out)
    22.         );

    23.         Fir_filter Fir_filter(
    24.                 .rst_n(rst_n),
    25.                 .clk(clk_PLL),
    26.                 .Signal_in(Mixer_out[23:12]),
    27.                 .Signal_out(Signal_out)
    28.         );
    29.         
    30. endmodule
    复制代码
        仿真得到下面结果,前三个波形为混频器输入和输出,最后的波形为滤波器输出,可以看到滤波器输出的结果为375KHz。
    仿真.jpg

    图 3 FIR测试结果

        工程链接:https://pan.baidu.com/s/1i0P6pzjkdHnT71_7zhIYjQ     提取码:8grs
        不是很明白的话可以参考杜勇老师《数字滤波器的MATLAB与FPGA实现》。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|小黑屋|手机版|Archiver|芯路恒电子技术论坛  

    GMT+8, 2019-9-18 00:25 , Processed in 0.175630 second(s), 11 queries , File On.

    Powered by Discuz! X3.3

    © 2001-2017 Comsenz Inc. Template By 【未来科技】【 www.wekei.cn 】

    快速回复 返回顶部 返回列表