基于Quartues ii和Modelsim的FIR滤波器仿真

该博客介绍了如何使用MATLAB设计FIR低通滤波器,生成测试数据并利用filterdesigner工具设置滤波器参数。在QuartusII中,使用Verilog编写了FIR滤波器模块,并在Modelsim中进行了功能仿真,展示了滤波后的波形效果。整个流程包括MATLAB中的滤波器设计、数据量化、滤波器系数导出,以及QuartusII中的硬件描述语言实现和仿真验证。
摘要由CSDN通过智能技术生成

基于Quartues ii和Modelsim的FIR滤波器仿真

设计需求

本设计需要实现基于FPGA的FIR低通滤波,采样频率5MHz,截止频率100kHz,利用Matlab设计FIR滤波器系数,并生成测试数据保存至txt文件。在Quartues ii中编写FIR滤波器模块,联合Modelsim进行功能仿真,观察滤波效果。

设计思路

本设计分为两个部分,一个是MATLAB中测试数据的产生和FIR滤波器的设计及验证;另一部分是Quartues ii中基于Verilog的FIR滤波器模块及testbench编写。

设计过程

MATLAB生成测试数据

用MATLAB产生5kHz和800kHz的混频信号,代码如下:

Fs = 5000000; %采样频率决定了两个正弦波点之间的间隔
N = 8192;     %采样点数
N1 = 0 : 1/Fs : N/Fs-1/Fs; %以频率Fs采8192个点的数据
s = sin(5000*2*pi*N1) + sin(800000*2*pi*N1)+3;

figure(1);
plot(N1,s)

得到的波形如图1所示

图1. 混频信号波形
将波形数据进行量化,并转换为十六进制保存到mem.txt中,作为原始数据导入到Modelsim中对所写的FIR滤波器模块进行测试。MATLAB代码如下:
fidc = fopen('E:\fault_detection_code\FIR_test1\mem.txt','wt');  
%将结果写入mem.txt文件,便于modesim使用
for x = 1 : N
   fprintf(fidc,'%x\n',round((s(x)/10)*4096));
end 
fclose(fidc);  

利用filterdesigner工具设计FIR滤波器

在MATLAB中用filterdesigner命令调出滤波器设计工具,界面如图2
图2 滤波器设计工具

图2. 滤波器设计工具

选择低通FIR滤波器,选择Hamming窗,设定阶数10阶,采样频率5MHz,截止频率100kHz,点击设计滤波器可以看到滤波器的幅频特性曲线。选择文件->导出,将滤波器系数导出到工作区。设计完成后生成的MATLAB代码,如下:

function Hd = test_filter_kaiser
%TEST_FILTER_KAISER 返回离散时间滤波器对象。

% MATLAB Code
% Generated by MATLAB(R) 9.9 and Signal Processing Toolbox 8.5.
% Generated on: 16-Sep-2022 11:01:37

% FIR Window Lowpass filter designed using the FIR1 function.

% All frequency values are in kHz.
Fs = 5000;  % Sampling Frequency

N    = 10;       % Order
Fc   = 100;      % Cutoff Frequency
flag = 'scale';  % Sampling Flag
Beta = 0.5;      % Window Parameter

% Create the window vector for the design algorithm.
win = kaiser(N+1, Beta);

% Calculate the coefficients using the FIR1 function.
b  = fir1(N, Fc/(Fs/2), 'low', win, flag);
Hd = dfilt.dffir(b);

% [EOF]

调用生成的滤波器函数对前文生成的混频信号进行滤波,

H=test_filter1;
d=filter(H,s);

figure(2);
plot(N1,d)

得到结果如图3所示,对比图1和图3,可以看到高频成分衰减了很多。
在这里插入图片描述

图3. 滤波后的波形

将设计的FIR滤波器抽头系数导出来。如下:
导出的FIR滤波器抽头系数为
0.0138133379804440 ,
0.0296928583924488 ,
0.0717059583915281 ,
0.124585240157610 ,
0.167915751691329 ,
0.184573706773281 ,
0.167915751691329 ,
0.124585240157610 ,
0.0717059583915281 ,
0.0296928583924488 ,
0.0138133379804440,
对其进行量化处理,乘以2^10后取整,得到抽头系数
14,30,73,128,172,189,172,128,73,30,14

