FPGA与MATLAB联合仿真FIR滤波器

FPGA与MATLAB联合仿真FIR滤波器

最近在做毕业课题,其中需要用到FIR滤波,所以在实际应用前需要对FIR进行仿真测试,具体步奏如下:

0、用matlab产生FIR滤波器所需参数,并量化为FPGA所需的指定位宽;

1、用matlab产生测试信号,并量化为指定位宽,作为FPGA的输入;

2、利用QuartusII调用FIR IP核,利用第0步产生的参数来设置FIR滤波器;

3、编写test_bench,利用modelsim对FIR进行仿真,并将滤波后数据写入到文本中;

4、将第3步中得到的滤波后数据通过matlab进行fft计算得到信号的频谱,观察滤波效果;

5、分析总结

按照上面的步奏,开始干活。

0、用matlab产生FIR滤波器所需参数,并量化为FPGA所需的指定位宽;

FIR滤波器针对线性相位系统,即信号经过系统后,所有频率都有一个固定的相位延迟,但是各频率成分的信号相对相位不变。而对于非线性相位系统在接受端无法通过只同步某一个频率成分的信号实现同步通带内所有信号的相位,此时可采用IIR滤波器。课题需要,信号的中心频率2.5MHz,采样率25MHz,所以按此设计一款带通滤波器FIR滤波器。
matlab为我们提供的很多窗函数,按性能好坏排序大致如下:凯撒窗>布拉克曼窗>海明窗>汉宁窗>矩形窗;除此之外,万能的matlab还提供了专用数字滤波器工具FDATOOL,这里我采用fdatool进行设计。
在matlab的命令窗口键入fdatool回车即可打开该工具,并设置好滤波器参数,具体如下图所示:
FPGA与MATLAB联合仿真FIR滤波器_第1张图片
值得一提的是,滤波器性能的好坏与指定的阶数有关,即滤波器的抽头系数,滤波器的系数与阶数关系为:抽头系数=指定阶数+1。刚开始设计时不清楚所需阶数,可以用matlab提供的函数来计算[n,f0,m0,w]=firpmord([2300000 2400000 2600000 2700000],[0 1 0],[0.1 0.01 0.1],25000000) 如果不清楚该函数的用法,可以在matlab的命令窗口键入 help firpmord即可查看帮助文件。通过该函数可以计算出n,即fir滤波器要达到指定的要求需要的最小阶数。然后在fdatool中写入该数值即可。
根据要求设计完滤波器后需要对系数进行量化,具体操作是点击fdatool窗口中左边顺数第三个按钮即为量化按钮,如下所示:
FPGA与MATLAB联合仿真FIR滤波器_第2张图片
此处量化为12bit,这和你使用的FPGA目标芯片有关,如果资源多可以选择量化为16bit,但是资源消耗比较严重,一般12bit足够了。最后在Analysis->Filter Coefficeients中查看系数,在File->Export中导出系数,如下所示,一个337阶,338个系数,完成第一步设计。
FPGA与MATLAB联合仿真FIR滤波器_第3张图片

1、用matlab产生测试信号,并量化为指定位宽,作为FPGA的输入;

为了测试FIR滤波器,我们需要产生信号,这里通过matlab产生叠加了1W功率的高斯白噪声,量化位宽为12bit,将其写入到文本文件中,其绘制的波形如下。FPGA与MATLAB联合仿真FIR滤波器_第4张图片

2、利用QuartusII调用FIR IP核,利用第0步产生的参数来设置FIR滤波器;

FIR滤波器本质上是做卷积,即多次乘加运算,在具体实现时有多种结构,分别是:半串行、全串行、并行和分布式,还是和前面一样,具体选择哪一种进行实现,要看你的目标芯片资源大小,如果资源多,需要计算速度快,那么选择并行;如果资源一般,速度要求中等,那么选择分布式,如果资源少,速度不做要求,那么串行就可以了。
打开QuartusII,调用FIR IP核,具体如下所示:
FPGA与MATLAB联合仿真FIR滤波器_第5张图片
点击第一步,配置参数。
FPGA与MATLAB联合仿真FIR滤波器_第6张图片
这一个窗口设置FPGA型号、系数位宽(前面我们量化为12bit,就在这里体现)、滤波器实现结构,我采用的是分布式,在窗口右边是输入信号的配置信息,我们前面是通过matlab产生并量化为12bit的输入信号,所以填写好即可。最后选择Edit Coefficient Set标签,如下图。
FPGA与MATLAB联合仿真FIR滤波器_第7张图片
选中Imported Coefficient set,导入我们之前用matlab产生的滤波器系数即可。
然后点击第二步,关于仿真设置,我们自己写仿真,所以直接第三步,有兴趣可以自己点开看看。这里需要提醒的是这一步是quartus自己给我们用户产生测试代码,专门用来进行FIR仿真使用,我在最开始的时候直接用这个来进行仿真,就是没用波形,所以才选择用matlab来产生信号进行测试(汗^^!)。不过通过这一系列测试,基本可以了解FPGA和matlab联合调试的一个操作流程,何乐不为(我们都是被逼的、被逼的。。。)。
最后一步是生产FIR滤波器,这一步很多人都无法生成FIR滤波器,我也是很多人之一,然后各种搜索,找方法来解决。在这里我给出我自己找到的方法总结如下(都是网友的力量)。
a、查看自己的license是否全面,否则不支持FIR、IIR、NCO等等IP核。具体操作:Tools->License Setup即可查看。如下图:
FPGA与MATLAB联合仿真FIR滤波器_第8张图片如果你的license比较全面,那么列表中就会比较多,一半在安装软件时默认的只有四五个可用。如果这里有问题,需要找一个完整的license即可;没问题就跳过这步;
b、如果License没问题,还是无法生成FIR IP核,可以在电脑中关闭Quartus_Map.exe应用即可。(多说一句,Quartus在运行的时候,有四个进程quartus_map、quartus_fit、quartus_asm、quartus_tan,其中前两个负责布局映射,耗时最大)
通过上面的方法基本可以解决目前遇到的问题,FIR IP核生成后,编写test_bench。

