SDSoC Platform Examples

Introduction

This appendix provides simple examples ofSDSoC™platforms created from a working hardware system built using the Vivado® Design Suite, with a software run-time environment, including operating system kernel, boot loaders, file system, and libraries that run on top of the hardware system. Each example demonstrates a commonly used platform feature, and is built upon the ZC702 board available from Xilinx.

  • zc702_axis_io- Accessing a data stream that could represent direct I/O from FPGA pins in an SDSoC platform
  • zc702_acp- Sharing a processing system AXI bus interface between the platform and thesdsccsystem compiler
Each example is structured with the following information:
  • Description of the platform and what it demonstrates.
  • Instructions to generate the SDSoC hardware platform meta-data file.
  • Instructions to create platform software libraries, if required.
  • Description of the SDSoC software platform meta-data file.
  • Basic platform testing.

In addition to these platform examples, it would be worthwhile to inspect the standard SDSoC platforms that are included in theSDx™IDE in the/platformsdirectory.

MicroBlaze Hardware Requirements

In addition to targeting Zynq andZynq® UltraScale+™ MPSoCdevices, you can build an SDSoC platform that targets anyXilinx®device by using the MicroBlaze processor as the target CPU (add reference toMicroBlaze™documentation). A MicroBlaze platform in SDSoC must be a self-contained system containing an LMB memory, MicroBlaze Debug Module (MDM), UART, and AXI Timer built using the Vivado Design Suite and SDK. A sample MicroBlaze example is in/sample/platforms/artyfolder. The figure below shows a minimal system. Notice that the JTAG UART is enabled in the MDM and appears as an AXI-Lite slave. The system runs on a clock (sys) delivered from the board.

Figure:Minimal MicroBlaze System

The SDSoC runtime requires the platform hardware to include two IPs: a timer for thesds_clock_counter()API, and a UART to print runtime error messages. Since a MicroBlaze processor has a single AXI Master port (M_AXI_DP) to control AXI slaves, a MicroBlaze platform must include an AXI interconnect connected to this port as described inExample: Sharing a Platform IP AXI Port.

MicroBlaze systems that use DDR typically connect the processor to the DDR via MIG using the cache facilities built into the MicroBlaze. An example system is shown below.

Figure:MicroBlaze System with MIG

In the system above, the MicroBlaze is configured with an 8 KB cache. The instruction and data cache ports (M_AXI_DCandM_AXI_IC) are connected to the MIG. The UART is connected to an on-board USB-to-UART converter chip and does not use the JTAG UART from the previous design. The system runs on the user-interface (UI) clock produced by MIG. Other than these differences, the MicroBlaze systems are identical.

Ports on the MIG’s AXI Interconnect IP can be registered using PFM properties as described inDeclaring AXI Portsfor the typeM_AXI_HPwhich is exactly the same as Zynq HP Ports. SDSoC runtime will invalidate or flush buffers in exactly the same way as it does for Zynq devices.

Example: Direct I/O in an SDSoC Platform

AnSDSoCplatform can include input and output subsystems; for example, analog-to-digital and digital-to-analog converters, or video I/O, by converting raw physical data streams intoAXI4-Streaminterfaces that are exported as part of the platform interface specification. For information on thezc702_axis_iosample platform, see “Using External I/O” in theSDSoC Environment User Guide. This example includes sample applications that demonstrate how an input data stream can be written directly into memory buffers without data loss, and how an application can "packetize" the data stream at the AXI transport level to communicate with other functions (including, but not limited to DMAs) that require packet framing.

Note:The source code for this platform can be found in <sdx_root>/samples/platforms/zc702_axis_io/src.

Run the following command from the command shell usingzc702_axis_io_dsa.tcl,aVivadoTcl script to build the hardware platform in a batch mode:

vivado –mode batch –source zc702_axis_io_dsa.tcl

Run the following command to build the platform in GUI mode to inspect the hardware system in theVivadoIP integrator:

