Initialize bitstream with ELF on PYNQ-Z2

Hi everyone, I’m trying to associate an ELF file with a bitstream, in order to automatically run an application on a Microblaze once my device (PYNQ-Z2) gets configured.

I’m currently working on a PYNQ-Z2 using Vivado+Vitis 2021.1, I also tried on Vivado+Vitis 2019.2 obtaining same results (failure). See below for details.

This is what I currently do:

  1. On Vivado, I create a minimal design using a Microblaze, I create the bitstream and export hardware as XSA platform;
  2. On Vitis, I create an HelloWorld minimal application, based on the exported plaftorm;
  3. On Vitis, I check that by “Running the application on Hardware”, it functions properly and prints on UART;
  4. On Vitis, I click on Xilinx->Program Device and select the correct ELF file to be embedded in the bitstream. I see from the Console that the command “update_mem” executes normally and apparently the BRAM initialization goes as it should.

Result: the PL of the board gets programmed but the application doesn’t run and I don’t read anything on the UART.

NOTE: I tried to apply this same exact flow also on a Kintex Ultrascale (on a KCU105) and the embedded ELF executed correctly at first try.

What I already tried:

  • Changing tool version: I tried working on Vivado+Vitis 2019.2, still failure;
  • Changing the hardware: I tried using another PYNQ-Z2 board, still failure;
  • Associate ELF on Vivado: I tried to embed the ELF in the bitstream using Vivado->Tools->Associate ELF and then programming the FPGA from Hardware Manager, still failure;

I want to remark that the design I’m implementing is close to the minimal one to run something on a Microblaze, and the application is an Hello World printing on UART.

What would you suggest to try? Are there some known issues about embedding an ELF in a bitstream for PYNQ-Z2 / Zynq7020?

Thanks in advance,


1 Like

I don’t see anything wrong with your steps. What UART are you connecting to?
This doesn’t seem like a PYNQ related question. You may be better trying to post or search on the Xilinx forums.


1 Like

Hi Cathal, thanks for the quick answer. I instantiated a AXI Uartlite IP block in the design and mapped two GPIO pins to be used as Tx/Rx. As I wrote I have no problems with the design, which executes correctly if launched from Vitis. I also tried to switch-on the LEDs instead of writing on the UART… same results, no signs of life from the board. Anyway, the strange thing is that the flow I followed works smoothly on other boards like KCU105, but not on the PYNQ. That’s why I thought to post here the question, after posting it on Xilinx forums (unfortunately not receiving an answer yet).

Is there anything different you’d try with respect to my steps?

Just to give a bit more of context, the final purpose of the project would be to do external configuration memory scrubbing from a PYNQ board to another PYNQ board, connected in a cluster. For this reason, a single bitstream file “embedding” an ELF to be executed would be very much convenient.

Thanks again,

1 Like

If I understand correctly, you have initialised your bitstream with the elf, so the MicroBlaze Institution/Data BRAMs are populated.
You load this from Vitis, which is only downloading the bitstream to configure the board and the design works.
You download the same bitstream from PYNQ and it doesn’t work.

  • Are you sure you are using the bitstream that has been updated with updatemem?
  • Are you using the PYNQ Overlay class to download the bitstream? If you are, can you boot the board, and then use Vitis/Vivado to download the bitstream to check it still works when PYNQ is running?

It sounds like your design has no dependency on anything related to PYNQ.

If this is the case, are there any signals (e.g. microblaze reset) connected from the PS that may be set/unset in the wrong way? Have you any other external inputs?

Can you post your block diagram, and code you are using to program the PL from PYNQ?


1 Like

Yes, the BRAM are populated and I also tried to manually initialise the BRAM using updatemem, still same failure.

Actually, using Vitis I download the bitstream and directly launch the baremetal application (if I understood correctly, Vitis uses xsct to do so). I’m sorry I didn’t mention this detail earlier. In this manner, the application runs correctly.

No, I’m not using using PYNQ Overlay class.

Here below you have the design I’m implementing. The only reset signal I’m not sure of (put there from the “connection automation” tool) is the one selected in orange.

The code I’m trying to run is the most basic Hello World template available in Vitis when creating a new project.


1 Like