分布式算法FIR滤波器
学院: 班级: 姓名: 学号: 指导老师:
1
一、设计目的
1.熟悉FPGA设计基本方法
2.掌握用Verilog语言设计一个数字滤波器
二、设计原理与方法
目前FIR滤波器的实现方法有三种:利用单片通用数字滤波器集成电路、DSP器件和可编
程逻辑器件实现。单片通用数字滤波器使用方便,但由于字长和阶数的规格较少,不能完全满足实际需要。使用DSP器件实现虽然简单,但由于程序顺序执行,执行速度必然不快。FPGA有着规整的内部逻辑阵列和丰富的连线资源,特别适合于数字信号处理任务,相对于串行运算为主导的通用DSP芯片来说,其并行性和可扩展性更好。但长期以来,FPGA一直被用于系统逻辑或时序控制上,很少有信号处理方面的应用,其原因主要是因为在FPGA中缺乏实现乘法运算的有效结构。现在这个问题得到了解决,使FPGA在数字信号处理方面有了长足的发展。
分布式算法(Distributed Arithmetic,DA)是一种已实现乘加运算为目的的运算方法。它与传统实现乘加运算算法的不同之处在于:执行部分积运算的先后顺序不同。简单地说,分布式算法在完成乘加功能时是通过将各输入数据每一对应位产生的部分积预先进行相加形成相应部分积,然后再对各部分积进行累加形成最终结果;而传统算法是等到所有乘积产生之后再进行相加来完成乘加运算的。与传统算法相比,分布式算法可极大地减少硬件电路规模,很容易实现流水线处理,提高电路的执行速度。
在实际中,不仅是对于滤波器方面,在卷积、相关、DFT等有乘累加运算的地方,都可以使用这种方法实现。DA设计的先决条件是滤波器的系数h[i]可以通过运算得到,那么在技术部分乘积项h[i]*x[n-1]就变成了一个常数乘法(也就是缩放)。DA算法的主要特点是,巧妙地利用查找表将固定系数的MAC运算转化为查表操作,其运算速度不随系数和输入数据位数的增加而降低,而且相对直接实现乘法器而言,在硬件规模上得到了极大的改善。 分布式FIR算法原理
分布式算法是在30年前被首次提出的,但直到Xilinx公司发明FPGA的查找表结构以后,DA算法才广泛应用在计算乘积和之中。对于FIR(有限长单位冲激响应)滤波器,其基本结构是一个分节的延时线,每一节的输出加权累加,得到滤波器的输出。其输出y就是输入x和系数h的内积:
N1yh,xh[n]x[n]n0 (1)
h[0]x[0]h[1]x[1]h[N1]n[N1]
2
输入数据x[n]可以采用B+1位补码来表示,即
B1x[n]2xB[n]Bxb0[n]2bb (2)
因为系数h为已知常数,则内积y可以写成:
B1N1by2h[n]xB[n]Bh[n]xb0n0[n]2b (3)
将式(3)中的第二部分展开,重新分别求和,这也是“分布式算法”名称的由来,可以得到:
B1N1b0h[n]xb[n]2h[0](xB1[0]2n0bB1xB2[0]2B2x0[0]2)00h[1](xB1[1]2B1xB2[1]2B1B2x0[1]2)B2h[N1](xB1[N1]2xB2[N1]2x0[N1]2)B10(h[0]xB1[0]h[1]xB1[1]h[N1]xB1[N1])2(h[0]xB2[0]h[1]xB2[1]h[N1]xB2[N1])2(h[0]x0[0]h[1]x0[1]h[N1]x0[N1])20B2(4) 这样就可以将
式(3)化简为
B1N1bby2h[n]xB[n]
B2h[n]xb0n0[n] (5)
计算h[n]xb[n],就是用查找表实现一个映射,然后再将此映射经过相应的二次幂加权,最后即可得到滤波器的输出。 分布式FIR的实现结构
图1给出了分布式FIR滤波器最直接的实现结构,虚线为流水线寄存器。对于小位宽的数
3
据来讲,Da算法不仅速度快,而且所占用的芯片资源也很少。
XB-1[0] „ X1[0] X0[0] LUT +/- 寄存器 XB-1[1] „ X1[1] X0[1] XB-1[N-1] „ X1[N-1] X0[N-1] Z-1
图1 移位加法DA结构
对于式(4)括号中的每一个乘积项都代表了输入变量的某一位与常量的二进制“与”操作,加号代表了算术和操作,指数因子对括号中的值加权。如果事先构造一个查找表,该表储存了括号中所有可能的组合值,就可以通过所有输入变量相对应的组合向量(xb[N-1], xb[N-2], „ ,xb[0])对该表进行寻址。该表结构如表1所示。
表1 构造规则
xb[N-1]xb[N-1] „00 „00 „ „ „ bN-2 „ „ „11 „xb[1]00 „ b1 „1 „ b0 „xb[0]查找表中值的设置0h[0]*0+h[1]*0+„+h[N-1]*0=01h[0]*1+h[1]*0+„+h[N-1]*0=h[0] „h[0]*b0+h[1]*b1+„+h[N-1]*bN-1 „1h[0]+h[1]+„+h[N-1] „ bN-1 „ 在LUT实现分布式算法是,由于LUT的规模随着N的增加而呈指数增加,如果滤波器系数N过多,则查表的规模十分庞大。为了减小规模,可以利用部分表计算。由于FIR滤波器是线性滤波器,因此低阶滤波器输出可以相加,由此定义一个高阶滤波器的输出。例如,可以把16输入的查找表分割成4个并行的查找表,如图2所示。依次类推,可以将更大的LUT分割成多个小LUT。如果加上流水线,这一结构的改变并不会降低速度,却可以大大减小设计规模。
4
XB-1[0] „ X1[0] X0[0] LUT XB-1[3] „ X1[3] X0[3] +/- 寄存器 XB-1[0] „ X1[0] X0[0] LUT + XB-1[3] „ X1[3] X0[3] XB-1[0] „ X1[0] X0[0] LUT XB-1[3] „ X1[3] X0[3] XB-1[0] „ X1[0] X0[0] LUT XB-1[3] „ X1[3] X0[3] Z-1
图2 简化规模的DA结构
三、FIR滤波器的具体设计方法
本设计是使用Verilog实现一个8阶对称系数的FIR滤波器,其系数分别是41,132,341,510,341,132,41。
该本滤波器的输入为12比特,先把相同系数对应的数据相加,输入到DA滤波器的数据经过符号位的扩展后变成13比特。这样可以看成是一个4阶的FIR滤波器,减小了构造表的复杂度。
设计程序:
module fir1(clk,reset,fir_in,fir_in_reg,fir_out,divfre_count_4b,divfre13_clk);
parameter S0=1'd0; //初始状态 parameter S1=1'd1; //处理状态
5
input clk; input reset;
input[11:0]fir_in;
output[12:0]fir_out; output[11:0]fir_in_reg;
output[3:0]divfre_count_4b; output divfre13_clk;
reg[12:0]fir_out;
reg[11:0]fir_in_reg; reg[12:0]shift_buf[7:0]; reg[12:0]add_buf[3:0];
//reg[12:0]state_shift_buf[4-1:0]; reg[12:0]state_shift_buf0; reg[12:0]state_shift_buf1; reg[12:0]state_shift_buf2; reg[12:0]state_shift_buf3;
wire[3:0]table_4b;
wire[11:0]table_out_12b;
reg[12:0]sum; reg STATE;
reg[3:0]divfre_count_4b; reg divfre13_clk;
integer i,j,k,l,m,n,p;
always@(posedge clk or negedge reset) begin
if(!reset) begin
divfre13_clk<=1'b0;
divfre_count_4b<=4'b0000; end else begin
//14分频6
if(divfre_count_4b==13) begin
divfre_count_4b<=4'b0000; divfre13_clk<=1'b1; end else
begin
divfre_count_4b<=divfre_count_4b+1'b1; //计数 divfre13_clk<=1'b0; end end end
always @(posedge clk or negedge reset) //数据输入 begin
if(!reset)
fir_in_reg<=12'b0000_0000_0000; else
if(divfre13_clk)
fir_in_reg<=fir_in; end
always @(posedge clk or negedge reset) begin
if(!reset)
for(i=0;i<=7;i=i+1)
shift_buf[i]<=13'b0000_0000_00000; else if(divfre13_clk) begin for(j=0;j<8-1;j=j+1) shift_buf[j+1]<= shift_buf[j]; shift_buf[0]<={fir_in_reg[11],fir_in_reg}; end end
always @(posedge clk or negedge reset) begin
if(!reset)
for(k=0;k<=4-1;k=k+1)
add_buf[k]<=13'b0000_0000_00000; else
if(divfre13_clk)
for(l=0;l<=3;l=l+1)
add_buf[l]<=shift_buf[l]+shift_buf[7-1];
7
end
always @(posedge clk or negedge reset) //有限状态机初始化,比特移位 begin
if(!reset) begin
//for(m=0;m<=4-1;m=m+1)
//state_shift_buf[m]<=13'b0000_0000_00000; state_shift_buf0<=13'b0000_0000_00000; state_shift_buf1<=13'b0000_0000_00000; state_shift_buf2<=13'b0000_0000_00000; state_shift_buf3<=13'b0000_0000_00000; STATE<=S0; end else
case(STATE)
S0:begin //初始状态
// for(n=0;n<=4-1;n=n+1)
//state_shift_buf[n]<= add_buf[n]; state_shift_buf0<=add_buf[0]; state_shift_buf1<=add_buf[1]; state_shift_buf2<=add_buf[2]; state_shift_buf3<=add_buf[3]; STATE<=S1; end
S1:begin //处理状态
if(divfre_count_4b==4'b1101) STATE<=S0; else
begin
for(p=0;p<=11;p=p+1) begin
state_shift_buf0[p]<=state_shift_buf0[p+1]; state_shift_buf1[p]<=state_shift_buf1[p+1]; state_shift_buf2[p]<=state_shift_buf2[p+1]; state_shift_buf3[p]<=state_shift_buf3[p+1]; end STATE<=S1; end end endcase end
8
assign table_4b[0]=state_shift_buf0[0]; assign table_4b[1]=state_shift_buf1[0]; assign table_4b[2]=state_shift_buf2[0]; assign table_4b[3]=state_shift_buf3[0];
DA_table U_DA(
.table_in_4b(table_4b),
.table_out_12b(table_out_12b) );
wire[26:0]sign_ex={table_out_12b[11],table_out_12b[11],table_out_12b[11], table_out_12b[11],table_out_12b[11],table_out_12b[11], table_out_12b[11],table_out_12b[11],table_out_12b[11], table_out_12b[11],table_out_12b[11],table_out_12b[11], table_out_12b[11],table_out_12b[11],table_out_12b[11], table_out_12b};
always @(posedge clk or negedge reset) begin
if(!reset)
sum<=27'b0; else
if(divfre_count_4b==4'b0000) sum<=27'b0; else
if(divfre_count_4b==4'b1101)
sum<=sum-delta(sign_ex,divfre_count_4b-4'b0001); else
sum<=sum+delta(sign_ex,divfre_count_4b-4'b0001); end
always @(posedge clk or negedge reset) begin
if(!reset)
fir_out<=27'b0; else
if(divfre_count_4b==4'b0000)
fir_out<=sum; //滤波器输出 end
function[13-1:0]delta; //定义移位寄存器左移 input[13-1:0]IQ; input[3:0]pipe;
9
begin
case(pipe)
4'b0000:delta=IQ;
4'b0001:delta={IQ[13-2:0],1'b0}; 4'b0010:delta={IQ[13-3:0],2'b00}; 4'b0011:delta={IQ[13-4:0],3'b000}; 4'b0100:delta={IQ[13-5:0],4'b0000}; 4'b0101:delta={IQ[13-6:0],5'b00000}; 4'b0110:delta={IQ[13-7:0],6'b000000}; 4'b0111:delta={IQ[13-8:0],7'b0000000}; 4'b1000:delta={IQ[13-9:0],8'b00000000}; 4'b1001:delta={IQ[13-10:0],9'b000000000}; 4'b1010:delta={IQ[13-11:0],10'b0000000000}; 4'b1011:delta={IQ[13-12:0],11'b00000000000}; 4'b1100:delta={IQ[13-13:0],12'b000000000000}; //4'b1101:delta={IQ[13-14:0],13'b0000000000000}; //4'b1110:delta={IQ[13-15:0],14'b00000000000000}; //4'b1111:delta={IQ[13-16:0],15'b000000000000000}; default:delta=IQ; endcase end endfunction
endmodule
module DA_table(table_in_4b,table_out_12b);
input [3:0] table_in_4b; output [11:0] table_out_12b; reg[11:0] table_out_12b;
always @(table_in_4b) begin
case(table_in_4b)
4'b0000:table_out_12b=0; 4'b0001:table_out_12b=41; 4'b0010:table_out_12b=132; 4'b0011:table_out_12b=173; 4'b0100:table_out_12b=341; 4'b0101:table_out_12b=382; 4'b0110:table_out_12b=473; 4'b0111:table_out_12b=514;
10
4'b1000:table_out_12b=510; 4'b1001:table_out_12b=551; 4'b1010:table_out_12b=642; 4'b0011:table_out_12b=683; 4'b1100:table_out_12b=851; 4'b1101:table_out_12b=892; 4'b1110:table_out_12b=983; 4'b1111:table_out_12b=1024; default:table_out_12b=0; endcase end endmodule
为了可以方便的判断程序输出结果的正确性,我们在仿真时采用了几个简单的数据作为采样后的数据输入。分别采用:1,2,3作为输入,则经过三次计算对应的输出应为41,241,728,十六进制数为29h,D6h,28Dh。与乘累加方式FIR滤波算法得出的结果完全一致。 输入后的波形如下图:
11
因篇幅问题不能全部显示,请点此查看更多更全内容