Commit 82906512 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

implemented run-time sequencer for the ahci_fsm, working on the actual sequence

parent 50d15e4c
Loading
Loading
Loading
Loading
+44 −2
Original line number Diff line number Diff line
@@ -54,6 +54,11 @@ 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

// PxCMD
    input                         pcmd_clear_icc, // clear PxCMD.ICC field
    input                         pcmd_esp,       // external SATA port (just forward value)
@@ -61,10 +66,15 @@ module ahci_ctrl_stat #(
    input                         pcmd_cr_set,    // command list run set
    input                         pcmd_cr_reset,  // command list run reset
    input                         pcmd_fr,        // ahci_fis_receive:get_fis_busy - change to HAB set/reset (set, do, reset)
    output                        pcmd_fre,       // FIS enable copy to memory
    input                         pcmd_clear_bsy_drq, // == ahci_fis_receive:clear_bsy_drq
    output                        pcmd_clo,       //RW1, causes ahci_fis_receive:clear_bsy_drq, that in turn resets this bit
    input                         pcmd_clear_st,  // RW clear ST (start) bit
    output                        pcmd_st,        // current value

    input                         pfsm_started,   // H: FSM done, P: FSM started (enable sensing pcmd_st_cleared)
    output reg                    pcmd_st_cleared,// ST bit cleared by software; TODO: check not in H:Init (5.3.2.10)
    
//clear_bsy_drq    
// Interrupt inputs
    input                         sirq_TFE, // RWC: Task File Error Status
@@ -96,7 +106,7 @@ module ahci_ctrl_stat #(
    input                         serr_ET,   // RWC: Transient Data Integrity Error (error not recovered by the interface)
    input                         serr_EM,   // RWC: Communication between the device and host was lost but re-established
    input                         serr_EI,   // RWC: Recovered Data integrity Error

    output                        serr_diag_X, // value of PxSERR.DIAG.X
     
    
// SCR0: SStatus
@@ -119,6 +129,8 @@ module ahci_ctrl_stat #(
    output reg              [3:0] sctl_ipm,          // Interface power management transitions allowed
    output reg              [3:0] sctl_spd,          // Interface maximal speed
    output reg              [3:0] sctl_det,          // Device detection initialization requested
    output reg                    sctl_det_changed,  // Software had written new value to sctl_det
    input                         sctl_det_reset,    // clear sctl_det_changed
    
    input                         pxci0_clear,       // PxCI clear
    output                        pxci0,             // pxCI current value
@@ -235,14 +247,22 @@ module ahci_ctrl_stat #(
    wire                          update_HBA_PORT__PxSERR = update_serr || update_first[3] || update_next[3];
    wire                          update_HBA_PORT__PxCMD =  update_pcmd || update_first[4] || update_next[4];
    wire                          update_HBA_PORT__PxCI =   update_pci  || update_first[5] || update_next[5];
    
    reg                           pfsm_started_r;    
    
    assign update_busy = (update_all && (|regs_changed)) || (|updating[5:1]);
    assign update_pending =  | regs_changed;
    assign pcmd_fre = |(HBA_PORT__PxCMD__FRE__MASK & PxCMD_r); 
    assign serr_diag_X = |(HBA_PORT__PxSERR__DIAG__X__MASK & PxSERR_r);
       
    
localparam PxIE_MASK =   HBA_PORT__PxIE__TFEE__MASK | // 'h40000000;
                         HBA_PORT__PxIE__IFE__MASK |  // 'h8000000;
                         HBA_PORT__PxIE__INFE__MASK | // 'h4000000;
                         HBA_PORT__PxIE__OFE__MASK |  // 'h1000000;
                         HBA_PORT__PxIE__PRCE__MASK | // 'h400000;
                         HBA_PORT__PxIE__PCE__MASK |  // 'h40;
                         HBA_PORT__PxIE__DPE__MASK |  // 'h20
                         HBA_PORT__PxIE__UFE__MASK |  // 'h10;
                         HBA_PORT__PxIE__SDBE__MASK | // 'h8;
                         HBA_PORT__PxIE__DSE__MASK |  // 'h4;
