.. rst-class:: break_before .. note:: The full documentation for the xibif-connection package can be found at `connection.xibif.ch `_. Writing Software ================ All the fuzz about drivers and interfaces is no use if there is no software being written! .. note:: Ensure that you have properly activated the Python environment you created when installing XiBIF. Start by navigating to ``sw``. You will find that there are already some files in this directory. - `regs.py`: A class representing your register block - `xibif_demo.py`: A collection of simple accesses to a XiBIF FPGA Note the line where the ``XibifConnection`` object is imported. This object serves as a hardware abstraction to interface with your board. .. code-block:: python from xibif_connection.api import XibifConnection board = XibifConnection(ip="192.168.1.10", uuid=0xDEAD_CAFE) board.connect() # establish a connection .. _writing-software-register-access: Register Access --------------- Now there is a connection to the board and you can already read/write your registers. However, you would have to remember all the register addresses and bitfield masks. To avoid this, there is the generated register map which is used like this: .. code-block:: python from regs import RegMap handleReg = RegMap(connection) handleReg.register_1 = 1 # set the value of register_1 handleReg.register_1_bf.field_1 = 1 # set the value of field_1 in register_1 (read-modify-write) val = handleReg.register_2 # get the value of register_2 val = handleReg.register_2.field_1 # get the value of field_1 in register_2 .. warning:: Each access to a register property will trigger a read/write operation on the FPGA. If you have defined special register access policies such as `rc` (read to clear), reading a register might clear a field that you are not interested in. .. hint:: If you want to modify multiple fields of the same register at one time, you will have to use standard masking and bit-shifting. The appropriate values are also saved in the ``RegMap``. For each register a ``_ADDR`` property specifies the register's address, and for each field the ``__MSK`` and ``__POS`` provide the values for bitfield operations. A field is read like this: .. code-block:: python rdata = connection.read(handleReg._ADDR) field_value = (rdata >> handleReg.__POS) & handleReg.__MSK and written like this: .. code-block:: python valToWrite = 1 rdata = connection.read(handleReg._ADDR) rdata = rdata & (~(handleReg.__MSK << handleReg.__POS)) rdata = rdata | (valToWrite << handleReg.__POS) connection.write(handleReg._ADDR, rdata) You can perform multiple field modifications before calling ``xibif.write()``. Streaming --------- In order to write to the AXI-stream, use: .. code-block:: python connection.write_stream(streamToWrite) To read data from the stream, you have two options. You can either read a specified number of 4-byte words from the stream or read all available data. .. code-block:: python # read All stream = connection.read_stream() # read 10 words (40 bytes) stream = connection.read_stream(10) It might be possible that an error occurs during streaming. To check if an error has occurred, the properties ``connection.status.[pc2plFifo|pl2pcFifo].axiError`` can be used. The error flags are saved until a flush of the FIFOs is performed. To flush the FIFOs, use: .. code-block:: python connection.flush_stream() The following error codes are possible: .. list-table:: :header-rows: 1 :widths: 30 70 * - Error Value - Description * - ``0`` - No error occurred during streaming. * - ``1`` - An AXI-Error on the AXI-Master interface occurred during streaming. * - ``2`` - The FIFO overflowed during streaming. This can happen if the PC or PL is not fast enough to read the data. * - ``3`` - Both an AXI-Error and a FIFO overflow occurred during streaming. AXI-Access ---------- The XiBIF platform provides a simple interface to access the AXI bus. This is useful for accessing IP blocks that are not part of the XiBIF platform. The interface is similar to the register access, but you have to specify the address of the register you want to access. .. note:: Only addresses that are routed through the AXI Firewall IP are accessible. Attach your AXI block to the AXI SmartConnect named ``peri``. To read a register, use: .. code-block:: python connection.read_axi(address) Similarly, to write to a register, use: .. code-block:: python connection.write_axi(address, value, mask=0xFFFFFFFF) The mask is optional and defaults to 0xFFFFFFFF. The mask is used to specify which bits of the register you want to write. For example, if you want to write only to the lower 16 bits of a register, you can use: .. code-block:: python connection.write_axi(address, value, 0x0000FFFF) Error Codes ~~~~~~~~~~~~ Only AXI-Addresses that are routed through the AXI Firewall IP are accessible. For Zynq-7000 platforms, the address needs to be in the range of ``0x40000000`` to ``0x4FFFFFFF``. For ZynqMP platforms, the address needs to be in the range of ``0xA0000000`` to ``0xAFFFFFFF``. Accessing other addresses will result in an error. It is further not possible to access the XiBIF IP Blocks with these functions. Calls to these addresses will result in an error.The following error codes are possible: .. list-table:: :header-rows: 1 :widths: 30 50 * - Error Code - Description * - ``AXI_ACCESS_OK`` - Access was successful. * - ``AXI_ACCESS_NOT_ALLOWED_RANGE`` - The address is not within the allowed range. It must be in the range of ``0x40000000`` to ``0x4FFFFFFF`` for Zynq-7000 platforms or ``0xA0000000`` to ``0xAFFFFFFF`` for ZynqMP platforms. * - ``AXI_ACCESS_NOT_ALLOWED_XIBIF_RANGE`` - The address is within the XiBIF reserved range and cannot be accessed. * - ``AXI_FIREWALL_ERROR`` - The AXI Firewall detected an error. * - ``AXI_FIREWALL_DATA_DEC0DEE3_DEADFA11`` - The AXI Firewall returned a specific error code indicating a data issue. If you expect to read the value ``0xDEADC0DE`` or ``0xDEADFA11`` you can disable this error by setting the property ``disable_axi_check_DEC0DEE3_DEADFA11`` to ``True``. * - ``AXI_ACCESS_ADDRESS_NOT_ALIGNED`` - The address is not aligned to 32bit values. The address must be a multiple of 4. Timeout ~~~~~~~ The timeout of the AXI Firewall IP can be configured using the command ``xibif settings``. It is specified in clock cycles of the AXI clock. The default is 100 clock cycles. .. code-block:: bash xibif settings --timeout_axi_firewall_clocks 100 Debugging --------- UART ~~~~ You can enable debugging information to be printed over UART. The simplest is to print out the status information of a connected XiBIF device by calling: .. code-block:: python connection.print_status_uart() Alternatively, you can enable all ``DEBUG_PRINTF`` in the software source code by calling: .. code-block:: python connection.set_uart_debug(True) Be aware that this will result in a lot of information, as every read, write, violation and so forth will be printed. To disable the debug information again, call the function with ``False`` as an argument. .. code-block:: python connection.set_uart_debug(False)