ahci_fsm.v 33.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*******************************************************************************
 * 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

23 24
module  ahci_fsm 
/*#(
25 26 27 28
//    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)
29 30
) */
(
31 32
    input                         hba_rst, // @posedge mclk
    input                         mclk, // for command/status
33 34 35
    input                         was_hba_rst,    // last reset was hba reset (not counting system reset)
    input                         was_port_rst,   // last reset was port reset
    
36 37 38 39 40 41 42 43
    // Writing FSM program memory
    input                         aclk,
    input                         arst,
    input                  [17:0] pgm_ad, // @aclk, address/data to program the AHCI FSM
    input                         pgm_wa,  // @aclk, address strobe to program the AHCI FSM
    input                         pgm_wd,  // @aclk, data strobe to program the AHCI FSM

    
44
    // direct communication with transposrt, link and phy layers
45
    input                   [1:0] phy_ready,     // goes up after comreset,cominit, align, ..., showing speed 
46
    output                        syncesc_send,  // Send sync escape
47
    input                         syncesc_send_done, // "SYNC escape until the interface is quiescent..."
48
    output                        comreset_send,     // Not possible yet?
49 50
    input                         cominit_got,   // asynchronously jumps to P:Cominit state
    output                        set_offline, // electrically idle
51
//    input                         x_rdy_collision, // X_RDY/X_RDY collision on interface 
52 53
    output                        send_R_OK,    // Should it be originated in this layer SM?
    output                        send_R_ERR,
54 55 56
    
    // Other signals....
    
57 58
    // Communication with ahci_ctrl_stat (some are not needed)
    // update register inputs (will write to register memory current value of the corresponding register)
59
    output                        pfsm_started, // H: FSM doene, P: FSM started (enable sensing pcmd_st_cleared)
60
    // update register inputs (will write to register memory current value of the corresponding register)
61
    // Removing - such updates are always done when startimng new state
62 63
///    input                         update_pending,
    output                        update_all,  // =fsm_jump[0]
64
    input                         update_busy, // valid same cycle as update_all
65 66 67 68 69 70 71 72 73
//    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
74 75

// PxCMD
76 77 78
///   output                        pcmd_clear_icc, // clear PxCMD.ICC field
///   output                        pcmd_esp,       // external SATA port (just forward value)
///   input                         pcmd_cr,        // command list run - current
79 80
    output                        pcmd_cr_set,    // command list run set
    output                        pcmd_cr_reset,  // command list run reset
81 82 83 84
//    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
85
    input                         pcmd_clo,       //RW1, causes ahci_fis_receive:clear_bsy_drq, that in turn resets this bit
86
///    output                        pcmd_clear_st,  // RW clear ST (start) bit Seems it is software controlled only
87
    input                         pcmd_st,        // current value
88 89
    input                         pcmd_st_cleared,// ST bit cleared by software;
    
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
//clear_bsy_drq    
// Interrupt inputs
    output                        sirq_TFE, // RWC: Task File Error Status
    output                        sirq_IF,  // RWC: Interface Fatal Error Status (sect. 6.1.2)
    output                        sirq_INF, // RWC: Interface Non-Fatal Error Status (sect. 6.1.2)
    output                        sirq_OF,  // RWC: Overflow Status
    output                        sirq_PRC, // RO:  PhyRdy changed Status
    output                        sirq_PC,  // RO:  Port Connect Change Status
    output                        sirq_DP,  // RWC: Descriptor Processed with "I" bit on
    output                        sirq_UF,  // RO:  Unknown FIS
    output                        sirq_SDB, // RWC: Set Device Bits Interrupt - Set Device bits FIS with 'I' bit set
    output                        sirq_DS,  // RWC: DMA Setup FIS Interrupt - DMA Setup FIS received with 'I' bit set
    output                        sirq_PS,  // RWC: PIO Setup FIS Interrupt - PIO Setup FIS received with 'I' bit set
    output                        sirq_DHR, // RWC: D2H Register FIS Interrupt - D2H Register FIS received with 'I' bit set
// SCR1:SError (only inputs that are not available in sirq_* ones
                                  //sirq_PC,
                                  //sirq_UF
107
// 5.3.2.3  P:NotRunning.8 - can not be implemented now, keeping @SuppressWarnings VEditor
108
    input                         serr_diag_X, // value of PxSERR.DIAG.X
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

     
    
// SCR0: SStatus
    output                        ssts_ipm_dnp,      // device not present or communication not established
    output                        ssts_ipm_active,   // device in active state
    output                        ssts_ipm_part,     // device in partial state
    output                        ssts_ipm_slumb,    // device in slumber state
    output                        ssts_ipm_devsleep, // device in DevSleep state
    
    output                        ssts_spd_dnp,      // device not present or communication not established
    output                        ssts_spd_gen1,     // Gen 1 rate negotiated
    output                        ssts_spd_gen2,     // Gen 2 rate negotiated
    output                        ssts_spd_gen3,     // Gen 3 rate negotiated
    
    output                        ssts_det_ndnp,     // no device detected, phy communication not established
    output                        ssts_det_dnp,      // device detected, but phy communication not established
    output                        ssts_det_dp,       // device detected, phy communication established
    output                        ssts_det_offline,  // device detected, phy communication established
128
    input                   [3:0] ssts_det,          // current value of PxSSTS.DET
129 130

 // SCR2:SControl (written by software only)
131 132
 ///   input                   [3:0] sctl_ipm,          // Interface power management transitions allowed
 ///   input                   [3:0] sctl_spd,          // Interface maximal speed
133
    input                   [3:0] sctl_det,          // Device detection initialization requested
134 135
    input                         sctl_det_changed,  // Software had written new value to sctl_det
    output                        sctl_det_reset,    // clear sctl_det_changed
136 137 138 139
    
    output                        pxci0_clear,       // PxCI clear
    input                         pxci0,             // pxCI current value
    
140
    // inputs from the DMA engine
141
///   input                         dma_prd_done, // output (finished next prd)
142 143
    output                        dma_prd_irq_clear, // reset pending prd_irq
    input                         dma_prd_irq_pend,  // prd interrupt pending. This is just a condition for irq - actual will be generated after FIS OK
144 145 146 147
///    input                         dma_cmd_busy, // output reg (DMA engine is processing PRDs)
///    input                         dma_cmd_done, // output (last PRD is over)
    output                        dma_cmd_abort,   // try to abort a command
    
148
    
149 150 151 152 153
    // Communication with ahci_fis_receive (some are unused)
    // Debug features
    input                         fis_first_invalid, // Some data available from FIFO, but not FIS head
    output                        fis_first_flush,   // Skip FIFO data until empty or FIS head

154 155
    input                         fis_first_vld, // fis_first contains valid FIS header, reset by 'get_*'
    input                   [7:0] fis_type,      // FIS type (low byte in the first FIS DWORD), valid with  'fis_first_vld'
156
    input                   [7:0] bist_bits,    // bits that define built-in self test
157
    
158
    // Receiving FIS
159 160 161 162 163 164 165
    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?)
166
//    input                         get_fis_busy,  // busy processing FIS 
167 168 169 170
    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
171
    input                         fis_extra,     // more data got from FIS than DMA can accept. Does not deny fis_ok. May have latency
172 173

    output                        set_update_sig, // when set, enables get_sig (and resets itself)
174 175
///    input                         pUpdateSig,     // state variable
///    input                         sig_available,  // device signature available
176 177 178
    output                        update_sig,        // update signature


179 180
    // 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
181 182
    output                        update_pio,    // update PxTFD.STS and PxTFD.ERR from pio_* (entry PIO:Update)
    
183 184
    output                        update_prdbc,  // update PRDBC in registers
    output                        clear_bsy_drq, // clear PxTFD.STS.BSY and PxTFD.STS.DRQ, update
185 186
    output                        clear_bsy_set_drq, // clear PxTFD.STS.BSY and sets PxTFD.STS.DRQ, update
    
187 188 189
    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
190 191
    output                        clear_xfer_cntr, // clear pXferCntr (is it needed as a separate input)?
    
192
    output                        decr_dwc,      // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers
193 194
//    output                 [11:0] decr_DXC_dw,   // decrement value (in DWORDs)
    input                         pxcmd_fre,     // control bit enables saving FIS to memory
195
    input                         pPioXfer,      // state variable
