/******************************************************************************* * Module: ahci_dma_rd_fifo * Date:2016-01-01 * Author: Andrey Filippov * Description: cross clocks, word-realign, 64->32 * Convertion from x64 QWORD-aligned AXI data @hclk to * 32-bit word-aligned data at mclk * * Copyright (c) 2016 Elphel, Inc . * ahci_dma_rd_fifo.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ahci_dma_rd_fifo.v 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify this Program, or any covered work, by linking or combining it * with independent modules provided by the FPGA vendor only (this permission * does not extend to any 3-rd party modules, "soft cores" or macros) under * different license terms solely for the purpose of generating binary "bitstream" * files and/or simulating the code, the copyright holders of this Program give * you the right to distribute the covered work without those independent modules * as long as the source code for them is available from the FPGA vendor free of * charge, and there is no dependence on any encrypted modules for simulating of * the combined code. This permission applies to you if the distributed code * contains all the components and scripts required to completely simulate it * with at least one of the Free Software programs. *******************************************************************************/ `timescale 1ns/1ps module ahci_dma_rd_fifo#( parameter WCNT_BITS = 21, parameter ADDRESS_BITS = 3 )( input mrst, input hrst, input mclk, input hclk, // hclk domain input [WCNT_BITS-1:0] wcnt, // decrementing word counter, 0- based (0 need 1, 1 - need 2, ...) valid @ start input [1:0] woffs, // 2 LSBs of the initial word address - valid @ start input start, // start transfer input [63:0] din, input din_av, input din_av_many, input last_prd, // last prd, flush partial dword if there were odd number of words transferred. valid @ start // Or maybe use "last_prd"? output din_re, output reg done, // this PRD data sent to cross-clock FIFO (may result in only half-dword sent out), // OK to fetch another PRD (if it was not the last) output done_flush, // finished last PRD (indicated by last_prd @ start), data left module // mclk domain output [31:0] dout, output dout_vld, input dout_re, output last_DW // dout contains last DW ,output [31:0] debug_dma_h2d ); localparam ADDRESS_NUM = (1<>1){1'b0}},{(ADDRESS_NUM>>1){1'b1}}};// 8'b00001111 // else if (fifo_rd && raddr[0]) fifo_nempty <= {fifo_nempty[ADDRESS_NUM-2:0], ~raddr[ADDRESS_BITS+1] ^ raddr[ADDRESS_BITS]}; else if (fifo_rd && raddr_r[0]) fifo_nempty <= {fifo_nempty[ADDRESS_NUM-2:0], ~raddr_r[ADDRESS_BITS+1] ^ raddr_r[ADDRESS_BITS]}; // fifo_dav <= fifo_full [raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS+1]; /// fifo_dav <= fifo_full [raddr_r[ADDRESS_BITS:1]] ^ raddr_r[ADDRESS_BITS+1]; fifo_dav <= fifo_full [raddr_w[ADDRESS_BITS:1]] ^ raddr_w[ADDRESS_BITS+1]; fifo_dav2 <= fifo_dav2_w; // fifo_full2[raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS+1]; if (mrst) flushing_mclk <= 0; else flushing_mclk <= flushing_hclk; fifo_do_r <= fifo_ram [raddr_w[ADDRESS_BITS:1]]; fifo_do_vld_r <= vld_ram [raddr_w[ADDRESS_BITS:1]]; end ahci_dma_rd_stuff ahci_dma_rd_stuff_i ( .rst (mrst), // input .clk (mclk), // input .din_av (fifo_dav), // input .din_avm_w(fifo_dav2_w), // input .din_avm (fifo_dav2), // input .flushing (flushing_mclk), // input // .din (raddr[0]?fifo_do[63:32]: fifo_do[31:0]), // input[31:0] // .dm (raddr[0]?fifo_do_vld[3:2]:fifo_do_vld[1:0]), // input[1:0] .din (raddr_r[0]?fifo_do_r[63:32]: fifo_do_r[31:0]), // input[31:0] .dm (raddr_r[0]?fifo_do_vld_r[3:2]:fifo_do_vld_r[1:0]), // input[1:0] .din_re (fifo_rd), // output .flushed (done_flush_mclk), // output reg: flush (end of last PRD is finished - data left module) .dout (dout), // output[31:0] reg .dout_vld (dout_vld), // output .dout_re (dout_re), // input .last_DW (last_DW) // output ); pulse_cross_clock #( .EXTRA_DLY(0) ) done_flush_i ( .rst (mrst), // input .src_clk (mclk), // input .dst_clk (hclk), // input .in_pulse (done_flush_mclk), // input .out_pulse (done_flush), // output .busy() // output ); assign debug_dma_h2d = { 14'b0, fifo_rd, raddr_r[4:0], fifo_do_vld_r[3:0], fifo_dav, fifo_dav2_w, fifo_dav2, flushing_mclk, done_flush_mclk, dout_vld, dout_re, last_DW }; endmodule