vivado –mode gui –source zc702_axis_io_dsa.tcl

The command opens theVivadoIDE and builds the platform. The resulting hardware system will look similar to the following block diagram.

Figure:zc702_axis_io Block Diagram

To make this design portable, this platform includes a free-running binary counter that generates a continuous stream of data samples at 50 MHz, which acts as a proxy for data streaming directly from FPGA pins. To convert this input data stream into anAXI4-StreamforSDSoCapplications, the platform connects the counter output to thes_axis_tdataslave port of anAXI4-Streamdata FIFO, with a constant block providing the requireds_axis_tvalidsignal, always one. The data FIFO IP is configured to store up to 1024 samples with an output clock of 100 MHz to provide system elasticity so that the consumer of the stream can process the stream "bubble-free" (i.e., without dropping data samples). In a real platform, the means for converting to anAXI4-Stream, relative clocking and amount of hardware buffering will vary according to system requirements.

Similar to input streaming off of an analog-to-digital converter, this data stream is not packetized, which means theAXI4-Streamhas noTLASTsignal. Consequently, anySDSoCapplication that consumes the data stream must be capable of handling unpacketized streams. Within theSDSoCenvironment, every data mover IP core (e.g., theVivadoAXI4Direct Memory Access IP (AXI DMA)) requires packetizedAXI4-Streams that include theTLASTsignal. To consume the streaming input from this platform, an application must employ direct hardware connections to theAXI4-Streamport.

TIP:A platform can also export an AXI4-Streamport that includes the TLASTsignal, in which case SDSoCapplications do not require direct connections to the port.

Declaring the SDSoC Hardware Platform Interface

As described inCreating the Platform Hardware Component, the hardware platform port interface is defined by setting PFM properties on cells and ports within aVivadoIP integrator block diagram.

In thezc702_axis_io_dsa.tclscript, this occurs in lines 45-67. Use the following steps to set the properties on cells and ports within aVivadoIP integrator block diagram.

  1. Declare the platform name as an IP-XACT VLNV (vendor:library:name:version) string using the following commands:
    set_property PFM_NAME \ "xilinx.com:zc702_axis_io:zc702_axis_io:1.0" \ [get_files ./zc702_axis_io_vivado/zc702_axis_io.srcs/\ sources_1/bd/zc702_axis_io/zc702_axis_io.bd]
  2. Declare a platform clock with id 1 using the following commands:
    set_property PFM.CLOCK { \ clk_out2 {id "1" is_default "true" proc_sys_reset "psr_1" } \ } [get_bd_cells /clk_wiz_0]

    Note that every clock must have an associatedproc_sys_resetthat provides synchronized reset signals for blocks using this clock.

  3. At least, one general purpose AXI master and one AXI slave port must be declared. Use the following command to declare the platform AXI interfaces, each with an associative list containing several attributes.
    set_property PFM.AXI_PORT { \ M_AXI_GP0 {memport "M_AXI_GP"} \ M_AXI_GP1 {memport "M_AXI_GP"} \ S_AXI_ACP {memport "S_AXI_ACP" sptag "ACP" memory "ps7 ACP_DDR_LOWOCM"} \ S_AXI_HP0 {memport "S_AXI_HP" sptag "HP0" memory ps7 HP0_DDR_LOWOCM"} \ S_AXI_HP1 {memport "S_AXI_HP" sptag "HP1" memory ps7 HP1_DDR_LOWOCM"} \ S_AXI_HP2 {memport "S_AXI_HP" sptag "HP2" memory ps7 HP2_DDR_LOWOCM"} \ S_AXI_HP3 {memport "S_AXI_HP" sptag "HP3" memory ps7 HP3_DDR_LOWOCM"} \ } [get_bd_cells /ps7]

    Each AXI port requires a memport memory type declaration, which must be one of the following:

    1. M_AXI_GP– a general purpose master
    2. S_AXI_ACP– a cache coherent slave
    3. S_AXI_HP– a high performance, non-cache coherent slave
    4. S_AXI_HPC– a high performance slave (Zynq UltraScale+ MPSoConly)
    5. MIG– a slave on an external DDR (MIG) memory controller IP

      An AXI slave port requires an sptag that provides a symbolic tag to represent the port, and two additional memory attributes.

    6. Memory instance: The cell name of the block in the IP integrator address editor
    7. Address segment: The ‘Base Name’ associated with the port as seen in theVivadoIP integrator address editor
  4. Use the following command to declare thestream_fifomasterAXI4-Streamport.
    set_property PFM.AXIS_PORT { \ M_AXIS {type "M_AXIS"} \ } [get_bd_cells /stream_fifo]
  5. Use the following command to declare the interrupt inputs by constructing a list of port names on aConcatblock that is connected to the interrupt port on theprocessing_system7block:
    set intVar [] for {set i 0} {$i < 16} {incr i} { lappend intVar In$i {} } set_property PFM.IRQ $intVar [get_bd_cells /xlconcat_0]
  6. After declaring the port interface, use the following command to generate the output products required to create the DSA from the block diagram:
    generate_target all \ [get_files ./zc702_axis_io_vivado/zc702_axis_io.srcs/\ sources_1/bd/zc702_axis_io/zc702_axis_io.bd]
  7. Use the following command to generate the DSA:
    write_dsa -force ./zc702_axis_io.dsa