@@ -254,6 +274,8 @@ localparam PxIS_MASK = HBA_PORT__PxIS__TFES__MASK | // 'h40000000;
                         HBA_PORT__PxIS__INFS__MASK | // 'h4000000;
                         HBA_PORT__PxIS__OFS__MASK |  // 'h1000000;
                         HBA_PORT__PxIS__PRCS__MASK | // 'h400000;
                         HBA_PORT__PxIS__PCS__MASK |  // 'h40;
                         HBA_PORT__PxIS__DPS__MASK |  // 'h20
                         HBA_PORT__PxIS__UFS__MASK |  // 'h10;
                         HBA_PORT__PxIS__SDBS__MASK | // 'h8;
                         HBA_PORT__PxIS__DSS__MASK |  // 'h4;
@@ -393,6 +415,9 @@ localparam PxCMD_MASK = HBA_PORT__PxCMD__ICC__MASK | // 'hf0000000;
    always @ (posedge mclk) begin
        if      (rst_por)              {sctl_ipm, sctl_spd, sctl_det} <= 0;
        else if (swr_HBA_PORT__PxSCTL) {sctl_ipm, sctl_spd, sctl_det} <= soft_write_data [11:0];
        
        if      (rst_por || sctl_det_reset)                                  sctl_det_changed <= 0;
        else if (swr_HBA_PORT__PxSCTL && (soft_write_data[3:0] != sctl_det)) sctl_det_changed <= 1;
    end
    
    // HBA_PORT__PxSERR register
@@ -420,6 +445,13 @@ localparam PxCMD_MASK = HBA_PORT__PxCMD__ICC__MASK | // 'hf0000000;
                          (HBA_PORT__PxCMD__FRE__MASK & PxCMD_r) | // no HBA control
                          (pcmd_clear_bsy_drq ? 0 : (PxCMD_r & HBA_PORT__PxCMD__CLO__MASK)) |
                          (pcmd_clear_st ?      0 : (PxCMD_r & HBA_PORT__PxCMD__ST__MASK)) )));
                          
        if      (mrst)                pfsm_started_r <= 0;
        else if (pfsm_started)        pfsm_started_r <= 1;                  
        
        if (!pfsm_started_r)          pcmd_st_cleared <= 0;
        else if (swr_HBA_PORT__PxCMD) pcmd_st_cleared <= |(HBA_PORT__PxCMD__ST__MASK & PxCMD_r & ~soft_write_data);
                          
    end
    
    // Update AXI registers with the current local data
@@ -470,6 +502,16 @@ localparam PxCMD_MASK = HBA_PORT__PxCMD__ICC__MASK | // 'hf0000000;
        else if (update_all) updating[5:1] <= regs_changed[5:1] & ~update_first[5:1];
        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;
        
        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
+24 −10
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ module ahci_fis_receive#(
    // Control Interface
    output reg                    fis_first_vld, // fis_first contains valid FIS header, reset by get_*
    // Receiving FIS
    input                         set_update_sig, // when set, enables get_sig (and resets itself)
    output                        pUpdateSig,     // state variable
    input                         get_sig,        // update signature
    input                         get_dsfis,
    input                         get_psfis,
@@ -55,13 +57,17 @@ module ahci_fis_receive#(
    input                         update_pio,    // update PxTFD.STS and PxTFD.ERR from pio_* (entry PIO:Update)
    input                         update_prdbc,  // update PRDBC in registers
    input                         clear_bsy_drq, // clear PxTFD.STS.BSY and PxTFD.STS.DRQ, update
    input                         clear_bsy_set_drq, // clear PxTFD.STS.BSY and sets PxTFD.STS.DRQ, update
    input                         set_bsy,       // set PxTFD.STS.BSY, update
    input                         set_sts_7f,    // set PxTFD.STS = 0x7f, update
    input                         set_sts_80,    // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update

    input                         clear_xfer_cntr, // clear pXferCntr (is it needed as a separate input)?
    input                         decr_dwc,      // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers
    input                  [11:0] decr_DXC_dw,   // decrement value (in DWORDs)
    
    input                         pcmd_fre,      // control bit enables saving FIS to memory (will be ignored for signature)
    
    // TODO: Add writing PRDBC here?
    output reg                    pPioXfer,      // state variable
    output                  [7:0] tfd_sts,       // Current PxTFD status field (updated after regFIS and SDB - certain fields)
