Commit 0f01238e authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Finished top modules of AHCI, started connecting them with existing link and phy layers

parent f4dc8593
Loading
Loading
Loading
Loading
+5 −6
Original line number Diff line number Diff line
@@ -54,10 +54,9 @@ module ahci_ctrl_stat #(
    input                         update_pcmd,
    input                         update_pci,

    // Next - obsolete?    
    output reg                    st01_pending,    // software turned PxCMD.ST from 0 to 1
    output reg                    st10_pending,    // software turned PxCMD.ST from 1 to 0
    input                         st_pending_reset,// reset both st01_pending and st10_pending
///    output reg                    st01_pending,    // software turned PxCMD.ST from 0 to 1
///    output reg                    st10_pending,    // software turned PxCMD.ST from 1 to 0
///    input                         st_pending_reset,// reset both st01_pending and st10_pending

// PxCMD
    input                         pcmd_clear_icc, // clear PxCMD.ICC field
@@ -505,7 +504,7 @@ localparam PxCMD_MASK = HBA_PORT__PxCMD__ICC__MASK | // 'hf0000000;
        else                 updating[5:1] <= updating[5:1] & ~ update_next[5:1];  
        
        // detect software setting for PxCMD.ST 0->1 and 1->0
        
/*        
        if      (mrst)                                                                             st01_pending <= 0;
        else if (swr_HBA_PORT__PxCMD && (HBA_PORT__PxCMD__ST__MASK &  soft_write_data & ~PxCMD_r)) st01_pending <= 1;
        if      (st_pending_reset)                                                                 st01_pending <= 0;
@@ -513,7 +512,7 @@ localparam PxCMD_MASK = HBA_PORT__PxCMD__ICC__MASK | // 'hf0000000;
        if      (mrst)                                                                             st10_pending <= 0;
        else if (swr_HBA_PORT__PxCMD && (HBA_PORT__PxCMD__ST__MASK & ~soft_write_data &  PxCMD_r)) st10_pending <= 1;
        if      (st_pending_reset)                                                                 st10_pending <= 0;
        
*/        
    end
    
endmodule
+55 −34
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ module ahci_fsm

    
    // direct communication with transposrt, link and phy layers
    input                         phy_ready,     // goes up after comreset,cominit, align, ...
    input                   [1:0] phy_ready,     // goes up after comreset,cominit, align, ..., showing speed 
    output                        syncesc_send,  // Send sync escape
    input                         syncesc_send_done, // "SYNC escape until the interface is quiescent..."
    output                        comreset_send,     // Not possible yet?
@@ -59,29 +59,31 @@ module ahci_fsm
    output                        pfsm_started, // H: FSM doene, P: FSM started (enable sensing pcmd_st_cleared)
    // update register inputs (will write to register memory current value of the corresponding register)
    // Removing - such updates are always done when startimng new state
    input                         update_pending,
    output                        update_all,
///    input                         update_pending,
    output                        update_all,  // =fsm_jump[0]
    input                         update_busy, // valid same cycle as update_all
    output                        update_gis,  // these following individual may be unneeded - just use universal update_all
    output                        update_pis,
    output                        update_ssts,
    output                        update_serr,
    output                        update_pcmd,
    output                        update_pci,
    input                         st01_pending,    // software turned PxCMD.ST from 0 to 1
    input                         st10_pending,    // software turned PxCMD.ST from 1 to 0
    output                        st_pending_reset,// reset both st01_pending and st10_pending
//    output                        update_gis,  // these following individual may be unneeded - just use universal update_all
//    output                        update_pis,
//    output                        update_ssts,
//    output                        update_serr,
//    output                        update_pcmd,
//    output                        update_pci,
///    input                         st01_pending,    // software turned PxCMD.ST from 0 to 1 - detected in the loop
///    input                         st10_pending,    // software turned PxCMD.ST from 1 to 0 - generates port reset
///    output                        st_pending_reset,// reset both st01_pending and st10_pending

// PxCMD
    output                        pcmd_clear_icc, // clear PxCMD.ICC field
    output                        pcmd_esp,       // external SATA port (just forward value)
    input                         pcmd_cr,        // command list run - current
