0
点赞
收藏
分享

微信扫一扫

【HB filter】基于FPGA的半带滤波器(HB) 的设计

1.软件版本

Quartusii12.1

2.本算法理论知识

       HBF模块由半带滤波器(HBF)和抽取模块组成。该模块的任务是实现2倍抽取进一步降低信号采样速率。由于HBF的冲激响应h(k)除零点外其余偶数点均为零,所以用HBF实现2倍抽取可以节省一半的运算量,对增强软件无线电的实时性非常重要,HBF还具有参数约束少,设计容易、方便的特点。半带滤波器的主要作用是滤除信号高频部分,防止抽取过程后信号发生频谱混叠。

       在实际中,需要将输入信号进行多次滤波和抽取,并逐次降低采样率,同时也降低对每一级抗混叠滤波器的要求,所以需要使用半带滤波器进行设计与实现。

阻带衰减:    ≥50dB

通带不平坦度:≤2dB

       通常情况下,半带滤波器的有三种基本的结构,一般结构,转置结构以及复用结构,下面我们将针对这三种结构的滤波效果以及硬件占用情况进行分析,从而选用最佳的设计方案。

★半带滤波器的系数确定

 通常情况下,半带滤波器的频谱特性如图1所示:

       频谱对称性的特点使得半带滤波器的时域冲击响应除极值点以外,在其余所有偶数点都为零,利用该性质,可以将运算量降低一半。

       本系统,我们将设计的滤波器,首先,我们可以使用和FIR滤波器设计方法相同的方法进行设计。根据的设计要求,输入的信号带宽为20M,前面设计的NCO,其载波频率为20M,所以,在进行下变频的时候,会产生两倍的频率分量,具体如下所示:

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

       所以,需要设计一个滤波器,其截止频率可以设定为20M,即大于20M的全部滤除,所以,通过上式,可以将其中的高频分量滤除掉。

       此外,由于你的要求中提高通带通带不平坦度≤2dB,那么通常情况下,滤波器的阶数需要设计为中高阶,这里,我们选用65阶的滤波器。

3.部分源码

在MATLAB命令行中输入FDAtool,然后显示如下的界面,进行滤波器的设计:

将通带和阻带放大,可以看到如下的结果:

可以看到,这么一个效果,通带的不平坦度和阻带的衰减基本满足设计需求。产生的滤波器系数如下所示:

其系数如下所示:

-0.00155965846190849

-0.00952583660975731

-0.0192068330061876

-0.0179259709192058

0.000712959523136487

0.0188957029356946

0.0105047070598809

-0.0188943413581846

-0.0266507867913233

0.0101837262873298

0.0460875556113994

0.0147245607722628

-0.0647700808685521

-0.0724069698055561

0.0782875722309085

0.306295132489419

0.416802321987223

0.306295132489419

0.0782875722309085

-0.0724069698055561

-0.0647700808685521

0.0147245607722628

0.0460875556113994

0.0101837262873298

-0.0266507867913233

-0.0188943413581846

0.0105047070598809

0.0188957029356946

0.000712959523136487

-0.0179259709192058

-0.0192068330061876

-0.00952583660975731

-0.00155965846190849

在FPGA中,需要将系数进行量化,我们乘以一个量化系数2^16。量化后的系数如下所示:

-102

-624

-1259

-1175

47

1238

688

-1238

-1747

667

3020

965

-4245

-4745

5131

20073

27316

20073

5131

-4745

-4245

965

3020

667

-1747

-1238

688

1238

47

-1175

-1259

-624

-102

module hb_filter_01(
                    i_clk,
						  i_rst,
						  i_din,
						  o_clk2,
						  o_dout
                   );
						 
parameter h16 = -102;						 
parameter h15 = -624;	
parameter h14 = -1259;	
parameter h13 = -1175;	
parameter h12 = 47;	
parameter h11 = 1238;	
parameter h10 = 688;	
parameter h9  = -1238;	
parameter h8  = -1747;		 					 
parameter h7  = 667;	
parameter h6  = 3020;	
parameter h5  = 965;	
parameter h4  = -4245;	
parameter h3  = -4745;	
parameter h2  = 5131;	
parameter h1  = 20073;	
parameter h0  = 27316;

	
input              i_clk;
input              i_rst;
input signed[15:0] i_din;
output             o_clk2;
output signed[31:0]o_dout;

//delay 33 units
integer i;
reg signed[15:0]men_delay[33:1];
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	       for(i=1;i<=33;i=i+1)
			 begin
			 men_delay[i] <= 16'd0;
			 end
	  end
else begin
          men_delay[1] <= i_din;
			 
	       for(i=2;i<=33;i=i+1)
			 begin
			 men_delay[i] <= men_delay[i-1];
			 end			 
     end
end


//level 1
reg signed[31:0]reg_adder01[33:1];
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	       for(i=1;i<=33;i=i+1)
			 begin
			 reg_adder01[i] <= 32'd0;
			 end
	  end
