Overlay hierarchy

My overlay has some layers of hierarchy. As an example I have some BRAM that look like this in the block design:

If I run the help on the overlay I get this:

IP Blocks
rf_path/usp_rf_data_converter_0 : xrfdc.RFdc
axi_gpio_spi_mux     : pynq.lib.axigpio.AxiGPIO
axi_uartlite_0       : pynq.overlay.DefaultIP
adc_gpio_0           : pynq.lib.axigpio.AxiGPIO
dac_gpio             : pynq.lib.axigpio.AxiGPIO
clk_phase_sync       : pynq.lib.axigpio.AxiGPIO
axil_scratchpad_1    : pynq.overlay.DefaultIP
rf_path/tx_beam/complex_mult_axil_0 : pynq.overlay.DefaultIP
mb_clk_sync_gpio0    : pynq.lib.axigpio.AxiGPIO
zynq_ultra_ps_e_0    : pynq.overlay.DefaultIP

hier_cap2            : pynq.overlay.DefaultHierarchy
rf_path              : pynq.overlay.DefaultHierarchy
hier_cap0            : pynq.overlay.DefaultHierarchy
hier_cap3            : pynq.overlay.DefaultHierarchy
hier_play            : pynq.overlay.DefaultHierarchy
hier_cap1            : pynq.overlay.DefaultHierarchy
rf_path/tx_beam      : pynq.overlay.DefaultHierarchy
hier_dac_cap         : pynq.overlay.DefaultHierarchy


GPIO Outputs

hier_playaxi_bram_ctrl_0 : Memory
hier_cap0axi_bram_ctrl_0 : Memory
hier_cap1axi_bram_ctrl_0 : Memory
hier_cap2axi_bram_ctrl_0 : Memory
hier_cap3axi_bram_ctrl_0 : Memory
hier_dac_capaxi_bram_ctrl_0 : Memory
PSDDR                : Memory

As you can see the hier_play BRAM doesn’t appear under the IP blocks, it appears under Memories as ‘hier_playaxi_bram_ctrl_0’.

In the MMIO example video here: Using PYNQ MMIO (Memory Mapped IO) - YouTube
The BRAM is assigned the DefaultIP driver but from the output of running help on my overlay it is not clear what driver has been assigned.

Running help on the memory gives:

Have things moved on from when that tutorial video was produced?

I seem to be able to perform single writes/reads ok using:
play = MMIO(play_base_address, mem_size)
play.write(offset, data)

however i’m not convinced if I do:
ol.hier_playaxi_bram_ctrl_0.write(offset, data)
that the data is being written to the correct place.

Hierarchies are a relatively recent addition to PYNQ. I can see why you are confused - you expect to see the BRAM listed under IP blocks. I don’t think things have moved on, I think the BRAM in the video shows in IP because it is not in a hierarchy. It gets complicated parsing hierarchies but I think we could look at trying to improve the consistency of this.

Do you have a problem using the BRAM, or why do you think your writes are not working correctly?


Hi @adi8v,

We are aware of the problem that BRAM controller do not show up in the ip_dict. This is something we will fix in the next release.

The MMIO should work fine.

If you want to add the BRAM controller in the ip_ditc, you can remove this line PYNQ/hwh_parser.py at master · Xilinx/PYNQ · GitHub


I’ve done a test access as per the MMIO tutorial I watched:

bram = ol.hier_playaxi_bram_ctrl_0.mmio.array
bram[0:8] = [1,2,3,4,5,6,7,8]

which outputs as expected:
array([1, 2, 3, 4, 5, 6, 7, 8, 0, 0], dtype=uint32)

I am then defining a complex waveform which I then want to write to the bram:

for i in range(numSamples):
    rads = np.pi/180
    # calculate I/Q values and write to memory
    iVal = int(amplitude * np.cos(stepSize * i * rads))
    qVal = int(amplitude * np.sin(stepSize * i * rads))
    write_data.append((qVal << 16) & 0xFFFF0000 | (iVal & 0xFFFF))

bram = write_data

But then if I read the data back using the none-np.array method:

play_mem = MMIO(play_base_address, mem_size)
read_iVal = []
read_qVal = []
for i in range(256):
    data = play_mem.read(i*4)
    read_iVal.append(int(data) & 0xFFFF)
    read_qVal.append(int(data) >> 16)
import matplotlib.pyplot as plt

You can see the original test data is still in the block RAM and not the waveform data as expected:

Can you spot what i’m doing incorrectly?


You are missing the index of the memory here:
bram = write_data

You need something like this.
bram[0:len(write_data)] = write_data



Thanks @cathalmccabe that seems to have done the trick.

1 Like