///   output                        pcmd_clear_icc, // clear PxCMD.ICC field
///   output                        pcmd_esp,       // external SATA port (just forward value)
///   input                         pcmd_cr,        // command list run - current
    output                        pcmd_cr_set,    // command list run set
    output                        pcmd_cr_reset,  // command list run reset
    output                        pcmd_fr,        // ahci_fis_receive:get_fis_busy
    output                        pcmd_clear_bsy_drq, // == ahci_fis_receive:clear_bsy_drq
//    output                        pcmd_fr,        // ahci_fis_receive:get_fis_busy
///    output                        pcmd_clear_bsy_drq, // == ahci_fis_receive:clear_bsy_drq

// Command List override, not yet implemented (optional), keeping @SuppressWarnings VEditor
    input                         pcmd_clo,       //RW1, causes ahci_fis_receive:clear_bsy_drq, that in turn resets this bit
    output                        pcmd_clear_st,  // RW clear ST (start) bit
///    output                        pcmd_clear_st,  // RW clear ST (start) bit Seems it is software controlled only
    input                         pcmd_st,        // current value
    input                         pcmd_st_cleared,// ST bit cleared by software;
    
@@ -102,20 +104,7 @@ module ahci_fsm
// SCR1:SError (only inputs that are not available in sirq_* ones
                                  //sirq_PC,
                                  //sirq_UF
    output                        serr_DT,   // RWC: Transport state transition error
    output                        serr_DS,   // RWC: Link sequence error
    output                        serr_DH,   // RWC: Handshake Error (i.e. Device got CRC error)
    output                        serr_DC,   // RWC: CRC error in Link layer
    output                        serr_DB,   // RWC: 10B to 8B decode error
    output                        serr_DW,   // RWC: COMMWAKE signal was detected
    output                        serr_DI,   // RWC: PHY Internal Error
                                  // sirq_PRC,
                                  // sirq_IF || // sirq_INF  
    output                        serr_EP,   // RWC: Protocol Error - a violation of SATA protocol detected
    output                        serr_EC,   // RWC: Persistent Communication or Data Integrity Error
    output                        serr_ET,   // RWC: Transient Data Integrity Error (error not recovered by the interface)
    output                        serr_EM,   // RWC: Communication between the device and host was lost but re-established
    output                        serr_EI,   // RWC: Recovered Data integrity Error
// 5.3.2.3  P:NotRunning.8 - can not be implemented now, keeping @SuppressWarnings VEditor
    input                         serr_diag_X, // value of PxSERR.DIAG.X

     
@@ -273,7 +262,7 @@ module ahci_fsm
//    wire                     [7:0] precond_w = pgm_data[17:10];   // select what to use - cond_met_w valis after precond_w, same time as conditions
//    reg                      [7:0] conditions;
    wire                           pre_jump_w =   (|async_pend_r) ? async_ackn : (cond_met_w & fsm_transitions[1]);
    wire                           fsm_act_done = get_fis_done || xmit_done;
    wire                           fsm_act_done = get_fis_done || xmit_done || (syncesc_send_pend && syncesc_send_done);
    wire                           fsm_wait_act_w = pgm_data[16]; // this action requires waiting for done
    wire                           fsm_last_act_w = pgm_data[17];

