流水线 FIR 滤波器的verilog实现

滤波器信号处理中比较常用的滤波器,这是一个基于流水线的FIR滤波器

//fir filter
//data witdh: 16
//filter coeff :-0.0003706  -0.0011344  -0.0018156  -0.0020642  -0.0012814   0.0010011   0.0045544   0.0080695   0.0093324   0.0061059  -0.0025289   -0.014965   -0.026692   -0.031215   -0.022162   0.0040632    0.046173    0.097395     0.14687     0.18274     0.19584     0.18274     0.14687    0.097395    0.046173   0.0040632   -0.022162   -0.031215   -0.026692   -0.014965  -0.0025289   0.0061059   0.0093324   0.0080695   0.0045544   0.0010011  -0.0012814  -0.0020642  -0.0018156  -0.0011344  -0.0003706
//model by crazyalpha (@github)
//email: [email protected]

module fir_filter(clk, data_in, fil_out);

  parameter dat_width = 16;
  parameter fil_len = 40;

  input clk;
  input [dat_width-1 : 0] data_in;
  output [dat_width-1 : 0] fil_out;

  wire [dat_width-1 :0] coef[(fil_len+1)>>1 :0];

  //filter coefficient
  assign coef[0] = -12;
  assign coef[1] = -37;
  assign coef[2] = -59;
  assign coef[3] = -68;
  assign coef[4] = -42;
  assign coef[5] = 33;
  assign coef[6] = 149;
  assign coef[7] = 264;
  assign coef[8] = 306;
  assign coef[9] = 200;
  assign coef[10] = -83;
  assign coef[11] = -490;
  assign coef[12] = -875;
  assign coef[13] = -1023;
  assign coef[14] = -726;
  assign coef[15] = 133;
  assign coef[16] = 1513;
  assign coef[17] = 3191;
  assign coef[18] = 4813;
  assign coef[19] = 5988;
  assign coef[20] = 6417;

  //input latch
  reg [dat_width-1 :0] data_tmp;
  always @(posedge clk)
  begin
      data_tmp <= data_in;
  end
  //multiply
  wire [dat_width*2-1 :0] m_result[(fil_len+1)>>1 :0];
  genvar j;
  generate for(j=0; j<=(fil_len+1)>>1; j=j+1)
  begin:filter1
      signed_mult signed_mult_inst(.dataa(data_tmp), .datab(coef[j]),.result(m_result[j]));
  end
  endgenerate

  //get sum
  integer i;
  reg [dat_width*2-1:0] fil_reg[fil_len:0];
  always @(posedge clk)
  begin
 	fil_reg[0] <= m_result[0];
	 	for(i=1; i<(fil_len+1)>>1; i=i+1)
			fil_reg[i] <= fil_reg[i-1] + m_result[i];	
		for(i=(fil_len+1)>>1; i<=fil_len; i=i+1)
			fil_reg[i] <= fil_reg[i-1] + m_result[fil_len-i];
  end

  //output
  wire [dat_width*2-1:0] filout_tmp = fil_reg[fil_len];
  assign fil_out =filout_tmp[dat_width*2-2:dat_width-1 ];
endmodule

//this signed_mult can(should) be replaced by megacore function
module signed_mult(dataa,datab,result);
  parameter  datin_width = 16;
  input [datin_width-1 :0]dataa, datab;
  output[datin_width*2-1 :0] result;
  assign result ={ {datin_width{dataa[datin_width-1]}}, dataa } * { {datin_width{datab[datin_width-1]}},datab };
endmodule     

以上滤波器是在modelsim中实现的,以下是testbench

`timescale 1ns/1ns;
module fir_testbench;
  
  parameter dat_width = 16;
  
  reg clk;
  reg [dat_width-1 :0] dat;
  
  wire[dat_width-1 :0] fil_o;

  integer handle1;
  reg fs;
  initial
  begin//sequence block    
  	 handle1 =$fopen("fsave.txt"); 
  	 #1080 fs = 1; 	//fir filter outputs  first data 
    #100000 fs=0;
    $fclose(handle1);
    $stop;
  end 
  initial 
  fork    //synchrous block
    
    dat = 0;
    clk =0;
    forever #10 clk=~clk;  
  join
  
  integer seed;
  
  always @(posedge clk )  
  begin
    dat <= $random(seed);  //generate a random ,
    if(fs == 1)
      $fwrite(handle1,"%d  %d \n",dat,fil_o);
  end
    
    
  fir_filter fir_filter_inst(clk, dat, fil_o);
  
endmodule

在testbench中采用随机数作为滤波器的输入,进行仿真处理,并将滤波器的输入和输出都保存在文件中,以便于进行 MATLAB处理。在Matlab中将保存的数据读出,再进行计算,并与仿真的结果进行比较对,以验证其正确性

clear;

file_name='fsave.txt';
fid = fopen(file_name,'r');
c = fscanf(fid,'%d');
fclose(fid);
for i=1: length(c)
    if(c(i)>32767)
        b(i) =  c(i)-65536;
    else b(i) =  c(i);
    end
end
d1=b(1:2:end);
d2=b(2:2:end);
stg=40;
wn=fir1(stg,10/51.2);
wpara=int32(32768*wn);
for i= 1: (length(d1)-stg)
    e(i)=sum(wpara.*int32(d1(i:i+stg)));
end
f=int16(e/32768);
m1=d2(stg+3:end);
m2=f(1:end-2);
n=int32(m1)-int32(m2);
subplot(3,1,1);
plot(m2);
subplot(3,1,2);
plot(m1);
subplot(3,1,3);
plot(n);


比较的结果如下图,第一图是MATLAB滤波的结果,第二图是Modelsim仿真滤波输出的结果,第三图两者结果相减。从第三图可以看出两者的计算结果最大有误差为1,这是matlab浮点运算与Modelsim定点运算方式不完全一致带来的差别。

流水线 FIR 滤波器的verilog实现_第1张图片

 

你可能感兴趣的:(流水线 FIR 滤波器的verilog实现)