基于FPGA的FIR滤波器的实现(5)— 并行结构FIR滤波器的FPGA代码实现

这篇具有很好参考价值的文章主要介绍了基于FPGA的FIR滤波器的实现(5)— 并行结构FIR滤波器的FPGA代码实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

三、并行结构的FPGA实现

并行结构,并行实现滤波器的累加运算,即并行将具有对称系数的输入数据进行相加,而后采用多个乘法器并行实现系数与数据的乘法运算,最后将所有乘积结果相加输出。这种结构具有最高的运行速度,因不需要累加运算,因此系数时钟频率可以与数据输出时钟频率保持一致。
与串行结构相比,更高的速度付出的是成倍的硬件资源的代价。
基于FPGA的FIR滤波器的实现(5)— 并行结构FIR滤波器的FPGA代码实现

设计实例

设计一个15阶的低通线性相位FIR滤波器,采用布莱克曼窗函数设计,截止频率为500Hz,采样频率为2000Hz;采用FPGA实现并行结构的滤波器,系数的量化位数为12bit,输入数据位宽为12bit,输出数据位宽为29bit,系统时钟2000Hz。

1、matlab参数与数据

FIR滤波器参数与串行结构实现的完全相同,请参照前一篇文章
链接: 基于FPGA的FIR滤波器的实现(4)— 串行结构FIR滤波器的FPGA代码实现

2、使用Verilog编写并行结构的FIR滤波器

  • RTL代码(需要先将matlab产生的noise_B和sin_B添加到工程目录下的simulation/modelsim文件夹中)
module FirParallel(
	input wire clk,
	input wire rst_n,
	input signed [11:0]Xin,
	output signed [28:0]Yout
);

	reg signed[11:0]Xin_reg[15:0];
	reg [3:0]i,j;
	
	//将数据存入移位寄存器
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		begin
			for(i=0;i<15;i=i+1)
				Xin_reg[i] = 12'd0;
		end
	else
		begin	//与串行结构不同,此处不用判断计数器状态
			for(j=0;j<15;j=j+1)
				Xin_reg[j+1] <= Xin_reg[j];
			Xin_reg[0] <= Xin;
		end
		
	//将对称系数的输入数据相加,同时将对应的滤波器系数送入乘法器
	//为了进一步提高运行速度,另外增加了一级寄存器
	reg signed[12:0]Add_reg[7:0];
	
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		begin
			for(i=0;i<8;i=i+1)
				Add_reg[i] = 13'd0;
		end
	else
		begin
			for(i=0;i<8;i=i+1)
				Add_reg[i] = {Xin_reg[i][11],Xin_reg[i]} + {Xin_reg[15-i][11],Xin_reg[15-i]};
		end

	//与串行结构不同,另外需要实例化8个乘法器IP核
	//实例化有符号数乘法器IP核mult
	wire signed[11:0]coe[7:0];		//滤波器为12bit量化数据
	wire signed[24:0]Mout[7:0];	//乘法器输出为25bit数据
	
	assign coe[0] = 12'h000;
	assign coe[1] = 12'hffd;
	assign coe[2] = 12'h00f;
	assign coe[3] = 12'h02e;
	assign coe[4] = 12'hf8b;
	assign coe[5] = 12'hef9;
	assign coe[6] = 12'h24e;
	assign coe[7] = 12'h7ff;
	
	mult mult_inst0(
		.clock(clk),
		.dataa(coe[0]),
		.datab(Add_reg[0]),
		.result(Mout[0])
	);
	
	mult mult_inst1(
		.clock(clk),
		.dataa(coe[1]),
		.datab(Add_reg[1]),
		.result(Mout[1])
	);
	
	mult mult_inst2(
		.clock(clk),
		.dataa(coe[2]),
		.datab(Add_reg[2]),
		.result(Mout[2])
	);
	
	mult mult_inst3(
		.clock(clk),
		.dataa(coe[3]),
		.datab(Add_reg[3]),
		.result(Mout[3])
	);
	
	mult mult_inst4(
		.clock(clk),
		.dataa(coe[4]),
		.datab(Add_reg[4]),
		.result(Mout[4])
	);
	
	mult mult_inst5(
		.clock(clk),
		.dataa(coe[5]),
		.datab(Add_reg[5]),
		.result(Mout[5])
	);
	
	mult mult_inst6(
		.clock(clk),
		.dataa(coe[6]),
		.datab(Add_reg[6]),
		.result(Mout[6])
	);
	
	mult mult_inst7(
		.clock(clk),
		.dataa(coe[7]),
		.datab(Add_reg[7]),
		.result(Mout[7])
	);
	
	//对滤波器系数与输入数据的乘法结果进行累加,并输出滤波后的数据
	//与串行结构不同,此处在一个时钟周期内直接将所有乘法器结果相加
	reg signed[28:0]sum;
	reg signed[28:0]yout;
	reg [3:0]k;
	
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		begin
			sum = 29'd0;
			yout <= 29'd0;
		end
	else
		begin
			yout <= sum;
			sum = 29'd0;
			for(k=0;k<8;k=k+1)
				sum = sum + Mout[k];
		end
	
	assign Yout = yout;