@@ -284,9 +273,33 @@ module ahci_fsm
    wire                           asynq_rq = cominit_got || pcmd_st_cleared;
    wire                           async_ackn = !fsm_preload && async_pend_r[0] && ((fsm_actions && !update_busy && !fsm_act_busy) || fsm_transitions[0]);   // OK to process async jump
    reg                            x_rdy_collision_pend;
    
    reg                            syncesc_send_pend; // waiting for 'syncesc_send' confiramtion 'syncesc_send_done'
    reg                      [1:0] phy_ready_prev;    // previous state of phy_ready / speed
    reg                            phy_ready_chng_r;  // pulse when phy_ready changes
    wire                           phy_ready_chng_w = !hba_rst && !was_rst && (phy_ready != phy_ready_prev);
    
    assign fsm_next = (fsm_preload || (fsm_actions && !update_busy && !fsm_act_busy) || fsm_transitions[0]) && !async_pend_r[0]; // quiet if received cominit is pending
    assign update_all = fsm_jump[0];

    assign ssts_ipm_dnp =      phy_ready_chng_r && (phy_ready_prev == 0);  // device not present or communication not established
    assign ssts_ipm_active =   phy_ready_chng_r && (phy_ready_prev != 0);  // device in active state
    assign ssts_ipm_part =     0;                                          // device in partial state
    assign ssts_ipm_slumb =    0;                                          // device in slumber state
    assign ssts_ipm_devsleep = 0;                                          // device in DevSleep state
    
    assign ssts_spd_dnp =      phy_ready_chng_r && (phy_ready_prev == 0);  // device not present or communication not established
    assign ssts_spd_gen1 =     phy_ready_chng_r && (phy_ready_prev == 1);  // Gen 1 rate negotiated
    assign ssts_spd_gen2 =     phy_ready_chng_r && (phy_ready_prev == 2);  // Gen 2 rate negotiated
    assign ssts_spd_gen3 =     phy_ready_chng_r && (phy_ready_prev == 3);  // Gen 3 rate negotiated
    
    assign ssts_det_ndnp =     phy_ready_chng_r && (phy_ready_prev == 0);  // no device detected, phy communication not established
    assign ssts_det_dnp =      0;                                          // device detected, but phy communication not established
    assign ssts_det_dp =       phy_ready_chng_r && (phy_ready_prev != 0);  // device detected, phy communication established

    assign sirq_OF =           0;  // RWC: Overflow Status (buffer overrun - should not happen, add?)
    assign sirq_PRC =          phy_ready_chng_r; // RO:  PhyRdy changed Status



    // Writing to the FSM program memory
    always @ (posedge aclk) begin
@@ -343,6 +356,13 @@ module ahci_fsm
        if (hba_rst || pcmd_cr_set) x_rdy_collision_pend <= 0;
        else if (x_rdy_collision)   x_rdy_collision_pend <= 1;
        
        if (hba_rst || syncesc_send_done) syncesc_send_pend <= 0;
        else if (syncesc_send)            syncesc_send_pend <= 1;
        
        if (was_rst && !hba_rst && !was_hba_rst && !was_port_rst) phy_ready_prev <= 0;
        else if (phy_ready_chng_w)                                phy_ready_prev <=  phy_ready;
        
        phy_ready_chng_r <= phy_ready_chng_w; 
        
    end

@@ -374,6 +394,7 @@ module ahci_fsm
        .SIRQ_DP            (sirq_DP),           // output reg 
        .SIRQ_DS            (sirq_DS),           // output reg 
        .SIRQ_IF            (sirq_IF),           // output reg 
        .SIRQ_INF           (sirq_INF),          // output reg 
        .SIRQ_PS            (sirq_PS),           // output reg 
        .SIRQ_SDB           (sirq_SDB),          // output reg 
        .SIRQ_TFE           (sirq_TFE),          // output reg 
