Commit 902a78af authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Started implementation of the DMA for AHCI

parent 6fdd001b
Loading
Loading
Loading
Loading

utils/ahci_dma.v

0 → 100644
+112 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Module: ahci_dma
 * Date:2016-01-01  
 * Author: andrey     
 * Description: DMA R/W over 64-AXI channel for AHCI implementation
 *
 * Copyright (c) 2016 Elphel, Inc .
 * ahci_dma.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.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 <http://www.gnu.org/licenses/> .
 *******************************************************************************/
`timescale 1ns/1ps

module  ahci_dma (
//    input         rst,
    input                         mrst, // @posedge mclk - sync reset
    input                         hrst, // @posedge hclk - sync reset
    
    input                         mclk, // for command/status
    input                         hclk,   // global clock to run axi_hp @ 150MHz
    // Control interface  (@mclk)
    input                  [31:7] ctba,         // command table base address
    input                         ctba_ld,      // load command table base address
    input                  [15:0] prdtl,        // number of entries in PRD table (valid at cmd_start)
    input                         cmd_start,     // start processing command table, reset prdbc
    // Some data from the command table will be used internally, data will be available on the general
    // sys_out[31:0] port and should be consumed
    output                        ct_busy,      // cleared after 0x20 DWORDs are read out
    // After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs,
    // not forwarding them to the output 
    output                        prd_done,     // prd done (regardless of the interrupt)
    output                        prd_irq,      // prd interrupt, if enabled
    output                        cmd_busy,     // all command 
    output                        cmd_done,
    
    // Data System memory -> HBA interface @ mclk
    output                 [31:0] sys_out,      // 32-bit data from the system memory to HBA - command table, dma data
    output                        sys_dav,      // at least one dword is ready to be read
    output                        sys_dav_many, // several DWORDs are in the FIFO (TODO: decide how many)
    input                         sys_re,       // sys_out data read, advance internal FIFO
    // Data HBA -> System memory  interface @ mclk
    output                 [31:0] sys_out,      // 32-bit data from the system memory to HBA - command table, dma data
    output                        sys_nfull,    // internal FIFO has room for more data (will decide - how big reserved space to keep)
    input                         sys_we,    
    
    // axi_hp signals write channel
    // write address
    output  [31:0] afi_awaddr,
    output         afi_awvalid,
    input          afi_awready, // @SuppressThisWarning VEditor unused - used FIF0 level
    output  [ 5:0] afi_awid,
    output  [ 1:0] afi_awlock,
    output  [ 3:0] afi_awcache,
    output  [ 2:0] afi_awprot,
    output  [ 3:0] afi_awlen,
    output  [ 1:0] afi_awsize,
    output  [ 1:0] afi_awburst,
    output  [ 3:0] afi_awqos,
    // write data
    output  [63:0] afi_wdata,
    output         afi_wvalid,
    input          afi_wready,  // @SuppressThisWarning VEditor unused - used FIF0 level
    output  [ 5:0] afi_wid,
    output         afi_wlast,
    output  [ 7:0] afi_wstrb,
    // write response
    input          afi_bvalid,
    output         afi_bready,
    input   [ 5:0] afi_bid,      // @SuppressThisWarning VEditor unused
    input   [ 1:0] afi_bresp,    // @SuppressThisWarning VEditor unused
    // PL extra (non-AXI) signals
    input   [ 7:0] afi_wcount,
    input   [ 5:0] afi_wacount,
    output         afi_wrissuecap1en,
    // AXI_HP signals - read channel
    // read address
    output  [31:0] afi_araddr,
    output         afi_arvalid,
    input          afi_arready,  // @SuppressThisWarning VEditor unused - used FIF0 level
    output  [ 5:0] afi_arid,
    output  [ 1:0] afi_arlock,
    output  [ 3:0] afi_arcache,
    output  [ 2:0] afi_arprot,
    output  [ 3:0] afi_arlen,
    output  [ 1:0] afi_arsize,
    output  [ 1:0] afi_arburst,
    output  [ 3:0] afi_arqos,
    // read data
    input   [63:0] afi_rdata,
    input          afi_rvalid,
    output         afi_rready,
    input   [ 5:0] afi_rid,     // @SuppressThisWarning VEditor unused
    input          afi_rlast,   // @SuppressThisWarning VEditor unused
    input   [ 1:0] afi_rresp,   // @SuppressThisWarning VEditor unused
    // PL extra (non-AXI) signals
    input   [ 7:0] afi_rcount,
    input   [ 2:0] afi_racount,
    output         afi_rdissuecap1en
);


endmodule
+46 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Module: ahci_dma_rd_fifo
 * Date:2016-01-01  
 * Author: andrey     
 * 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 <http://www.gnu.org/licenses/> .
 *******************************************************************************/
`timescale 1ns/1ps

