FPGA教程目录
MATLAB教程目录
---------------------------------------------------------------------------------------
目录
1.软件版本
2.本算法理论知识
3.核心代码
4.操作步骤与仿真结论
5.参考文献
0.完整源码获得方式
方式1:微信或者QQ联系博主
方式2:订阅MATLAB/FPGA教程,免费获得教程案例以及任意2份完整源码
1.软件版本
vivado2019.2、MATLAB2021a
2.本算法理论知识
FIR(Finite Impulse Response)滤波器是一种有限长单位冲激响应滤波器,又称为非递归型滤波器。FIR 滤波器具有严格的线性相频特性,同时其单位响应是有限长的,因而是稳定的系统,在数字通信、图像处理等领域都有着广泛的应用。FIR 滤波器是有限长单位冲击响应滤波器。直接型结构如下:
FIR 滤波器本质上就是输入信号与单位冲击响应函数的卷积,表达式如下:
我们可以看到,一个串行结构的FIR滤波器,其首先通过延迟模块得到延迟后的输入信号x,然后和对应的FIR系数相乘,然后再求和就可以输出滤波结果。
3.核心代码
这里,我们设计一个低阶的滤波器,首先通过MATLAB来确定FIR滤波器的系数,运行如下的MATLAB程序:
clc;
clear;
close all;
warning off;
h = hamming(7);
figure;
plot(h,'b-o')
h2 = round(1023*h)
这里使用hamming汉明窗函数自动产生系数,7表示窗函数的长度。
运行这个程序,可以得到FIR汉明窗的系数:
可以看到,我们产生了7个点长度的汉明窗。
matlab中的最后一行h2 = round(1023*h),表示滤波器系数量化之后h变为h2:
h2 =
82
317
788
1023
788
317
82
然后在vivado中,新建一个文件,命名为fir_tops.v,其代码如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/03/26 23:06:35
// Design Name:
// Module Name: fir_tops
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fir_tops(
input i_clk,
input i_rst,
input signed[1:0]i_din,
output signed[15:0]o_dout
);
//滤波器系数
parameter b0 = 14'd82;
parameter b1 = 14'd317;
parameter b2 = 14'd788;
parameter b3 = 14'd1023;
parameter b4 = 14'd788;
parameter b5 = 14'd317;
parameter b6 = 14'd82;
reg signed[1:0]x0;
reg signed[1:0]x1;
reg signed[1:0]x2;
reg signed[1:0]x3;
reg signed[1:0]x4;
reg signed[1:0]x5;
reg signed[1:0]x6;
//xn延迟
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
x0 <= 2'd0;
x1 <= 2'd0;
x2 <= 2'd0;
x3 <= 2'd0;
x4 <= 2'd0;
x5 <= 2'd0;
x6 <= 2'd0;
end
else begin
x0 <= i_din;
x1 <= x0;
x2 <= x1;
x3 <= x2;
x4 <= x3;
x5 <= x4;
x6 <= x5;
end
end
//使用乘法器IP核计算乘法
wire signed[15:0]r0;
multer multer_u0 (
.CLK(i_clk), // input wire CLK
.A(x0), // input wire [1 : 0] A
.B(b0), // input wire [13 : 0] B
.SCLR(i_rst), // input wire SCLR
.P(r0) // output wire [15 : 0] P
);
wire signed[15:0]r1;
multer multer_u1 (
.CLK(i_clk), // input wire CLK
.A(x1), // input wire [1 : 0] A
.B(b1), // input wire [13 : 0] B
.SCLR(i_rst), // input wire SCLR
.P(r1) // output wire [15 : 0] P
);
wire signed[15:0]r2;
multer multer_u2 (
.CLK(i_clk), // input wire CLK
.A(x2), // input wire [1 : 0] A
.B(b2), // input wire [13 : 0] B
.SCLR(i_rst), // input wire SCLR
.P(r2) // output wire [15 : 0] P
);
wire signed[15:0]r3;
multer multer_u3 (
.CLK(i_clk), // input wire CLK
.A(x3), // input wire [1 : 0] A
.B(b3), // input wire [13 : 0] B
.SCLR(i_rst), // input wire SCLR
.P(r3) // output wire [15 : 0] P
);
wire signed[15:0]r4;
multer multer_u4 (
.CLK(i_clk), // input wire CLK
.A(x4), // input wire [1 : 0] A
.B(b4), // input wire [13 : 0] B
.SCLR(i_rst), // input wire SCLR
.P(r4) // output wire [15 : 0] P
);
wire signed[15:0]r5;
multer multer_u5 (
.CLK(i_clk), // input wire CLK
.A(x1), // input wire [1 : 0] A
.B(b5), // input wire [13 : 0] B
.SCLR(i_rst), // input wire SCLR
.P(r5) // output wire [15 : 0] P
);
wire signed[15:0]r6;
multer multer_u6 (
.CLK(i_clk), // input wire CLK
.A(x6), // input wire [1 : 0] A
.B(b6), // input wire [13 : 0] B
.SCLR(i_rst), // input wire SCLR
.P(r6) // output wire [15 : 0] P
);
assign o_dout = r0+r1+r2+r3+r4+r5+r6;
endmodule
通过parameter语句,定义滤波器系数
然后通过多个乘法器,将延迟后的数据和滤波器系数相乘。
其中,上述程序中multer乘法器模块,使用vivado的IP核实现,具体操作如下:
点击IP calalog,然后点击multiplier
乘法器的参数设置如下:
点击ok,然后弹出
点击generate
此时,在vivado中,可以看到:
在vivado中,点击IP source
可以看到乘法器IP核的接口配置:
双击multer.veo,就可以看到右侧的乘法器接口,将接口复制到verilog中,就有了上述程序
调用方法和C语言中类似,()中为实际的信号名称,如上图,输入数据x0,系数b0,时钟i_clk,复位i_rst,输出乘积r0.。
FPGA的TB文件程序如下:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/03/26 23:21:32
// Design Name:
// Module Name: test_fir
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module test_fir;
reg i_clk;
reg i_rst;
reg signed[1:0]i_din;
wire signed[15:0]o_dout;
fir_tops fir_tops_u(
.i_clk (i_clk),
.i_rst (i_rst),
.i_din (i_din),
.o_dout (o_dout)
);
initial
begin
i_clk=1'b1;
i_rst=1'b1;
i_din=2'b00;
#1000
i_rst=1'b0;
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b11;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b11;
#10
i_din=2'b00;
#30
i_din=2'b11;
#10
i_din=2'b00;
#30
i_din=2'b11;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b11;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
#30
i_din=2'b11;
#10
i_din=2'b00;
#30
i_din=2'b11;
#10
i_din=2'b00;
#30
i_din=2'b11;
#10
i_din=2'b00;
#30
i_din=2'b01;
#10
i_din=2'b00;
end
always #5 i_clk=~i_clk;
endmodule
4.操作步骤与仿真结论
在vivado中,选择fir_tops这个顶层文件,右击,设置set as top
然后再选择test_fir,右击,设置set as top
然后点击run simulation,选择行为仿真
然后点击如下三角形,进行仿真
仿真后将得到:
同时选中
右击,设置进制,选择有符号十进制
然后 同时选中
右击,选择波形显示
得到如下滤波效果
上述案例,也可以直接和博主联系,获得完整工程文件。
5.参考文献
[1]郭继昌, 李香萍, 滕建辅. 基于位串行分布式算法和FPGA实现FIR电路的研究[J]. 电子测量与仪器学报, 2001, 15(2):7.