196 197
    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
198
///    input                   [7:0] tfd_err,       // Current PxTFD error field (updated after regFIS and SDB)
199
    input                         fis_i,         // value of "I" field in received regsD2H or SDB FIS
200
///    input                         sdb_n,         // value of "N" field in received SDB FIS 
201
    input                         dma_a,         // value of "A" field in received DMA Setup FIS 
202
///    input                         dma_d,         // value of "D" field in received DMA Setup FIS
203 204
    input                         pio_i,         // value of "I" field in received PIO Setup FIS
    input                         pio_d,         // value of "D" field in received PIO Setup FIS
205 206
///    input                   [7:0] pio_es,        // value of PIO E_Status
///    input                         sactive0,      // bit 0 of sActive DWORD received in SDB FIS
207
    // Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed
208
///    input                  [31:2] xfer_cntr,     // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc
209 210 211 212
    input                         xfer_cntr_zero,// valid next cycle                   
    
    // Communication with ahci_fis_transmit
    // Command pulses to execute states
213 214
    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
215
    output                        cfis_xmit,    // transmit command (wait for dma_ct_busy == 0)
216
    output                        dx_xmit,      // send FIS header DWORD, (just 0x46), then forward DMA data
217 218
                                                // transmit until error, 2048DWords or pDmaXferCnt 
    output                        atapi_xmit,   // tarsmit ATAPI command FIS
219
    input                         xmit_done,
220
//    input                         xmit_busy,
221 222 223 224

    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
225 226
//    input                         syncesc_recv, // These two inputs interrupt transmit
//    input                         xmit_err,     // 
227
    input                  [ 2:0] dx_err,       // bit 0 - syncesc_recv, 1 - xmit_err, 2 - X_RDY/X_RDY collision (valid @ xmit_err and later, reset by new command)
228
    
229
///    input                  [15:0] ch_prdtl,    // Physical region descriptor table length (in entries, 0 is 0)
230 231 232 233 234
    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
235 236
    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,
237
                                               // maximal is 16 (0x10)
238
///    input                  [11:0] dwords_sent // number of DWORDs transmitted (up to 2048)                                 
239 240 241

);
`include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams
242 243 244 245 246
`include "includes/fis_types.vh"        // @SuppressThisWarning VEditor : Some  localparams unused
    wire                           tfd_bsy =     tfd_sts[7];
    wire                           tfd_drq =     tfd_sts[4];
    wire                           tfd_sts_err = tfd_sts[0];
    
247
    reg                     [ 9:0] pgm_waddr;
248 249 250
//    wire                           pgm_ren;
//    wire                           pgm_regen;
    wire                           cond_met_w; // calculated from signals and program conditions decoder
251 252
    reg                     [ 9:0] pgm_jump_addr;
    reg                     [ 9:0] pgm_addr;
253 254 255 256 257
    wire                    [17:0] pgm_data;
    reg                            was_rst;
//    reg                            jump_r; 
    reg                      [2:0] fsm_jump;
    wire                           fsm_next;
Andrey Filippov's avatar
Andrey Filippov committed
258
    reg                            fsm_next_r;
259 260 261 262
    reg                            fsm_actions;     // processing actions
    reg                            fsm_act_busy;
    reg                      [1:0] fsm_transitions; // processing transitions
    reg                            fsm_preload;    // read first sequence data (2 cycles for regen)
