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?
+159 −20

File changed.

Preview size limit exceeded, changes collapsed.

+93 −26

File changed.

Preview size limit exceeded, changes collapsed.

+18 −2
Original line number Diff line number Diff line
@@ -100,6 +100,13 @@ module axi_ahci_regs#(
    input              [31:0] hba_din,
    output             [31:0] hba_dout,
    
// Program FSM memory
    output reg         [17:0] pgm_ad, // @aclk, address/data to program the AHCI FSM
    output reg                pgm_wa, // @aclk, address strobe to program the AHCI FSM
    output reg                pgm_wd, // @aclk, data strobe to program the AHCI FSM
    
    
    
//  other control signals
    output reg         [ 3:0] afi_wcache,
    output reg         [ 3:0] afi_rcache,
@@ -160,6 +167,8 @@ module axi_ahci_regs#(
    
    wire                   high_sel = bram_waddr_r[ADDRESS_BITS-1]; // high addresses - use single-cycle writes without read-modify-write
    wire                   afi_cache_set_w = bram_wen_r && !high_sel && (bram_addr == HBA_PORT__AFI_CACHE__WR_CM__ADDR);
    wire                   pgm_fsm_set_w =   bram_wen_r && !high_sel && (bram_addr == HBA_PORT__PGM_AHCI_SM__PGM_AD__ADDR);
    wire                   pgm_fsm_and_w = |(ahci_regs_di & HBA_PORT__PGM_AHCI_SM__AnD__MASK);
    
    wire                   set_hba_rst =  bram_wen_r && !high_sel && (bram_addr == GHC__GHC__HR__ADDR) && (ahci_regs_di & GHC__GHC__HR__MASK);
    wire                   set_port_rst = bram_wen_r && !high_sel && (bram_addr == HBA_PORT__PxSCTL__DET__ADDR) &&
@@ -228,7 +237,6 @@ module axi_ahci_regs#(
        if (arst || set_hba_rst) was_port_rst_aclk <= 0;
        else if (port_rst_on)    was_port_rst_aclk <= 1;

                     
    end

    always @ (hba_clk) begin
@@ -243,6 +251,14 @@ module axi_ahci_regs#(
        else if (afi_cache_set_w)  {afi_wcache,afi_rcache}  <= ahci_regs_di[7:0];
    end    

    always @(posedge aclk) begin
        if (arst) {pgm_wa,pgm_wd}  <= 0;
        else      {pgm_wa,pgm_wd}  <= {2{pgm_fsm_set_w}} & {pgm_fsm_and_w, ~pgm_fsm_and_w};
        
        if (pgm_fsm_set_w) pgm_ad <= ahci_regs_di[17:0];
    end    


/*
Will generate async reset on both HBA reset(for some time) and port reset (until released) 
until it is more clear about GTX reset options. Such reset will be applied to both PLL and GTX,
Loading