Commit 428626df authored by Andrey Filippov's avatar Andrey Filippov
Browse files

started fsm for the to ahci module

parent bd53b296
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ module ahci_fis_receive#(
    input                         hba_rst, // @posedge mclk - sync reset
    input                         mclk, // for command/status
    // Control Interface
    output reg                    fis_first_vld, // fis_first contains valid FIS header, reset by get_*
    // Receiving FIS
    input                         get_sig,        // update signature
    input                         get_dsfis,
@@ -44,8 +45,8 @@ module ahci_fis_receive#(
    input                         get_ufis,
    input                         get_data_fis,
    input                         get_ignore,    // ignore whatever FIS (use for DMA activate too?)
    output reg                    get_fis_busy,  // busy processing FIS 
    output reg                    fis_first_vld, // fis_first contains valid FIS header, reset by get_*
    output                        get_fis_busy,  // busy processing FIS 
    output reg                    get_fis_done,  // done processing FIS (see fis_ok, fis_err, fis_ferr)
    output reg                    fis_ok,        // FIS done,  checksum OK reset by starting a new get FIS
    output reg                    fis_err,       // FIS done, checksum ERROR reset by starting a new get FIS
    output                        fis_ferr,      // FIS done, fatal error - FIS too long
@@ -169,6 +170,7 @@ localparam DATA_TYPE_ERR = 3;
    reg          [15:0] tf_err_sts;
    reg                 update_err_sts_r;
    reg                 update_prdbc_r;
    reg                 get_fis_busy_r;
    
    // Forward data to DMA (dev->mem) engine
    assign              dma_in_valid = dma_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready && !too_long_err;
@@ -186,7 +188,7 @@ localparam DATA_TYPE_ERR = 3;
    assign tfd_err = tf_err_sts[15:8];
    
    assign xfer_cntr = xfer_cntr_r[31:2];
    
    assign get_fis_busy = get_fis_busy_r;
     
    always @ (posedge mclk) begin
        if (hba_rst || dma_in_stop) dma_in <= 0;
@@ -247,9 +249,11 @@ localparam DATA_TYPE_ERR = 3;

        fis_end_r <= {fis_end_r[0], fis_end_w};
        
        if      (hba_rst)                     get_fis_busy <= 0;
        else if (get_fis)                     get_fis_busy <= 1;
        else if (too_long_err || fis_end_w)   get_fis_busy <= 0; 
        if      (hba_rst)                     get_fis_busy_r <= 0;
        else if (get_fis)                     get_fis_busy_r <= 1;
        else if (too_long_err || fis_end_w)   get_fis_busy_r <= 0;
        
        get_fis_done <=  get_fis_busy_r && (too_long_err || fis_end_w);
        
        if      (hba_rst || get_fis)          fis_first_vld <= 0;
        else if (is_FIS_HEAD)                 fis_first_vld <= 1;

ahci/ahci_fsm.v

0 → 100644
+126 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Module: ahci_fsm
 * Date:2016-01-10  
 * Author: andrey     
 * Description: AHCI host+port0 state machine
 *
 * Copyright (c) 2016 Elphel, Inc .
 * ahci_fsm.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_fsm.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_fsm #(
//    parameter PREFETCH_ALWAYS =   0,
    parameter READ_REG_LATENCY =  2, // 0 if  reg_rdata is available with reg_re/reg_addr, 2 with re/regen
