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

news2024/12/29 10:01:22

硬件: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.2
	static 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.2
	static data_t shift_reg[N];
	acc_t acc=0;
	shift_reg[0] = x;
TDL: // time delay line
	for(int i = N - 1; i > 0; i--)
	{
		shift_reg[i] = shift_reg[i - 1];
	}
MAC: // multiple accumulate
	for(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) begin
    if(!resetn) begin
        fir_out_reg <= 32'd0;
    end
    else begin
        if(fir_out_vld) begin
            fir_out_reg <= fir_out;
        end
    end
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.coloradmin.cn/o/890481.html

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

相关文章

也许你正处于《孤注一掷》中的“团队”,要留心了

看完这部电影&#xff0c;心情久久不能平静&#xff0c;想了很多&#xff0c;倒不是担心自己哪天也成为“消失的yaozi”&#xff0c;而是在想&#xff0c;我们每天所赖以生存的工作&#xff0c;跟电影里他们的工作比&#xff0c;差别在哪里呢&#xff1f; 目录 1. 产品的本质…

【UniApp开发小程序】商品详情展示+评论、评论展示、评论点赞+商品收藏【后端基于若依管理系统开发】

文章目录 界面效果界面实现工具js页面日期格式化 后端收藏ControllerServicemapper 评论ControllerServiceMapper 商品Controller 阅读Service 界面效果 【说明】 界面中商品的图片来源于闲鱼&#xff0c;若侵权请联系删除 【商品详情】 【评论】 界面实现 工具js 该工…

即拼七人拼团模式怎么玩?如何留存消费者?

如今&#xff0c;流量稀缺&#xff0c;任何流量都需要付出一定的成本&#xff0c;商家做私域亦是如此。我们能做的就是降低预算&#xff0c;探索属于自己的方法。如何进行私域引流&#xff1f; 现阶段&#xff0c;新消费品牌提升品牌力的关键就在于构建品牌与消费者之间的信任关…

大家gobigger连接后不能调亮度(亮度不能保存)解决办法

关于gobigger连接后不能调亮度&#xff0c;会不会感觉是gobigger很爽的一点&#xff1f;其实不是&#xff0c;可以通过以下方法解决。如果解决你的问题给记得点赞&#xff0c;感谢支持。 现象&#xff1a; 数据线连接后&#xff0c;用滚轮调节亮度到最高点&#xff0c;当时是很…

JavaWeb+JSP+SQL server学生学籍管理系统设计与实现(源代码+论文+开题报告+外文翻译+答辩PPT)

需求分析 本系统主要是针对各个高校的学生学籍进行管理&#xff0c;系统满足以下几点要求&#xff1a; 系统安全性。由于此系统中的操作都是由用户操作的&#xff0c;所以对于用户的权限设置比较严格。对于数据库&#xff0c;设置了不同用户的权限&#xff0c;不同权限进入不…

前端下载文件的几种方式使用Blob下载文件

前端下载文件的几种方式 使用Blob下载文件 在前端下载文件是个很通用的需求&#xff0c;一般后端会提供下载的方式有两种&#xff1a; 1.直接返回文件的网络地址&#xff08;一般用在静态文件上&#xff0c;比如图片以及各种音视频资源等&#xff09; 2.返回文件流&#xff08;…

UE5.2 LyraDemo源码阅读笔记(五)输入系统

Lyra里使用了增强输入系统&#xff0c;首先知道增强输入系统里的三个类型配置。 一、Input Actions (IA)&#xff1a; 输入操作带来的变量&#xff0c;与玩家的输入组件绑定&#xff0c;回调里驱动玩家行为。 二、InputMappingContext&#xff08;IMC&#xff09;&#xff1a…

批量删除文件名中特定文字的方法

怎么批量删除文件名中特定文字&#xff1f;作为一个上班族&#xff0c;在电脑上进行批量文件名称的修改是一个非常常见的事情。如果你有大量的图片、视频、音乐和其他文件&#xff0c;希望批量删除文件名中的特定文字&#xff0c;那么不妨看看下面的介绍&#xff0c;并尝试使用…

制定设备维护管理计划时需要考虑的不同维护策略

在现代企业运营中&#xff0c;保障关键资产的稳定运行对于实现高效生产和客户满意度至关重要。然而&#xff0c;如何制定适合企业的设备维护管理计划却是一个需要深入思考和策划的重要问题。不同类型的维护策略可以满足不同的运营需求和预算限制。在本文中&#xff0c;我们将探…

