Skip to content
Yaman Umuroglu edited this page Feb 13, 2016 · 2 revisions

keywords: DRAM, AXI, burst, DMA, multichannel

Components for accessing external memory interfaces. These components operate on an own, simple "intermediate representation" for memory requests/responses, which can be converted to platform-specific memory interfaces via adapters.

Currently, the implementation is much more "hardware" than what traditional DMA controllers look like; it is assumed that the access patterns are known at (hardware) compile time, and the appropriate multi-channel DMA systems are instantiated (so there is no enable/disabling of channels, setting of stride values etc. from software).

Overview of Components

GenericMemoryRequest and GenericMemoryResponse - bundles for representing memory requests and responses

Master/slave ports can be added to components by using the GenericMemoryMasterPort and GenericMemorySlavePort. Inspired by how AXI interfaces are structured, these ports use Decoupled (ready-valid) interfaces for pushing-pulling requests and responses. Note that these are full-duplex (separate read and write channels) port definitions.

To read or write contiguous blocks of memory, StreamReader and StreamWriter can come in handy. They include stream resizers, so it's possible to read/write contiguous streams that are smaller than the memory port width. StreamReader contains some support for auto-throttling via built-in FIFOs, so that the request rate can be maximized even when the resulting stream is read slowly. This prevents e.g. head-of-line blocking in multichannel scenarios.

ReadReqGen and WriteReqGen generate a stream of memory requests that can read/write blocks of memory. They are much simpler than StreamReader and StreamWriter (e.g. they don't handle the responses or write data, just generate read/write requests)

ReqInterleaver and RespDeinterleaver can be used to share a single memory port between several DMAs, creating a multichannel memory system. "routing functions" can be defined to associate request/response IDs with particular ports of the interleaver/deinterleaver. (Note that there isn't much point doing this unless the platform's memory interface supports multiple outstanding transactions).

TODO:

  • support write bursts
  • support sub-word reads and writes, only whole-word reads and writes have been tested so far (e.g. if the platform memory port is 64 bits wide, cannot do 32-bit reads or writes
  • restrict alignment checks
  • make burst sizes more parametrizable, platforms may not permit bursts without alignment
  • frequency optimizations, less combinational logic.
  • comb. loop issues in some cases with the RespDeinterleaver, can use QueuedDeinterleaver for now.
  • support strides and scatter-gather DMA (ArrayReader / ArrayWriter does this to some extent)
  • support software-programmable multichannel (good old DMA)
Clone this wiki locally