I use PYNQ a lot and one of the things I have been meaning to blog about is how it interacts with hardware.
Whether it’s a custom overlay or one from the community, PYNQ is great at abstracting away the challenges of working with the hardware in the overlay. Often, before we can start the main functionality of the overlay (which normally uses DMA), we need to configure the IP blocks in the overlay for the specific application at hand.
The simplest way to do this is to use the read or write class which is provided as part of the default IP class that wraps the Memory Mapped IO (MMIO) PYNQ class to support the selected driver.
Of course, when we use the read / write default IP class, we need to know the register offsets and the bit definition.
To demonstrate this, I created a simple hardware overlay for the PYNQ-Z1 which contains an AXI timer and AXI GPIO device.
To access the timer registers, we can use the read and write functions to read the registers in the AXI Timer memory map. This memory map is defined in PG079. In PYNQ, we can interact with this memory map by using the write and read classes for the default IP.
However, to do that we need to continually refer to the product guide for the register offsets along with the bit fields of each register.
For example, we can use the following command to read the Timer 0 Counter register.
Similarly, we can write to the register 0 to start the counter with the appropriate bits set.
However, a simpler way to work with register mapped interfaces is to use the register map view. This saves us from having to remember register addresses and even bit fields in each register.
We can access the register list by calling the register_map object for the specific IP block. For example, we get the following when querying the register map of the AXI Timer.
Making the same call for the AXI GPIO shows the information below.
Using these methods, we can quickly and easily start developing applications that require setting up, over AXI-Lite interfaces in the programmable logic.
We can read and write to the AXI Timer using the register map settings.
We can also use the auto complete feature to further aid the use of the register map implementations. This is also especially useful for showing the additional objects that are available for that specific IP. You can use the auto complete by hitting tab.
The register map is a particularly useful feature to use in the development of our PYNQ solutions.
One word of caution, however. Be careful when passing register map register objects to other Python functions or methods. These other methods may request a read of the object without your awareness and this may have unexpected effects on your application, like FIFO samples being lost for example.
In the coming weeks, I will also push out a few more blogs with PYNQ tips and tricks.