142亿亿次/秒?长安汽车与百度达成战略合作,推动智能低碳出行

8月17日&#xff0c;重庆长安汽车股份有限公司与百度正式达成战略合作协议&#xff0c;双方将在多个领域展开深度合作&#xff0c;包括云计算、人工智能、大数据和物联网。这一合作旨在推动长安汽车向智能低碳的出行科技公司转型。 据悉&#xff0c;双方还共同建立了长安汽车智…

时序数据库influxdb笔记

官方资料 https://docs.influxdata.com/influxdb/v2.7/install/?tLinux https://www.influxdata.com/influxdb/ 安装 1、linux平台下 1&#xff09;下载 2&#xff09;解压 3&#xff09;添加账户&#xff08; adduser influx&#xff09; 4&#xff09;设置目录权限 5…

NodeJs导出PDF

&#xff08;优于别人&#xff0c;并不高贵&#xff0c;真正的高贵应该是优于过去的自己。——海明威&#xff09; 场景 根据订单参数生成账单PDF 结果 示例代码 /* eslint-disable no-unused-vars */ /* eslint-disable no-undef */ /* eslint-disable complexity */ const…

忘记LockSupport怎么用了?那我们举个有趣的小例子,永远记住它!

概述 LockSupport是一个非常方便实用的线程阻塞工具&#xff0c;它可以在线程内任意位置让线程阻塞。和Thread.suspend()相比&#xff0c;它弥补了由于resume()在前发生&#xff0c;导致线程无法继续执行的情况。和Object.wait()方法相比&#xff0c;它不需要先获得某个对象的…

用easyui DataGrid编辑树形资料

easyui显示编辑树形资料有TreeGrid元件&#xff0c;但是这个元件的vue版本和react版本没有分页功能。virtual scroll功能也表现不佳。 我用DataGrid来处理。要解决的问题点&#xff1a; &#xff08;1&#xff09;如何显示成树形。即&#xff0c;子节点如何有缩进。 先计算好…

精准无误的公文材料:感谢爱校对软件

在公文处理的过程中&#xff0c;无论是机构还是企业&#xff0c;我们都追求精准无误的结果。在这个信息化、智能化不断发展的时代&#xff0c;爱校对软件以其卓越的性能和优质的服务&#xff0c;赢得了大家的广泛好评。 首先&#xff0c;爱校对软件采用了最新的自然语言处理和…

深入了解msfconsole功能详解

一、前言 正如上篇文章所述&#xff0c;刚开始接触msf&#xff0c;单纯是为了分析某些漏洞&#xff0c;然后在msf中查找相应漏洞软件版本&#xff0c;系统版本的exp便于漏洞分析&#xff0c;同时进行偶尔的exp修改&#xff0c;这就是初期对于msf的使用&#xff0c;以至于我认为…

ai写真制作让你的照片焕发异彩

最近&#xff0c;越来越多的人开始使用ai写真应用程序来美化他们的照片。这些应用程序使用人工智能技术来将人们的照片变成更有艺术感的写真照&#xff0c;是人们的照片看起来更加生动、自然。今天&#xff0c;我将通过几幅生动的ai写真照片&#xff0c;来带你深入探索ai写真ap…

高等数学教材重难点题型总结(三)微分中值定理和导数的应用

第三章&#xff0c;微分中值定理的证明题等&#xff0c;非常重要&#xff0c;需要牢牢掌握 1.证明中值定理对某函数在给定区间上的正确性 2.与中值定理有关的证明题 3.微分中值定理应用于求证不等式 4.洛必达法则求极限 5.洛必达的经典错误反例 6.按某项实现多项式幂展开 7.求带…

外卖订餐系统源码:数字化餐饮新篇章

在当今数字化时代&#xff0c;外卖订餐系统源码成为餐饮行业的一颗明星&#xff0c;为餐厅和顾客提供了无与伦比的便捷体验。在本文中&#xff0c;我们将一起探索一个简单的外卖订餐系统源码示例&#xff0c;了解它是如何将美食带到您的门口的。 # 导入所需模块 import time#…

影响力再度提升,Smartbi多次蝉联Gartner、IDC等权威认可

近期&#xff0c;思迈特软件捷报频传&#xff0c;Smartbi凭借技术创新实力和产品能力&#xff0c;成功入选Gartner中国增强数据分析代表厂商及自助分析代表厂商&#xff0c;同时&#xff0c;连续三年蝉联“IDC中国FinTech 50”榜单。 Part.1 再次被Gartner提名 Smartbi深度融…