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

相关推荐
FPGA小迷弟7 分钟前
FPGA状态机设计详解:从Moore到Mealy的完整指南
fpga开发·fpga
zlinear数据采集卡15 小时前
D223的PWM电机控制:6路独立脉冲+加减速算法深度解析
arm开发·stm32·嵌入式硬件·算法·fpga开发·架构
zlinear数据采集卡19 小时前
ZLinear产品线全景对比:D223 vs DABL7606 vs DABL-G511选型指南
arm开发·嵌入式硬件·算法·fpga开发·开源
何事误红尘1 天前
ZYNQ学习FPGA笔记(一):vivado安装、XC7Z045
fpga开发
zlinear数据采集卡2 天前
D223的SRAM硬件记录仪:外部触发与瞬态波形捕获方案
arm开发·嵌入式硬件·fpga开发·开源
szxinmai主板定制专家2 天前
基于 RK3588 + Xilinx Kintex-7 FPGA 异构工业主控板设计方案
arm开发·人工智能·嵌入式硬件·fpga开发·zynq
Rambo.xia2 天前
RFSoC高速采集卡设计项目:一块板卡串联综合优化5大核心技术
单片机·嵌入式硬件·fpga开发
XMAIPC_Robot2 天前
RK3588+STM32:高性能机器人运动控制解决方案,兼顾实时性与AI算力
人工智能·stm32·嵌入式硬件·算法·fpga开发·机器人·arm+fpga
zlinear数据采集卡2 天前
D223的DDS信号发生器:10000点查找表与4通道16位DAC波形输出
arm开发·嵌入式硬件·fpga开发·开源
物质波波波3 天前
WS-RPE:面向边缘物理AI实时特征值计算的硬件工作窃取调度器与冗余PE激活架构
人工智能·fpga开发·架构·系统架构·硬件架构