OpenCores
URL https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk

Subversion Repositories qaz_libs

[/] [qaz_libs/] [trunk/] [axi4_lib/] [src/] [axi4_to_axis_basic_dma.sv] - Rev 31

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2015 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////


module
  axi4_to_axis_basic_dma
  #(
    A, // address bus width
    N,  // data bus width in bytes
    I,  // ID width
    BASE_ADDRESS, // must be on 4K boundry
    BUFFER_SIZE,
    BURST_LENGTH,
    MAX_BURSTS, // max number of burst the FIFO can hold
    BYTES_PER_TUSER = 0 //  bytes per tuser bit . Set to 0 for transfer based.
  )
  (
    axi4_if axi4_m,
    axis_if axis_out,
    input   dma_enable,
    input   aclk,
    input   aresetn
  );

  // --------------------------------------------------------------------
  //
  localparam R_D = BURST_LENGTH * MAX_BURSTS;
  localparam AR_D = 2;
  localparam WATERMARK = BURST_LENGTH * (MAX_BURSTS - AR_D);
  localparam STRIDE = N * BURST_LENGTH;
  localparam ADDRESS_END = BASE_ADDRESS + BUFFER_SIZE;
  localparam AR_STOP  = (BUFFER_SIZE % STRIDE)  ? ADDRESS_END - STRIDE  : ADDRESS_END;
  localparam R_STOP   = (BUFFER_SIZE % N)       ? ADDRESS_END - N       : ADDRESS_END;
  localparam U = N / BYTES_PER_TUSER;


// --------------------------------------------------------------------
// synthesis translate_off
  localparam N_4K = 'h1000 / 'h8; // number of bytes in 4K
  initial
  begin
    a_4k_mod_base_address: assert(BASE_ADDRESS % 'h1000 == 0) else $fatal;
    a_4k_gt_eq_stride: assert(N_4K >= STRIDE) else $fatal;
    a_4k_mod_stride: assert('h1000 % STRIDE == 0) else $fatal;
    a_n: assert((N % BYTES_PER_TUSER == 0)) else $fatal;
    a_buffer_size: assert(BUFFER_SIZE % N == 0) else $fatal;
    a_bytes_per_tuser: assert(BYTES_PER_TUSER != 0) else $fatal; // need to fix
  end
// synthesis translate_on
// --------------------------------------------------------------------


  // --------------------------------------------------------------------
  //
  axi4_if #(.A(A), .N(N), .I(I))  axi4_read_fifo(.*);
  axis_if #(.N(N), .U(U))         axis_in(.*);


  // --------------------------------------------------------------------
  //
  reg [(A-1):0] araddr_r;
  wire araddr_en = (araddr_r < AR_STOP);
  wire r_watermark;
  wire ar_wr_full;
  wire ar_wr_en = ~ar_wr_full & ~r_watermark & araddr_en & dma_enable;

  always_ff @(posedge aclk)
    if(~aresetn | ~araddr_en)
      araddr_r <= BASE_ADDRESS;
    else if(ar_wr_en)
      araddr_r <= araddr_r + STRIDE;


  // --------------------------------------------------------------------
  //
  reg [(A-1):0] r_rd_addr;
  wire r_rd_addr_en = (r_rd_addr < R_STOP);
  wire r_rd_addr_start = (r_rd_addr == BASE_ADDRESS);
  wire r_rd_addr_end   = (r_rd_addr == R_STOP);
  wire r_rd_empty;
  wire r_topped_off;
  wire r_rd_en = ~r_rd_empty & r_rd_addr_en & axis_in.tready;

  always_ff @(posedge aclk)
    if(~aresetn | ~r_rd_addr_en)
      r_rd_addr <= BASE_ADDRESS;
    else if(r_rd_en)
      r_rd_addr <= r_rd_addr + N;


  // --------------------------------------------------------------------
  //
  axi4_m_to_read_fifos #(.A(A), .N(N), .I(I), .R_D(R_D), .AR_D(AR_D), .WATERMARK(WATERMARK))
    axi4_m_to_read_fifos_i(.*);


  // --------------------------------------------------------------------
  //
  assign axi4_read_fifo.araddr    = araddr_r;
  assign axi4_read_fifo.arid      = 0;
  assign axi4_read_fifo.arburst   = 2'b01;
  assign axi4_read_fifo.arsize    = $clog2(N);
  assign axi4_read_fifo.arlen     = BURST_LENGTH - 1;
  assign axi4_read_fifo.rready    = 1;


  // --------------------------------------------------------------------
  //
  assign axi4_m.awaddr    = 0;
  assign axi4_m.awburst   = 0;
  assign axi4_m.awcache   = 0;
  assign axi4_m.awid      = 0;
  assign axi4_m.awlen     = 0;
  assign axi4_m.awlock    = 0;
  assign axi4_m.awprot    = 0;
  assign axi4_m.awqos     = 0;
  assign axi4_m.awregion  = 0;
  assign axi4_m.awsize    = 0;
  assign axi4_m.awvalid   = 0;
  assign axi4_m.bready    = 0;
  assign axi4_m.wdata     = 0;
  assign axi4_m.wid       = 0;
  assign axi4_m.wlast     = 0;
  assign axi4_m.wstrb     = 0;
  assign axi4_m.wvalid    = 0;


  // --------------------------------------------------------------------
  //
  assign axis_in.tvalid = ~r_rd_empty;
  assign axis_in.tdata = axi4_read_fifo.rdata;
  assign axis_in.tlast = axi4_read_fifo.rlast;
  assign axis_in.tuser[0] = r_rd_addr_start;
  assign axis_in.tuser[U-1:1] = 0; // need to fix


  // --------------------------------------------------------------------
  //
  axis_register_slice #(.N(N), .U(U))
    axis_register_slice_i(.*);


// --------------------------------------------------------------------
//
endmodule

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.