PYNQ-Z2调试笔记:使用PL的硬件IP定制overlay实现加速(How to accelerate a function with PYNQ)

本篇主要介绍,使用PYNQ板上可编程逻辑部分的IP核定制overlay,并与python自带的函数进行比较,以突出可编程逻辑部分的加速优势。


目录

前言

正文

(1)使用python的scipy模块函数对信号源信号滤波

(2)使用Vivado的滤波器核生成overlay

(3)使用overlay对相同信号源信号滤波,比较时间开销

结尾


​​​​​​​

前言

在前面的帖子中:https://blog.csdn.net/CSD_N_csdn/article/details/105669069,介绍了使用Vivado HLS制作了一个具有加法器功能的IP核,然后使用此IP核定制overlay,并在PYNQ上使用python调用验证功能。

本篇以前面的帖子为基础,省去了制作IP核的部分。一方面,直接调用Vivado的滤波器IP核,生成overlay,然后在jupyter-notebook上调用此overlay,实现对信号源信号的滤波,这用到了可编程逻辑部分,属于硬件加速,计算时间1。另一方面,调用python的scipy模块,scipy模块是具有滤波功能的函数,使用此函数对相同的信号源信号滤波,这属于纯软件实现滤波,计算时间2。将时间1与时间2比较,以突出硬件加速(即overlay方法)的优势。

正文

(1)使用python的scipy模块函数对信号源信号滤波

首先,在浏览器打开jupyter,新建python3文件,输入如下代码,这段代码的大致意思是定义了一个函数,将使用它来绘制数据,n_samples参数可以限制绘制的样本数量。其作用就是绘制一会儿要显示的信号。

%matplotlib notebook
import matplotlib.pyplot as plt

def plot_to_notebook(time_sec,in_signal,n_samples,out_signal=None):
    plt.figure()
    plt.subplot(1, 1, 1)
    plt.xlabel('Time (usec)')
    plt.grid()
    plt.plot(time_sec[:n_samples]*1e6,in_signal[:n_samples],'y-',label='Input signal')
    if out_signal is not None:
        plt.plot(time_sec[:n_samples]*1e6,out_signal[:n_samples],'g-',linewidth=2,label='FIR output')
    plt.legend()

再输入如下代码,用于模拟信号源生成信号,这里生成的信号是低频正弦信号,并混有高频噪声。

#模拟信号源生成输入信号
import numpy as np

T = 0.002

fs = 100e6 #采样频率

n = int(T * fs)   #采样点数

t = np.linspace(0, T, n, endpoint=False)

samples = 10000*np.sin(0.2e6*2*np.pi*t) + 1500*np.cos(46e6*2*np.pi*t) + 2000*np.sin(12e6*2*np.pi*t)

#信号源为200kHz的正弦信号,46MHz和12MHz的低幅度信号作为输入的模拟噪声。

samples = samples.astype(np.int32)   #将样本转换为32位整数
print('Number of samples: ',len(samples))
#输出采样点数
plot_to_notebook(t,samples,1000)  
#画图

运行效果如图,即滤波前的信号:

下面调用scipy函数对上述信号进行滤波,代码如下:

代码中的coeffs为滤波器的系数向量,获取网站https://www.youtube.com/watch?v=LoLCtSzj9BU(需要翻墙),该网站是一个免费的滤波器设计网站。配置通频带、阻带和采样率,点击DESIGN FILTER,即可获取右边的系数向量。

#采用SciPy函数调用的软件FIR滤波器

from scipy.signal import lfilter

coeffs = [-255,-260,-312,-288,-144,153,616,1233,1963,2739,3474,4081,4481,4620,4481,4081,3474,2739,1963,1233,616,153,-144,-288,-312,-260,-255]
#滤波器系数,生成0-5MHz频带的低通滤波器。

import time
start_time = time.time()
sw_fir_output = lfilter(coeffs,70e3,samples)
stop_time = time.time()
sw_exec_time = stop_time - start_time
print('Software FIR execution time: ',sw_exec_time) #输出软件滤波器的滤波耗时。

# 画图
plot_to_notebook(t,samples,1000,out_signal=sw_fir_output)

运行效果如图,即使用scipy函数滤波后的信号对比:

时间开销打印为0.08311s

(2)使用Vivado的滤波器核生成overlay

