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

相关推荐
尤老师FPGA15 小时前
HDMI数据的接收发送实验(二十)
fpga开发
千寻xun1 天前
三、实战篇-NVME SSD控制之FPGA实现(一)
fpga开发·nvme ssd·nvme协议
XMAIPC_Robot1 天前
软硬协同实时控制|RK3588业务调度+FPGA硬件时序,ethercat实现半导体设备微秒级响应(125us)
linux·arm开发·人工智能·fpga开发
upper20201 天前
从零开始设计riscv cpu记录之七
fpga开发·riscv·riscv设计·btb·分支预测
ARM|X86+FPGA工业主板厂家2 天前
AI视觉跟随运动控制实战|RK3588 NPU检测+FPGA EtherCAT多轴联动精准跟随方案,适用于半导体视觉对位等
人工智能·fpga开发·硬件工程·ethercat·实时系统
XMAIPC_Robot2 天前
RK3588+FPGA半导体设备量产踩坑大全|发热、时序漂移、推理抖动、成像干扰、EMC干扰方案
人工智能·嵌入式硬件·fpga开发·arm+fpga
凡亿卓达方案设计2 天前
FPGA硬件开发怎么选靠谱方案商?
fpga开发
Eloudy2 天前
QSFP28、RoCEv2、RFSoC-4x2 数据传输与器件链路
网络·fpga开发·rocev2
Echo_cy_3 天前
基于ZYNQ-7000的Ethernet驱动配置
linux·驱动开发·嵌入式硬件·fpga开发·ethernet·zynq
現実君3 天前
关于MCU下位替换FPGA的经验与方案
单片机·嵌入式硬件·fpga开发