Overlay hierarchy

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

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

Hierarchies
-----------
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

Interrupts
----------
None

GPIO Outputs
------------
None

Memories
------------
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?

Cathal

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

Mario

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]
bram[0:10]

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
plt.figure()
plt.plot(np.int16(read_iVal))
plt.plot(np.int16(read_qVal))
plt.show()

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

Can you spot what i’m doing incorrectly?

Thanks.

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

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

Cathal

2 Likes

Thanks @cathalmccabe that seems to have done the trick.

1 Like