@@ -181,6 +187,7 @@ localparam DATA_TYPE_ERR = 3;
    reg           [7:0] pio_es_r;        // value of PIO E_Status
    reg           [7:0] pio_err_r;
    
    reg                 pUpdateSig_r = 1;     // state variable
    
    // 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;
@@ -203,7 +210,7 @@ localparam DATA_TYPE_ERR = 3;
    assign data_in_dwords = data_in_dwords_r;
    
    assign pio_es = pio_es_r;
     
    assign pUpdateSig = pUpdateSig_r; 
    always @ (posedge mclk) begin
        if (hba_rst || dma_in_stop) dma_in <= 0;
        else if (dma_in_start)      dma_in <= 1;
@@ -233,9 +240,13 @@ localparam DATA_TYPE_ERR = 3;
                         ({4{get_ufis}}     & UFIS32_LENM1 )  |
                         ({4{get_data_fis}} & DMAH_LENM1)     |
                         ({4{get_ignore}}   & IGNORE_LENM1 );
           fis_save <=    !get_data_fis && !get_ignore && !get_sig;
//           fis_save <=    pcmd_fre && !get_data_fis && !get_ignore && !get_sig;
           // save signature FIS to memory if waiting (if not - ignore FIS)
           // for non-signature /non-data - obey pcmd_fre 
           fis_save <=    get_sig? pUpdateSig_r : (pcmd_fre && !get_data_fis && !get_ignore);
           
           is_data_fis <= get_data_fis;
           update_sig <=  get_sig?    1 : 0;
           update_sig <=  ((get_sig && pUpdateSig_r)?    1 : 0);
           reg_ds <=      get_dsfis ? 1 : 0;
           reg_ps <=      get_psfis ? 1 : 0;
           reg_d2h <=     get_rfis ?  1 : 0;    
@@ -296,7 +307,8 @@ localparam DATA_TYPE_ERR = 3;
        else if (reg_ps[0])                   tf_err_sts  <= {hba_data_in[31:24],hba_data_in[23:16]};
        else if (update_pio)                  tf_err_sts  <= {pio_err_r, pio_es_r};
        else if (reg_sdb)                     tf_err_sts  <= {hba_data_in[15:8], tf_err_sts[7], hba_data_in[6:4], tf_err_sts[3],hba_data_in[2:0]};
        else if (clear_bsy_drq || set_bsy)    tf_err_sts  <= tf_err_sts & {8'hff,clear_bsy_drq,3'h7,clear_bsy_drq,3'h7} | {8'h0,set_bsy,7'h0};
        else if (clear_bsy_drq || set_bsy || clear_bsy_set_drq)
                                              tf_err_sts  <= tf_err_sts & {8'hff,clear_bsy_drq,3'h7,clear_bsy_drq,3'h7} | {8'h0,set_bsy,3'h0,clear_bsy_set_drq,3'h0};
        else if (set_sts_7f || set_sts_80)    tf_err_sts  <= {tf_err_sts[15:8],set_sts_80,{7{set_sts_7f}}} ;
        
        reg_we <= reg_we_w || update_sig[3] || update_err_sts_r || update_prdbc_r;
@@ -317,7 +329,7 @@ localparam DATA_TYPE_ERR = 3;
        if (hba_rst)                          pio_es_r  <=         0;
        else if (reg_ps[3])                   pio_es_r  <=         hba_data_in[31:24];
        
        if (hba_rst || reg_sdb)               xfer_cntr_r[31:2] <= 0;
        if (hba_rst || reg_sdb || clear_xfer_cntr) xfer_cntr_r[31:2] <= 0;
        else if (reg_ps[4] || reg_ds[5])           xfer_cntr_r[31:2] <= {reg_ds[5]?hba_data_in[31:16]:16'b0, hba_data_in[15:2]} + hba_data_in[1]; // round up
        else if (decr_dwc)                         xfer_cntr_r[31:2] <= {xfer_cntr_r[31:2]} - {18'b0, decr_DXC_dw[11:0]};
        
@@ -333,6 +345,8 @@ localparam DATA_TYPE_ERR = 3;
        if (hba_rst || update_pio) pPioXfer <= 0;
        else if (reg_ps[4])        pPioXfer <= 1;
        
        if (hba_rst || set_update_sig) pUpdateSig_r <= 1;
        else if (update_sig[3])        pUpdateSig_r <= 0;
        
        
        // Maybe it is not needed if the fsm will send this pulse?
Loading