本篇主要介绍,使用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方法)的优势。
首先,在浏览器打开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
打开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生成完成。
我们继续(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
本篇博客到此就结束了,文中有不严谨之处欢迎批评指正,下方评论交流,韭菜会尽快回复的!
但行努力,莫问前程,如果您觉着文章有用,请点赞鼓励,谢谢!