在Quartues ii中编写FIR滤波器模块

代码如下:

module FIR_test1(
	input CLK,
	input RSTn,
	input [11:0]FIR_IN,
	output reg [23:0]FIR_OUT
);
	
	

reg[11:0] delay_pipeline1;
reg[11:0] delay_pipeline2;
reg[11:0] delay_pipeline3;
reg[11:0] delay_pipeline4;
reg[11:0] delay_pipeline5;
reg[11:0] delay_pipeline6;
reg[11:0] delay_pipeline7;
reg[11:0] delay_pipeline8;
reg[11:0] delay_pipeline9;
reg[11:0] delay_pipeline10;
reg[11:0] delay_pipeline11;


wire[7:0] coeff1 = 8'd14;	//抽头系数
wire[7:0] coeff2 = 8'd30;
wire[7:0] coeff3 = 8'd73;
wire[7:0] coeff4 = 8'd128;
wire[8:0] coeff5 = 9'd172;
wire[7:0] coeff6 = 8'd189;
wire[7:0] coeff7 = 8'd172;
wire[7:0] coeff8 = 8'd128;
wire[7:0] coeff9 = 8'd73;
wire[7:0] coeff10 = 8'd30;
wire[7:0] coeff11 = 8'd14;

reg signed [23:0] multi_data1 ;//乘积结果
reg signed [23:0] multi_data2 ;
reg signed [23:0] multi_data3 ;
reg signed [23:0] multi_data4 ;
reg signed [23:0] multi_data5 ;
reg signed [23:0] multi_data6 ;
reg signed [23:0] multi_data7 ;
reg signed [23:0] multi_data8 ;
reg signed [23:0] multi_data9 ;
reg signed [23:0] multi_data10 ;
reg signed [23:0] multi_data11 ;


//每到来一个时钟信号,读入一个数据,更新一次delay_pipeline。
always@(posedge CLK or negedge RSTn)
if(!RSTn)
begin
	delay_pipeline1 <= 12'b0 ;
	delay_pipeline2 <= 12'b0 ;
	delay_pipeline3 <= 12'b0 ;
	delay_pipeline4 <= 12'b0 ;
	delay_pipeline5 <= 12'b0 ;
	delay_pipeline6 <= 12'b0 ;
	delay_pipeline7 <= 12'b0 ;
	delay_pipeline8 <= 12'b0 ;
	delay_pipeline9 <= 12'b0 ;
	delay_pipeline10<= 12'b0 ;
	delay_pipeline11<= 12'b0 ;
end
else
begin
	delay_pipeline1 <= FIR_IN;
	delay_pipeline2 <= delay_pipeline1 ;
	delay_pipeline3 <= delay_pipeline2 ;
	delay_pipeline4 <= delay_pipeline3 ;
	delay_pipeline5 <= delay_pipeline4 ;
	delay_pipeline6 <= delay_pipeline5 ;
	delay_pipeline7 <= delay_pipeline6 ;
	delay_pipeline8 <= delay_pipeline7 ;
	delay_pipeline9 <= delay_pipeline8 ;
	delay_pipeline10 <= delay_pipeline9 ;
	delay_pipeline11 <= delay_pipeline10 ;
end


//将输入经过延时的信号和滤波器系数相乘,每到来一个时钟便将一个新的乘积结果更新到multi_data中。这里直接使用“*”,编译后Quartues ii会自动调用乘法器IP核
always@(posedge CLK or negedge RSTn) 
begin
	if(!RSTn)
		multi_data1 <= 23'b0 ;
	else
		multi_data1 <= delay_pipeline1*coeff1 ;
end
		
always@(posedge CLK or negedge RSTn) 
begin
	if(!RSTn)
		multi_data2 <= 23'b0 ;
	else
		multi_data2 <= delay_pipeline2*coeff2 ;
end
		
always@(posedge CLK or negedge RSTn)
begin
	if(!RSTn)
		multi_data3 <= 23'b0 ;
	else
		multi_data3 <= delay_pipeline3*coeff3 ;
end
		