module  ahci_dma_rd_fifo#(
    parameter WCNT_BITS = 21
)(
    input                 mrst,
    input                 hrst,
    input                 mclk,
    input                 hclk,
    input [WCNT_BITS-1:0] wcnt,
    input          [63:0] din,
    input                 din_av,
    input                 din_av_many,
    output                din_re,
    
    output         [31:0] dout,
    output                dout_av,
    output                dout_av_many,
    input                 dout_re
);


endmodule
+77 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Module: ahci_dma_rd_stuff
 * Date:2016-01-01  
 * Author: andrey     
 * Description: Stuff DWORD data with missing words into continuous 32-bit data
 *
 * Copyright (c) 2016 Elphel, Inc .
 * ahci_dma_rd_stuff.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_stuff.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 <http://www.gnu.org/licenses/> .
 *******************************************************************************/
`timescale 1ns/1ps

module  ahci_dma_rd_stuff(
    input             rst,      // sync reset
    input             clk,      // single clock
    input             din_av,   // input data available
    input             din_avm,  // >1 word of data available
    input             flush,    // output partial dword if available (should be ? cycles after last _re/ with data?)
    input      [31:0] din,      // 32-bit input dfata
    input       [1:0] dm,       // data mask showing which (if any) words in input dword are valid 
    output            din_re,   // read input data
    output reg [31:0] dout,     // output 32-bit data
    output            dout_vld, // output data valid
    input             dout_re   // consumer reads output data (should be anded with dout_vld)
);
    reg  [15:0] hr; // holds 16-bit data from previous din_re if not consumed
    reg         hr_full;
    reg         dout_vld_r;
    reg         flushing;
    wire        din_av_safe = din_av && (din_avm || !din_re);
    wire  [1:0] dav_in = {2{din_av_safe}} & dm;
    wire        two_words_avail = &dav_in || (|dav_in && hr_full);
    assign din_re = (din_av_safe && !(|dm)) || ((!dout_vld_r || dout_re) && (two_words_avail)) ; // flush
    assign dout_vld = dout_vld_r;
    always @ (posedge clk) begin
        if ((!dout_vld_r || dout_re) && (two_words_avail || flushing) ) begin
            if (hr_full)               dout[15: 0] <= hr;
            else                       dout[15: 0] <= din[15: 0];
            
            if (hr_full && dav_in[0])  dout[31:16] <= din[15: 0];
            else                       dout[31:16] <= din[31:16];
        end

        // todo add reset/flush
        if (!dout_vld_r || dout_re)
            // 2 but not 3 sources available
            if (flushing || ((two_words_avail) && ! (&dav_in && hr_full))) hr_full <= 0;
        else if (dav_in[0] ^ dav_in[1]) hr_full <= 1;

        if ((!dout_vld_r || dout_re) && (&dav_in && hr_full)) hr <= din[31:16];
        else if ((dav_in[0] ^ dav_in[1]) && !hr_full)         hr <= dav_in[0]? din[15:0] : din[31:16];

        if      (rst)                                                                    dout_vld_r <= 0;
        else if ((!dout_vld_r || dout_re) && (two_words_avail || (flushing && hr_full))) dout_vld_r <= 1;
        else if (dout_re)                                                                dout_vld_r <= 0;
        
        if      (rst)                                               flushing <= 0;
        else if (flush)                                             flushing <= 1;
        else if ((!dout_vld_r || dout_re) && !(&dav_in && hr_full)) flushing <= 0; 

        
    end
    


endmodule