Enabling live audio/audio stream in pynq-z1

Hi! I’m new to this forum and the world of PYNQ. When playing around with the Jupyter examples, after some googling I noticed that the PYNQ-Z1 apparently doesn’t support live audio processing much in the premade overlays, and I thought it would be a great practice to try to work on it.
I’m quite new to all this, but my basic question is this: In PYNQ-Z1 reference manual, the PDM ADC of the microphone signal is described, and apparently the output of this process goes to G18 pin of the ZYNQ programmable logic on the FPGA (?). Now, If I wanted to create a custom overlay for the audio processing (first to just enable the basic live audio streaming functionality into the python side), how could I access the G18 microphone data pin of the Zynq programmable logic?

My basic plan would be to try to buffer the audio samples in the FPGA, and then send interrupts from there to the python side in Jupyter for python to read and process those values every time the buffer gets full. Later on, perhaps some FPGA accelerated DSP algorithms could be brought to the picture as well to accelerate the DSP in python. Big world of possibilities would be opened up by enabling the live audio processing.

I was thinking of modifying/building on top of this example of AXI/DMA demos that I found (I had some other links in mind too but I’m only allowed to link 1):

PYNQ AXI DMA Example

Any help in trying to figure out the basic architecture here would be much appreciated, I’m a newbie. My basic intuition at the moment would be that somehow perhaps I could access the microphone pin in Vivado to take the input of the buffering system from there (pin G18), and output interrupts to python for python to read the register values on the Jupyter side, but this also feels somewhat naive and perhaps I’ve missed many important points. Got to start somewhere. First, I’d just need to figure out where to access that pin 18 - is it somehow in Vivado? Thanks!

Okay I’ve now got this idea up to a point where it looks like this:

now, the problem lies with the interrupts from the AXI DMA to the ZYNQ PS. I’m not getting the interrupts work in my code, and I’m wondering whether interrupts would be the way to go at all. I get this error:


ImportError Traceback (most recent call last)
Input In [31], in <cell line: 2>()
1 from pynq import Overlay, allocate
----> 2 from pynq.pl import Interrupt
3 import numpy as np
4 import time

ImportError: cannot import name ‘Interrupt’ from ‘pynq.pl’ (/usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/pl.py)

My code looks like this:

from pynq import Overlay, allocate
from pynq.pl import Interrupt
import numpy as np
import time

Load the overlay

overlay = Overlay(“audiotesti3design_wrapper.bit”)
print(“Overlay loaded successfully!”)

Access the DMA and Interrupt

dma = overlay.axi_dma_0
interrupt = Interrupt(overlay.axi_dma_0.s2mm_introut) # Access the AXI DMA interrupt

Parameters

chunk_size = 64 # Number of PCM samples to process
input_buffer = allocate(shape=(chunk_size,), dtype=np.uint16)

Main loop to acquire and process microphone data

print(“Starting continuous data acquisition using interrupts. Press Ctrl+C to stop.”)

try:
while True:
# Start DMA transfer
dma.recvchannel.transfer(input_buffer)

    # Wait for the interrupt from the DMA (s2mm_introut)
    print("Waiting for DMA interrupt...")
    interrupt.wait()

    # Ensure the transfer is complete
    dma.recvchannel.wait()

    # Print received microphone values
    print("Microphone values:")
    for i in range(min(10, chunk_size)):  # Print only the first 10 samples
        print(f"Sample {i}: {input_buffer[i]}")

    time.sleep(0.1) 

except KeyboardInterrupt:
print(“Data acquisition stopped by user.”)

finally:
# Clean up resources
interrupt.clear()
input_buffer.freebuffer()
print(“Resources freed. Program exited successfully.”)

I’m wondering if this idea of buffering the samples and sending interrupt when the axi fifo is full is the way to go at all. I think it should work since I plugged the s2mm_introut of the AXI DMA to the IRQ_F2P[0:0] of the ZYNQ PS, but I don’t know whats wrong.

Perhaps the right way would be to use this kind of thing from this tutorial instead?

if there is someone out there seeing these messages, thanks for any possible help in advance!