3、编写test_bench,利用modelsim对FIR进行仿真,并将滤波后数据写入到文本中;

在tb文件中例化FIR顶层(我简单的封装了一下,只显示输入输出即时钟复位信号),然后通过Verilog中读文件操作将前面matlab产生的输入信号读入,并依次给输入端口,并把输出的数据写到文本文件中,用于后面matlab验证。这里给出test_bench代码,如下。

`timescale 1ns/1ps
module tb_fir;

reg         clk         ;
reg         rst_n       ;
reg[11:0]   din         ;
wire[29:0]   dout       ;
parameter CLK_PERIOD = 10;

fir_quartus u_fir_quartus
(
.clk(clk),
.rst_n(rst_n),
.din(din),
.dout(dout)
);

initial
    begin
        clk = 0;
        rst_n = 0;
        #100
        rst_n = 1;

    end 
always #CLK_PERIOD clk = ~clk;//50M

//读取数据
parameter N = 4096;
integer i;
reg[11:0] memo_s [1:N];
reg[11:0] memo_n [1:N];
initial
    begin
        //$readmemb("Source_Bin.txt",memo_n);
        $readmemb("Noise_Bin.txt",memo_n);
        i = 0;
        repeat(N)
            begin
                i = i + 1;
                din = memo_n[i];
                #CLK_PERIOD;
            end 
    end 

integer file_out,sin_print;
initial file_out = $fopen("n_out.txt");
//always@(posedge clk)
//  begin
//      
//      //$fdisplay(file_out,"%0d",dout);//十进制输出
//      if(!file_out)
//          begin
//              $display("Could not open file!");
//              $finish;
//          end 
//  end 
reg[4:0] cnt;
always @(posedge clk ,negedge rst_n)
    if(!rst_n)
        cnt <= 'd0;
    else if(cnt>=10)
        cnt <= cnt;
    else cnt <= cnt + 1'b1;

always @(posedge clk)
  begin
    if(rst_n==1'b1&cnt==10)
      begin
        if (dout < (1<<29))
          sin_print = dout;
        else
          sin_print =  dout - (1<<30);

    $fdisplay (file_out, "%0d", sin_print);
      end
end

endmodule

完成test_bench编写后,在 quartus中打开modelsim联合仿真,仿真波形如下。
FPGA与MATLAB联合仿真FIR滤波器_第9张图片

4、将第3步中得到的滤波后数据通过matlab进行fft计算得到信号的频谱,观察滤波效果;

我们将第3步中得到滤波后的数据读入到matlab中进行fft计算,得到信号频谱,分析滤波前后的效果。
FPGA与MATLAB联合仿真FIR滤波器_第10张图片
FPGA与MATLAB联合仿真FIR滤波器_第11张图片
FPGA与MATLAB联合仿真FIR滤波器_第12张图片
FPGA与MATLAB联合仿真FIR滤波器_第13张图片
通过对比可以看到,滤波前后信号的时域波形和频谱相应,滤波后抑制了高斯白噪声,只有2.5MHz的原始信号。

5、分析总结

通过前面4步的验证,对FIR滤波器的FPGA实现有了一些了解,基本熟悉了matlab和FPGA联合仿真的流程。值得一提的是,在用modelsim仿真时,我当时出现一个情况就是找不到库,虽然我已经添加了,后来发现在于modelsim仿真时,FIR IP核要放在工程根目录下,否则就会报错“auk_dispip_lip”,只需要将IP核文件放在工程根目录下即可。同时在quartus工程文件下的simulation->modelsim中有自动生成的.do文件,可以直接运行.do文件,方便后期再次调试,也可以自己编写.do文件。推荐先用GUI操作,熟悉整个来龙去脉后再写脚本,这样更便于理解。
2017/11/13

你可能感兴趣的:(FPGA学习)