Skip to content

axi_dmac code documentation/summary #992

@catkira

Description

@catkira

What happens when a src_fifo_inf to dest_axi_mm DMA transfer is initiated?

  1. CPU writes DMA descriptor into registers
    dest_addr
    src_addr
    length

  2. axi_dmac_regmap_requests waits until req_ready goes high and then submitts the request

  3. request_generator creates a request_id

    • it only takes some MSBs from req_length, LSBs that are the size of a burst are discarded
      (.req_burst_count(req_length[DMA_LENGTH_WIDTH-1:BYTES_PER_BURST_WIDTH]))
    • it is started when request_generator and source are ready
      (req_gen_valid = req_valid & req_req_gen_ready & req_src_ready)
    • checks if there is still space in the FIFO, if not it throttles
      • checks if (response_id != id_next), if yes it generates an id for the next burst until no burst is left
  4. src_fifo_inf also receives the request from axi_dmac_regmap_requests, but it only stores the
    number of beats for the last burst (req_length[BYTES_PER_BURST_WIDTH-1:0])

    • it moves data from input (din) to output (fifo_data) without latency
    • it signals end of burst with fifo_last
    • the last burst is only as long as req_length[BYTES_PER_BURST_WIDTH-1:0]
  5. output of src_fifo_inf is buffered in axi_register_slice and then fed into axi_dmac_burst_memory

    • src_partial_burst is always 0 for src_fifo_inf
  6. axi_dmac_burst_memory containts a FIFO that can store some bursts

    • src_id is used as write index (src_id is not received from outside but generated inside
      by incrementing it with every src_clk cycle)
    • dest_request_id (=src_id) is output and goes into the dest_axi_mm module
    • src_beat_counter and dest_beat_counter are used to index the beat on the write and read side
    • a new burst is generated on the output when de dest_data_request_id input goes one up
    • dest_burst_valid = dest_data_request_id != dest_id_next
    • dest_id is used as read index, it is incremented everytime (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1)
      (dest_address_id comes from the dest_axi_mm module)
  7. dest_axi_mm received data from the burst memory and forwards it to the axi_mm interface.
    Its main job is the creation of the write addresses with the adress_generator module.

    • the response_handler module inside creates a response id by incrementing everytime
      when (bready == 1'b1 && bvalid == 1'b1)
      • the response_handler sets enabled output to 0 when all responses are received
        if (request_id == id) enabled <= 1'b0; (enable input can override this)
    • The dest_axi_mm module uses the response_handler while the dest_axi_stream and dest_fifo_inf modules use the response_generator module.
      Both modules are very similar, except that response_handler as an extra input input [1:0] bresp that is uses instead of the fixed response RESP_OKAY in the response_generator module.

What happens when the source interface aborts a transfer? (can only happen for src_axi_stream!)

  1. the src_axi interface signals an abort via the s_axi_last signal. It is detected in the data_mover module.
    s_axi_last signal is only an indicator for an abort, if it is not the regular end of a burst.
    In case of an abort, the data_mover generates a rewind request (rewind_req_data = {transfer_id,req_xlast_d,id_next})

  2. the rewind interface goes into the request_generator (rewind_req_valid, rewind_req_data).
    the request_generator then rewinds requests for bursts that are after the aborted burst and generates a completion request.

  3. the completion request goes into the response_manager. The response_manager waits until all "to_complete" transfers are
    finished and then resumes normal operation

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions