HLS实现FIR低通滤波器+System Generator仿真

硬件:ZYNQ7010
软件:MATLAB 2019b、Vivado 2017.4、HLS 2017.4、System Generator 2017.4

1、MATLAB设计低通滤波器

  FPGA系统时钟 50MHz,也是采样频率。用 MATLAB 生成 1MHz 和 10MHz 的正弦波叠加的信号,并量化为 14bit 整数。把叠加信号输出到 txt 文件用于 HLS 的仿真。MATLAB 工作空间里的变量用于搭建 System Generator 模型。

N = 1024;
fs = 50e6; %50MHz
ts = 1/fs;
Q = 14;
A = 2;
t = (1:N)*ts;
f1 = 1e6; %1MHz
f2 = 10e6;%10MHz
s1 = A*sin(2*pi*f1*t);
s2 = A*sin(2*pi*f2*t);
s = s1+s2;
s = s./max(abs(s));
s = round(s.*(2^(Q-1)-1)); % quantize
% output for testbench
fid = fopen('.\data.txt','w');
for i = 1:length(s)fprintf(fid,'%d\n', s(i));
end
fclose(fid);

  用 MATLAB 的 fir1 函数设计一个归一化截止频率为 0.2 的 10 阶低通 FIR 滤波器,即截止频率为 5MHz,有 11 个滤波器系数。最后也将滤波器系数量化为 14bit 整数。

Q = 14;
b = fir1(10,0.2);
figure();
freqz(b,1);
b = b./max(abs(b));
b = round(b.*(2^(Q-1)-1)); % quantize

2、HLS编写FIR滤波器代码并优化、仿真

// fir.h
#ifndef _FIR_H_
#define _FIR_H_
#include <ap_int.h>
#define N 11
typedef ap_int<32> coef_t;
typedef ap_int<32> data_t;
typedef ap_int<32> acc_t;
void fir(acc_t *y,data_t x);
#endif
// fir.cpp
#include "fir.h"
void fir(acc_t *y,data_t x)
{const coef_t c[N] = {0,322,1644,4229,6989,8191,6989,4229,1644,322,0}; //low pass 0.2static data_t shift_reg[N];acc_t acc=0;
Shift_Accum_Loop:for(int i = N - 1;i >= 0;i--){if(i == 0){acc += x * c[0];shift_reg[0] = x;}else{shift_reg[i] = shift_reg[i - 1];acc += shift_reg[i] * c[i];}}*y = acc;
}
// tb_fir.cpp
#include "fir.h"
#include <fstream>
#include <iostream>
using namespace std;
int main()
{ifstream fp_strmi("data.txt");ofstream fp_strmo("..\\..\\..\\..\\fir_matlab\\fir_out.txt");int val;acc_t fir_out;if(!fp_strmi.is_open()){cerr << "Error! data.txt is not able to open.\n";}if(!fp_strmo.is_open()){cerr << "Error! fir_out.txt is not able to open.\n";}for(int i=0; i<1024; i++){fp_strmi >> val;fir(&fir_out, (data_t)val);fp_strmo << (int)fir_out << "\n";}fp_strmi.close();fp_strmo.close();return 0;
}

在这里插入图片描述
  首先编写一个没有经过任何优化的C语言代码,C Synthesis后得到的性能估计,见上图。Shift_Accum_Loop 循环了 11 次,每次循环用时两个时钟周期,这说明了这个循环是顺序执行的,没有充分发挥 FPGA 能够并行计算的特点。fir 函数的执行延时(Latency)是 23 个时钟周期,执行间隔(Interval)也是 23 个时钟这期。进行 C/RTL Cosimulation,输出的波形见下图,波形很奇怪,其实只有 y_V_ap_vld为高电平时的 y_V 数据是正确的,y_V_ap_vld 的相邻两个上升沿之间间隔了 24 个时钟周期(480ns)。ap_read 为高电平时,读入一个叠加信号数据到 x_V,可以看出整个系统的采样频率不是 50MHz,而是 (50/24)MHz。

在这里插入图片描述
  优化 FIR 滤波器的代码,将滤波器系数和输入信号的数据类型改为 ap_int<14>,shift_reg 指定用寄存器实现,Shift_Accum_Loop 循环中的寄存器移位操作(延时线,TDL)和乘累加(MAC)操作分开写到两个 for 循环里,再将这两个循环展开,Cpp 代码和directive 指令在下面列出。因为 TDL 的循环次数是 10 次,所以 factor 是 10,MAC 循环次数是 11 次, factor 填 11。

// fir.h
#ifndef _FIR_H_
#define _FIR_H_
#include <ap_int.h>
#define N 11
typedef ap_int<14> coef_t;
typedef ap_int<14> data_t;
typedef ap_int<32> acc_t;
void fir(acc_t *y,data_t x);
#endif
// fir.cpp
#include "fir.h"
void fir(acc_t *y,data_t x)
{const coef_t c[N] = {0,322,1644,4229,6989,8191,6989,4229,1644,322,0}; //low pass 0.2static data_t shift_reg[N];acc_t acc=0;shift_reg[0] = x;
TDL: // time delay linefor(int i = N - 1; i > 0; i--){shift_reg[i] = shift_reg[i - 1];}
MAC: // multiple accumulatefor(int i = N - 1; i >= 0; i--){acc += shift_reg[i] * c[i];}*y = acc;
}
# directive 
set_directive_array_partition -type complete -dim 1 "fir" shift_reg
set_directive_unroll -skip_exit_check -factor 10 "fir/TDL"
set_directive_unroll -skip_exit_check -factor 11 "fir/MAC"
set_directive_interface -mode ap_ctrl_none "fir"

  C Synthesis后得到的性能估计如下图所示。fir 函数的执行延时(Latency)是 1 个时钟周期,执行间隔(Interval)也是 1 个时钟这期。进行 C/RTL Cosimulation,此时波形好看一点,依然是y_V_ap_vld为高电平时的 y_V 数据是正确的,y_V_ap_vld 的相邻两个上升沿之间间隔了 2 个时钟周期(40ns),整个系统的采样频率是 25MHz,输出的低频正弦信号频率是 500KHz。在后续System Generator 仿真时情况会发生变化,注意看。

在这里插入图片描述在这里插入图片描述

3、搭建System Generator模型,导入HLS模块

  搭建一个如下图所示的 System Generator 模型,其中 counter 用于产生 ROM 的地址信号,ROM 中存着叠加信号的数据。这些模块都是高电平复位,而我的开发板按键按下去后是低电平,所以在 reset 后加了 not 模块翻转电平。HLS 模块导入了优化后的 fir 代码,并且将模块的端口协议改为了 ap_ctrl_none。
在这里插入图片描述
  下图给出了 System Generator 的仿真结果。可以看到滤波后的正弦信号不平滑,输出数据是 y_V_ap_vld 高电平时有效,y_V_ap_vld 的相邻两个上升沿之间间隔两个时钟周期,正弦信号的周期是 50 个时钟周期,正好对应 50MHz 时钟频率下的 1MHz。为什么和 HLS 中的 C/RTL Cosimulation 结果不一样呢?因为这里输入的叠加信号是按 50MHz 的采样频率输入到 HLS 模块的,但是 HLS 模块处理一个输入数据需要两个时钟周期,相当于对输入信号又进行了一次下采样,采样频率变成了 25MHz,同时采样点数也减少了,此时滤波器的截止频率为 0.2 × 25 / 2 = 2.5 0.2×25/2=2.5 0.2×25/2=2.5MHz,同样可以滤出 1MHz 的正弦信号。前面 C/RTL Cosimulation 时只是采样频率变小了,但是采样点数没有少,导致输出的正弦信号频率也减小。

在这里插入图片描述  把这个模型生成 IP 核,下载到开发板上进行验证。

4、上板验证

  创建一个 Vivado 工程,例化 System Generator 模型生成的 IP 核和一个 ila IP 核,写一个寄存器把 fir_out 根据 fir_out_vld 寄存一次,代码如下。

module fir_hls_sysgen_top(input resetn,input clk);
wire [31:0] fir_out;
wire fir_out_vld;
fir_filter_0 fir_filter_inst (.reset(resetn),                // input wire [0 : 0] reset.clk(clk),                    // input wire clk.fir_out(fir_out),          // output wire [31 : 0] fir_out.fir_out_vld(fir_out_vld)  // output wire [0 : 0] fir_out_vld
);
reg [31:0] fir_out_reg;
always @(posedge clk or negedge resetn) beginif(!resetn) beginfir_out_reg <= 32'd0;endelse beginif(fir_out_vld) beginfir_out_reg <= fir_out;endend
end
ila_0 ila0_inst (.clk(clk), // input wire clk.probe0(fir_out), // input wire [31:0]  probe0  .probe1(fir_out_reg), // input wire [31:0]  probe1 .probe2(fir_out_vld) // input wire [0:0]  probe2
);
endmodule

  ila 抓取的波形如下图所示。可以看到 fir_out_vld 相邻两个上升沿间隔两个时钟周期,滤波输出的正弦信号周期为 50 个时钟周期,fir_out 波形和 simulink 仿真的是一样的,并且 fir_out_reg 的波形更平滑一些。

在这里插入图片描述完整工程下载地址:HLS设计FIR滤波器工程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/40462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web网页浏览器远程访问jupyter notebook服务器【内网穿透】

文章目录 前言1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 前言 Jupyter Notebook&#xff0c;它是一个交互式的数据科学和计算环境&#xff0c;支持多种编程语言&#xff0c;如…

Hyper-v导致Vmware window无法启动崩溃记录

最近有几次vmware启动window10直接崩溃情况&#xff0c;显示蓝屏报错。一开始没在意&#xff0c;以为是因为固态硬盘错了几个字节导致的&#xff1f; 但后来想想不对啊。vmware用了也有10来年了&#xff0c;稳得一笔&#xff0c;在仔细思考了一下后发现打不开的win10这三个虚拟…

设计模式之构建器(Builder)C++实现

1、构建器提出 在软件功能开发中&#xff0c;有时面临“一个复杂对象”的创建工作&#xff0c;该对象的每个功能接口由于需求的变化&#xff0c;会使每个功能接口发生变化&#xff0c;但是该对象使用每个功能实现一个接口的流程是稳定的。构建器就是解决该类现象的。构建就是定…

【Java】项目管理工具Maven的安装与使用

文章目录 1. Maven概述2. Maven的下载与安装2.1 下载2.2 安装 3. Maven仓库配置3.1 修改本地仓库配置3.2 修改远程仓库配置3.3 修改后的settings.xml 4. 使用Maven创建项目4.1 手工创建Java项目4.2 原型创建Java项目4.3 原型创建Web项目 5. Tomcat启动Web项目5.1 使用Tomcat插件…

【CTF-web】备份是个好习惯(查找备份文件、双写绕过、md5加密绕过)

题目链接&#xff1a;https://ctf.bugku.com/challenges/detail/id/83.html 经过扫描可以找到index.php.bak备份文件&#xff0c;下载下来后打开发现是index.php的原代码&#xff0c;如下图所示。 由代码可知我们要绕过md5加密&#xff0c;两数如果满足科学计数法的形式的话&a…

模型预测笔记(一):数据清洗及可视化、模型搭建、模型训练和预测代码一体化和对应结果展示(可作为baseline)

模型预测 一、导入关键包二、如何载入、分析和保存文件三、修改缺失值3.1 众数3.2 平均值3.3 中位数3.4 0填充 四、修改异常值4.1 删除4.2 替换 五、数据绘图分析5.1 饼状图5.1.1 绘制某一特征的数值情况&#xff08;二分类&#xff09; 5.2 柱状图5.2.1 单特征与目标特征之间的…

OpenCV基本操作——算数操作

目录 图像的加法图像的混合 图像的加法 两个图像应该具有相同的大小和类型&#xff0c;或者第二个图像可以是标量值 注意&#xff1a;OpenCV加法和Numpy加法之间存在差异。OpenCV的加法是饱和操作&#xff0c;而Numpy添加的是模运算 import numpy as np import cv2 as cv imp…

[数据集][目标检测]钢材表面缺陷目标检测数据集VOC格式2279张10类别

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;2279 标注数量(xml文件个数)&#xff1a;2279 标注类别数&#xff1a;10 标注类别名称:["yueyawan",&…

jenkins 连接服务器,提示Can‘t connect to server