Making the SDSoC Platform from the Command Line

As described in Software Platform Data Creation, the following platform components provide the application run time context:
  • Bootloaders
  • Operating system
  • File system

The/samples/platforms/zc702_axis_io/src/zc702_axis_io_pfm.tclfile is a a tcl script that builds theSDSoCplatform by incorporating the DSA hardware and software components that were built using PetaLinux andSDx(SDK style first-stage boot loader project).

Run the following command from anSDSoCcommand shell to build the platform in batch mode usingzc702_axis_io_pfm.tclSDxtcl script which is executed by thexsctutility provided as part of SDx.:

xsct –sdx ./zc702_axis_io_dsa.tcl
  1. Use the following command to create a platform object in thexsctcommand line interpreter:
    platform -name zc702_axis_io \ -desc "Zynq ZC702 Board with direct I/O" \ -hw ./zc702_axis_io.dsa -out ./output \ -prebuilt -samples samples
  2. Use the following command to create a new system configuration for Linux applications:
    system -name linux -display-name "Linux" \ -boot ./boot -readme ./generic.readme
  3. Use the following command to define a processor group or domain for this system configuration:
    domain -name linux -proc ps7_cortexa9_0 \ -os linux -image ./linux/image
  4. Use the following command to register boot files for the Linux system configuration:
    boot -bif ./linux/linux.bif
  5. Use the following command to register QEMU arguments and a directory containing boot files to supportSDSoCemulation:
    domain -qemu-args ./qemu/lnx/qemu_args.txt domain -qemu-data ./boot
  6. Use the following command to create and populate a standalone ('bare metal') system configuration:
    system -name standalone -display-name "Standalone" -boot ./boot -readme ./generic.readme domain -name standalone -proc ps7_cortexa9_0 -os standalone app -lscript ./standalone/lscript.ld boot -bif ./standalone/standalone.bif domain -qemu-args ./qemu/std/qemu_args.txt domain -qemu-data ./boot
  7. Use the following command to create theSDSoCplatform:
    platform –generate

    This script creates anSDKPlatform project calledzc702_axis_ioin the following directory:

    output/zc702_axis_io/export/

Platform Sample Designs

An SDSoCplatform can include sample applications that demonstrate its use, as described in Sample Applications. The SDxIDE looks for a file called samples//description.json( template.xml) for information on the sample application within a platform. The template.xmlfile for the zc702_axis_ioplatform lists several test applications, each of which is of specific interest.
  

