FIR滤波器设计(包括Verilog HDL设计以及MATLAB设计)

FIR滤波器设计

滤波器原理:滤波器就是对特定的频率或者特定频率以外的频率进行消除的电路,被广泛用于通信系统和信号处理系统中。从功能角度,数字滤波器对输入离散信号的数字代码进行运算处理,以达到滤除频带外信号的目的。

有限冲激响应(FIR)滤波器就是一种常用的数字滤波器,采用对已输入样值的加权和来形成它的输出。其系统函数为:

其中表示延时一个时钟周期,表示延时两个周期。

对于输入序列X[n]的FIR滤波器可用下图所示结构示意图来表示,其中X[n]是输入数据流。各级的输入连接和输出连接称为抽头,系数被称为抽头系数。一个M阶的FIR滤波器将会有M+1个抽头。通过移位寄存器用每个时钟边沿n(时见下标)处的数据流采样值乘以抽头系数,并将它们加起来形成输出。

 

 

其verilog HDL设计代码为:

module FIR(Data_out, Data_in, clock, reset);  
 
     output[9:0] Data_out;  
 
     input[3:0] Data_in;  
 
     input clock, reset;  
 
    wire[9:0] Data_out;  
 
     wire[3:0] samples_0,samples_1,samples_2,samples_3,  
 
                  samples_4,samples_5,samples_6,samples_7,samples_8;  
 
                  
 
    //例化模块  
 
     shift_register U1(.Data_in(Data_in), .clock(clock), .reset(reset),  
 
                             .samples_0(samples_0),.samples_1(samples_1),  
 
                             .samples_2(samples_2),.samples_3(samples_3),  
 
                             .samples_4(samples_4),.samples_5(samples_5),  
 
                             .samples_6(samples_6),.samples_7(samples_7),  
 
                             .samples_8(samples_8));  
 
       
 
     
 
       
 
    caculator U2(.samples_0(samples_0),.samples_1(samples_1),  
 
                            .samples_2(samples_2),.samples_3(samples_3),  
 
                            .samples_4(samples_4),.samples_5(samples_5),  
 
                             .samples_6(samples_6),.samples_7(samples_7),  
 
                            .samples_8(samples_8), .Data_out(Data_out));  
 
  
 
   
 
  
 
 endmodule  
 
 
 //移位寄存器模块  
 
 //移位寄存器用于存储输入的数据流,本例中主要负责存储8个4位宽输入数据信号,作为Caculator模块的输入。  
 
 module shift_register(Data_in, clock, reset, samples_0, samples_1, samples_2, samples_3,  
 
                          samples_4, samples_5, samples_6, samples_7, samples_8);  
 
                  
 
     input[3:0] Data_in;  
 
     input clock, reset;  
 
    output[3:0] samples_0, samples_1, samples_2, samples_3,  
 
                  samples_4, samples_5, samples_6, samples_7, samples_8;  
 
    reg[3:0] samples_0, samples_1, samples_2, samples_3,  
 
                 samples_4, samples_5, samples_6, samples_7, samples_8;  
 
    always@(posedge clock or posedge reset)  
 
    begin  
 
     if(reset)  
 
    begin  
 
         samples_0 <= 4'b0;  
         samples_1 <= 4'b0;  
         samples_2 <= 4'b0;  
         samples_3 <= 4'b0;  
        samples_4 <= 4'b0;  
         samples_5 <= 4'b0;  
         samples_6 <= 4'b0;  
        samples_7 <= 4'b0;  
         samples_8 <= 4'b0;  
     end  
    else  
     begin  
         samples_0 <= Data_in;  
         samples_1 <= samples_0;  
         samples_2 <= samples_1;  
         samples_3 <= samples_2;  
         samples_4 <= samples_3;  
         samples_5 <= samples_4;  
         samples_6 <= samples_5;  
         samples_7 <= samples_6;  
         samples_8 <= samples_7;  
      
    end  
       
    end  
   
   
 endmodule  
   
 //计算模块  
