Added sections about FIR filter implementation and testing
|}
</pre>
This Technical Note shows hot to run PYNQ on Bora platform. It is worth remembering that, even though the procedure was tested on Bora, it should work on BoraX as well without any modification.
To see PYNQ in action, please see [https://www.youtube.com/watch?v=LoLCtSzj9BU this clip]. ==Setting up the boardTestbed's Hardware and Software Configuration==<pre class="workstation-terminal mw-collapsible mw-collapsed">As stated before, the procedure was tested on Bora/BoraEVB hardware platform.
With regard to the software configuration, the following versions were used:
*U-Boot 2018.1 (at the time of this writing, '''this version was not officially supported by any BELK release yet''')
*Linux kernel 4.14.0 (at the time of this writing, '''this version was not officially supported by any BELK release yet''')
*Root filesystem: extracted from [http://files.digilent.com/Products/PYNQ/pynq_z1_v2.3.zip Pynq-Z1 v2.3 image] and mounted from microSD card.
xilinx@pynq:~$ cat /proc/version Original root file system included several kernel drivers built as modules. The Linux version 4.14.0-xilinx-00008-ge79ecef-dirty (sysadmin@stage-OptiPlex-7010) (gcc version 7.2kernel used for this test was different than the kernel released along with the PYNQ's root file system, however.1 20171011 (Linaro GCC 7Consequently, these modules were not compatible with the kernel running on Bora.2-2017To overcome this issue, these drivers were linked statically into the kernel image.11-rc1)) #8 SMP PREEMPT Fri Sep 14 10:33:28 CEST 2018
==Setting Up the Board==
U-Boot environment was configured in order to retrieve the kernel image and the device tree blob from the microSD card. Also, it was configured to make the kernel to mount the root file system from a partition of the microSD card.
The following box shows the full boot process (clock on the "Expand" box):<pre class="workstation-terminal mw-collapsible mw-collapsed">U-Boot 20142018.07-0496701-g7b885e100022-dirty g322f20f (Feb 20 2015 Aug 28 2018 - 1711:0120:2719 +0200) [belk-2.1.0]
Model: BoraBoard: BORAXilinx ZynqSilicon: v3.1
I2C: ready
DRAM: ECC disabled 1 GiB
Relocating to 3ff22000, new gd at 3eae1ee8, sp at 3eae1ec0
NAND: 1024 MiB
MMC: zynq_sdhcisdhci@e0100000: 0(SD)SF: Detected S25FL256S_64K s25fl256s_64k with page size 256 Bytes, erase size 64 KiB, total 32 MiB3BIn: serial@e0001000Out: serial@e0001000Err: serial@e0001000NetSF: Gem.e000b000Detected s25fl256s_64k with page size 256 Bytes, erase size 64 KiB, total 3BHit any key to stop autobootSF: 0 Detected s25fl256s_64k with page size 256 Bytes, erase size 64 KiB, total 3BGem.e000b000 Waiting for PHY auto negotiation to complete...... doneSOM ConfigID#: 00000001Using Gem.e000b000 deviceSOM UniqueID#: 01234567:89abcdefTFTP from server 192.168.2.10; our IP address is 192.168.2.11ds2431_readmem(): error in chip resetFilename 'bora/uImage'.ds2431_readmem(): error in reading bufferLoad addressds2431_readmem(): 0x2080000error in chip resetLoadingds2431_readmem(): error in reading bufferCB ConfigID CRC mismatch for 0x00000000 (was 0x00000000, expected 0x2144df1c) atCB ConfigID#: ffffffffCB UniqueID################################################################: 00000000:00000000 #################################################################Net: ZYNQ GEM: e000b000, phyaddr 7, interface rgmii-id #################################################################eth0: ethernet@e000b000 #################################################################Hit ENTER within 3 seconds to stop autoboot ###################reading uImage 64140752 bytes read in 239 ms (16.8 5 MiB/sdoneBytes transferred = 4082664 (3e4be8 hex)Using Gem.e000b000 deviceTFTP from server 192.168.2.10; our IP address is 192.168.2.11Filename 'bora/reading bora.dtb'.Load address: 0x2000000Loading: # 310678 bytes read in 13 ms (801.4 MiB8 KiB/sdoneBytes transferred = 10634 (298a hex)Unknown command FDT: property som_configid FDT: override 'configidsom_configid' - try with 'help00000001'FDT: property cb_configid does not match
## Booting kernel from Legacy Image at 02080000 ...
*First, a software implementation of an FIR filter was created
*A hardware implementation of the same FIR filter was generated using the [https://www.xilinx.com/products/intellectual-property/fir_compiler.html FIR Compiler] provided by Vivado.
*The resulting IP was instantiated in Programmable Logic (PL).
*Using Jupyter Notebooks, a simple Python test code was edited and run to exercise the filter.
**Two different approaches were used: generic driver and IP-specific driver.
This example was inspired by [http://www.fpgadeveloper.com/2018/03/how-to-accelerate-a-python-function-with-pynq.html this tutorial].
===Basic Operations===
*In order to open the Jupyter Notebook web dashboard, do the following steps:
**Open the browser (only Google Chrome is supported)
**Go to http://<IP address>:9090 if your board is connected to a computer via static IP address or to <nowiki>http://pynq:9090</nowiki> if your host can resolve the target's hostname
**Log in with username <code>xilinx</code> and password <code>xilinx</code>.
[[File:PYNQ-jupyter-welcome.png|thumb|center|600px|Jupyter Notebook web dashboard]]
*To move files to/from Jupyter Notebook it is convenient to share the home directory of the target's <code>xilinx</code> user. For instance, to access the Pynq home area as a network drive via Samba protocol:
*Open a file browser and click "Go" > "Enter Location"
*Log as <code>xilinx</code> with password <code>xilinx</code>.
===Editing and executing Python functions===
Before implementing the FIR filter in PL, we created a software implementation with the [https://www.scipy.org/ SciPy] library. To verify it, we applied it to a noisy signal.
In essence we
* created a new notebook by clicking on the ''New'' button at the top and select ''Python 3''
[[File:PYNQ-jupyter-new-file.png|thumb|center|600px|Creating a new notebook]]
*selected ''Code'' on the top bar and write some Python code
* clicked ''Run'' on the top bar to run code on a kernel.
The following image shows the noisy and the filtered signals.
[[File:PYNQ-jupyter-FIR-result.png|thumb|center|600px|Input and output signals]]
For more details, please refer to the section [http://www.fpgadeveloper.com/2018/03/how-to-accelerate-a-python-function-with-pynq.html ''Software FIR filter using SciPy''].
===Implementing a Hardware-Accelerated Version of the FIR Filter in PL===
To access an hardware-accelerated function from Python, PYNQ requires to load a custom overlay. Overlays are built with Vivado and are composed by:
*an FPGA bitstream (.bit file)
*a block design (.tcl file)
====Creating and Running a New Custom Overlay: Approach #1====
We created a custom overlay associated with the hardware implementation of the FIR filter. This first approach made use of the FIR Compiler tool provided by Vivado.
The fundamental steps required to do this are:
*Opening a new Vivado project, selecting ''RTL project'' and ''Bora SOM'' as the target board
*Creating your block design
**Adding ''FIR compiler'' block (included in Vivado default IP) and setting it up
**Adding ''AXI direct memory access'' block and setting it up
**On ''ZYNQ7 Processing System'' block, enabling a ''High-Performance AXI 32b/64b Slave Ports'' on interface HP0
**Connecting AXIS_DATA bus of AXI and FIR block
**''Runnin Connection Automation'' to complete wiring
*Creating Hierarchy of AXI and FIR block named <code>filter</code>
=====Running Custom Overlays with Generic Driver =====
To access the overlay with the generic driver:
*Load <code>Overlay</code> and <code>Xlnx</code> modules from <code>pynq</code> and <code>pynq.lib.dma</code>.
*Create <code>Overlay</code> and <code>Xlnk</code> objects
These steps allows you to communicate directly through a DMA buffer.
For more details, please refer to the section [http://www.fpgadeveloper.com/2018/03/how-to-accelerate-a-python-function-with-pynq.html ''Hardware FIR Implementation''].
=====Running Custom Overlays with IP-Specific Driver =====
To access the overlay with a specific driver:
*Import <code>DefaultHierarchy</code> from <code>pynq</code>
*create a new class for FIR filter with a method to communicate directly thorough a DMA buffer
*create a <code>checkhierarchy</code> method to check the IP contained under ''filter'' hierarchy
For more details, please refer to the section [http://www.fpgadeveloper.com/2018/03/how-to-accelerate-a-python-function-with-pynq.html ''Driver for FIR accelerator''].
====Creating and Running a New Custom Overlay: Approach #2====
This approach makes use of a different method to implement the filter. In this case, the filter was written in C++ and implemented by using [https://www.xilinx.com/products/design-tools/vivado/integration/esl-design.html Vivado High-Level Synthesis (HLS)].
The fundamental steps required to do this are:
*Opening a new Vivado HLS project, selecting Bora SOM as the target board
*Creating a new C++ source file
*Writing C++ code of FIR custom IP
**Creating AXI Stream interfaces for input and output
**Defining FIR coefficients and normalizing their values
**Using some #pragmas to optimize the execution of the algorithm
*Synthesizing new IP running ''Run C synthesis''
*Exporting new IP running ''Export RTL''
*Opening a new Vivado project, selecting RTL project and Bora SOM as the target board
*Adding the new IP in IP list
**Opening ''IP Catalog''
**Adding repository of the custom IP
To complete the procedure and export the Vivado project, the same steps described previously have to be done.
The data flows are implemented as AXI streams. The following images show the input and the output to/from the filter respectively.