//    parameter READ_CT_LATENCY =   1, // 0 if  ct_rdata is available with reg_re/reg_addr, 2 with re/regen
    parameter ADDRESS_BITS =     10 // number of memory address bits - now fixed. Low half - RO/RW/RWC,RW1 (2-cycle write), 2-nd just RW (single-cycle)
)(
    input                         hba_rst, // @posedge mclk
    input                         mclk, // for command/status
    // notification from axi_ahci_regs that software has written data to register
    input      [ADDRESS_BITS-1:0] soft_write_addr,  // register address written by software
    input                  [31:0] soft_write_data,  // register data written (after applying wstb and type (RO, RW, RWC, RW1)
    input                         soft_write_en,     // write enable for data write
//    input                         soft_arst,        // reset SATA PHY not relying on SATA clock
   // R/W access to AXI/AHCI registers, shared with ahci_fis_receive and ahci_fis_transmit modules
    output     [ADDRESS_BITS-1:0] regs_addr,
    output                        regs_we,
//   output                 [3:0] regs_wstb, Needed?
    output                  [1:0] regs_re, // [0] - re, [1] - regen
    output                 [31:0] regs_din,
    input                  [31:0] regs_dout,
    
    // direct communication with transposrt, link and phy layers
    input                         phy_ready, // goes up after comreset,cominit, align, ...
    
    // Other signals....
    
    // Communication with ahci_fis_receive (some are unused
    input                         fis_first_vld, // fis_first contains valid FIS header, reset by get_*
    // Receiving FIS
    output                        get_sig,        // update signature
    output                        get_dsfis,
    output                        get_psfis,
    output                        get_rfis,
    output                        get_sdbfis,
    output                        get_ufis,
    output                        get_data_fis,
    output                        get_ignore,    // ignore whatever FIS (use for DMA activate too?)
    input                         get_fis_busy,  // busy processing FIS 
    input                         get_fis_done,  // done processing FIS (see fis_ok, fis_err, fis_ferr)
    input                         fis_ok,        // FIS done,  checksum OK reset by starting a new get FIS
    input                         fis_err,       // FIS done, checksum ERROR reset by starting a new get FIS
    input                         fis_ferr,      // FIS done, fatal error - FIS too long
    // next commands use register address/data/we for 1 clock cycle - after next to command (commnd - t0, we - t2)
    output                        update_err_sts,// update PxTFD.STS and PxTFD.ERR from the last received regs d2h
    output                        update_prdbc,  // update PRDBC in registers
    output                        clear_bsy_drq, // clear PxTFD.STS.BSY and PxTFD.STS.DRQ, update
    output                        set_bsy,       // set PxTFD.STS.BSY, update
    output                        set_sts_7f,    // set PxTFD.STS = 0x7f, update
    output                        set_sts_80,    // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update
    output                        decr_dwc,      // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers
    output                 [11:2] decr_DXC_dw,   // decrement value (in DWORDs)
    input                   [7:0] tfd_sts,       // Current PxTFD status field (updated after regFIS and SDB - certain fields)
                                                 // tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR
    input                   [7:0] tfd_err,       // Current PxTFD error field (updated after regFIS and SDB)
    input                         fis_i,         // value of "I" field in received regsD2H or SDB FIS
    input                         sdb_n,         // value of "N" field in received SDB FIS 
    input                         dma_a,         // value of "A" field in received DMA Setup FIS 
    input                         dma_d,         // value of "D" field in received DMA Setup FIS
    input                         pio_i,         // value of "I" field in received PIO Setup FIS
    input                         pio_d,         // value of "D" field in received PIO Setup FIS
    input                   [7:0] pio_es,        // value of PIO E_Status
    // Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed
    input                  [31:2] xfer_cntr,     // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc
    input                         xfer_cntr_zero,// valid next cycle                   
    
    // Communication with ahci_fis_transmit
    // Command pulses to execute states
    output                        fetch_cmd,   // Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS)
                                               // wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd
    output                        cfis_xmit,    // transmit command (wait for dma_ct_busy == 0)
    output                        dx_transmit,  // send FIS header DWORD, (just 0x46), then forward DMA data
                                                // transmit until error, 2048DWords or pDmaXferCnt 
    output                        atapi_xmit,   // tarsmit ATAPI command FIS
    input                         done,
    input                         busy,

    output                        clearCmdToIssue, // From CFIS:SUCCESS 
    input                         pCmdToIssue, // AHCI port variable
//    output                        dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output
    input                         fetch_cmd_busy, // does not include prefetching CT
    output                        syncesc_recv, // These two inputs interrupt transmit
    output                        xmit_err,     // 
    input                  [ 1:0] dx_err,       // bit 0 - syncesc_recv, 1 - xmit_err  (valid @ xmit_err and later, reset by new command)
    
    input                  [15:0] ch_prdtl,    // Physical region descriptor table length (in entries, 0 is 0)
    input                         ch_c,        // Clear busy upon R_OK for this FIS
    input                         ch_b,        // Built-in self test command
    input                         ch_r,        // reset - may need to send SYNC escape before this command
    input                         ch_p,        // prefetchable - only used with non-zero PRDTL or ATAPI bit set
    input                         ch_w,        // Write: system memory -> device
    input                         ch_a,        // ATAPI: 1 means device should send PIO setup FIS for ATAPI command
    input                   [4:0] ch_cfl,      // length of the command FIS in DW, 0 means none. 0 and 1 - illegal,
                                               // maximal is 16 (0x10)
    input                  [11:2] dwords_sent // number of DWORDs transmitted (up to 2048)                                 

);
`include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams

/*
Notes:
 Implement sync esc request/ackn in TL (available in LL)
*/
endmodule
+175 −87
Original line number Diff line number Diff line
@@ -29,7 +29,11 @@ module ahci_top#(
    input             aclk,    // clock - should be buffered
    input             arst,    // @aclk sync reset, active high
    input             mclk,    // SATA system clock (current 75MHz for SATA2)
    input             mrst,    // reset in mclk clock domain
    input             mrst,    // reset in mclk clock domain (after SATA PLL is on)
    // async reset for SATA (mrst will be responce to it)
    output            hba_arst,          // hba async reset (currently does ~ the same as port reset)
    output            port_arst,         // port0 async reset by software
    
    input             hclk,    // AXI HP interface clock for 64-bit DMA (current - 150MHz
    input             hrst,    // reset in hclk clock domain
// MAXIGP1   
@@ -143,17 +147,28 @@ module ahci_top#(
    wire [ADDRESS_BITS-1:0] soft_write_addr;  // register address written by software
    wire             [31:0] soft_write_data;  // register data written (after applying wstb and type (RO, RW, RWC, RW1)
    wire                    soft_write_en;    // write enable for data write
    wire                    soft_arst;        // reset SATA PHY not relying on SATA clock
                                                // TODO: Decode from {bram_addr, ahci_regs_di}, bram_wen_d
//    wire                    hba_arst;       // hba async reset (currently does ~ the same as port reset)
//    wire                    port_arst;      // port0 async reset by software
// 2. HBA R/W registers, use hba clock
    wire                    hba_rst;
    wire                    regs_we;
    wire              [1:0] regs_re; // [0] - re, [1] - regen
    wire                    regs_we_fsm;
    wire              [1:0] regs_re_fsm;
    wire             [31:0] regs_din_from_fsm; // from fsm
    wire                    regs_we_freceive;
    wire              [1:0] regs_re_ftransmit; // [0] - re, [1] - regen
    wire [ADDRESS_BITS-1:0] regs_faddr; // read/write adderss from ahci_fsm
    wire [ADDRESS_BITS-1:0] regs_waddr;
    wire [ADDRESS_BITS-1:0] regs_raddr;
    wire             [31:0] regs_din;
    wire             [31:0] regs_din_from_freceive;
    wire             [31:0] regs_dout;
    wire [ADDRESS_BITS-1:0] regs_addr = ({ADDRESS_BITS{regs_we}} & regs_waddr) | ({ADDRESS_BITS{regs_re[0]}} & regs_raddr);
    wire [ADDRESS_BITS-1:0] regs_addr = ({ADDRESS_BITS{regs_we}} & regs_waddr) |
                                        ({ADDRESS_BITS{regs_re[0]}} & regs_raddr) |
                                        ({ADDRESS_BITS{regs_re_fsm[0] | regs_we_fsm}} & regs_faddr);
                                        
    wire             [31:0] regs_din =  ({32{regs_we_freceive}} & regs_din_from_freceive) |
                                        ({32{regs_we_fsm}} &      regs_din_from_fsm);
    wire              [1:0] regs_re = regs_re_ftransmit | regs_re_fsm; // [0] - re, [1] - regen
    wire                    regs_we = regs_we_freceive | regs_we_fsm;
    
//---------------------    

@@ -179,9 +194,84 @@ module ahci_top#(
    wire             [31:0] dma_dout;    // output[31:0] 
    wire                    dma_dav; // output
    wire                    dma_re;      // input
    wire             [31:0] d2h_data;// input[31:0] 
    wire                    dma_in_ready; // output
    wire                    dma_we;      // input
// ---------------------------------------
    wire             [31:0] xfer_cntr; 
    wire                    xfer_cntr_zero; 

    /* Instance template for module ahci_fsm */
    ahci_fsm #(
        .READ_REG_LATENCY(2),
        .ADDRESS_BITS(10)
    ) ahci_fsm_i (
        .hba_rst         (hba_rst),            // input
        .mclk            (mclk),               // input
        .soft_write_addr (soft_write_addr),    // input[9:0] 
        .soft_write_data (soft_write_data),    // input[31:0] 
        .soft_write_en   (soft_write_en),      // input
        .regs_addr       (regs_faddr),         // output[9:0] 
        .regs_we         (regs_we_fsm),        // output
        .regs_re         (regs_re_fsm),        // output[1:0] 
        .regs_din        (regs_din_from_fsm),  // output[31:0] 
        .regs_dout       (regs_dout),          // input[31:0]
         
        .phy_ready(), // input
        .fis_first_vld(), // input
        .get_sig(), // output
        .get_dsfis(), // output
        .get_psfis(), // output
        .get_rfis(), // output
        .get_sdbfis(), // output
        .get_ufis(), // output
        .get_data_fis(), // output
        .get_ignore(), // output
        .get_fis_busy(), // input
        .get_fis_done(), // input
        .fis_ok(), // input
        .fis_err(), // input
        .fis_ferr(), // input
        .update_err_sts (), // output
        .update_prdbc(), // output
        .clear_bsy_drq(), // output
        .set_bsy(), // output
        .set_sts_7f(), // output
        .set_sts_80(), // output
        .decr_dwc(), // output
        .decr_DXC_dw(), // output[11:2] 
        .tfd_sts(), // input[7:0] 
        .tfd_err(), // input[7:0] 
        .fis_i(), // input
        .sdb_n(), // input
        .dma_a(), // input
        .dma_d(), // input
        .pio_i(), // input
        .pio_d(), // input
        .pio_es(), // input[7:0] 
        .xfer_cntr(), // input[31:2] 
        .xfer_cntr_zero(), // input
        .fetch_cmd(), // output
        .cfis_xmit(), // output
        .dx_transmit(), // output
        .atapi_xmit(), // output
        .done(), // input
        .busy(), // input
        .clearCmdToIssue(), // output
        .pCmdToIssue(), // input
        .fetch_cmd_busy(), // input
        .syncesc_recv(), // output
        .xmit_err(), // output
        .dx_err(), // input[1:0] 
        .ch_prdtl(), // input[15:0] 
        .ch_c(), // input
        .ch_b(), // input
        .ch_r(), // input
        .ch_p(), // input
        .ch_w(), // input
        .ch_a(), // input
        .ch_cfl(), // input[4:0] 
        .dwords_sent() // input[11:2] 
    );



@@ -223,7 +313,8 @@ module ahci_top#(
        .soft_write_addr  (soft_write_addr), // output[9:0] 
        .soft_write_data  (soft_write_data), // output[31:0] 
        .soft_write_en    (soft_write_en),   // output
        .soft_arst        (soft_arst),       // output
        .hba_arst         (hba_arst),        // output
        .port_arst        (port_arst),        // output
        .hba_clk          (mclk),            // input
        .hba_rst          (hba_rst),         // input   
        .hba_addr         (regs_addr),       // input[9:0] 
@@ -264,17 +355,7 @@ module ahci_top#(
        .sys_in                (d2h_data),      // input[31:0] 
        .sys_nfull             (dma_in_ready),  // output
        .sys_we                (dma_we),        // input
/*
    // xmit: DMA (memory -> device) interface
    input                  [31:0] dma_out,      // 32-bit data from the DMA module, HBA -> device port
    input                         dma_dav,      // at least one dword is ready to be read from DMA module
    output                        dma_re,       // read dword from DMA module to the output register
    // rcv: Forwarding data to the DMA engine
    input                         dma_in_ready,        // DMA engine ready to accept data
    output                        dma_in_valid         // Write data to DMA dev->memory channel


*/        
        .afi_awaddr        (afi_awaddr),        // output[31:0] 
        .afi_awvalid       (afi_awvalid),       // output
        .afi_awready       (afi_awready),       // input
@@ -326,6 +407,9 @@ module ahci_top#(
    ) ahci_fis_receive_i (
        .hba_rst           (hba_rst),           // input
        .mclk              (mclk),              // input
        
        .fis_first_vld     (), // output reg 

        .get_sig           (), // input
        .get_dsfis         (), // input
        .get_psfis         (), // input
@@ -334,8 +418,9 @@ module ahci_top#(
        .get_ufis          (), // input
        .get_data_fis      (), // input
        .get_ignore        (), // input
        
        .get_fis_busy      (), // output reg 
        .fis_first_vld     (), // output reg 
        .get_fis_done      (), // output reg 
        .fis_ok            (), // output reg 
        .fis_err           (), // output reg 
        .fis_ferr          (), // output
@@ -356,18 +441,19 @@ module ahci_top#(
        .pio_i             (), // output reg 
        .pio_d             (), // output reg 
        .pio_es            (), // output[7:0] reg 
        .xfer_cntr         (), // output[31:2] 
        .xfer_cntr_zero    (), // output reg 
        .xfer_cntr         (xfer_cntr[31:2]),        // output[31:2] 
        .xfer_cntr_zero    (xfer_cntr_zero),         // output reg
         
        .reg_addr          (regs_waddr),             // output[9:0] reg 
        .reg_we            (regs_we),    // output reg 
        .reg_data          (regs_din),   // output[31:0] reg 
        .reg_we            (regs_we_freceive),       // output reg 
        .reg_data          (regs_din_from_freceive), // output[31:0] reg 
        .hba_data_in       (d2h_data),               // input[31:0] 
        .hba_data_in_type  (d2h_type),               // input[1:0] 
        .hba_data_in_valid (d2h_valid),              // input
        .hba_data_in_many  (d2h_many),               // input
        .hba_data_in_ready (d2h_ready),              // output
        .dma_in_ready      (), // input
        .dma_in_valid      () // output
        .dma_in_ready      (dma_in_ready),           // input
        .dma_in_valid      (dma_we)                  // output
    );

    ahci_fis_transmit #(
@@ -378,10 +464,12 @@ module ahci_top#(
    ) ahci_fis_transmit_i (
        .hba_rst           (hba_rst),                // input
        .mclk              (mclk),                   // input

        .fetch_cmd         (), // input
        .cfis_xmit         (), // input
        .dx_transmit       (), // input
        .atapi_xmit        (), // input
        
        .done              (), // output reg 
        .busy              (), // output reg 
        .clearCmdToIssue   (), // input
@@ -400,21 +488,21 @@ module ahci_top#(
        .ch_cfl            (), // output[4:0] 
        .dwords_sent       (), // output[11:2] reg 
        .reg_addr          (regs_raddr),        // output[9:0] reg 
        .reg_re            (regs_re),    // output[1:0]
        .reg_re            (regs_re_ftransmit), // output[1:0]
        .reg_rdata         (regs_dout),         // input[31:0] 
        .xfer_cntr         (), // input[31:2] 
        .xfer_cntr         (xfer_cntr[31:2]),   // input[31:2] 
        .dma_ctba_ld       (ctba_ld),           // output
        .dma_start         (dma_cmd_start),     // output
        .dma_dev_wr        (), // output
        .dma_ct_busy       (), // input
        .dma_dev_wr        (dev_wr),            // output
        .dma_ct_busy       (dma_ct_busy),       // input
        .dma_prd_start     (dma_prd_start),     // output reg 
        .dma_cmd_abort     (dma_cmd_abort),     // output reg 
        .ct_addr           (dma_ct_addr),       // output[4:0] reg 
        .ct_re             (dma_ct_re),         // output[1:0]
        .ct_data           (), // input[31:0] 
        .dma_out           (), // input[31:0] 
        .dma_dav           (), // input
        .dma_re            (), // output
        .ct_data           (dma_ct_data),       // input[31:0] 
        .dma_out           (dma_dout),          // input[31:0] 
        .dma_dav           (dma_dav),           // input
        .dma_re            (dma_re),            // output
        .todev_data        (h2d_data),          // output[31:0] reg 
        .todev_type        (h2d_type),          // output[1:0] reg 
        .todev_valid       (h2d_valid),         // output