//Caculator模块用于进行8输入信号与抽头系数的乘法和累加,并产生滤波之后输出信号Data_out。应该指出  
 //的是,FIR滤波器系数具有对称性,在本例中b0 = b8, b1 = b7, b2 = b6, b3 = b5,因此,可以通过先  
 //将输入信号相加再与抽头系数相乘的方式,减少乘法器电路的数量和芯片面积  
 module caculator(samples_0, samples_1, samples_2, samples_3,samples_4,  
                  samples_5, samples_6, samples_7, samples_8, Data_out);  
     input[3:0] samples_0, samples_1, samples_2, samples_3,  
                   samples_4, samples_5, samples_6, samples_7, samples_8;  
     output[9:0] Data_out;  
     wire[9:0] Data_out;  
     wire[3:0] out_tmp_1, out_tmp_2, out_tmp_3, out_tmp_4;  
     wire[7:0] out1, out2, out3, out4, out5;  
       
     parameter b0 = 4'b0010;  
     parameter b1 = 4'b0011;  
     parameter b2 = 4'b0110;  
     parameter b3 = 4'b1010;  
    parameter b4 = 4'b1100;  
       
     wallace U1(.x(b0), .y(out_tmp_1), .out(out1));  
     mul_addtree U2(.mul_a(b1), .mul_b(out_tmp_2), .mul_out(out2));  
    mul_addtree U3(.mul_a(b2), .mul_b(out_tmp_3), .mul_out(out3));  
     mul_addtree U4(.mul_a(b3), .mul_b(out_tmp_4), .mul_out(out4));  
     mul_addtree U5(.mul_a(b4), .mul_b(samples_4), .mul_out(out5));  
     assign out_tmp_1 = samples_0 + samples_8;  
     assign out_tmp_2 = samples_1 + samples_7;  
     assign out_tmp_3 = samples_2 + samples_6;  
     assign out_tmp_4 = samples_3 + samples_5;  
     assign Data_out = out1 + out2 +out3 +out4 +out5;  
   
 endmodule  
   
  
 module mul_addtree(mul_a, mul_b, mul_out);  
     input[3:0] mul_a, mul_b;  
     output[7:0] mul_out;  
    wire[7:0] mul_out;  
     wire[7:0] stored0, stored1, stored2, stored3;  
     wire[7:0] add01, add23;  
       
    assign stored3 = mul_b[3]?{1'b0, mul_a, 3'b0}:8'b0;  
     assign stored2 = mul_b[2]?{2'b0, mul_a, 2'b0}:8'b0;  
     assign stored1 = mul_b[1]?{3'b0, mul_a, 1'b0}:8'b0;  
     assign stored0 = mul_b[0]?{4'b0, mul_a}:8'b0;  
       
     assign add01 = stored1 + stored0;  
    assign add23 = stored3 + stored2;  
     assign mul_out = add01 +add23;  
  
 endmodule  
   
 module wallace(x,y,out);  
     parameter size = 4; //定义参数,乘法器的位数  
    input [size - 1 : 0] x,y; //输入y是乘数,x是被乘数  
    output [2*size - 1 : 0] out;  
    wire [size*size - 1 : 0] a; //a为部分积  
     wire [1 : 0] b0, b1; //第一级的输出,包含进位  
     wire [1 : 0] c0, c1, c2, c3; //第二级的输出,包含进位  
    wire [5 : 0] add_a, add_b; //第三极的输入  
    wire [6 : 0] add_out; //第三极的输出  
     wire [2*size - 1 : 0] out; //乘法器的输出(组合逻辑)  
       
     assign a = {x[3],x[2],x[3],x[1],x[2],x[3],x[0],x[1],  
                 x[2],x[3],x[0],x[1],x[2],x[0],x[1],x[0]}  
                &{y[3],y[3],y[2],y[3],y[2],y[1],y[3],y[2]  
                ,y[1],y[0],y[2],y[1],y[0],y[1],y[0],y[0]}; //部分积  
    hadd U1(.x(a[8]), .y(a[9]), .out(b0));  //2输入半加器(第一级)  
     hadd U2(.x(a[11]), .y(a[12]), .out(b1));//第一级  
     hadd U3(.x(a[4]), .y(a[5]), .out(c0)); //第二级  
      
     fadd U4(.x(a[6]), .y(a[7]), .z(b0[0]), .out(c1)); //3输入全加器(第二级)  
     fadd U5(.x(b1[0]), .y(a[10]), .z(b0[1]), .out(c2));  
     fadd U6(.x(a[13]), .y(a[14]), .z(b1[1]), .out(c3));  
       
       
    assign add_a = {c3[1],c2[1],c1[1],c0[1],c0[0],a[2]}; //加法器(第三极)  
     assign add_b = {a[15],c3[0],c2[0],c1[0],a[3],a[1]};  
     assign add_out = add_a + add_b;  
     assign out = {add_out,a[0]};  
   
 endmodule  
   
 //全加器模块  
 module fadd(x, y, z, out);  
    input x, y, z;  
     output [1 : 0] out;  
     assign out = x + y + z;   
 endmodule  
   
//半加器模块  
 module hadd(x, y, out);  
    input x, y;  
    output [1 : 0] out;  
     assign out = x + y;  
 endmodule

测试代码为:

 //测试文件  
 
 `timescale 1ns/1ns;  
 
  
 
 module FIR_tb;  
 
     reg clock, reset;  
 
     reg[3:0] Data_in;  
 
     wire[9:0] Data_out;  
 
      
 
     FIR U1(.Data_out(Data_out), .Data_in(Data_in), .clock(clock), .reset(reset));  
 
    initial  
 
     begin  
 
         Data_in = 0;  
 
         clock = 0;  
 
         reset = 1;  
 
         #10 reset =0;  
 
     end  
 
       
 
     always  
 
    begin  
 
     #5 clock <= ~clock;  
     #5 Data_in <= Data_in + 1;  
     end  
       
 endmodule  
 

在Modelsim中仿真所得波形如下:

放大截图为:

下面进行MATLAB生成滤波器的实验:

MATLAB生成30阶低通1MHz海明窗函数设计步骤:

(1)在MATLAB命令窗口中输入“fdatool”出现如下对话框:

 

 

 

(2)设定为低通滤波器。

(3)选择FIR滤波器的设计类型为窗函数。

设置FIR滤波器为30阶滤波器,选择窗函数的类型为海明窗函数,海明窗函数可以得到旁瓣更小的效果,能量更加集中在主瓣中,主瓣的能量约占99.963%,第一旁瓣的峰值比主瓣小40dB,但主瓣宽度与海明窗相同。它定义为:

(4)输入抽样频率和截止频率,分别是16MHz和1MHz。

(5)点击Design Filter 得到结果,如下图:

 

 

(6)量化输入输出,点击工作栏左边的量化选项,即“set quantization parameters”选项,选择定点,设置输入字长为8,其他选择默认,如下图示:

 

 

设置完成后,点击Targets中Generate HDL,选择生成Verilog 代码,设置路径,MATLAB即可生成设计好的滤波器Verilog HDL 代码以及测试文件,仿真结果如下图:

  

如上图所示,当输入为线性,或者输入频率较低时,输出幅度不会被抑制,当输入频率较高,输出幅度会受到大幅度抑制,而当输入为白噪声或者混频信号时,滤波器会过滤掉高频信号。

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值