Jump to content
  • 0

Zynq - data copy from PS to PL without importing IPs?


Joseph Fourier

Question

I have got Arty Z7-20 with hope to design a special purpose hardware with only open description (no proprietary IPs, pure VHDL+Constrains). Now, after a week of intensive Google search I am still completely out of any viable option. I have read Zynq Tech Reference and while it describes the SoC architecture, it doesn't provide any HDL example of how to copy data between PL and PS.

If there are no AXI signals available on HDL behav level,  can data be transferred alternatively maybe directly through DDR or anything else? 

PS: I surely understand I need to design AXI controller in HDL, but this is what I want to do.

Thanks!

Link to comment
Share on other sites

10 answers to this question

Recommended Posts

Hi,

I haven't been around here much lately, but I saw your post and thought I had something of use to you.

Here is an AXI Slave, connected to the a PL, written in only VHDL: It only decodes a few addresses, and doesn't decode the entire assigned address range.

http://hamsterworks.co.nz/mediawiki/index.php/Simple_AXI_Slave

Feel free to drop me an email, but it has been a while since I've had spare time to do any of this stuff....

Link to comment
Share on other sites

2 hours ago, Joseph Fourier said:

For PS to write to BRAM, PL must contain an AXI logic configured, right? Otherwise I cannot see other data channels on the Zynq diagram

Yes. An AXI Slave interface would be needed to read/write to one of the BRAM ports, and the PL design can read/write to the second port on the BRAM.

Another other option might be to make an AXI master, that can write into and/or read from the PS's memory., but architecting this way seems wrong.

The last option would be to route some of the MIO pins into the fabric, but this gives you a very narrow, restrictive low bandwidth connection compared to a AXI slave.

Link to comment
Share on other sites

15 hours ago, hamster said:

Yes. An AXI Slave interface would be needed to read/write to one of the BRAM ports, and the PL design can read/write to the second port on the BRAM.

Another other option might be to make an AXI master, that can write into and/or read from the PS's memory., but architecting this way seems wrong.

The last option would be to route some of the MIO pins into the fabric, but this gives you a very narrow, restrictive low bandwidth connection compared to a AXI slave.

Your simple AXI slave looks very interesting, thanks! What I still don't understand:

1) how do you get this number: (uint32_t *)(0x43C0<<16)

is it a kind of memory-mapped AXI register in PS address space? but I cannot find it in documentation

2) is your hello.c program a standalone code (will run not under Linux), right? It would be helpful to see a Makefile or just commands how to build an image from C code.

Thanks for your great help!

Link to comment
Share on other sites

6 hours ago, Joseph Fourier said:

Your simple AXI slave looks very interesting, thanks! What I still don't understand:

1) how do you get this number: (uint32_t *)(0x43C0<<16)

is it a kind of memory-mapped AXI register in PS address space? but I cannot find it in documentation

2) is your hello.c program a standalone code (will run not under Linux), right? It would be helpful to see a Makefile or just commands how to build an image from C code.

Thanks for your great help!

1) That is based on the address window assigned to the AXI port in the PS configuration. Look at the screen grab below the block diagram for the PS in that web page.

2) The hello Program was made in the Eclipse IDE that Vivado provides for bare-metal development. Under linux you will either need a devices driver, or using shared memory or something, or I would tend to open /dev/mem and seek and write in there for a quick hack.

 

Link to comment
Share on other sites

2 hours ago, Joseph Fourier said:

>> That is based on the address window assigned to the AXI port in the PS configuration.

In that case for a completely open description there must be an additional source file where this information is presented, no?

Yes, of course. But at the time I was playing with that project was only interested in developing a working understanding of AXI. 

I assume there is a magical binary file that contains all the configuration bits for the PS subsystem block, that forms part of the configuration/boot image for the Zynq....

Link to comment
Share on other sites

@hamster  I was able to run your AXI Slave interface. It works great!

It is now very easy to exchange information between PS and PL, and it even supports execute-in-place (e.g. I can put ARM instructions to register file and run PS CPU directly from it).

 

I have some questions about your AXI Slave design:

