FIR 数字滤波器 --verilog设计实现

  • FIR 数字滤波器设计
    • 在FPGA实现FIR滤波器时,最常用的是直接型结构,简单方便,在实现直接型结构时,可以选择串行结构/并行结构/分布式结构。
    • 串行结构,即串行实现FIR滤波器的乘累加操作,数据的处理速度较慢。N阶串行FIR滤波器,数据的输入速率=系统处理时钟速率/滤波器长度(N+1),本例程使用7阶串行,系统时钟32MHz,这样的数据输入速率(采样率)为4MHz。

串行FIR数字滤波器

  • 信号说明
    • data_in15:0 :输入信号为0.5MHz叠加1.8MHz信号,采样时钟为4MHz(系统处理时钟/滤波器阶数)16bit量化;
    • h0-h8 :滤波器系数8bit量化,4MHz抽样,低通滤波器(Low Pass Filter,LPF),截止频率为1MHz,窗函数设计。
    • data_out15:0:输出信号为0.5MHz信号,16bit。

    • 数字滤波器系数设计--利用filterDesigner工具设计数字滤波器

    • 在matlab中输入 filterDesigner 打开滤波器设计工具

      filterDesigner

  • 参数配置
    • 选择低通滤波器
    • FIR 滤波器 -函数
    • 指定阶 -7阶
    • blackman窗函数
    • 频率设定:采样率Fs = 4MHz ,滤波器截至频率Fc = 1MHz
  • 参数量化:
    • 选择左下第三个框
    • 选择定点数
    • 选择8bit
    • 点击应用
  • 导出参数
    • 点击File- Export
    • 点击导出系数
    • 在点击目标-xinlinx系数(coe文件)
  • 生成的coe文件包含h0-h7 ,7阶低通滤波器系数8bit。

复制代码
module fir(
	input wire 			clk,        //系统时钟 32MHz
	input wire 			rst_n,      //系统复位信号
	input wire 			data_clk,   //数据时钟 4MHz
	input signed[15:0] 		data_in,    //输入数据16bit, 0.5MHz+1.8MHz信号叠加
	output reg signed[15:0]         data_out    //输出数据16bit, 0.5MHz信号
);

//移位操作,输入数据寄存
      reg signed[15:0] x1;
      reg signed[15:0] x2;
      reg signed[15:0] x3;
      reg signed[15:0] x4;
      reg signed[15:0] x5;
      reg signed[15:0] x6;
      reg signed[15:0] x7;

always @ (posedge data_clk or negedge rst_n)begin
	if(!rst_n)begin
		x1 <= 16'b0;
		x2 <= 16'b0;
		x3 <= 16'b0;
		x4 <= 16'b0;
		x5 <= 16'b0;
		x6 <= 16'b0;
		x7 <= 16'b0;
	end
	else begin
		x1 <= data_in;
		x2 <= x1;
		x3 <= x2;
		x4 <= x3;
		x5 <= x4;
		x6 <= x5;
		x7 <= x6;
	end
end

//滤波器系数h[7:0] 由matlab获得
wire signed[7:0] h0 = 8'h00;
wire signed[7:0] h1 = 8'hfe;
wire signed[7:0] h2 = 8'h13;
wire signed[7:0] h3 = 8'h70;
wire signed[7:0] h4 = 8'h70;
wire signed[7:0] h5 = 8'h13;
wire signed[7:0] h6 = 8'hfe;
wire signed[7:0] h7 = 8'h06;

//计数器实现延时,7阶滤波器,8拍延时
reg [2:0] counter;
always @ (posedge clk or negedge rst_n)begin
	if(~rst_n)begin
		counter <= 3'b0;
	end
	else begin
		counter <= counter + 1'b1;
	end
end 

//数据与滤波器系数相乘
reg signed[15:0] 	mult_a;    //寄存的输入数据
reg signed[7:0] 	mult_b;    //滤波器系数
wire signed[23:0] 	mult_p;    //data_in[15:0] * h[7:0]  
assign mult_p = mult_a * mult_b;

always @ (posedge clk or negedge rst_n)begin
	if(~rst_n)begin
		mult_a <= 16'b0;
		mult_b <= 8'b0;
	end
	else begin
		case(counter)
			3'b000:begin
				mult_a <= data_in;
				mult_b <= h0;
			end
			3'b001:begin
				mult_a <= x1;
				mult_b <= h1;
			end
			3'b010:begin
				mult_a <= x2;
				mult_b <= h2;
			end
			3'b011:begin
				mult_a <= x3;
				mult_b <= h3;
			end
			3'b100:begin
				mult_a <= x4;
				mult_b <= h4;
			end
			3'b101:begin
				mult_a <= x5;
				mult_b <= h5;
			end
			3'b110:begin
				mult_a <= x6;
				mult_b <= h6;
			end
			3'b111:begin
				mult_a <= x7;
				mult_b <= h7;
			end
		endcase
	end
