• 0
dcc

ARTY board, read from DDR3 and write to PMOD

Question

Hi, I have a simple design. In an ARTY board, I need to read from ddr3 initialized in SDK and write to pmod constantly in a loop. What is the recommended way to do this? Do I need to use the DMA? Is there a reference design for ARTY board?

Thanks

Share this post


Link to post
Share on other sites

5 answers to this question

Recommended Posts

  • 0

Hi @dcc,

Is your project using a soft core processor like Microblaze or HDL(vhdl/veriglog)? If you are using Microblaze what Pmod are you using? We have many Pmod IP on github here(sdk code provided). If you are using Microblaze we are in the process of updating/revising our Pmod IP tutorial here so currently I use use the getting started with Microblaze tutorial on the resource page here and then add the Pmod IP when you add the uart IP.

cheers,

Jon 

Share this post


Link to post
Share on other sites
  • 0

@dcc,

If all you want to do is stuff the from an 8-bit A/D into a UART, there's no reason why you would need either an SDK, MicroBlaze, or even a DMA.  Indeed, even if you wanted an SDK with MicroBlaze, a 1Msps A/D output isn't going to be very friendly with the microcontroller, and ... there may not even be a successful microcontroller at all that would work for you.

I think what you rather want to do is describe your interface.  For example, if your A/D has an 8'bit value output together with a 1'bit strobe value (true for one clock when the A/D value is valid), then there's no reason why you can't go directly into a UART transmitter logic without ever touching the MicroBlaze (or an even better ZipCPU) microprocessor.  If you decide you really do want all this extra *stuff*, please feel free to consider the OpenArty design which has both a ZipCPU and a DMA within it. (Even using the reference design, I'd recommend bypassing the CPU for your design.  A 1Mbps A/D ouput is just going to be a struggle for a CPU to keep up with.)

Dan

 

Share this post


Link to post
Share on other sites
  • 0

 

@jpeyron @D@n thanks ... Currently I am using pmodmic3 and a custom made board attached to the shield connector (12 bits parallel DAC). It's a pure RTL design, and I have been feeding the DAC with FPGA's ROMs and logging the data with ILA chipscope easily. I need a bigger memory to feed the DAC. and log the data back.(feeding the 12 bit DAC @ 400K sample/sec is more important) 

I do prefer RTL and staying away from SDK, but not sure how to initialize the memory outside of SDK. 

appreciate your comments.

Share this post


Link to post
Share on other sites
  • 1

@dcc,

If you actually want to set/read memory, you'll need to learn how to interact with a bus.  I like to use a B4 pipelined wishbone bus.  I find it very simple and easy to use.  For example, you can find a very simple block RAM device here that interacts with a wishbone bus.  (It would be even simpler if I wasn't keeping my high speed and low speed code in the same file ...)

Xilinx has committed themselves to the AXI bus--a bus that requires the management of five separate data paths just to get right.  If you want access to DDR3 SDRAM, you'll need to use Xilinx's memory interface generator (MIG) to build an interface for you.  (I tried without MIG, made lots of progress, but ... after two months of full time work on it hadn't finished the task.  It's a shame.  The memory access delay would've been about half of what Xilinx's delay is.)  Xilinx's MIG generates a DDR3 interface to a memory using an AXI controller.  You can see how I interact with that AXI controller in my own Arty design here.  Within that file, take a look at the mig_axis component and then roll your eyes with me at the quantity of wires and communications paths you need to handle just to read or write from memory.  :P Yuck.

That's why, in the same file, you'll find a wishbone to axi bridge, one I call wbm2axisp, or wishbone master to AXI slave pipelined.  As a result, I can interact with that core using wishbone signals, such as i_wb_cyc to indicate that I am accessing the bus (needs to be high throughout the transaction), i_wb_stb to request a memory interaction (only needs to be high for one clock while o_wb_stall is low per request), i_wb_addr (specifying the address of my request, must be valid any time i_wb_stb is high), i_wb_we (specifies if I am reading or writing), i_wb_data (data to write, must be valid anytime i_wb_stb and i_wb_we are high), o_wb_ack (true any time a memory access completes), o_wb_stall (true if the memory isn't ready to accept a transaction), and o_wb_data (the data result of any read transaction).  The number of wishbone signals are truly ... much less than that giant AXI bus.  (10 signals, of which 4 have multiple bits associated with them.)  Looking at the AXI bus, to interact with it you will need 35 signals, of which 23 have multiple bits.  Take your pick.  :D  (By the way, going from an 8-bit data width to the 128 bit data width used by the DDR3 SDRAM is not nearly as hard as it sounds, if that's something you would be struggling with.)

If you are trying to read/write from memory to support both an ADC and a DAC, you'll need a couple of things.  One of them is a FIFO.  You can see an example of a FIFO supporting a UART here.  DDR3 memory speed can be unpredictable, and it can drop out suddenly for a refresh cycle while you are trying to interact with it.  Worse, that MIG interface takes upwards of 24 clocks to complete a transaction.  (If you pipeline your requests, only the first will take 24 clocks, the rest can take one clock.  See the wishbone B4 spec for a discussion of this.)  However, with a FIFO you can weather some of these problems without dropping samples, and even get on and off the memory bus faster.  Second, you'll need an arbiter--something that decides of the two transactions you'd like to make, which of them actually gets access to the bus.  You can find my own wishbone arbiter here.

If you are wondering just how to get a wishbone transaction working, I have examples ranging from simple to complex.  For example, here is a simple prefetch example that just reads a single value from memory (i.e., the next instruction for a CPU).  Here's another, similar example, which reads two values from memory at a time.  (When working with that SDRAM, the first can take 24 cycles per read, the second can do two reads in 25 clock cycles.)  And, while we are at it, here's an example which reads 2^N values at once--but since it's got a cache within it, it ... tends to be more complicated.  Another example would be the code I've used for building my own DMA.  Take your pick.  How deep would you like to dive into this?  I could go on and on for a while with more examples ... :D

Is this the sort of thing you are looking for?  Let me know, and I can offer more, explain any of the above, or ... you tell me.

Yours,

Dan

 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now