1) AXI_a*size has no effect on INCR type of burst transactions, but according to AXI protocol: the increment value depends on the size of the transfer. You set it only for WRAP type, is it correct? Thus, burst size is always 0 for INCR type?

2) Do you know how PS initiates INCR burst type? A kind of memset/memcpy need to be used for that or an incrementing pointer will also work?

3) Where WRAP type is necessary? How to use PS to work in WRAP mode?

 

You may also update your wiki page with following:

0) Create provided VHDL files

1) Create a block-diagram and add PS IP core to it

2) Apply configuration provided by your board's pre-settings; this will set all necessary initialization settings for PS (e.g. clock frequencies, DDR bindings, etc.)

3) Press auto-configure (or how it's called) ==> this will connect PS IP to DDR and to fixed IO

4) Add "External ports" to the diagram (create new AXI_CLK and AXI external ports) and connect them to PS ports

5) Generate VHDL wrapping code for this block diagram

6) Put generated system under axi_test_top by renaming it to axi_test_wrapper (default name is design_#_wrapper in my Vivado version)

7) This will auto-connect block-diagram external ports with axi_test_top

8 ) Add constrains file and rename/uncomment external ports where necessary

9) Generate bitstream

10) File->Export->Hardware and create .hwf file which contains PS configuration

11) Open Xilinx SDK and create a new project: select  .hwf  file as Hardware BSP for this project

12) Now, Xilinx SDK will auto-generate few .c and .h files which contain necessary PS initialization ==> clocks, IRQs, DDR, etc.

13) Add hello_world.c application to the project

 

@hamster Thank you very much. I've learned a bunch of new things thanks to your help!

 

 

Link to comment
Share on other sites

On 8/29/2018 at 12:11 AM, Joseph Fourier said:

@hamster  I was able to run your AXI Slave interface. It works great!

It is now very easy to exchange information between PS and PL, and it even supports execute-in-place (e.g. I can put ARM instructions to register file and run PS CPU directly from it).

 

I have some questions about your AXI Slave design:

1) AXI_a*size has no effect on INCR type of burst transactions, but according to AXI protocol: the increment value depends on the size of the transfer. You set it only for WRAP type, is it correct? Thus, burst size is always 0 for INCR type?

2) Do you know how PS initiates INCR burst type? A kind of memset/memcpy need to be used for that or an incrementing pointer will also work?

3) Where WRAP type is necessary? How to use PS to work in WRAP mode?

 

You may also update your wiki page with following:

0) Create provided VHDL files

1) Create a block-diagram and add PS IP core to it

2) Apply configuration provided by your board's pre-settings; this will set all necessary initialization settings for PS (e.g. clock frequencies, DDR bindings, etc.)

3) Press auto-configure (or how it's called) ==> this will connect PS IP to DDR and to fixed IO

4) Add "External ports" to the diagram (create new AXI_CLK and AXI external ports) and connect them to PS ports

5) Generate VHDL wrapping code for this block diagram

6) Put generated system under axi_test_top by renaming it to axi_test_wrapper (default name is design_#_wrapper in my Vivado version)

7) This will auto-connect block-diagram external ports with axi_test_top

8 ) Add constrains file and rename/uncomment external ports where necessary

9) Generate bitstream

10) File->Export->Hardware and create .hwf file which contains PS configuration

11) Open Xilinx SDK and create a new project: select  .hwf  file as Hardware BSP for this project

12) Now, Xilinx SDK will auto-generate few .c and .h files which contain necessary PS initialization ==> clocks, IRQs, DDR, etc.

13) Add hello_world.c application to the project

 

@hamster Thank you very much. I've learned a bunch of new things thanks to your help!

 

 

Hi! You are welcome - notes added: http://hamsterworks.co.nz/mediawiki/index.php/Simple_AXI_Slave#Notes_from_the_Internet

Answers:

1) Might be a bug - if it is, email me the fix :)

2) No idea - but you need to have the correct number of transfers to stop the bus form locking up. I suspect DMA might be needed.

3) "Where WRAP type is necessary? How to use PS to work in WRAP mode?" Interesting question. I assume that it is used to fill cache lines. The data at the address being requested is delivered first, then the rest of the cache line is filled. As this address range is uncached I suspect it is unused.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...