end

//累加求和32bit
reg signed[31:0] data_out_temp;  
 
always @ (posedge clk or negedge rst_n)begin
	if(~rst_n)begin
		data_out_temp <= 32'b0;
		data_out <= 16'b0;
	end
	else begin
		data_out_temp <= data_out_temp + mult_p;
		if(counter == 3'b111)begin
			data_out <= data_out_temp[31:16];   //数据截断,取前16bit
			data_out_temp <= 32'b0;
		end
	end
end 
endmodule

  • 仿真
    • 波形数据产生--由matlab产生数据16bit 数据,4MHz刷新

      %%清内存,关闭窗口 准备工作
      clear
      close all
      clc

      %%signal
      % f(x) = A1sin(w1t+p1) + A2sin(w2t+p2);
      %三要素
      A1 = 1; %幅度1
      A2 = 0.5; %幅度2

      f1 = 0.5; %信号1频率为 0.5MHz
      f2 = 1.8; %信号2频率为 1.8MHz

      Fs = 4; %采样频率为 4MHz
      N = 16; %量化位数 16bit

      w1 = 2pif1; %角频率1
      w2 = 2pif2; %角频率2

      p1 = 0; %相位1
      p2 = 0; %相位2

      %采样
      T = 16;
      %fs = 20*f;
      d = 1/Fs;

      t = -T/2:d:T/2;

      s1 = A1sin(w1t+p1);
      s2 = A2sin(w2t+p2);
      %s2 = A2sin(w2t+p);
      s = s1 +s2;

      save sinwave.txt -ascii s;

      fid= fopen('data_signed.txt','w'); %保存文本文档的文件名
      % fprintf(fid,'%d',data_signed);

      fprintf(fid,'%04x\r\n',typecast(int16(s),'uint16'));
      fclose(fid);

      figure(1)
      subplot(3,1,1);
      plot(t,s1);
      xlabel('时间/s');
      ylabel('幅度');

      subplot(3,1,2);
      plot(t,s2);
      xlabel('时间/s');
      ylabel('幅度');

      subplot(3,1,3);
      plot(t,s);
      xlabel('时间/s');
      ylabel('幅度');

    • testbench

      module tb_fir_filter();
      reg clk;
      reg rst_n;
      reg data_clk;
      reg signed[15:0] data_in;
      wire signed[15:0] data_out;

      initial begin
      dumpfile("wave.vcd"); //生成的vcd文件名称 dumpvars(0,tb_fir_filter ); //tb模块名称
      end

      initial begin
      clk = 1'b0;
      data_clk = 1'b0;
      rst_n = 1'b0;
      #100 rst_n = 1'b1;
      end

      always #16 clk = ~clk; //32MHz
      always #128 data_clk = ~data_clk; //4MHz

      //将matlab生成的数据导入到寄存器中
      parameter data_num = 64; //4个周期
      reg [5:0] addr;
      reg [15:0] mem [0:data_num-1];

      initial begin
      # 100;
      $readmemh("data_signed.txt", mem);
      addr = 6'b0;
      end

      always #10 begin
      data_in = mem[addr][15:0];
      addr = addr + 1'b1;
      end

      fir uut(
      .clk (clk),
      .rst_n (rst_n),
      .data_clk (data_clk),
      .data_in (data_in),
      .data_out (data_out)
      );

      endmodule

相关推荐
zlinear数据采集卡1 小时前
从协议解析到波形实时显示:硬核拆解ZLinear采集卡上位机软件的开发架构
arm开发·单片机·嵌入式硬件·fpga开发·架构·开源
pcjiushizhu2 小时前
ModelSim 仿真时 Simulate 无反应或只显示 Loading 的解决方法:网卡问题排查
fpga开发
FPGA小迷弟5 小时前
vivado中的AXI Interconnect到底应该怎么用,他的底层原理是什么,一篇文档全部理清楚!!!
网络协议·tcp/ip·fpga开发·verilog·fpga
国科安芯14 小时前
ASC4T245S分组双向控制架构深度解析:独立DIR/OE控制、QFN16封装与混合方向总线桥接
单片机·嵌入式硬件·物联网·fpga开发·架构·risc-v
尤老师FPGA1 天前
GT系列2:GT基础架构(二)
fpga开发
想你依然心痛1 天前
电源时序控制:多路电源的上电顺序与监控——复位、看门狗
fpga开发
Eloudy1 天前
hsb fpga/ 目录分析
fpga开发·量子计算
Hello-FPGA1 天前
GPU Direct DMA RDMA 与FPGA 通讯在Jetson 平台的测试表现
fpga开发
落chen4 天前
基于FPGA的串口UART-强化篇
fpga开发·串口·rs232