【FPGA学习】MATLAB与FPGA实现FIR滤波器
本篇博客记录一下在matlab设计和在FPGA平台实现FIR滤波器的方法,平台是Xilinx的ZYNQ
参考:
AMBA AXI-Stream Protocol Specification
使用matlab设计FIR滤波器
fdatool是matlab中专用的滤波器设计工具,在matlab中的命令行窗口直接输入fdatool即可(也可以用filterDesigner):
打开后的界面如下:
- 设置滤波器的参数,在界面的下半部
- 响应类型:也就是滤波器类型
- 设计方法:设计FIR滤波器和IIR滤波器的各种方法
- 滤波器阶数:定义滤波器的阶数,可指定阶数(对于n阶滤波器,指定阶数应填写n-1)或直接根据选择的滤波器类型使用最小阶数
- 频率设定:定义频带的各参数
- 幅值设定:定义幅值衰减的情况
- 当采用窗函数设计时,还可以选择可选的窗函数
这个界面实际上是左边的最下面的设计滤波器选项:
由于我们要将FIR滤波器在FPGA的硬件上实现,因此还要在左边的第三个选项选择设置量化参数,并选择定点数:
同时在分子字长还可以设定滤波器定点系数的长度
实例
本博客以一个示例来说明整个过程,滤波器要求如下:
- FIR滤波器输入采样率为100kHz
- 滤波器通带的单边带带宽为20kHz
- 带外衰减为90dB
- 带内波纹为1dB
- 滤波器系数为定点数,ADC采样信号(即输入信号)的位数为24位,滤波器系数的位数可自己定义
输入信号的频谱如下所示:
根据如上的要求,可在matlab中设计滤波器:
设计完成后在上面的目标即可生成Xilinx系数文件(.coe文件):
调用FIR IP核
实现FIR滤波器可以直接调用提供的IP核,本篇博客中使用的是vivado中的FIR IP核
在工程左边中点击IP Catalog:
搜索FIR即可找到需要调用的IP核:
首先需要配置滤波器的系数:
接下来需要配置一下输入的采样频率以及时钟频率
还需要修改一些输入数据的位数等参数:
在Interface中还可以看到IP核的复位信号和使能信号,我这里将复位信号改为了低电平有效:
在vivado中生成IP核后,可以在IP Sources中的Instantiation Template中获取例化IP核的模板,比如在.veo中就是可以获取Verilog的例化模板:
可以直接根据这个进行例化
在编写Verilog代码之前需要对IP核有所了解,这个一方面要看Xilinx官方的IP手册,FIR IP核对应的是PG149,另一方面可以在IP核配置界面的Implementation Details可以看到一些信息,尤其是确定接口信号的位数:
接口控制模块编写如下:
// Xilinx FIR IPcore Interface Control
module fir_control(
input sys_clk, // 50M clock
input sys_rst_n,
input [23:0] s_axis_data_tdata,
input s_axis_data_tvalid,
output m_axis_data_tvalid,
output s_axis_data_tready,
output [41:0] fir_out,
output reg clk_100k
);
parameter count = 250;
wire [47:0] m_axis_data_tdata;
reg [15:0] cnt;
// reg clk_100k;
assign fir_out = m_axis_data_tdata[41:0];
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
begin
cnt <= 16'd0;
clk_100k <= 1'b0;
end
else if(cnt < count - 1)
begin
cnt <= cnt + 1;
end
else
begin
cnt <= 16'd0;
clk_100k <= ~clk_100k;
end
end
fir_compiler_0 fir (
.aresetn(sys_rst_n), // input wire aresetn
.aclk(clk_100k), // input wire aclk
.s_axis_data_tvalid(s_axis_data_tvalid), // input wire s_axis_data_tvalid
.s_axis_data_tready(s_axis_data_tready), // output wire s_axis_data_tready
.s_axis_data_tdata(s_axis_data_tdata), // input wire [23 : 0] s_axis_data_tdata
.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
.m_axis_data_tdata(m_axis_data_tdata) // output wire [47 : 0] m_axis_data_tdata
);
endmodule
同时还编写了testbench用于测试,testbench一方面要读取输入信号数据,另一方面要将输出信号输出到一个文件里,在matlab进行测试,这些都要用到Verilog语法中的系统任务:
- 使用数据文件对存储器进行初始化:\(readmemb和\)readmemh,分别可以用于读取二进制数和十六进制数
- $readmemb("<file_name>",<memory_name>,<start_addr>,<finish_addr>);
- <start_addr>和<finish_addr>是可选的,<start_addr>的默认值是存储器数组的开始位置,<finish_addr>的默认值是数据文件或存储器的结束位置
- 可以将Verilog的输出重定向到选择的文件
- 打开文件:$fopen
- <file_handle>=$fopen("<file_name>");
- \(fopen返回一个被称为**多通道描述符**的**32位**值,多通道描述符中只有一位被设置成1,标准输出有一个多通道描述符,其最低位被设置成1,标准输出也称通道0,标准输出是一直开放的,以后对\)fopen的每一次调用都会打开一个新的通道,并返回一个32位的描述符,其中最多可设置到第30位,第31位是保留位
- 写文件:\(fdisplay、\)fmonitor和$fwrite
- $fdisplay(<file_descripr or>,p1,p2,...,pn);
- $fmonitor(<file_descripr or>,p1,p2,...,pn);
- p1,p2,...,pn可以是变量,信号名或带引号的字符串
- 关闭文件:$fclose
- $fclose(<file_descriptor>);
- 文件一旦被关闭就不能再写入,多通道描述符中的相应位被设置成0,下一次$fopen的调用可以重用这一位
- 打开文件:$fopen
testbench编写如下:
module fir_tp;
// fir_control Parameters
parameter PERIOD = 20 ;
parameter count = 250;
// fir_control Inputs
reg sys_clk = 0 ;
reg sys_rst_n = 0 ;
reg [23:0] s_axis_data_tdata = 0 ;
reg s_axis_data_tvalid = 0 ;
// fir_control Outputs
wire m_axis_data_tvalid ;
wire s_axis_data_tready ;
wire [41:0] fir_out ;
reg [23:0] data_test [1023:0];
reg [31:0] cnt;
wire clk_100k;
integer file;
reg [41:0] fir_out_buf = 0;
initial
begin
#10 sys_rst_n = 1;
s_axis_data_tdata = 24'd0;
cnt <= 32'd0;
$readmemh("C:/Users/zhaoyuheng/Desktop/ASIC_experiment/input.txt",data_test);
s_axis_data_tvalid = 1;
file = $fopen("C:/Users/zhaoyuheng/Desktop/ASIC_experiment/output.txt","w");
forever #(PERIOD/2) sys_clk=~sys_clk;
end
fir_control #(
.count ( count ))
u_fir_control (
.sys_clk ( sys_clk ),
.sys_rst_n ( sys_rst_n ),
.s_axis_data_tdata ( s_axis_data_tdata [23:0] ),
.s_axis_data_tvalid ( s_axis_data_tvalid ),
.m_axis_data_tvalid ( m_axis_data_tvalid ),
.s_axis_data_tready ( s_axis_data_tready ),
.fir_out ( fir_out [41:0] ),
.clk_100k (clk_100k)
);
always @(posedge clk_100k) begin
if(cnt == 1024 - 1)
begin
$stop;
end
else
begin
if(s_axis_data_tready == 1 && m_axis_data_tvalid == 1)
begin
cnt <= cnt + 1;
s_axis_data_tdata <= data_test[cnt];
fir_out_buf <= fir_out;
$fwrite(file,"%b\n",fir_out_buf);
end
end
end
endmodule
在matlab中验证
matlab中读取txt文件:
cstr=textread('C:\Users\zhaoyuheng\Desktop\input.txt','%s');
n=length(cstr);
d = zeros(n,1);
for i=1:n
d(i)=hex2dec(cstr{i}); % 16进制数转换为10进制数,如果要将2进制数转换为10进制数要用bin2dec函数
end
plot(abs(fft(d)));
load函数只能读取10进制数
利用Verilog实现FIR滤波器
除了直接使用FIR的IP核外,还可以直接用Verilog语言来实现FIR滤波器,这里就用一个实例说明
我使用了正点原子的新起点FPGA开发板以及高速ADDA模块,实现一个简单的电压采集系统,实现输入16kHz与17kHz信号的分离,输出信号直接使用ADI的AD9834,系统如下:
高速ADDA
正点原子的高速ADDA模块的硬件结构图如下:
- AD9708芯片输出的是一对差分电流信号,经过处理后输出的模拟电压范围是-5V~5V
- AD9280芯片的输入模拟电压转换范围是0V2V,因此电压输入端从-5V5V衰减到0V~2V之间
AD9708
AD9708是8位的电流输出型DAC,速率可以达到125MSPS,供电电压范围为2.7V-5.5V,其时序图如下:
其中,ts是输入建立时间,tH是保持时间
FIR的Verilog实现
【FPGA学习】MATLAB与FPGA实现FIR滤波器的更多相关文章
- 转载论文关于fir滤波器的fpga实现
摘 要 本文讨论的FIR滤波器因其具有严格的线性相位特性而得到广泛的应用.在工程实践中,往往要求信号处理具有实时性和灵活性,本论文研究FIR的FPGA解决方案正体现了电子系统的微型化和单片化. 本论文 ...
- FIR滤波器的FPGA实现方法
FIR滤波器的FPGA实现方法 2011-02-21 23:34:15 来源:互联网 非常重要的基本单元.近年来,由于FPGA具有高速度.高集成度和高可靠性的特点而得到快速发展.随着现代数字 ...
- FPGA学习网站
1. OPENCORES.ORG这里提供非常多,非常好的PLD了内核,8051内核就可以在里面找到.进入后,选择project或者由 http//www.opencores.org/browse.c ...
- [整理]FPGA学习资料汇总
01.特权同学倾情奉献海量FPGA学习资料 http://pan.baidu.com/s/1pJIb32F
- 如何学习FPGA?FPGA学习必备的基础知识
如何学习FPGA?FPGA学习必备的基础知识 时间:2013-08-12 来源:eepw 作者: 关键字:FPGA 基础知识 FPGA已成为现今的技术热点之一,无论学生还是工程师都希望 ...
- 芯航线FPGA学习套件之4*4矩阵键盘模块测试手册
芯航线FPGA学习套件之4*4矩阵键盘模块测试手册 本手册以简明扼要的方式介绍芯航线FPGA学习套件提供的矩阵键盘模块的测试方法: 连接开发板,如下所示: 2.将矩阵键盘模块与开发板按如下图所 ...
- 芯航线FPGA学习套件之多通道串行ADDA(TLV1544,TLC5620)模块测试手册
芯航线FPGA学习套件之多通道串行ADDA模块测试手册 本手册以简明扼要的方式介绍芯航线FPGA学习套件提供的ADDA模块的测试方法: 连接开发板,如下所示: 2.将ADDA V1.1模块与开 ...
- FPGA学习之基本结构
如何学习FPGA中提到第一步:学习.了解FPGA结构,FPGA到底是什么东西,芯片里面有什么,不要开始就拿个开发板照着别人的东西去编程.既然要开始学习FPGA,那么就应该从其基本结构开始.以下内容是我 ...
- 第二篇-FPGA学习之RoadMap
古语云:知己知彼,百战不殆.那么既然选择了FPGA之路,欲练此功,必先-- 必先了解清楚,FPGA的特点,FPGA善于/不善于解决什么类型问题,以及FPGA应用的方向,FPGA学习的要素等等. 一.F ...
- FPGA与MATLAB数据交互高效率验证算法——仿真阶段
之前博文是对基本设计技巧的总结和一些小设计随笔,内容有点杂,缺乏目的性.本来后续计划设计几个小项目,但导师的任务比较紧,所以为了提高效率,后续博客会涉及到很多算法方面的设计与验证的内容,主要关于OFD ...
随机推荐
- 学习.NET MAUI Blazor(二)、MAUI是个啥
随着.NET 7的发布,MAUI也正式发布了.那么MAUI是个啥?我们先来看看官方解释: .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移 ...
- History模式的配置细节
旧文从语雀迁移过来,原日期:2021-09-13 前言 我们知道,vue 单页面应用打包出来是静态资源,一般需要 nginx 或者其他服务器访问:当如果 Vue Router 是采用 History ...
- Hive详解(03) - hive基础使用
Hive详解(03) - hive基础使用 Hive数据类型 基本数据类型 对于Hive的String类型相当于数据库的varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个 ...
- 物以类聚人以群分,通过GensimLda文本聚类构建人工智能个性化推荐系统(Python3.10)
众所周知,个性化推荐系统能够根据用户的兴趣.偏好等信息向用户推荐相关内容,使得用户更感兴趣,从而提升用户体验,提高用户粘度,之前我们曾经使用协同过滤算法构建过个性化推荐系统,但基于显式反馈的算法就会有 ...
- 如何通过Terraform Associate考试并获得证书
1 什么是Terraform? Terraform是一个IaC工具,IaC全称为Infrastructure as Code,基础设施即代码.它的理念是通过代码来管理基础设施,如服务器.数据库等,更多 ...
- 腾讯出品小程序自动化测试框架【Minium】系列(三)元素定位详解
写在前面 昨天转发这篇文章时,看到群里有朋友这样说: 这么卷吗?这个框架官方已经不维护了. 姑且不说卷不卷的问题,要是能卷明白,别说还真不错: 不维护又怎样?我想学习,想会,分享给很期待这系列的文章的 ...
- 深度剖析 Linux 伙伴系统的设计与实现
在上篇文章 <深入理解 Linux 物理内存分配全链路实现> 中,笔者为大家详细介绍了 Linux 内存分配在内核中的整个链路实现: 但是当内核执行到 get_page_from_free ...
- 安装云崽Bot+GPT3插件
安装云崽Bot+GPT3插件 这次我们来搭建云崽Bot,云崽Bot其实是一个用于原神的机器人,不过众多大佬开发出了很多有趣的插件供我们使用,这次我们就是用其中的一个插件Chat-gpt(其不是正宗的C ...
- 【已解决】将jsp文件在浏览器打开直接出现代码,在浏览器出现本地地址,tomcat报错
问题背景: 导入了一个项目直接打开可以,但是想跟一遍代码,把配置文件全部整理成为一个springmvc的基础配置文件 跟着配置到自己tomcat就不管怎样都是下面的截图 希望可以帮到一起报错的朋友快 ...
- Syntax Error: Error: Cannot find module ‘node-sass‘
出现问题原因: vscode运行前端项目输入npm run dev命令触发此错误 解决办法: 指定淘宝镜像安装node-sass win+r 打开cmd控制台输入 npm install -g cnp ...