else begin
     		 reg_adder01[1] <= 32'd0;
			 reg_adder01[2] <= h15 *  men_delay[2];
			 reg_adder01[3] <= 32'd0;
			 reg_adder01[4] <= h13 *  men_delay[4];
			 
     		 reg_adder01[5] <= 32'd0;
			 reg_adder01[6] <= h11 *  men_delay[6];
			 reg_adder01[7] <= 32'd0;
			 reg_adder01[8] <= h9  *  men_delay[8];		
		
     		 reg_adder01[9] <= 32'd0;
			 reg_adder01[10]<= h7  *  men_delay[10];
			 reg_adder01[11]<= 32'd0;
			 reg_adder01[12]<= h5  *  men_delay[12];

     		 reg_adder01[13]<= 32'd0;
			 reg_adder01[14]<= h3  *  men_delay[14];
			 reg_adder01[15]<= 32'd0;
			 reg_adder01[16]<= h1  *  men_delay[16];
			 
//============================================================
     		 reg_adder01[17]<= h0  *  men_delay[17];
//============================================================	
		 
			 reg_adder01[18]<= h1  *  men_delay[18];
			 reg_adder01[19]<= 32'd0;
			 reg_adder01[20]<= h3  *  men_delay[20];	
     		 reg_adder01[21]<= 32'd0;
			 
			 reg_adder01[22]<= h5  *  men_delay[22];
			 reg_adder01[23]<= 32'd0;
			 reg_adder01[24]<= h7  *  men_delay[24];
     		 reg_adder01[25]<= 32'd0;
			 
			 reg_adder01[26]<= h9  *  men_delay[26];
			 reg_adder01[27]<= 32'd0;
			 reg_adder01[28]<= h11 *  men_delay[28];
     		 reg_adder01[29]<= 32'd0;
			 
			 reg_adder01[30]<= h13 *  men_delay[30];
			 reg_adder01[31]<= 32'd0;
			 reg_adder01[32]<= h15 *  men_delay[32];
			 reg_adder01[33]<= 32'd0;		 
     end
end


//level 2
reg signed[31:0]reg_adder02[9:1];

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	       for(i=1;i<=9;i=i+1)
			 begin
			 reg_adder02[i] <= 32'd0;
			 end
	  end
else begin
     		 reg_adder02[1] <= reg_adder01[2] + reg_adder01[32];
			 reg_adder02[2] <= reg_adder01[4] + reg_adder01[30];
			 reg_adder02[3] <= reg_adder01[6] + reg_adder01[28];
			 reg_adder02[4] <= reg_adder01[8] + reg_adder01[26];
			 
     		 reg_adder02[5] <= reg_adder01[17];
			 
			 reg_adder02[6] <= reg_adder01[10]+ reg_adder01[24];
			 reg_adder02[7] <= reg_adder01[12]+ reg_adder01[22];
			 reg_adder02[8] <= reg_adder01[14]+ reg_adder01[20];		
     		 reg_adder02[9] <= reg_adder01[16]+ reg_adder01[18];
     end
end


//level 3
reg signed[31:0]reg_adder03[5:1];

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	       for(i=1;i<=5;i=i+1)
			 begin
			 reg_adder03[i] <= 32'd0;
			 end
	  end
else begin
     		 reg_adder03[1] <= reg_adder02[1] + reg_adder02[9];
			 reg_adder03[2] <= reg_adder02[2] + reg_adder02[8];
			 reg_adder03[3] <= reg_adder02[3] + reg_adder02[7];
			 reg_adder03[4] <= reg_adder02[4] + reg_adder02[6];
     		 reg_adder03[5] <= reg_adder02[5];
     end
end

//level 4
reg signed[31:0]reg_adder04[3:1];

always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	       for(i=1;i<=3;i=i+1)
			 begin
			 reg_adder04[i] <= 32'd0;
			 end
	  end
else begin
     		 reg_adder04[1] <= reg_adder03[1] + reg_adder03[5];
			 reg_adder04[2] <= reg_adder03[2] + reg_adder03[3];
			 reg_adder04[3] <= reg_adder03[4];
     end
end

//level 5
reg signed[31:0]r_dout = 32'd0;
reg signed[31:0]o_dout = 32'd0;      
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	  r_dout <= 32'd0; 
	  end
else begin
	  r_dout <= reg_adder04[1] + reg_adder04[2] + reg_adder04[3];
     end
end
	

reg[3:0]cnt = 4'b00000;
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	  cnt <= 4'b0000;
	  end
else begin
     cnt <= cnt + 4'b0001;
     end
end

assign o_clk2 = cnt[0];

always @(posedge o_clk2 or posedge i_rst)
begin
     if(i_rst)
	  begin
	  o_dout <= 32'd0; 
	  end
else begin
	  o_dout <= r_dout;
     end
end


	
endmodule						 

4.仿真分析

该模块的硬件占用资源为:

其仿真结果如下所示:

A01-115

举报

相关推荐

0 条评论