endmodule 
  • 仿真测试模块
`timescale 1ns/1ns


module FirParallel_tb;

	reg clk;
	reg rst_n,write_en;		
	reg [11:0]Xin;
	wire [28:0]Yout;
	wire clk_data;   //数据时钟,速率为时钟的八分之一
	

	FirParallel FirParallel_inst(
		.clk(clk),
		.rst_n(rst_n),				
		.Xin(Xin),		//数据输入频率为2khz
		.Yout(Yout)	//滤波后的输出数据
	);
	
	parameter clk_period = 500000;		//设置时钟信号周期/频率:2KHz
	parameter data_num = 2000;			//仿真数据长度
	parameter time_sim = data_num*clk_period;	//仿真时间
	
	initial clk=1'b1;
	always #(clk_period/2) clk=~clk;
	
	initial begin
		rst_n=1'b0;
		write_en=1'b0;
		#20000 rst_n = 1'b1;
		write_en=1'b1;
		#time_sim $stop;
		Xin = 12'd10;
	end
	
	
	//从外部文件读入数据作为测试激励
	integer Pattern;
	reg [11:0]stimulus[1:data_num];
	initial begin
		//$readmemb("noise_B.txt",stimulus);
		$readmemb("sin_B.txt",stimulus);
		Pattern = 0;
		repeat(data_num)
			begin
				Pattern = Pattern + 1;
				Xin = stimulus[Pattern];
				#clk_period;
			end
	end
		
	//将仿真数据dout写入外部文件中
	integer file_out;
	initial begin
		//file_out = $fopen("noise_out.txt");
		file_out = $fopen("sout.txt");
		if(!file_out)
		begin
			$display("could not open file!");
			$finish;
		end
	end
	
	wire rst_write;
	wire signed [28:0]dout_s;
	assign dout_s = Yout;
	assign rst_write = clk & (rst_n);
	always @(posedge rst_write)
		$fdisplay(file_out,"%d",dout_s);
	
endmodule 
  • 仿真波形图
    基于FPGA的FIR滤波器的实现(5)— 并行结构FIR滤波器的FPGA代码实现

3、使用matlab将产生的程序进行仿真验证

  • M程序:
%E4_7_NoiseAndCarrierOut.M
f1=200;       %信号1频率为200Hz
f2=800;       %信号2频率为800Hz
Fs=2000;      %采样频率为2KHz
N=12;         %量化位数

%从文本文件中读取数据
%测试输入数据分别放在Noise_in和S_in变量中
fid=fopen('C:\matlab work\fir1_1\filterCoe\noise.txt','r');
[Noise_in,N_n]=fscanf(fid,'%lg',inf);
fclose(fid);

fid=fopen('C:\matlab work\fir1_1\filterCoe\sin.txt','r');
[S_in,S_n]=fscanf(fid,'%lg',inf);
fclose(fid);

%滤波后的输出结果数据分别放在Noise_out和S_out变量中
fid=fopen('C:\matlab work\fir1_1\filterCoe\noise_out.txt','r');
[Noise_out,N_count]=fscanf(fid,'%lg',inf);
fclose(fid);

fid=fopen('C:\matlab work\fir1_1\filterCoe\sout.txt','r');
%fid=fopen('C:\matlab work\fir1_1\filterCoe\E4_7_Sout.txt','r');
[S_out,S_count]=fscanf(fid,'%lg',inf)
fclose(fid);

%归一化处理
Noise_out=Noise_out/max(abs(Noise_out));
S_out=S_out/max(abs(S_out));
Noise_in=Noise_in/max(abs(Noise_in));
S_in=S_in/max(abs(S_in));

%求信号的幅频响应
out_noise=20*log10(abs(fft(Noise_out,1024))); out_noise=out_noise-max(out_noise);
out_s=20*log10(abs(fft(S_out(150:length(S_out)),1024))); out_s=out_s-max(out_s);

in_noise=20*log10(abs(fft(Noise_in,1024))); in_noise=in_noise-max(in_noise);
in_s=20*log10(abs(fft(S_in,1024))); in_s=in_s-max(in_s);
%滤波器本身的幅频响应
hn=black_fpga;
m_hn=20*log10(abs(fft(hn,1024))); m_hn=m_hn-max(m_hn);

%设置幅频响应的横坐标单位为Hz
x_f=[0:(Fs/length(out_noise)):Fs/2];
%只显示正频率部分的幅频响应
mf_noise=out_noise(1:length(x_f));
mf_s=out_s(1:length(x_f));
mf_in_noise=in_noise(1:length(x_f));
mf_in_s=in_s(1:length(x_f));
mf_hn=m_hn(1:length(x_f));
%绘制幅频响应曲线
figure(1);
subplot(211);
plot(x_f,mf_in_noise,'--',x_f,mf_noise,'-',x_f,mf_hn,'--');
xlabel('频率(Hz)');ylabel('幅度(dB)');title('FPGA仿真白噪声信号滤波前后的频谱');
legend('输入信号频谱','输出信号频谱','滤波器响应');
grid;
subplot(212);
plot(x_f,mf_in_s,'--',x_f,mf_s,'-',x_f,mf_hn,'--');
xlabel('频率(Hz)');ylabel('幅度(dB)');title('FPGA仿真合成单频信号滤波前后的频谱');
axis([0 1000 -100 0]);
legend('输入信号频谱','输出信号频谱','滤波器响应');
grid;

%绘制时域波形
%设置显示数据范围
t=0:1/Fs:50/Fs;t=t*1000; 
t_in_noise=Noise_in(1:length(t));
t_in_s=S_in(1:length(t));
t_out_noise=Noise_out(1:length(t));
t_out_s=S_out(1:length(t));
figure(2);
subplot(211);
plot(t,t_in_noise,'--',t,t_out_noise,'-');
xlabel('时间(ms)');ylabel('幅度');title('FPGA仿真白噪声信号滤波前后的时域波形');
legend('输入信号波形','输出信号波形');
grid;
subplot(212);
plot(t,t_in_s,'--',t,t_out_s,'-');
xlabel('时间(ms)');ylabel('幅度');title('FPGA仿真合成单频信号滤波前后的时域波形');
legend('输入信号波形','输出信号波形');
grid;
  • 仿真波形图
    基于FPGA的FIR滤波器的实现(5)— 并行结构FIR滤波器的FPGA代码实现
    基于FPGA的FIR滤波器的实现(5)— 并行结构FIR滤波器的FPGA代码实现

可以看到,并行结构的FIR滤波器设计成功,并且性能相比于串行结构更好,设计成功。文章来源地址https://www.toymoban.com/news/detail-435364.html

到了这里,关于基于FPGA的FIR滤波器的实现(5)— 并行结构FIR滤波器的FPGA代码实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FIR滤波器的FPGA实现【IP核实现版】

    本文使用FPGA来实现FIR滤波器设计,设计中使用的DDS、乘法器与FIR滤波器均采用IP core进行实现,实现效果是将3MHz和4MHz的正弦信号混频后使用FIR低通滤波器滤除7MHz信号得到1MHz的信号。 首先用两个DDS核生成3MHz以及4MHz的正弦波信号。 注意:此处的dds的命名要和代码中对应,系统

    2024年02月04日
    浏览(52)
  • 利用FPGA实现全串行低通FIR滤波器

    设计一个15阶(长度为16)的具有线性相位低通FIR滤波器,采用布拉克曼窗函数设计,截止频率为500HZ,抽样频率为2000HZ;采用FPGA实现全串行FIR滤波器,系数的量化位数为12比特,输入数据位数为12比特,输出数据位数为29比特,系统时钟为16KHZ 设计思路 :首先采用MATLAB根据要

    2024年02月07日
    浏览(50)
  • 基于FPGA的FIR数字滤波器设计(quartus和vivado程序都有)。

    基于FPGA的FIR数字滤波器设计(quartus和vivado程序都有)。 附: 1.配套quartus从MATLAB系数生成直到仿真成功说明文档。 2.配套仿真出波形(图1)的视频。      

    2024年02月10日
    浏览(49)
  • 解析使用FPGA逻辑实现FIR滤波器的几种架构

    有限脉冲响应(finite impulse response,FIR)数字滤波器         FIR滤波器的实质就是输入序列与系统脉冲响应的卷积,即:         其中,N为滤波器的阶数,也即抽头数;x(n)为第n个输入序列;h(n)为FIR滤波器的第n级抽头系数。         FIR滤波器基本结构如下:      

    2024年02月08日
    浏览(41)
  • FPGA 的数字信号处理:Verilog 实现简单的 FIR 滤波器

    该项目介绍了如何使用 Verilog 实现具有预生成系数的简单 FIR 滤波器。 不起眼的 FIR 滤波器是 FPGA 数字信号处理中最基本的模块之一,因此了解如何将具有给定抽头数及其相应系数值的基本模块组合在一起非常重要。因此,在这个关于 FPGA 上 DSP 基础实用入门的教程中,将从一

    2024年02月09日
    浏览(50)
  • FPGA设计FIR滤波器低通滤波器,代码及视频

    名称:FIR滤波器低通滤波器 软件:Quartus 语言:Verilog/VHDL 本资源含有verilog及VHDL两种语言设计的工程,每个工程均可实现以下FIR滤波器的功能。 代码功能: 设计一个8阶FIR滤波器(低通滤波器),要求截止频率为20KHz,使用线性相位结构。 参数设计方法: 使用matlab软件设计滤

    2024年02月08日
    浏览(53)
  • FIR滤波器简述及FPGA仿真验证

    数字滤波器的设计,本项目做的数字滤波器准确来说是FIR滤波器。 FIR滤波器(有限冲激响应滤波器),与另一种基本类型的数字滤波器——IIR滤波器(无限冲击响应滤波器)相对应,其实就是将所输入的信号都看成是离散的,用离散的冲击信号代替实际的信号。对于FIR滤波器

    2024年02月09日
    浏览(50)
  • FPGA 的 DSP:Verilog 中的简单 FIR 滤波器

    本项目介绍如何用 Verilog 实现一个带有预生成系数的简单 FIR 滤波器。 简陋的 FIR 滤波器是 FPGA 数字信号处理中最基本的构建模块之一,因此了解如何利用给定的抽头数和相应的系数值组装一个基本模块非常重要。因此,在这个关于在 FPGA 上入门 DSP 基础知识的实用方法迷你系

    2024年03月17日
    浏览(42)
  • FIR滤波器的Verilog实现

    FIR滤波器是非递归型滤波器的简称,又叫 有限长单位冲激响应滤波器 。带有常系数的FIR滤波器是一种LTI(线性时不变)数字滤波器。冲激响应是有限的意味着在滤波器中没有发反馈。长度为N的FIR输出对应于输入时间序列x(n)的关系由一种有限卷积和的形式给出,具体形式如下:

    2024年02月11日
    浏览(35)
  • STM32 FIR实时数字滤波器实现

    首先是生成不同周期的正弦波:         由于定时器设置为250us进入一次中断,每秒可进入中断4000次,为了生成25HZ的正弦信号,一个周期内生成160个数据;为了生成200HZ的正弦信号,一个周期内生成20个数据,故代码如下:     sin_1=arm_sin_f32(3.141592654*i/80)+1;//25HZ 信号   

    2024年02月14日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包