To use a platform in theSDxIDE, you must add it to the platform repository for the Eclipse workspace as described in the following steps.

  1. LaunchXilinxSDxand provide a path to your workspace such as/myplatforms/.
  2. Create a new project by selectingFile>New>Xilinx SDx Project.
  3. Specify the type of project as anApplication Project, and clickNext.
  4. Specify a project name in the Create New SDx Project page such asmy_zc702_axis_io, and clickNext.
  5. In the Choose Hardware Platform page clickAdd Custom Platform.

    Figure:Add Custom Platform

  6. Navigate to the folder containing the platform/samples/platforms/zc702_axis_io.
  7. The platform will show up in the Choose Hardware Platform Page. Selectzc702_axis_io (custom)and clickNext.

    Figure:Choose Hardware Platform

  8. On the System Configuration page, keep the defaultLinuxfor System Configuration and clickNext.
  9. On the Templates page, selectUnpacketized AXI4-Stream to DDRto test the platform with one of the sample applications, and clickFinish.

    Thes2mm_data_copyfunction is pre-selected for hardware acceleration. The program data flow withins2mm_data_copy_wrappercreates a direct signal path from the platform input to a hardware function calleds2mm_data_copythat then pushes the data to memory as azero_copydatamover. That is, thes2mm_data_copyfunction acts as a custom DMA. The main program allocates four buffers, invokess2mm_data_copy_wrapper, and then checks the written buffers to ensure that data values are sequential, i.e., the data is written bubble-free. For simplicity, this program does not reset the counter, so the initial value depends upon how much time elapses between board power-up and invoking the program.

  10. Open upmain.cpp. Key points to observe are:
    • Buffers are allocated usingsds_allocto guarantee physically contiguous allocation required for the zero_copy datamover.
      unsigned *bufs[NUM_BUFFERS]; unsigned* rbuf0; for(int i=0; i
    • Specify the connectivity between hardware function and the platform using thesys_portpragma.
      // s2mm "DMA" accelerator #pragma SDS data sys_port (fifo:stream_fifo_M_AXIS) #pragma SDS data zero_copy(buf) int s2mm_data_copy(unsigned *fifo, unsigned buf[BUF_SIZE]) { #pragma HLS interface axis port=fifo for(int i=0; i
  11. Build the application by clicking on the Build icon in the toolbar. When the build completes, theDebugfolder contains ansd_cardfolder with the boot image and application ELF.
  12. After the build finishes, copy the contents of thesd_carddirectory onto an SD card, boot, and runmy_zc702_axis_io.elf.
sh-4.3# cd /mnt sh-4.3# ./my_zc702_axis_io.elf TEST PASSED! sh-4.3#

Example: Sharing a Platform IP AXI Port

To share an AXI master (slave) interface between a platform IP and the accelerator and data motion IPs generated by the SDSoC compilers, employ the SDSoC Tcl API to declare the first unused AXI master (slave) port (in index order) on the AXI interconnect IP block connected to the shared interface. Your platform must use each of the lower indexed masters (slaves) on this AXI interconnect.

SDSoC Platform Hardware Interface

Use the following steps to build the SDSoC hardware platform interface within a Vivado IDE:
Note:The source code for this platform is available in /samples/platforms/zc702_acp/srcfile.
  1. Run the following command from the command shell usingzc702_acp_dsa.tcl, a Vivado tcl script to build the hardware platform in a batch mode:
    vivado –mode batch –source zc702_acp_dsa.tcl

    You can also build the platform in GUI mode to inspect the hardware system in Vivado IP integrator. Run the following command to build the platform in GUI mode:

    vivado –mode gui –source zc702_acp_dsa.tcl

    This command will open the Vivado IDE and build the platform. The resulting hardware system will look similar to the following block diagram.

    Figure:zc702_acp Block Design

  2. Use the following commands to declare the platform name as an IP-XACT VLNV (vendor:library:name:version) string:
    set_property PFM_NAME \ "xilinx.com:zc702_acp:zc702_acp:1.0" \ [get_files ./zc702_acp_vivado/zc702_acp.srcs/\ sources_1/bd/zc702_acp/zc702_acp.bd]
  3. Use the following command to declare a platform clock with id 1:
    set_property PFM.CLOCK { \ clk_out1 {id "2" is_default "true" proc_sys_reset "psr_0" } \ clk_out2 {id "1" is_default "false" proc_sys_reset "psr_1" } \ clk_out3 {id "0" is_default "false" proc_sys_reset "psr_2" } \ clk_out4 {id "3" is_default "false" proc_sys_reset "psr_3" } \ } [get_bd_cells /clk_wiz_0]

    Note that every clock must have an associatedproc_sys_resetthat provides synchronized reset signals for blocks using this clock.

  4. At least one general purpose AXI master and one AXI slave port must be declared. Use the following command to declare the platform AXI interfaces from the processing system IP, each with an associative list containing several attributes:
    set_property PFM.AXI_PORT { \ M_AXI_GP1 {memport "M_AXI_GP"} \ S_AXI_HP0 {memport "S_AXI_HP" sptag "HP0" memory ps7 HP0_DDR_LOWOCM"} \ S_AXI_HP1 {memport "S_AXI_HP" sptag "HP1" memory ps7 HP1_DDR_LOWOCM"} \ S_AXI_HP2 {memport "S_AXI_HP" sptag "HP2" memory ps7 HP2_DDR_LOWOCM"} \ S_AXI_HP3 {memport "S_AXI_HP" sptag "HP3" memory ps7 HP3_DDR_LOWOCM"} \ } [get_bd_cells /ps7]

    Each AXI port requires a memport memory type declaration, which must be one of the following:

    • M_AXI_GP– a general purpose master
    • S_AXI_ACP– a cache coherent slave
    • S_AXI_HP– a high performance, non-cache coherent slave
    • S_AXI_HPC– a high performance slave (Zynq UltraScale+ MPSoConly)
    • MIG– a slave on an external DDR (MIG) memory controller IP

      An AXI slave port requires an sptag that provides a symbolic tag to represent the port, and two additional memory attributes.

    • Memory instance – the cell name of the block in the IP integrator address editor
    • Address segment – the ‘Base Name’ associated with the port as seen in the Vivado IP integrator address editor
  5. The platform uses both theS_AXI_ACPandM_AXI_GP0ports on the processing system. Use the following Tcl code to declare additional ports on the axi_interconnect IPs within the platform:
    set gpMasters [] for {set i 1} {$i < 64} {incr i} { lappend gpMasters M[format %02d $i]_AXI {memport "M_AXI_GP"} } set_property PFM.AXI_PORT $gpMasters \ [get_bd_cells /axi_ic_ps7_M_AXI_GP0] set acpSlaves [] for {set i 1} {$i < 8} {incr i} { lappend acpSlaves S[format %02d $i]_AXI {memport "S_AXI_ACP" \ sptag "ACP" memory "ps_ACP_DDR_LOWOCM"} } set_property PFM.AXI_PORT $acpSlaves \ [get_bd_cells /axi_ic_ps7_S_AXI_ACP]

    Note that the memport attribute is inherited from the processing system port connected to the axi_interconnect.

  6. Use the following command declares the interrupt inputs by constructing a list of port names on a Concat block that is connected to the interrupt port on the processing_system7 block:
    set intVar [] for {set i 0} {$i < 16} {incr i} { lappend intVar In$i {} } set_property PFM.IRQ $intVar [get_bd_cells /xlconcat_0]
  7. After declaring the port interface, use the following command to generate the output products required to create the DSA from the block diagram:
    generate_target all \ [get_files ./zc702_acp_vivado/zc702_acp.srcs/\ sources_1/bd/zc702_acp/zc702_acp.bd]
  8. Finally, use the following command to generate the DSA:
    write_dsa -force ./zc702_acp.dsa