Xilinx®Zynq®All Programmable device是基于ARM®Cortex®-A9双核处理器(简称处理系统或PS)集成FPGA fabric(简称可编程逻辑或PL)的SOC。PS子系统包括许多专用外围设备(内存控制器、USB、Uart、IIC、SPI等),可以在PL覆盖层中使用额外的硬件IP进行扩展.
Overlays,或硬件库,是可编程/可配置的FPGA设计,将用户应用程序从Zynq的处理系统扩展到可编程逻辑。Overlays可用于加速软件应用程序,或为特定应用程序定制硬件平台。
例如,图像处理是fpga能够提供加速度的典型应用。软件程序员可以使用类似于软件库的Overlay在FPGA结构上运行一些图像处理功能(例如边缘检测、阈值化等)。Overlay可以根据需要动态加载到FPGA,就像一个软件库一样。在本例中,可以在不同的Overlay实现单独的图像处理函数,并根据需要从Python中加载这些函数。
PYNQ提供了一个Python接口,可以通过运行在PS中的Python来控制PL中的Overlay。FPGA设计是一项需要硬件工程知识和专业知识的专门任务。PYNQ的Overlay由硬件设计人员创建,并使用这个PYNQ Python API进行包装。然后,软件开发人员可以使用Python接口来编程和控制专用的硬件Overlay,而不需要自己设计Overlay。这类似于由专家开发人员创建的软件库,然后由许多在应用程序级别工作的其他软件开发人员使用。
Loading an Overlay
默认情况下,在启动时将一个名为base的Overlay(位流)下载到PL中。基础Overlay层可以被认为是一个参考设计的板子。新的Overlay可以安装或复制到板上,并可以在系统运行时加载到PL中。
Overlay通常包括:
配置FPGA结构的位流
Vivado设计Tcl文件来确定可用的IP
将ip作为属性公开的Python API
PYNQ Overlay类可用于加载一个Overlay。通过指定位流文件的名称来实例化Overlay。默认情况下,实例化Overlay还会下载位流并解析Tcl文件。
from pynq import Overlay
base_ overlay= Overlay("base.bit")
对于base Overlay,我们可以使用现有的base Overlay类;这个类将位流上可用的ip公开为这个类的属性。
[1]:from pynq.overlays.base import BaseOverla
base_ overlay = BaseOverlay("base.bit")
一旦Overlay被实例化,就可以使用help()方法来发现Overlay中的内容。帮助信息可用于与Overlay层交互。注意,如果您在自己的板上尝试以下代码,您可能会看到不同的结果,这取决于您使用的PYNQ版本以及您使用的板。
[2]:print( help(base_overlay))
以次的led、按钮实验为例:
在程序最后加上:
print( help(base))
class BaseOverlay(pynq.overlay.Overlay)
| The Base overlay for the Pynq-Z2
|
| This overlay is designed to interact with all of the on board peripherals
| and external interfaces of the Pynq-Z2 board. It exposes the following
| attributes:
|
Attributes |
---|
iop_pmoda : IOP |
IO processor connected to the PMODA interface |
iop_pmodb : IOP |
IO processor connected to the PMODB interface |
iop_arduino : IOP |
IO processor connected to the Arduino interface |
iop_rpi : IOP |
IO processor connected to the RPi interface |
trace_rpi : pynq.logictools.TraceAnalyzer |
Trace analyzer block on RPi interface, controlled by PS. |
trace_pmoda : pynq.logictools.TraceAnalyzer |
Trace analyzer block on PMODA interface, controlled by PS. |
trace_pmodb : pynq.logictools.TraceAnalyzer |
Trace analyzer block on PMODB interface, controlled by PS. |
leds : AxiGPIO |
4-bit output GPIO for interacting with the green LEDs LD0-3 |
buttons : AxiGPIO |
4-bit input GPIO for interacting with the buttons BTN0-3 |
switches : AxiGPIO |
2-bit input GPIO for interacting with the switches SW0 and SW1 |
rgbleds : [pynq.board.RGBLED] |
Wrapper for GPIO for LD4 and LD5 multicolour LEDs |
video : pynq.lib.video.HDMIWrapper |
HDMI input and output interfaces |
audio : pynq.lib.audio.Audio |
Headphone jack and on-board microphone |
pin_select : GPIO |
The pin selection between PMODA (0) and RPI header (1). |
Method resolution order: |
BaseOverlay |
pynq.overlay.Overlay |
pynq.pl.Bitstream |
pynq.pl._BitstreamMeta |
builtins.object |
Methods defined here: |
init(self, bitfile, **kwargs) |
Return a new Overlay object. |
An overlay instantiates a bitstream object as a member initially. |
Parameters |
---------- |
bitfile_name : str |
The bitstream name or absolute path as a string. |
download : bool |
Whether the overlay should be downloaded. |
partial : |
Flag to indicate whether or not the bitstream is partial. |
Note |
---- |
This class requires a Vivado TCL file to be next to bitstream file |
with same name (e.g. base.bit and base.tcl ). |
select_pmoda(self) |
Select PMODA in the shared pins. |
This is done by writing a 0 (default) to the pin_select |
GPIO instance. |
select_rpi(self) |
Select RASPBERRYPI in the shared pins. |
This is done by writing a 1 to the pin_select |
GPIO instance. |
---------------------------------------------------------------------- |
Methods inherited from pynq.overlay.Overlay: |
dir(self) |
dir() -> list |
default dir() implementation |
getattr(self, key) |
Overload of getattr to return a driver for an IP or |
hierarchy. Throws an RuntimeError if the overlay is not loaded. |
download(self) |
The method to download a bitstream onto PL. |
Note |
---- |
After the bitstream has been downloaded, the “timestamp” in PL will be |
updated. In addition, all the dictionaries on PL will |
be reset automatically. |
Returns |
------- |
None |
is_loaded(self) |
This method checks whether a bitstream is loaded. |
This method returns true if the loaded PL bitstream is same |
as this Overlay’s member bitstream. |
Returns |
------- |
bool |
True if bitstream is loaded. |
load_ip_data(self, ip_name, data) |
This method loads the data to the addressable IP. |
Calls the method in the super class to load the data. This method can |
be used to program the IP. For example, users can use this method to |
load the program to the Microblaze processors on PL. |
Note |
---- |
The data is assumed to be in binary format (.bin). The data name will |
be stored as a state information in the IP dictionary. |
Parameters |
---------- |
ip_name : str |
The name of the addressable IP. |
data : str |
The absolute path of the data to be loaded. |
Returns |
------- |
None |
reset(self) |
This function resets all the dictionaries kept in the overlay. |
This function should be used with caution. In most cases, only those |
dictionaries keeping track of states need to be updated. |
Returns |
------- |
None |
---------------------------------------------------------------------- |
Methods inherited from pynq.pl.Bitstream: |
convert_bit_to_bin(self) |
The method to convert a .bit file to .bin file. |
A .bit file is generated by Vivado, but .bin files are needed |
by the Zynq Ultrascale FPGA manager driver. Users must specify |
the absolute path to the source .bit file, and the destination |
.bin file and have read/write access to both paths. |
Note |
---- |
Imlemented based on: https://blog.aeste.my/?p=2892 |
Returns |
------- |
None |
parse_bit_header(self) |
The method to parse the header of a bitstream. |
The returned dictionary has the following keys: |
“design”: str, the Vivado project name that generated the bitstream; |
“version”: str, the Vivado tool version that generated the bitstream; |
“part”: str, the Xilinx part name that the bitstream targets; |
“date”: str, the date the bitstream was compiled on; |
“time”: str, the time the bitstream finished compilation; |
“length”: int, total length of the bitstream (in bytes); |
“data”: binary, binary data in .bit file format |
Returns |
------- |
Dict |
A dictionary containing the header information. |
Note |
---- |
Implemented based on: https://blog.aeste.my/?p=2892 |
---------------------------------------------------------------------- |
Data and other attributes inherited from pynq.pl.Bitstream: |
BS_FPGA_MAN = ‘/sys/class/fpga_manager/fpga0/firmware’ |
BS_FPGA_MAN_FLAGS = ‘/sys/class/fpga_manager/fpga0/flags’ |
---------------------------------------------------------------------- |
Data descriptors inherited from pynq.pl._BitstreamMeta: |
dict |
dictionary for instance variables (if defined) |
weakref |
list of weak references to the object (if defined) |
从上面的help()可以看出,在这种情况下,overlays层包括一个leds实例,从报告中可以看出这是一个AxiGPIO类:
“”"
leds : AxiGPIO
| 4-bit output GPIO for interacting with the green LEDs LD0-3
“”"
在leds对象上运行help()将提供关于该对象的更多信息,包括其API的详细信息
print( help(base.leds))
Help on Channel in module pynq.lib.axigpio object:
class Channel(builtins.object)
| Class representing a single channel of the GPIO controller.
| (类表示GPIO控制器的单个通道。)
| Wires are and bundles of wires can be accessed using array notation
| with the methods on the wires determined by the type of the channel::
| (可以使用数组表示法访问连接和连接束上的方法由电线上的通道类型决定::)
|
| input_channel[0].read()
| output_channel[1:3].on()
|
| This class instantiated not used directly, instead accessed through
| the AxiGPIO
classes attributes. This class exposes the wires
| connected to the channel as an array or elements. Slices of the
| array can be assigned simultaneously.
| (这个类没有直接使用,而是通过 ’ AxiGPIO '类属性。该类公开连接
| 以数组或元素的形式连接到通道的,以数组或元素的形式连接到通道。片的
| 数组可以同时分配。)
|
| Methods defined here:
| (方法定义:)
| getitem(self, idx)
|
| init(self, parent, channel)
| Initialize self. See help(type(self)) for accurate signature.
|
| len(self)
|
| read(self)
| Read the state of the input pins
|
| setdirection(self, direction)
| Set the direction of the channel
|
| Must be one of AxiGPIO.{Input, Output, InOut} or the string
| ‘in’, ‘out’, or ‘inout’
|
| setlength(self, length)
| Set the number of wires connected to the channel
| (设置连接到通道的电线数量)
| wait_for_interrupt_async(self)
| Wait for the interrupt on the channel to be signalled
|
| This is intended to be used by slices waiting for a particular
| value but can be used in any situation to wait for a per-channel
| interrupt.
|
| write(self, val, mask)
| Set the state of the output pins
Data descriptors defined here: |
dict |
dictionary for instance variables (if defined) |
weakref |
list of weak references to the object (if defined) |
trimask |
Gets or sets the tri-state mask for an inout channel |
API可用于控制对象。例如,下面的单元格将打开板上的LD0。
[3]: base.leds[0].toggle()
关于其他IP的信息可以从overlay实例中以类似的方式找到,如下所示。
rgbled的相关内容:
Help on list object:
class list(object)
| list() -> new empty list
| list(iterable) -> new list initialized from iterable’s items
|
| Methods defined here:
|
| add(self, value, /)
| Return self+value.
|
| contains(self, key, /)
| Return key in self.
|
| delitem(self, key, /)
| Delete self[key].
|
| eq(self, value, /)
| Return selfvalue.
|
| ge(self, value, /)
| Return self>=value.
|
| getattribute(self, name, /)
| Return getattr(self, name).
|
| getitem(…)
| x.getitem(y) <> x[y]
|
| gt(self, value, /)
| Return self>value.
|
| iadd(self, value, /)
| Implement self+=value.
|
| imul(self, value, /)
| Implement self*=value.
|
| init(self, /, args, **kwargs)
| Initialize self. See help(type(self)) for accurate signature.
|
| iter(self, /)
| Implement iter(self).
|
| le(self, value, /)
| Return self<=value.
|
| len(self, /)
| Return len(self).
|
| lt(self, value, /)
| Return self
| mul(self, value, /)
| Return self
|
| ne(self, value, /)
| Return self!=value.
|
| new(args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| repr(self, /)
| Return repr(self).
|
| reversed(…)
| L.reversed() – return a reverse iterator over the list
|
| rmul(self, value, /)
| Return selfvalue.
|
| setitem(self, key, value, /)
| Set self[key] to value.
|
| sizeof(…)
| L.sizeof() – size of L in memory, in bytes
|
| append(…)
| L.append(object) -> None – append object to end
|
| clear(…)
| L.clear() -> None – remove all items from L
|
| copy(…)
| L.copy() -> list – a shallow copy of L
|
| count(…)
| L.count(value) -> integer – return number of occurrences of value
|
| extend(…)
| L.extend(iterable) -> None – extend list by appending elements from the iterable
|
| index(…)
| L.index(value, [start, [stop]]) -> integer – return first index of value.
| Raises ValueError if the value is not present.
|
| insert(…)
| L.insert(index, object) – insert object before index
|
| pop(…)
| L.pop([index]) -> item – remove and return item at index (default last).
| Raises IndexError if list is empty or index is out of range.
|
| remove(…)
| L.remove(value) -> None – remove first occurrence of value.
| Raises ValueError if the value is not present.
|
| reverse(…)
| L.reverse() – reverse IN PLACE
|
| sort(…)
| L.sort(key=None, reverse=False) -> None – stable sort IN PLACE
Data and other attributes defined here: |
hash = None |
buttons的内容
Help on Channel in module pynq.lib.axigpio object:
class Channel(builtins.object)
| Class representing a single channel of the GPIO controller.
|
| Wires are and bundles of wires can be accessed using array notation
| with the methods on the wires determined by the type of the channel::
|
| input_channel[0].read()
| output_channel[1:3].on()
|
| This class instantiated not used directly, instead accessed through
| the AxiGPIO
classes attributes. This class exposes the wires
| connected to the channel as an array or elements. Slices of the
| array can be assigned simultaneously.
|
| Methods defined here:
|
| getitem(self, idx)
|
| init(self, parent, channel)
| Initialize self. See help(type(self)) for accurate signature.
|
| len(self)
|
| read(self)
| Read the state of the input pins
|
| setdirection(self, direction)
| Set the direction of the channel
|
| Must be one of AxiGPIO.{Input, Output, InOut} or the string
| ‘in’, ‘out’, or ‘inout’
|
| setlength(self, length)
| Set the number of wires connected to the channel
|
| wait_for_interrupt_async(self)
| Wait for the interrupt on the channel to be signalled
|
| This is intended to be used by slices waiting for a particular
| value but can be used in any situation to wait for a per-channel
| interrupt.
|
| write(self, val, mask)
| Set the state of the output pins
Data descriptors defined here: |
dict |
dictionary for instance variables (if defined) |
weakref |
list of weak references to the object (if defined) |
trimask |
Gets or sets the tri-state mask for an inout channel |
http://www.pynq.io/