+183 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Module: ahci_sata_layers
 * Date:2016-01-19  
 * Author: andrey     
 * Description: Link and PHY SATA layers
 *
 * Copyright (c) 2016 Elphel, Inc .
 * ahci_sata_layers.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_sata_layers.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_sata_layers(
    input              exrst,   // master reset that resets PLL and GTX    
    output             rst,     // PHY-generated reset after PLL lock
    output             clk,     // PHY-generated clock, 75MHz for SATA2
// Data/type FIFO, host -> device   
    // Data System memory or FIS -> device
    input       [31:0] h2d_data,     // 32-bit data from the system memory to HBA (dma data)
    input       [ 1:0] h2d_type,     // 0 - data, 1 - FIS head, 2 - FIS LAST
    input              h2d_valid,    // input  register full
    output             h2d_ready,     // send FIFO has room for data (>= 8? dwords)
 
// Data/type FIFO, device -> host
    output      [31:0] d2h_data,         // FIFO input  data
    output      [ 1:0] d2h_type,    // 0 - data, 1 - FIS head, 2 - R_OK, 3 - R_ERR (last two - after data, so ignore data with R_OK/R_ERR)
    output             d2h_valid,  // Data available from the transport layer in FIFO                
    output             d2h_many,    // Multiple DWORDs available from the transport layer in FIFO           
    input              d2h_ready,   // This module or DMA consumes DWORD
    
   // communication with link/phys layers
    output      [ 1:0] phy_ready, // 0 - not ready, 1..3 - negotiated speed
    output             syncesc_recv, // These two **puts interrupt transmit
    output             xmit_err,     // Error during sending of a FIS
    input              syncesc_send,  // Send sync escape
    output             syncesc_send_done, // "SYNC escape until the interface is quiescent..."
    input              comreset_send,     // Not possible yet?
    output             cominit_got,
    input              set_offline, // electrically idle
    output             x_rdy_collision, // X_RDY/X_RDY collision on interface 
    
    input              send_R_OK,    // Should it be originated in this layer SM?
    input              send_R_ERR,
    
    // additional errors from SATA layers (single-clock pulses):
    output             serr_DT,   // RWC: Transport state transition error
    output             serr_DS,   // RWC: Link sequence error
    output             serr_DH,   // RWC: Handshake Error (i.e. Device got CRC error)
    output             serr_DC,   // RWC: CRC error in Link layer
    output             serr_DB,   // RWC: 10B to 8B decode error
    output             serr_DW,   // RWC: COMMWAKE signal was detected
    output             serr_DI,   // RWC: PHY Internal Error
                                  // sirq_PRC,
                                  // sirq_IF || // sirq_INF  
    output             serr_EP,   // RWC: Protocol Error - a violation of SATA protocol detected
    output             serr_EC,   // RWC: Persistent Communication or Data Integrity Error
    output             serr_ET,   // RWC: Transient Data Integrity Error (error not recovered by the interface)
    output             serr_EM,   // RWC: Communication between the device and host was lost but re-established
    output             serr_EI,   // RWC: Recovered Data integrity Error
    // additional control signals for SATA layers
    input        [3:0] sctl_ipm,          // Interface power management transitions allowed
    input        [3:0] sctl_spd          // Interface maximal speed
);

    link #(
        .DATA_BYTE_WIDTH(4)
    ) link_i (
        .rst              (), // input wire 
        .clk              (), // input wire 
    // data inputs from transport layer
        .data_in          (), // input[31:0] wire // input data stream (if any data during OOB setting => ignored)
    // in case of strange data aligments and size (1st mentioned @ doc, p.310, odd number of words case)
    // Actually, only last data bundle shall be masked, others are always valid.
    // Mask could be encoded into 3 bits instead of 4 for qword, but encoding+decoding aren't worth the bit
    // TODO, for now not supported, all mask bits are assumed to be set
        .data_mask_in     (), // input[1:0] wire 
        .data_strobe_out  (), // output wire  // buffer read strobe
        .data_last_in     (), // input wire // transaction's last data budle pulse
        .data_val_in      (), // input wire // read data is valid (if 0 while last pulse wasn't received => need to hold the line)
        .data_out         (), // output[31:0] wire  // read data, same as related inputs
        .data_mask_out    (), // output[1:0] wire // same thing - all 1s for now. TODO
        .data_val_out     (), // output wire // count every data bundle read by transport layer, even if busy flag is set // let the transport layer handle oveflows by himself
        .data_busy_in     (), // input wire  // transport layer tells if its inner buffer is almost full
        .data_last_out    (), // output wire 
        .frame_req        (), // input wire  // request for a new frame transition
        .frame_busy       (), // output wire // a little bit of overkill with the cound of response signals, think of throwing out 1 of them // LL tells back if it cant handle the request for now
        .frame_ack        (), // output wire // LL tells if the request is transmitting
        .frame_rej        (), // output wire // or if it was cancelled because of simultanious incoming transmission
        .frame_done_good  (), // output wire // TL tell if the outcoming transaction is done and how it was done
        .frame_done_bad   (), // output wire 
        .incom_start      (), // output wire // if started an incoming transaction
        .incom_done       (), // output wire // if incoming transition was completed
        .incom_invalidate (), // output wire // if incoming transition had errors
        .incom_ack_good   (), // input wire  // transport layer responds on a completion of a FIS
        .incom_ack_bad    (), // input wire  // oob sequence is reinitiated and link now is not established or rxelecidle
        .link_reset       (), // input wire  // oob sequence is reinitiated and link now is not established or rxelecidle
        .sync_escape_req  (), // input wire  // TL demands to brutally cancel current transaction
        .sync_escape_ack  (), // output wire // acknowlegement of a successful reception?
        .incom_stop_req   (), // input wire  // TL demands to stop current recieving session
        // inputs from phy
        .phy_ready        (), // input wire        // phy is ready - link is established
        // data-primitives stream from phy
        .phy_data_in      (), // input[31:0] wire  // phy_data_in
        .phy_isk_in       (), // input[3:0] wire   // charisk
        .phy_err_in       (), // input[3:0] wire   // disperr | notintable
        // to phy
        .phy_data_out     (), // output[31:0] wire 
        .phy_isk_out      () // output[3:0] wire   // charisk
    );
    reg        [8:0] h2d_raddr;
    reg        [8:0] h2d_waddr;
    reg        [8:0] d2h_raddr;
    reg        [8:0] d2h_waddr;
    wire       [1:0] dummy1;
    sata_phy #(
        .DATA_BYTE_WIDTH(4)
    ) sata_phy_i (
        .extrst          (), // input wire 
        .clk             (), // output wire 
        .rst             (), // output wire 
        .reliable_clk    (), // input wire 
        .phy_ready       (), // output wire 
        .gtx_ready       (), // output wire 
        .debug_cnt       (), // output[11:0] wire 
        .extclk_p        (), // input wire 
        .extclk_n        (), // input wire 
        .txp_out         (), // output wire 
        .txn_out         (), // output wire 
        .rxp_in          (), // input wire 
        .rxn_in          (), // input wire 
        .ll_data_out     (), // output[31:0] wire 
        .ll_charisk_out  (), // output[3:0] wire 
        .ll_err_out      (), // output[3:0] wire 
        .ll_data_in      (), // input[31:0] wire 
        .ll_charisk_in   () // input[3:0] wire 
    );
    
    ram18p_var_w_var_r #(
        .REGISTERS    (1),
        .LOG2WIDTH_WR (5),
        .LOG2WIDTH_RD (5)
    ) fifo_h2d_i (
        .rclk     (clk), // input
        .raddr    (h2d_raddr), // input[8:0] 
        .ren      (), // input
        .regen    (), // input
        .data_out (), // output[35:0] 
        .wclk     (clk), // input
        .waddr    (h2d_waddr), // input[8:0] 
        .we       (), // input
        .web      (4'hf), // input[3:0] 
        .data_in  ({2'b0,h2d_type,h2d_data}) // input[35:0] 
    );

    ram18p_var_w_var_r #(
        .REGISTERS    (1),
        .LOG2WIDTH_WR (5),
        .LOG2WIDTH_RD (5)
    ) fifo_d2h_i (
        .rclk     (clk), // input
        .raddr    (d2h_raddr), // input[8:0] 
        .ren      (), // input
        .regen    (), // input
        .data_out ({dummy1,d2h_type,d2h_data}), // output[35:0] 
        .wclk     (clk), // input
        .waddr    (d2h_waddr), // input[8:0] 
        .we       (), // input
        .web      (4'hf), // input[3:0] 
        .data_in  () // input[35:0] 
    );

endmodule
+117 −123

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ module axi_ahci_regs#(
    input      [11:0] wid,     // WID[11:0], input
    input             wlast,   // WLAST, input
    input      [ 3:0] wstb,    // WSTRB[3:0], input
// AXI PS Master GP0: Write Responce
// AXI PS Master GP0: Write response
    output            bvalid,  // BVALID, output
    input             bready,  // BREADY, input
    output     [11:0] bid,     // BID[11:0], output
Loading