cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
lhometga
Visitor
Visitor
687 Views
Registered: ‎06-25-2019

How to interface custom IP with MIG DDR3 via AXI master burst

 

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:

bd.PNG

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,

Laura

0 Kudos
1 Reply
dgisselq
Scholar
Scholar
631 Views
Registered: ‎05-21-2015

@lhometga,

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:

  1. On a reset, every *VALID signal goes to its reset position.  This is required.
  2. When you are ready to start, you would set ARVALID and ARADDR.  For simplicity, you can keep ARID=0 and ARLEN = 0 (single beat burst).  To keep things simple, make sure you use only aligned  addresses--such that ARADDR[$clog2(C_AXI_DATA_WIDTH)-4:0] == 0.  While not required, it makes the logic much simpler for a beginner.  You'll also want to set, for simplicity, the size of the beat to the bus width: ARSIZE=$clog2(C_AXI_DATA_WIDTH)-3.  Be very careful if you try to copy Xilinx's example codes for this purpose, since they've often gotten this expression wrong.
  3. Many of the other signals can just be set to zero as well: ARPROT, ARREGION, ARUSER, ARLOCK, ARCACHE, etc.  The memory controller is likely to just ignore these anyways.
  4. Once ARVALID && ARREADY are both true, you can go on to requesting the next beat of information.

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,

  1. Clear your internal read state before you start making address requests, and record where (internally) you want to put incoming data.  Also make a note of how many incoming data words you expect to receive.
  2. Once the transaction begins, hold RREADY high (if you can).  If you can't do this, things just get more complex.
  3. Now, for every clock where (RVALID && RREADY), write a word to your internal memory and increment the address within the internal memory.
  4. Once the last word has been received (yes, that means you need two counters--one for address transmission, and one for words received), clear your state machine.

Writes are similar.  When you are ready to write results back,

  1. Set AWVALID && AWADDR to the place you wish to write to.  As with reading, keeping the address aligned makes things much simpler.  You may set AWLEN =0 again if you would like--it keeps things simple.  Once AWVALID && AWREADY are true, you can issue the write address request for the next beat of data.
  2. As before, many of the other AW* signals may be set to zero: AWLOCK, AWCACHE, AWPROT, AWREGION, AWUSER, etc.  The memory is likely to ignore these.
  3. At the same time you start setting AWVALID, you'll also want to start setting WVALID.  The W* channel will contain the data you wish to write back.  Hence, you'll want to set WVALID  and WDATA (the data you wish to write) and WSTRB (byte indicators, of which data bytes you wish to write to).  If you've set AWLEN==0, then you'll also want to hold WLAST high.  Once WVALID && WREADY are both true, you can then move on to the next data sample.

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.

Dan

0 Kudos