在Jenkins 添加服务器时&#xff0c;提示 Cant connect to server&#xff0c;如图 搞了好久&#xff0c;不知道为什么不行~原来是行的&#xff0c;现在删了 新建一个也不行。

2023牛客暑期多校训练营8-C Clamped Sequence II

2023牛客暑期多校训练营8-C Clamped Sequence II https://ac.nowcoder.com/acm/contest/57362/C 文章目录 2023牛客暑期多校训练营8-C Clamped Sequence II题意解题思路代码 题意 解题思路 先考虑不加紧密度的情况&#xff0c;要支持单点修改&#xff0c;整体查询&#xff0…

[C++]笔记 - 知识点积累

一.运算符的优先级 一共15个级别 最高优先级 : () []最低优先级 :逗号表达式倒数第二低优先级 : 赋值和符合赋值(,,-...) ! >算术运算符 > 关系运算符 > && >> || >赋值运算符 二.数据类型转换 隐式类型转换 算数转换 char int long longlong flo…

解决Java中的“Unchecked cast: java.lang.Object to java.util.List”问题

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

搜索二叉树

目录 搜索二叉树的性质 搜索二叉树的实现、 插入 删除 代码 在以前我们学过二叉树,但是在对二叉树的学习中发现,似乎二叉树并没有什么作用,要论增删它比不上链表,论随机访问也没法和顺序表比,对于当时的我们是一头雾水,那么现在它的功能终于是体现出来了,这里就是我们要讲的…

[Go版]算法通关村第十一关白银——位运算的高频算法题

目录 专题1&#xff1a;位移的妙用题目&#xff1a;位1的个数&#xff08;也被称为汉明重量&#xff09;解法1&#xff1a;遍历所有位&#xff0c;判断每个位的数字是否是1Go代码 解法2&#xff1a;依次消除每个1的位 numnum&(num-1)Go代码 题目&#xff1a;比特位计数思路…

Mac 卸载appium

安装了最新版的appium 2.0.1,使用中各种问题&#xff0c;卡顿....,最终决定回退的。记录下卸载的过程 1.打开终端应用程序 2.卸载全局安装的 Appium 运行以下命令以卸载全局安装的 Appium&#xff1a; npm uninstall -g appium 出现报错&#xff1a;Error: EACCES: permiss…

云安全攻防(十二)之 手动搭建 K8S 环境搭建

手动搭建 K8S 环境搭建 首先前期我们准备好三台 Centos7 机器&#xff0c;配置如下&#xff1a; 主机名IP系统版本k8s-master192.168.41.141Centos7k8s-node1192.168.41.142Centos7k8s-node2192.168.41.143Centos7 前期准备 首先在三台机器上都执行如下的命令 # 关闭防火墙…

postman测试后端增删改查

目录 一、本文介绍 二、准备工作 &#xff08;一&#xff09;新建测试 &#xff08;二&#xff09;默认url路径查看方法 三、增删改查 &#xff08;一&#xff09;查询全部 &#xff08;二&#xff09;增加数据 &#xff08;三&#xff09;删除数据 &#xff08;四&…

nginx反向代理流程

一、nginx反向代理流程 反向代理&#xff1a;使用代理服务器来接受internet上的连接请求&#xff0c;然后将请求转发给内部网络中的上游服务器&#xff0c;并将上游服务器得到的结果返回给请求连接的客户端&#xff0c;代理服务器对外表现就是一个web服务器。Nginx就经常拿来做…

【内网穿透】如何实现在外web浏览器远程访问jupyter notebook服务器

文章目录 前言1. Python环境安装2. Jupyter 安装3. 启动Jupyter Notebook4. 远程访问4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5. 固定公网地址 前言 Jupyter Notebook&#xff0c;它是一个交互式的数据科学和计算环境&#xff0c;支持多种编程语言&#xff0c;如…

【爱书不爱输的程序猿】公网访问本地搭建的WEB服务器之详细教程

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本地电脑搭建Web服务器并用cpolar发布至公网访问 前言1. 首先将PHPStudy、WordPress、cpolar下载到电脑2. 安装PHPStudy3. 安装cpolar&#xff0c;进入Web-UI界面4.安装wordpress5.…