263 264
//    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;
265
    wire                           pre_jump_w =   (|async_pend_r) ? async_ackn : |(cond_met_w & fsm_transitions[1]);
266
    wire                           fsm_act_done = get_fis_done || xmit_done || (syncesc_send_pend && syncesc_send_done);
267 268 269 270 271 272 273 274 275
    wire                           fsm_wait_act_w = pgm_data[16]; // this action requires waiting for done
    wire                           fsm_last_act_w = pgm_data[17];

    wire                           fsm_pre_act_w = fsm_actions && fsm_next; // use it as CS for generated actions (registered)
    
    reg                      [1:0] async_pend_r; // waiting to process cominit_got
    reg                            async_from_st; // chnge to multi-bit if there will be more sources for async transitions
    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
276
//    reg                            x_rdy_collision_pend;
277 278 279 280
    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);
Andrey Filippov's avatar
Andrey Filippov committed
281
    reg                            was_last_action_r; // delay last action if it was fsm_wait_act;
282 283
    
    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
284 285 286 287 288 289 290 291 292 293 294 295 296 297
    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
Andrey Filippov's avatar
Andrey Filippov committed
298
//    assign ssts_det_dnp =      0;                                          // device detected, but phy communication not established
299 300 301 302 303 304
    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


305 306 307 308

    // Writing to the FSM program memory
    always @ (posedge aclk) begin
        if      (arst)   pgm_waddr <= 0;
309
        else if (pgm_wa) pgm_waddr <= pgm_ad[ 9:0];
310 311 312 313 314 315 316 317 318 319 320
        else if (pgm_wd) pgm_waddr <=  pgm_waddr + 1;
    end
    // Reset addresses - later use generated
    localparam LABEL_POR =        11'h000;
    localparam LABEL_HBA_RST =    11'h002;
    localparam LABEL_PORT_RST =   11'h004;
    localparam LABEL_COMINIT =    11'h006;
    localparam LABEL_ST_CLEARED = 11'h008;

    always @ (posedge mclk) begin
        if      (hba_rst)                                                    pgm_jump_addr <= (was_hba_rst || was_port_rst) ? (was_hba_rst? LABEL_HBA_RST:LABEL_PORT_RST) : LABEL_POR;
Andrey Filippov's avatar
Andrey Filippov committed
321 322
//        else if (async_pend_r[1])                                            pgm_jump_addr <= async_from_st? LABEL_ST_CLEARED : LABEL_COMINIT;
        else if (async_pend_r[0])                                            pgm_jump_addr <= async_from_st? LABEL_ST_CLEARED : LABEL_COMINIT;
323
        else if (fsm_transitions[0] && (!cond_met_w || !fsm_transitions[1])) pgm_jump_addr <= pgm_data[9:0];
324 325 326 327 328 329 330 331
        
        was_rst <= hba_rst;
               
        fsm_jump <= {fsm_jump[1:0], pre_jump_w | (was_rst & ~hba_rst)};
        
        if   (fsm_jump[0]) pgm_addr <= pgm_jump_addr;
        else if (fsm_next) pgm_addr <= pgm_addr + 1;
        
332 333
//        if            (hba_rst) conditions <= 0; 
//        if (fsm_transitions[0]) conditions <= precond_w;
334 335 336 337 338
        
        if      (hba_rst)                                   fsm_actions <= 0;
        else if (fsm_jump[2])                               fsm_actions <= 1;
        else if (fsm_last_act_w && fsm_next)                fsm_actions <= 0;
        
Andrey Filippov's avatar
Andrey Filippov committed
339
        if (fsm_actions && fsm_next)                        was_last_action_r <= fsm_last_act_w;
340
        
Andrey Filippov's avatar
Andrey Filippov committed
341 342 343 344
        if      (hba_rst || pre_jump_w)                                fsm_transitions <= 0;
        else if ((fsm_last_act_w && fsm_actions && fsm_next && !fsm_wait_act_w) ||
                 (fsm_act_busy && fsm_act_done && was_last_action_r) ) fsm_transitions <= 1;
        else                                                           fsm_transitions <= {fsm_transitions[0],fsm_transitions[0]};
