02-10-2020 11:37 AM - edited 02-10-2020 11:38 AM
I am using Vivado 2019.1 and a Virtex-7 VC707 to interface a custom IP with a DDR3-SDRAM.
Here's a piece of the block design for this configuration:
My intention is to read data from the DDR3 and store it in an internal BRAM in my curstom IP. Then do some calculations, and write the output data back to the DDR3.
I can't seem to find the proper documentation that specifies how to deal with the signals needed in the master interfaces (m_axi signals).
I have been checking this module: https://japan.xilinx.com/support/documentation/ip_documentation/axi_master_burst/v2_0/pg162-axi-master-burst.pdf
and included it in my custom IP, as explained in this tutorial: https://www.youtube.com/watch?v=EXULPtmJWbs&t=1647s
but I wasn't successful in my implementation.
I would greatly appreciate if you could provide me some explanation, documentation, or tutorials that could set me on the right path to achieve this.
Thank you for your time,
02-11-2020 04:43 AM
Reading from memory requires some things--like what address you are reading from, and how many words (or bytes) you intend to read. The same is true of writing.
Your task would fit nicely between a pair of data movers. For example, you might have an AXIMM2S read from memory and present your multiply unit with values. You might even use two--if you wanted to read your values from two separate places. You could then use an AXIS2MM to write the values back to memory, while placing your IP in the middle. Both of these are AXI masters, and the combination of what they both do might be perfect for what you want to do.
While Xilinx's data mover cores are encrypted, you might find the open source data movers in this repository to be the examples you are looking for.
At the same time, such data movers may well be overkill for your project. An AXI based data mover isn't a trivial design--although it is a high speed design. It requires an AXI-Lite interface to set up the transfer, an AXI master interface to make the transfer, and a stream interface (with FIFO) just in case the downstream (or upstream, depending upon direction) interface isn't (yet) ready.
So, let's walk through the basics of how something like this might work:
That's the first process, the request. AXI allows the response to come back some time later, perhaps after 20 requests (or more) have been made. For this reason, you'll want a separate process to handle the returns,
Writes are similar. When you are ready to write results back,
That's the AXI master transaction in a nutshell.
You asked about burst transactions. These are more difficult. In general, you would set AxLEN to one less than the length of the burst--up to 8'hff for a 256 length burst, and only issue one AxVALID rather than a series of them. You would probably also want to set AxBURST to 2'b01 (incrementing addresses), and (for simplicity) AxSIZE to $clog2(C_AXI_DATA_WIDTH)-3.
There are some ugly rules to doing this, however. One of them is that no burst can cross a 4kB boundary.
The other important part about burst transactions is the xLAST signal. On the last beat of any write burst, you will need to make certain WLAST is set. If you only keep AWLEN==0, you can then just leave WLAST high. Otherwise you'll need to count your way through the data and set it appropriately. The AXI slave (SDRAM in this case) will be doing the same thing with your read results, and setting RLAST high on the last beat of any burst.
Did I mention that it gets complex? ;) It is doable, but there are a lot of things you need to keep track of. The full AXI protocol is defined in the specification, something that would be well worth reading and studying.