always@(posedge CLK or negedge RSTn) 
begin
	if(!RSTn)
		multi_data4 <= 23'b0 ;
	else
		multi_data4 <= delay_pipeline4*coeff4 ;
end
		
always@(posedge CLK or negedge RSTn) 
begin
	if(!RSTn)
		multi_data5 <= 23'b0 ;
	else
		multi_data5 <= delay_pipeline5*coeff5 ;
end
		
always@(posedge CLK or negedge RSTn)
begin
	if(!RSTn)
		multi_data6 <= 23'b0 ;
	else
		multi_data6 <= delay_pipeline6*coeff6 ;
end
		
always@(posedge CLK or negedge RSTn) 
begin
	if(!RSTn)
		multi_data7 <= 23'b0 ;
	else
		multi_data7 <= delay_pipeline7*coeff7 ;
end
		
always@(posedge CLK or negedge RSTn)
begin
	if(!RSTn)
		multi_data8 <= 23'b0 ;
	else
		multi_data8 <= delay_pipeline8*coeff8 ;
end
		
always@(posedge CLK or negedge RSTn) 
begin
	if(!RSTn)
		multi_data9 <= 23'b0 ;
	else
		multi_data9 <= delay_pipeline9*coeff9 ;
end

always@(posedge CLK or negedge RSTn) 
begin
	if(!RSTn)
		multi_data10 <= 23'b0 ;
	else
		multi_data10 <= delay_pipeline10*coeff10 ;
end

always@(posedge CLK or negedge RSTn)
begin
	if(!RSTn)
		multi_data11 <= 23'b0 ;
	else
		multi_data11 <= delay_pipeline11*coeff11 ;
end


//将乘积累加,累加的结果就是滤波后的信号。
always@(posedge CLK or negedge RSTn)
begin
	if(!RSTn)
		FIR_OUT <= 23'b0 ;
	else
		FIR_OUT <= (multi_data1 + multi_data2 + multi_data3 + multi_data4 +multi_data5 + multi_data6 + multi_data7 + multi_data8 + multi_data9 + multi_data10 + multi_data11)>>10 ;
end
		
endmodule

接下来编写testbench,代码如下:

`timescale 1 ns/ 1 ps
module FIR_test1_tb();
// constants                                           
// general purpose registers
//reg eachvec;
// test vector input registers
reg CLK;
reg [11:0] FIR_IN;
reg RSTn;
reg [11:0] mem[1:8192];//用来存放读入的8192个数据

// wires                                               
wire [23:0]  FIR_OUT;
reg [13:0] i;

// assign statements (if any)                          
FIR_test1 i1 (
// port map - connection between master ports and signals/registers   
	.CLK(CLK),
	.FIR_IN(FIR_IN),
	.FIR_OUT(FIR_OUT),
	.RSTn(RSTn)
);
initial                                                
begin                                                  
// code that executes only once                        
// insert code here --> begin  
	$readmemh("E:/fault_detection_code/FIR_test1/mem.txt",mem);//读入3.1中产生的波形数据文件mem.txt,文件路径注意不要搞错
	RSTn = 0;
	CLK = 0;
	#50 RSTn = 1;
	#1000000 $stop;
                                                       
// --> end                                             
$display("Running testbench");                       
end 

always #100 CLK=~CLK;

always@(posedge CLK or negedge RSTn) //每次时钟到达,给FIR_IN一个输入数据
begin
      if(!RSTn)                                
			FIR_IN <= 12'b0 ;

      else
			FIR_IN <= mem2[i];     
end
 
always@(posedge CLK or negedge RSTn) 
begin
      if(!RSTn)
			i <= 12'd0;
      else
			i <= i + 1'd1;
end
                                                   
//always                                                 
// optional sensitivity list                           
// @(event1 or event2 or .... eventn)                  
//begin                                                  
// code executes for every event on sensitivity list   
// insert code here --> begin                          
                                                       
//@eachvec;                                              
// --> end                                             
//end                                                    
endmodule

FIR滤波器模块和testbench编译完成后,进行RTL仿真,可以得到滤波后的波形,如图4所示,
在这里插入图片描述

图4. RTL仿真结果
  • 10
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值