赞
踩
本设计需要实现基于FPGA的FIR低通滤波,采样频率5MHz,截止频率100kHz,利用Matlab设计FIR滤波器系数,并生成测试数据保存至txt文件。在Quartues ii中编写FIR滤波器模块,联合Modelsim进行功能仿真,观察滤波效果。
本设计分为两个部分,一个是MATLAB中测试数据的产生和FIR滤波器的设计及验证;另一部分是Quartues ii中基于Verilog的FIR滤波器模块及testbench编写。
用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所示
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);
在MATLAB中用filterdesigner命令调出滤波器设计工具,界面如图2
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,可以看到高频成分衰减了很多。
代码如下:
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所示,
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。