欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

流水线 FIR 滤波器的verilog实现

程序员文章站 2024-03-24 22:39:28
...

滤波器信号处理中比较常用的滤波器,这是一个基于流水线的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: aaa@qq.com

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实现

 

相关标签: verilog fir filter