/*******************************************************************************
* 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