打开Vivado,新建一个工程,这里我命名为project_demo,点击Next,选择Boards为PYNQ-Z2,然后Next,最后Finish。

点击左侧Create Block Design,弹框点击OK。

添加ZYNQ7的IP核,然后点击自动连线(Run Connection Automation),勾选左侧,点击OK。

然后添加滤波器IP核,双击此IP核进行设置,首先修改系数向量(Coefficient Vector),

系数向量(Coefficient Vector)获取网站https://www.youtube.com/watch?v=LoLCtSzj9BU(需要翻墙),该网站是一个免费的滤波器设计网站。配置通频带、阻带和采样率,点击DESIGN FILTER,即可获取右边的系数向量,复制粘贴到IP核的配置框里。如图

然后修改输入采样频率为100,修改时钟频率为100。

修改输入数据位宽为32,修改Output Rounding Mode为Non Symmetric Rounding Up模式,修改输出宽度为32。

最后修改TLAST为Packet Framing,勾选Output TREADY,其他不做修改,点击OK。

添加DMA的IP核,双击此IP核设置,取消勾选Enable Scatter Gather Engine,Width of Buffer Length Register修改为23,点击OK。

将axi_dma_0与fir_compiler_0进行手动连线,连完如图

对processing_system7_0进行配置,勾选如图所示接口,点击OK。

点击自动连线(Run Connection Automation),全部勾选,点击OK。

再次点击自动连线(Run Connection Automation),全部勾选,点击OK。

改名,将axi_dma_0改为fir_dma,将fir_compiler_0改为fir。对fir_dma点击Create Hieracty,如图,改名为filter,点击OK。

点击保存,点击生成硬件封装(Create HDL Wrapper)。

然后是生成bit文件,这个时间比较久。

上面完成后,点击Export Block Design生成Tcl文件。

下面就是熟悉的操作了,在此工程文件夹中找到bit文件,tcl文件和hwh文件,修改名字统一为fir_accel,在PYNQ中新建文件夹fir_accel,将三个文件粘贴到文件夹中。

至此,overlay生成完成。

(3)使用overlay对相同信号源信号滤波,比较时间开销

我们继续(1)中的python3文件进行编程,下面调用overlay实现滤波,代码如下:

#硬件滤波器实现

from pynq import Overlay
import pynq.lib.dma


overlay = Overlay('/home/xilinx/pynq/overlays/fir_accel/fir_accel.bit')  #加载overlay文件


dma = overlay.filter.fir_dma  #加载滤波器的DMA


from pynq import Xlnk
import numpy as np

# 为输入和输出信号分配缓冲区
xlnk = Xlnk()
in_buffer = xlnk.cma_array(shape=(n,), dtype=np.int32)
out_buffer = xlnk.cma_array(shape=(n,), dtype=np.int32)

np.copyto(in_buffer,samples)

 
import time
start_time = time.time() #读取开始的时间点
dma.sendchannel.transfer(in_buffer)
dma.recvchannel.transfer(out_buffer)
dma.sendchannel.wait()
dma.recvchannel.wait()
stop_time = time.time()  #读取jieshushijia
hw_exec_time = stop_time-start_time
print('Hardware FIR execution time: ',hw_exec_time)  #输出硬件滤波器的滤波耗时
print('Hardware acceleration factor: ',sw_exec_time / hw_exec_time) #输出加速比

# 画图
plot_to_notebook(t,samples,1000,out_signal=out_buffer)

# 释放缓冲区
in_buffer.close()
out_buffer.close()

运行结果如下:

打印的第一个结果是调用overlay滤波的时间开销,第二个结果是与(1)中软件滤波所用时间的比值,即加速比,达到了20倍以上!

结尾

帖子到这里就结束了,反观PYNQ开发板硬件加速的流程及方法,发现它要求使用者具有ZYNQ方面的硬件开发知识,并且对python的调用方法熟练掌握,所以下一步的学习依然任重而道远!


参考英文视频教程:https://www.bilibili.com/video/BV1ax411Z7B4

overlay文件以及jupyter的ipynb文件链接:https://pan.baidu.com/s/1slDxWPTdoBKCw0x4w-PKow 
提取码:9b9h


本篇博客到此就结束了,文中有不严谨之处欢迎批评指正,下方评论交流,韭菜会尽快回复的!

但行努力,莫问前程,如果您觉着文章有用,请点赞鼓励,谢谢!

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值