345 346 347 348 349 350 351 352 353 354 355 356 357 358
        
        if (hba_rst) fsm_preload <= 0;
        else         fsm_preload <= |fsm_jump[1:0];
        
        if      (hba_rst)       fsm_act_busy <= 0;
        else if (fsm_pre_act_w) fsm_act_busy <= fsm_wait_act_w;
        else if (fsm_act_done)  fsm_act_busy <= 0;
        
        if (pcmd_st_cleared) async_from_st <= 1;
        else if   (asynq_rq) async_from_st <= 0;
        
        if (hba_rst) async_pend_r <= 0;
        else async_pend_r <= {async_pend_r[0], asynq_rq | (async_pend_r[0] & ~async_ackn)};  
        
359
        
360 361
//        if (hba_rst || pcmd_cr_set) x_rdy_collision_pend <= 0;
//        else if (x_rdy_collision)   x_rdy_collision_pend <= 1;
362
        
363 364 365 366 367 368 369
        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; 
370
        
371 372
    end

373
    ram18p_var_w_var_r #(
374 375 376
        .REGISTERS(1),
        .LOG2WIDTH_WR(4),
        .LOG2WIDTH_RD(4)
377
        `include "includes/ahxi_fsm_code.vh" 
378 379 380 381 382 383 384 385 386
    ) fsm_pgm_mem_i (
        .rclk     (mclk),      // input
        .raddr    (pgm_addr),  // input[10:0] 
        .ren      (fsm_next),  // input
        .regen    (fsm_next),  // input
        .data_out (pgm_data),  // output[17:0] 
        .wclk     (aclk),      // input
        .waddr    (pgm_waddr), // input[10:0] 
        .we       (pgm_wd),    // input
Andrey Filippov's avatar
Andrey Filippov committed
387
        .web      (4'hf),     // input[7:0] 
388 389 390
        .data_in  (pgm_ad)     // input[17:0] 
    );

391
    action_decoder action_decoder_i (
392 393 394 395 396 397 398 399 400
        .clk                (mclk),              // input
        .enable             (fsm_pre_act_w),     // input
        .data               (pgm_data[10:0]),    // input[10:0]
    // CTRL_STAT
        .PXSERR_DIAG_X      (sirq_PC),           // output reg 
        .SIRQ_DHR           (sirq_DHR),          // output reg 
        .SIRQ_DP            (sirq_DP),           // output reg 
        .SIRQ_DS            (sirq_DS),           // output reg 
        .SIRQ_IF            (sirq_IF),           // output reg 
401
        .SIRQ_INF           (sirq_INF),          // output reg 
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
        .SIRQ_PS            (sirq_PS),           // output reg 
        .SIRQ_SDB           (sirq_SDB),          // output reg 
        .SIRQ_TFE           (sirq_TFE),          // output reg 
        .SIRQ_UF            (sirq_UF),           // output reg 
        .PFSM_STARTED       (pfsm_started),      // output reg 
        .PCMD_CR_CLEAR      (pcmd_cr_reset),     // output reg 
        .PCMD_CR_SET        (pcmd_cr_set),       // output reg 
        .PXCI0_CLEAR        (pxci0_clear),       // output reg 
        .PXSSTS_DET_1       (ssts_det_dnp),      // output reg 
        .SSTS_DET_OFFLINE   (ssts_det_offline),  // output reg 
        .SCTL_DET_CLEAR     (sctl_det_reset),    // output reg 
    // FIS RECEIVE
        .SET_UPDATE_SIG     (set_update_sig),    // output reg 
        .UPDATE_SIG         (update_sig),        // output reg 
        .UPDATE_ERR_STS     (update_err_sts),    // output reg 
        .UPDATE_PIO         (update_pio),        // output reg 
        .UPDATE_PRDBC       (update_prdbc),      // output reg 
        .CLEAR_BSY_DRQ      (clear_bsy_drq),     // output reg 
        .CLEAR_BSY_SET_DRQ  (clear_bsy_set_drq), // output reg 
        .SET_BSY            (set_bsy),           // output reg 
        .SET_STS_7F         (set_sts_7f),        // output reg 
        .SET_STS_80         (set_sts_80),        // output reg 
        .XFER_CNTR_CLEAR    (clear_xfer_cntr),   // output reg 
        .DECR_DWC           (decr_dwc),          // output reg 
        .FIS_FIRST_FLUSH    (fis_first_flush),   // output reg
    // FIS_TRANSMIT
        .CLEAR_CMD_TO_ISSUE (clearCmdToIssue),   // output reg
    // DMA
        .DMA_ABORT          (dma_cmd_abort),     // output reg 
        .DMA_PRD_IRQ_CLEAR  (dma_prd_irq_clear), // output reg
    // SATA TRANSPORT/LINK/PHY
        .XMIT_COMRESET      (comreset_send),     // output reg 
        .SEND_SYNC_ESC      (syncesc_send),      // output reg 
        .SET_OFFLINE        (set_offline),       // output reg 
        .R_OK               (send_R_OK),         // output reg 
        .R_ERR              (send_R_ERR),        // output reg
    // FIS TRANSMIT/WAIT DONE
        .FETCH_CMD          (fetch_cmd),         // output reg 
        .ATAPI_XMIT         (atapi_xmit),        // output reg 
        .CFIS_XMIT          (cfis_xmit),         // output reg 
442
        .DX_XMIT            (dx_xmit),           // output reg
443 444 445 446 447 448 449 450
    //FIS RECEIVE/WAIT DONE
        .GET_DATA_FIS       (get_data_fis),      // output reg 
        .GET_DSFIS          (get_dsfis),         // output reg 
        .GET_IGNORE         (get_ignore),        // output reg 
        .GET_PSFIS          (get_psfis),         // output reg 
        .GET_RFIS           (get_rfis),          // output reg 
        .GET_SDBFIS         (get_sdbfis),        // output reg 
        .GET_UFIS           (get_ufis)           // output reg 
451 452
    );

453
// Condition inputs may be registered if needed
454
    condition_mux condition_mux_i (
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
        .clk                   (mclk),                                    // input
        .sel                   (pgm_data[17:10]),                         // input[7:0]
        .condition             (cond_met_w),                              // output
    //COMPOSITE
        .ST_NB_ND              (pcmd_st && !tfd_bsy &&!tfd_drq),          // input PxCMD.ST & !PxTFD.STS.BSY & !PxTFD.STS.DRQ
        .PXCI0_NOT_CMDTOISSUE  (pxci0 && !pCmdToIssue),                   // input pxci0 && !pCmdToIssue was pIssueSlot==32, -> p:SelectCmd
        .PCTI_CTBAR_XCZ        (pCmdToIssue && xfer_cntr_zero && ch_r ),  // input  pCmdToIssue && ch_r && xfer_cntr_zero
        .PCTI_XCZ              (pCmdToIssue && xfer_cntr_zero),           // input  pCmdToIssue && xfer_cntr_zero
        .NST_D2HR              (!pcmd_st && (fis_type == FIS_D2HR)),      // input !ST && (FIS == FIS_D2HR) TODO: does it mean either BSY or DRQ are 1?
        .NPD_NCA               (!pio_d && !ch_a),                         // input  pio_d = 0 && ch_a == 0
        .CHW_DMAA              (ch_w && dma_a),                           // input ch_w && dma_a
    // CTRL_STAT
        .SCTL_DET_CHANGED_TO_4 (sctl_det_changed && (sctl_det == 4)),     // input (requires sctl_det_reset after)
        .SCTL_DET_CHANGED_TO_1 (sctl_det_changed && (sctl_det == 1)),     // input (requires sctl_det_reset after)
        .PXSSTS_DET_NE_3       (ssts_det != 3),                           // input  ssts_det!=3, // device detected, phy communication not established
        .PXSSTS_DET_EQ_1       (ssts_det == 1),                           // input
        .NPCMD_FRE             (!pxcmd_fre),                              // input !pcmd_fre (docs: goto P:NotRunning, but we need to clear FIFO)
    // FIS RECEIVE
        .FIS_OK                (fis_ok),                                  // input
        .FIS_ERR               (fis_err),                                 // input
        .FIS_FERR              (fis_ferr),                                // input
        .FIS_EXTRA             (fis_extra),                               // input
        .FIS_FIRST_INVALID     (fis_first_invalid),                       // input
        .FR_D2HR               (fis_first_vld && (fis_type == FIS_D2HR)), // input fis_first_vld & fis_type == 0x34 (D2H Register)
        .FIS_DATA              (fis_first_vld && (fis_type == FIS_DATA)), // input fis_first_vld && (fis_type == 'h46)
        .FIS_ANY               (fis_first_vld),                           // input
        .NB_ND_D2HR_PIO        (((fis_type == FIS_D2HR) || (fis_type == FIS_PIOS)) && !tfd_bsy && !tfd_drq), // input ((FIS == FIS_D2HR) || (FIS == FIS_PIOS)) && !PxTFD.STS.BSY & !PxTFD.STS.DRQ
        .D2HR                  (  fis_type == FIS_D2HR),                  // input  FIS == FIS_D2HR
        .SDB                   (  fis_type == FIS_SDB),                   // input
        .DMA_ACT               (  fis_type == FIS_DMAA),                  // input
        .DMA_SETUP             (  fis_type == FIS_DMAS),                  // input
        .BIST_ACT_FE           (( fis_type == FIS_BIST) && (|bist_bits)), // input FIS == FIS_BIST && |bist_bits
        .BIST_ACT              (( fis_type == FIS_BIST)),                 // input FIS == FIS_BIST#  && !(|bist_bits)
        .PIO_SETUP             (  fis_type == FIS_PIOS),                  // input
        .NB_ND                 (!tfd_bsy &&!tfd_drq),                     // input PxTFD.STS.BSY =’0’ and PxTFD.STS.DRQ =’0’
        .TFD_STS_ERR           ( tfd_sts_err),                            // input  tfd_sts[0]
        .FIS_I                 (fis_i),                                   // input
        .PIO_I                 (pio_i),                                   // input
        .NPD                   (!pio_d),                                  // input pio_d = 0 , "ch_a == 1" is not needed
        .PIOX                  (pPioXfer),                                // input
        .XFER0                 (xfer_cntr_zero),                          // input  xfer_cntr_zero
        .PIOX_XFER0            (pPioXfer && xfer_cntr_zero),              // input pPioXfer && xfer_cntr_zero
    // FIS_TRANSMIT
        .CTBAA_CTBAP           (ch_a && ch_p),                            // input
        .CTBAP                 (ch_p),                                    // input
        .CTBA_B                (ch_b),                                    // input
        .CTBA_C                (ch_c),                                    // input
        .TX_ERR                (dx_err[1]),                               // input  dx_err[1] (reset by new command)
        .SYNCESC_ERR           (dx_err[0]),                               // input
    // DMA
        .DMA_PRD_IRQ_PEND      (dma_prd_irq_pend),                        // input
    // SATA TRANSPORT/LINK/PHY        
507
        .X_RDY_COLLISION       (dx_err[2]) //x_rdy_collision_pend)                     // input
508
    );
509

510

511

512
/*
513 514 515 516
    output                        update_all,
    input                         update_busy, // valid same cycle as update_all


517 518 519 520 521
Notes:
 Implement sync esc request/ackn in TL (available in LL)
*/
endmodule