1.滤波器是信号处理中经常使用东西。自己在这两天中,也遇到很多的问题,也不断的理解滤波器的实质,其实就是一个乘累加,
alter 有专门的ip核,我们可以直接使用。但是就算是调用ip核,也会遇到很多的问题,需要破解fir_ip的核,默认的licence可能没有
下面自己简单的记录一下fir ip核的过程。希望可以帮到一些人。
2.首先先建立一个工程。建好如下:
2.打开ip核界面
3.选这个,还有保存路径
4。如下图所示,开始使用fir ip核
5.点击step1,如下图
6.点击Edit coefficient set
7.参数默认,我们设计了一个低通滤波器,采样率10M,截止频率1.25M,一会我们产生一个1M的信号+3M的信号,将此混合的信号进行滤波,使用滤波器之后,会将3M的信号滤掉,保留1M的信号。
8.其他参数默认,然后点击完成Finish
9.进行step2,勾选上,然后finish
10.step3完成,等一会,然后点击Exit
11.Yes
12.然后开始例化ipcore程序
(1)顶层文件
module fir_test
(
input reset_n,
input clk,
input signed [11:0] Xin, //数据输入
output signed [25:0] Yout //滤波后的输出数据
);
wire source_valid, sink_ready;
wire [1:0] source_error;
wire sink_valid = 1'b1;
//采样率10M
fir_ipcore fir_inst
(
.clk (clk), //输入,时钟信号
.reset_n (reset_n), //输入,低电平有效复位
.ast_sink_data (Xin), //输入,采样输入数据
.ast_sink_valid (sink_valid), //输入,置1时向FIR滤波器输入数据
.ast_source_ready (1'b1), //输入,源准备好
.ast_sink_error (2'd0), //输入,标识信宿端出现的错误
.ast_source_data (Yout), //输出,滤波器输出,位宽与设计的滤波器参数有关
.ast_sink_ready (sink_ready), //输出,
.ast_source_valid (source_valid), //输出,FIR输出数据有效时该信号置位
.ast_source_error (source_error) //输出,标识信源端出现的错误
);
endmodule
(2)testbench文件
`timescale 1 ns/1 ns
module fir_tb();
//变量
reg clk ;
reg rst_n;
wire [25:0] dout;
//时钟周期,单位为ns,可在此修改时钟周期。
parameter CYCLE = 20;
//复位时间,此时表示复位3个时钟周期的时间。
parameter RST_TIME = 3 ;
//生成本地时钟50M
initial begin
clk = 1;
forever
#(CYCLE/2)
clk=~clk;
end
//产生复位信号
initial begin
rst_n = 1;
#2;
rst_n = 0;
#(CYCLE*RST_TIME);
rst_n = 1;
end
parameter data_num = 1000; // 读取数据的个数
parameter BUF_SIZE = 12; // 保证能存放字符的最大值,位宽
// 从外部读取txt文件
reg [BUF_SIZE-1:0] read_buf[0:data_num -1];
reg [BUF_SIZE-1:0] din;
integer i = 0;
// 读取文本信息将文本信息放到read_buf中
initial $readmemh("C:/Users/USER/Desktop/alter_fir/src/din.txt", read_buf);
//显示读取的内容
initial begin
#(CYCLE);
$display("Content of read_buf after reading data file:");
for(i = 0; i<data_num; i = i+1)begin
#(CYCLE);
din = read_buf[i];
$display("%d:%d", i, read_buf[i]); //以十进制显示
end
end
// 将数据保存到txt中
integer file_out;
initial
begin
file_out = $fopen("C:/Users/USER/Desktop/alter_fir/src/dout.txt");
if (!file_out) begin
$display("can't open file");
$finish;
end
end
wire signed [25:0] dout_s = dout; //要写入的信号
wire rst_write = clk & rst_n; //复位期间不应写入数据
always @ (posedge rst_write)
$fdisplay(file_out, "%d", dout_s);
//待测试的模块例化
fir_test fir_test_uut(
.reset_n (rst_n),
.clk (clk ),
.Xin (din),
.Yout (dout)
);
endmodule
其中testbench中用到了txt文件的读写,还有就是txt中文件的产生
13.我们将使用quartus+modelsim的联合仿真,在这个界面,设置测试文件,如果不会联合仿真,可以看看正点原子的课程,其中有讲解
14.开始仿真
15运行20us
16运行结果
17,src中dout文件,是滤波之后的结果
18.将结果放到matlab中分析,我们可以看到1,2两张图是使用matlab的滤波器的结果,3.4是刚才dout文件的结果,
下面是matlab的程序
clc;
close all;
%产生1M+3M的信号,作为fpga的低通滤波器测试信号
fs=10e+6;
width=7; %rom的位宽
f1=1e+6; %1M的信号
f2=3e+6; %3M的信号
T=1e-4;
n=round(T*fs);
t=linspace(0,T,n);
f=linspace(-fs/2,fs/2,n);
y_sin_1m = round(sin(2*pi*f1*t)*(2^(width-1)-1))+100;
y_sin_3m = round(sin(2*pi*f2*t)*(2^(width-1)-1))+100;
y=(y_sin_1m+y_sin_3m); %混合的信号
Hd=lowpass1M;
y_after=filter(Hd,y);
ff=linspace(-fs/2,fs/2,length(y_after));
fft_y=fftshift(fft(y_after));
figure;
plot(ff,abs(fft_y));
title('matlab 产生信号的频谱');
figure;
plot(y_after);
title('matlab 产生的信号');
%将信号写入data.txt.用在testbench中
fid = fopen('data.txt','w');
fprintf(fid,'%x\n',y); %以十六进制写入
fclose(fid);
%将fpga产生的数据,分析信号和频谱
[data]=textread('dout.txt','%d');
S_1=data;
ff=linspace(-fs/2,fs/2,length(data));
%对测试中频信号进行混频
fft_y=fftshift(fft(S_1));
figure;
plot(ff,abs(fft_y));
title('altera fir ip 滤波信号的频谱');
figure;
plot(data);
title('altera fir ip 滤波的信号');
我的文件格式
下面是全部例程的百度云盘