ahci_sata_layers.v 30.1 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_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

23
module  ahci_sata_layers #(
24 25 26 27 28
`ifdef USE_DATASCOPE
    parameter ADDRESS_BITS =         10, //for datascope
    parameter DATASCOPE_START_BIT =  14, // bit of DRP "other_control" to start recording after 0->1 (needs DRP)
    parameter DATASCOPE_POST_MEAS =  16, // number of measurements to perform after event
`endif        
29 30 31 32 33 34
    parameter BITS_TO_START_XMIT =    6,   // wait H2D FIFO to have 1 << BITS_TO_START_XMIT to start FIS transmission (or all FIS fits)
    parameter DATA_BYTE_WIDTH =       4,
    parameter ELASTIC_DEPTH =         4, //5, With 4/7 got infrequent overflows!
    parameter ELASTIC_OFFSET =        7, //  5 //10
    parameter FREQ_METER_WIDTH =     12
    
35
)(
36 37
    input              exrst,   // master reset that resets PLL and GTX
    input              reliable_clk, // use aclk that runs independently of the GTX
38 39 40 41 42
    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)
43
    input       [ 1:0] h2d_mask,     // set to 2'b11
44
    input       [ 1:0] h2d_type,     // 0 - data, 1 - FIS head, 2 - FIS LAST
45 46
    input              h2d_valid,    // output  register full
    output             h2d_ready,    // h2d FIFO has room for data (>= 8? dwords)
47 48 49
 
// Data/type FIFO, device -> host
    output      [31:0] d2h_data,         // FIFO input  data
50
    output      [ 1:0] d2h_mask,     // set to 2'b11
51 52 53 54 55 56
    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
57 58
    output      [ 1:0] phy_speed,       // 0 - not ready, 1..3 - negotiated speed (Now 0/2)
    output             gtx_ready,       // How to use it?
59 60 61 62 63
    output             xmit_ok,         // received R_OK after transmission
    output             xmit_err,        // Error during/after sending of a FIS (got R_ERR)
    output             x_rdy_collision, // X_RDY/X_RDY collision on interface 
    output             syncesc_recv,    // Where to get it?

64
    input              pcmd_st_cleared,      // PxCMD.ST 1->0 transition by software
65
    input              syncesc_send,      // Send sync escape
66 67 68 69 70 71 72 73 74
    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
    
    input              send_R_OK,    // Should it be originated in this layer SM?
    input              send_R_ERR,
    
    // additional errors from SATA layers (single-clock pulses):
75
    
76 77 78 79 80 81 82 83
    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,
84
    output             serr_EE,   // RWC: Internal error (such as elastic buffer overflow or primitive mis-alignment)
85 86 87 88 89 90
    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
91 92
    input        [3:0] sctl_ipm,  // Interface power management transitions allowed // @SuppressThisWarning Veditor Unused (yet)
    input        [3:0] sctl_spd,  // Interface maximal speed                        // @SuppressThisWarning Veditor Unused (yet)
93 94 95 96 97 98 99 100 101

    // Device high speed pads and clock inputs    
    // ref clk from an external source, shall be connected to pads
    input   wire        extclk_p, 
    input   wire        extclk_n,
    // sata link data pins
    output  wire        txp_out,
    output  wire        txn_out,
    input   wire        rxp_in,
102
    input   wire        rxn_in,
103 104 105 106 107 108 109 110
`ifdef USE_DATASCOPE
// Datascope interface (write to memory that can be software-read)
    output                    datascope_clk,
    output [ADDRESS_BITS-1:0] datascope_waddr,
    output                    datascope_we,
    output             [31:0] datascope_di,
`endif    
    
Andrey Filippov's avatar
Andrey Filippov committed
111 112 113 114 115 116 117 118 119 120
`ifdef USE_DRP
    input               drp_rst,
    input               drp_clk,
    input               drp_en, // @aclk strobes drp_ad
    input               drp_we,
    input        [14:0] drp_addr,       
    input        [15:0] drp_di,
    output              drp_rdy,
    output       [15:0] drp_do ,
`endif    
121
    output  [FREQ_METER_WIDTH - 1:0] xclk_period,      // relative (to 2*clk) xclk period
122
    output       [31:0] debug_phy,
123 124
    output       [31:0] debug_link,
    input               hclk // just for testing
125
    
126
    
127
);
128
    localparam PHY_SPEED = 2; // SATA2
129 130 131 132 133 134 135 136 137 138
    localparam FIFO_ADDR_WIDTH = 9;
    
    localparam D2H_TYPE_DMA =      0;
    localparam D2H_TYPE_FIS_HEAD = 1;
    localparam D2H_TYPE_OK =       2;
    localparam D2H_TYPE_ERR =      3;

    localparam H2D_TYPE_FIS_DATA = 0; // @SuppressThisWarning VEditor unused
    localparam H2D_TYPE_FIS_HEAD = 1;
    localparam H2D_TYPE_FIS_LAST = 2;
139
    
Andrey Filippov's avatar
Andrey Filippov committed
140 141
    wire               phy_ready;        // active when GTX gets aligned output
    wire               link_established; // Received 3 back-to-back non-ALIGNp 
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
    wire        [31:0] ll_h2d_data_in;
    wire         [1:0] ll_h2d_mask_in;
    wire               ll_strobe_out;
    wire               ll_h2d_last;
    wire         [1:0] h2d_type_out;
    
    wire        [31:0] ll_d2h_data_out;
    wire        [ 1:0] ll_d2h_mask_out;
    wire               ll_d2h_valid;
    wire               ll_d2h_almost_full;
//    wire               ll_d2h_last; // may loose ll timing and send 'last' after data. Now assuming no data comes next xyxle after last
//    wire         [1:0] d2h_type_in;
    reg          [1:0] d2h_type_in;
    reg                fis_over_r;  // push 1 more DWORD (ignore) + type (ERR/OK) when received FIS is done/error         
    
Andrey Filippov's avatar
Andrey Filippov committed
157
//    wire ll_frame_req_w;       // pre ll_frame_req
158
    reg  ll_frame_req;         // -> link // request for a new frame transition
Andrey Filippov's avatar
Andrey Filippov committed
159 160
    wire ll_frame_ackn;        // acknowledge for ll_frame_req
//    wire ll_frame_busy;        // link -> // 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
161 162 163 164 165 166 167 168
//    wire ll_frame_ack;         // link -> // LL tells if the request is transmitting not used
//    wire ll_frame_rej;         // link -> // or if it was cancelled because of simultanious incoming transmission
//    wire ll_frame_done_good;   // link -> // TL tell if the outcoming transaction is done and how it was done
//    wire ll_frame_done_bad;    // link ->
     
    wire ll_incom_start;       // link -> // if started an incoming transaction    assuming this and next 2 are single-cycle
    wire ll_incom_done;        // link -> // if incoming transition was completed
    wire ll_incom_invalidate;  // link -> // if incoming transition had errors
169 170 171
    reg ll_incom_invalidate_r; // error delayed by 1 clock - if eof was incorrect (because of earlier data error)
                               // let last data dword to pass through
    
172 173 174
//    wire incom_ack_good = send_R_OK;    // -> link  // transport layer responds on a completion of a FIS
//    wire incom_ack_bad = send_R_ERR;     // -> link  // oob sequence is reinitiated and link now is not established or rxelecidle
    
175 176 177
    wire ll_link_reset = ~phy_ready;        // -> link  // oob sequence is reinitiated and link now is not established or rxelecidle //TODO Alexey:mb it shall be independent
    
//    wire ll_incom_stop_req;    // -> link  // TL demands to stop current recieving session (use !PxCMD.ST)?
178 179 180 181 182 183 184 185 186 187 188 189
    
    wire [DATA_BYTE_WIDTH*8 - 1:0] ph2ll_data_out;
    wire [DATA_BYTE_WIDTH   - 1:0] ph2ll_charisk_out; // charisk
    wire [DATA_BYTE_WIDTH   - 1:0] ph2ll_err_out;     // disperr | notintable
    wire [DATA_BYTE_WIDTH*8 - 1:0] ll2ph_data_in;
    wire [DATA_BYTE_WIDTH   - 1:0] ll2ph_charisk_in;  // charisk

    wire     [FIFO_ADDR_WIDTH-1:0] h2d_raddr;
    wire                     [1:0] h2d_fifo_re_regen;    
    wire     [FIFO_ADDR_WIDTH-1:0] h2d_waddr;
    wire       [FIFO_ADDR_WIDTH:0] h2d_fill;
    wire                           h2d_nempty;
190
//    wire                           h2d_under;
191 192 193 194 195 196
    
    wire     [FIFO_ADDR_WIDTH-1:0] d2h_raddr;
    wire                     [1:0] d2h_fifo_re_regen;    
    wire     [FIFO_ADDR_WIDTH-1:0] d2h_waddr;
    wire       [FIFO_ADDR_WIDTH:0] d2h_fill;
    wire                           d2h_nempty;
197
//    wire                           d2h_over;
198 199 200 201 202 203 204
    wire                           h2d_fifo_rd = h2d_nempty && ll_strobe_out; // TODO: check latency in link.v
    wire                           h2d_fifo_wr = h2d_valid;
    
    wire                           d2h_fifo_rd = d2h_valid && d2h_ready;
    wire                           d2h_fifo_wr = ll_d2h_valid || fis_over_r; // fis_over_r will push FIS end to FIFO
    reg                            h2d_pending;    // HBA started sending FIS to fifo
    
205 206
 //   wire                    [31:0] debug_phy;
 //   wire                    [31:0] debug_link;
207 208 209

    wire                           rxelsfull; 
    wire                           rxelsempty; 
210 211
    wire                           xclk;             // output receive clock, just to measure frequency
//    wire  [FREQ_METER_WIDTH - 1:0] xclk_period;      // relative (to 2*clk) xclk period
Andrey Filippov's avatar
Andrey Filippov committed
212 213
    
    wire debug_detected_alignp; // oob detects ALIGNp, but not the link layer
214
    wire                    [31:0] debug_phy0;
215 216 217
    
    wire [31:0]                    datascope0_di;
    
Andrey Filippov's avatar
Andrey Filippov committed
218
//    assign debug_sata = {link_established, phy_ready, debug_phy[29:16],debug_link[15:0]}; // 
219
//    assign debug_sata = debug_link[31:0]; // 
Andrey Filippov's avatar
Andrey Filippov committed
220
///    assign debug_sata = debug_phy;
221
    
222
//    assign debug_sata = {debug_link[31:4],debug_phy[3:0]} ; // 
223
//    assign debug_sata = {debug_link[31:8],debug_phy[7:0]} ; // 
224
//    assign debug_sata = {debug_link[27:20],debug_phy[23:0]} ; // 
225
    
Andrey Filippov's avatar
Andrey Filippov committed
226
    assign ll_h2d_last =  (h2d_type_out == H2D_TYPE_FIS_LAST); 
227 228 229
    assign d2h_valid = d2h_nempty;
    assign d2h_many =  |d2h_fill[FIFO_ADDR_WIDTH:3]; // 
    
Andrey Filippov's avatar
Andrey Filippov committed
230
    assign h2d_ready = !h2d_fill[FIFO_ADDR_WIDTH] && !(&h2d_fill[FIFO_ADDR_WIDTH:3]);
231 232
    assign ll_d2h_almost_full   = d2h_fill[FIFO_ADDR_WIDTH] || &d2h_fill[FIFO_ADDR_WIDTH-1:6]; // 63 dwords (maybe use :5?) - time to tell device to stop 
    
Andrey Filippov's avatar
Andrey Filippov committed
233
//    assign ll_frame_req_w = !ll_frame_busy && h2d_pending && (((h2d_type == H2D_TYPE_FIS_LAST) && h2d_fifo_wr ) || (|h2d_fill[FIFO_ADDR_WIDTH : BITS_TO_START_XMIT]));
234 235
// Separating different types of errors, sync_escape from other problems. TODO: route individual errors to set SERR bits
//assign  incom_invalidate = state_rcvr_eof & crc_bad & ~alignes_pair | state_rcvr_data   & dword_val &  rcvd_dword[CODE_WTRMP];
Andrey Filippov's avatar
Andrey Filippov committed
236 237 238 239 240 241 242
//    assign phy_speed = phy_ready ? PHY_SPEED:0;
//    assign serr_DB = phy_ready && (|ph2ll_err_out);
//    assign serr_DH = phy_ready && (xmit_err);
    assign phy_speed = link_established ? PHY_SPEED:0;
    assign serr_DB =   link_established && (|ph2ll_err_out);
    assign serr_DH =   link_established && (xmit_err);
    //
243 244
    
// not yet assigned errors
Andrey Filippov's avatar
Andrey Filippov committed
245 246 247 248
///    assign serr_DT = phy_ready && (comreset_send); // RWC: Transport state transition error
///    assign serr_DS = phy_ready && (cominit_got);   // RWC: Link sequence error
///    assign serr_DC = phy_ready && (serr_DW);       // RWC: CRC error in Link layer
    assign serr_DT = phy_ready && (0); // RWC: Transport state transition error
Andrey Filippov's avatar
Andrey Filippov committed
249 250
//    assign serr_DS = phy_ready && (0);   // RWC: Link sequence error
//    assign serr_DC = phy_ready && (0);       // RWC: CRC error in Link layer
Andrey Filippov's avatar
Andrey Filippov committed
251
//    assign serr_DB = phy_ready && (0);   // RWC: 10B to 8B decode error
252 253 254
    assign serr_EE = phy_ready && (rxelsfull || rxelsempty);
    assign serr_DI = phy_ready && (0);   // rxelsfull);   // RWC: PHY Internal Error // just debugging
    assign serr_EP = phy_ready && (0);   // rxelsempty);   // RWC: Protocol Error - a violation of SATA protocol detected // just debugging
Andrey Filippov's avatar
Andrey Filippov committed
255 256 257 258
    assign serr_EC = phy_ready && (0);   // RWC: Persistent Communication or Data Integrity Error
    assign serr_ET = phy_ready && (0);   // RWC: Transient Data Integrity Error (error not recovered by the interface)
    assign serr_EM = phy_ready && (0);   // RWC: Communication between the device and host was lost but re-established
    assign serr_EI = phy_ready && (0);   // RWC: Recovered Data integrity Error
259
    
260
    reg [1:0] debug_last_d2h_type_in;
261 262
    reg [1:0] debug_last_d2h_type;
    
263 264
    always @ (posedge clk) begin
        if (d2h_fifo_wr) debug_last_d2h_type_in<= d2h_type_in;
265
        if (d2h_fifo_rd) debug_last_d2h_type<=    d2h_type;
266
    end
267
    /*
268 269 270
    assign debug_phy = {h2d_type_out[1:0],h2d_type[1:0],
                        ll_h2d_last,d2h_valid,  d2h_type[1:0],
                        debug_last_d2h_type_in, d2h_type_in[1:0],
271 272 273 274 275 276 277 278
                        debug_last_d2h_type[1:0],
                        d2h_fill[1:0],
                        1'b0,
                        d2h_fifo_wr,
                        d2h_fifo_re_regen[1:0],
                        d2h_waddr[1:0],
                        d2h_raddr[1:0],
                        debug_phy0[ 7:0]};
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
*/
/*                        
    assign debug_phy = {h2d_type_out[1:0],h2d_type[1:0],
                        ll_h2d_last,d2h_valid,  d2h_type[1:0],
//                        debug_last_d2h_type_in, d2h_type_in[1:0],
//                        debug_last_d2h_type[1:0],
//                        d2h_fill[1:0],
//                        1'b0,
//                        d2h_fifo_wr,
//                        d2h_fifo_re_regen[1:0],
//                        d2h_waddr[1:0],
//                        d2h_raddr[1:0],
                        debug_phy0[23:0]};
*/
assign debug_phy = debug_phy0; 

295 296
//                        debug_phy0[15:0]};
//                        debug_phy0[19:0]};
297 298 299 300 301 302 303 304 305 306
    
/*
// Data/type FIFO, device -> host
    output      [31:0] d2h_data,         // FIFO input  data
    output      [ 1:0] d2h_mask,     // set to 2'b11
    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
*/    
307 308 309
//        .comreset_send   (comreset_send),     // input
//        .cominit_got     (cominit_got),       // output wire 
//        .comwake_got     (serr_DW),            // output wire 
310
    
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
    `ifdef DATASCOPE_INCOMING_RAW
        assign datascope_di   = {5'b0,debug_link[5],datascope0_di[25:0]};// aligns_pair tx
    `else
        // Mix transmitted alignes pair, but only to the closest group of 6 primitives
        reg dbg_was_link5; // alignes pair sent
        wire dbg_was_link5_xclk; // alignes pair sent

        always @ (posedge datascope_clk) begin
            if (dbg_was_link5_xclk) dbg_was_link5 <= 1;
            else if (datascope_we)  dbg_was_link5 <= 0; 
        end        

        pulse_cross_clock #(
            .EXTRA_DLY(0)
        ) dbg_was_link5_i (
            .rst       (rst),                // input
            .src_clk   (clk),                // input
            .dst_clk   (datascope_clk),      // input
            .in_pulse  (debug_link[5]),      // input// is actually a two-cycle
            .out_pulse (dbg_was_link5_xclk), // output
            .busy()                          // output
        );

        assign datascope_di   = {dbg_was_link5,datascope0_di[30:0]};// aligns_pair tx
        
    `endif
337 338
    link #(
        .DATA_BYTE_WIDTH(4)
339
    ) link (
340 341
        .rst              (rst),                   // input wire 
        .clk              (clk),                   // input wire 
342
    // data inputs from transport layer
343
        .data_in          (ll_h2d_data_in),        // input[31:0] wire // input data stream (if any data during OOB setting => ignored)
344
    // TODO, for now not supported, all mask bits are assumed to be set
345 346 347 348 349 350 351 352 353 354 355 356
        .data_mask_in     (ll_h2d_mask_in),        // input[1:0] wire 
        .data_strobe_out  (ll_strobe_out),         // output wire  // buffer read strobe
        .data_last_in     (ll_h2d_last),           // input wire // transaction's last data budle pulse
        .data_val_in      (h2d_nempty),            // input wire // read data is valid (if 0 while last pulse wasn't received => need to hold the line)
        
        .data_out         (ll_d2h_data_out),       // output[31:0] wire  // read data, same as related inputs
        .data_mask_out    (ll_d2h_mask_out),       // output[1:0] wire // same thing - all 1s for now. TODO
        .data_val_out     (ll_d2h_valid),          // 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     (ll_d2h_almost_full),    // input wire  // transport layer tells if its inner buffer is almost full
        .data_last_out    (),                      // ll_d2h_last),        // output wire not used
        
        .frame_req        (ll_frame_req),          // input wire  // request for a new frame transmission
Andrey Filippov's avatar
Andrey Filippov committed
357 358
        .frame_busy       (), // ll_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        (ll_frame_ackn),         // ll_frame_ack), // output wire // LL tells if the request is transmitting
359 360 361 362 363 364 365 366 367 368 369 370 371
        .frame_rej        (x_rdy_collision),       // output wire // or if it was cancelled because of simultanious incoming transmission
        .frame_done_good  (xmit_ok),               // output wire // TL tell if the outcoming transaction is done and how it was done
        .frame_done_bad   (xmit_err),              // output wire 
        
        .incom_start      (ll_incom_start),        // output wire // if started an incoming transaction
        .incom_done       (ll_incom_done),         // output wire // if incoming transition was completed
        .incom_invalidate (ll_incom_invalidate),   // output wire // if incoming transition had errors
        .incom_sync_escape(syncesc_recv),          // output wire  - received sync escape
        .incom_ack_good   (send_R_OK),             // input wire  // transport layer responds on a completion of a FIS
        .incom_ack_bad    (send_R_ERR),            // input wire  // oob sequence is reinitiated and link now is not established or rxelecidle
        .link_reset       (ll_link_reset),         // input wire  // oob sequence is reinitiated and link now is not established or rxelecidle
        .sync_escape_req  (syncesc_send),          // input wire  // TL demands to brutally cancel current transaction
        .sync_escape_ack  (syncesc_send_done),     // output wire // acknowlegement of a successful reception?
372
        .incom_stop_req   (pcmd_st_cleared),       // input wire  // TL demands to stop current receiving session
Andrey Filippov's avatar
Andrey Filippov committed
373 374
        .link_established (link_established),      // output wire
        .link_bad_crc     (serr_DC),               // output wire // Bad CRC at EOF
375
        // inputs from phy
376
        .phy_ready        (phy_ready),             // input wire        // phy is ready - link is established
377
        // data-primitives stream from phy
378 379 380
        .phy_data_in      (ph2ll_data_out),        // input[31:0] wire  // phy_data_in
        .phy_isk_in       (ph2ll_charisk_out),     // input[3:0] wire   // charisk
        .phy_err_in       (ph2ll_err_out),         // input[3:0] wire   // disperr | notintable
381
        // to phy
382
        .phy_data_out     (ll2ph_data_in),         // output[31:0] wire 
Andrey Filippov's avatar
Andrey Filippov committed
383 384
        .phy_isk_out      (ll2ph_charisk_in),       // output[3:0] wire   // charisk
        .debug_out        (debug_link)
385
    );
386 387
    
    always @ (posedge clk) begin
388
        ll_incom_invalidate_r <=                       ll_incom_invalidate;
389 390 391 392
        // FIS receive D2H
        // add head if ll_d2h_valid and  (d2h_type_in == D2H_TYPE_OK) || (d2h_type_in == D2H_TYPE_ERR)? Or signal some internal error 
        if (rst || ll_incom_start)                     d2h_type_in <= D2H_TYPE_FIS_HEAD; // FIS head
        else if (ll_d2h_valid)                         d2h_type_in <= D2H_TYPE_DMA;          // FIS BODY
393
        else if (ll_incom_done || ll_incom_invalidate_r) d2h_type_in <= ll_incom_invalidate_r ? D2H_TYPE_ERR: D2H_TYPE_OK;
394 395
        
        if (rst) fis_over_r <= 0;
396
        else fis_over_r <= (ll_incom_done || ll_incom_invalidate_r) && (d2h_type_in == D2H_TYPE_DMA); // make sure it is only once
397 398 399 400
        // Second - generate internal error?
        
        // FIS transmit H2D
        // Start if all FIS is in FIFO (last word received) or at least that many is in FIFO
401
        if      (rst || ll_frame_req)                            h2d_pending <= 0; // ?
402 403
        else if ((h2d_type == H2D_TYPE_FIS_HEAD) && h2d_fifo_wr) h2d_pending <= 1;
        
Andrey Filippov's avatar
Andrey Filippov committed
404 405 406 407 408 409
        if (rst)                                                        ll_frame_req <= 0;
//        else     ll_frame_req <= ll_frame_req_w;
        else if (h2d_pending &&
                  (((h2d_type == H2D_TYPE_FIS_LAST) && h2d_fifo_wr ) ||
                   (|h2d_fill[FIFO_ADDR_WIDTH : BITS_TO_START_XMIT])))  ll_frame_req <= 1;
        else if (ll_frame_ackn)                                         ll_frame_req <= 0;          
410 411 412 413 414
        
        
    end


415
    sata_phy #(
416 417 418 419 420
`ifdef USE_DATASCOPE
        .ADDRESS_BITS        (ADDRESS_BITS),  // for datascope
        .DATASCOPE_START_BIT (DATASCOPE_START_BIT),
        .DATASCOPE_POST_MEAS (DATASCOPE_POST_MEAS),
`endif    
421 422 423
        .DATA_BYTE_WIDTH     (DATA_BYTE_WIDTH),
        .ELASTIC_DEPTH       (ELASTIC_DEPTH),
        .ELASTIC_OFFSET      (ELASTIC_OFFSET)
424
    ) phy (
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
        .extrst              (exrst),             // input wire 
        .clk                 (clk),               // output wire 
        .rst                 (rst),               // output wire 
        .reliable_clk        (reliable_clk),      // input wire 
        .phy_ready           (phy_ready),         // output wire 
        .gtx_ready           (gtx_ready),         // output wire 
        .debug_cnt           (), // output[11:0] wire 
        .extclk_p            (extclk_p),          // input wire 
        .extclk_n            (extclk_n),          // input wire 
        .txp_out             (txp_out),           // output wire 
        .txn_out             (txn_out),           // output wire 
        .rxp_in              (rxp_in),            // input wire 
        .rxn_in              (rxn_in),            // input wire 
        .ll_data_out         (ph2ll_data_out),    // output[31:0] wire 
        .ll_charisk_out      (ph2ll_charisk_out), // output[3:0] wire 
        .ll_err_out          (ph2ll_err_out),     // output[3:0] wire 
        .ll_data_in          (ll2ph_data_in),     // input[31:0] wire 
        .ll_charisk_in       (ll2ph_charisk_in),  // input[3:0] wire
        .set_offline         (set_offline),       // input
        .comreset_send       (comreset_send),     // input
        .cominit_got         (cominit_got),       // output wire 
        .comwake_got         (serr_DW),           // output wire 
        .rxelsfull           (rxelsfull),         // output wire 
        .rxelsempty          (rxelsempty),        // output wire 
449

450 451 452 453
        .cplllock_debug      (),
        .usrpll_locked_debug (),
        .re_aligned          (serr_DS),           // output reg 
        .xclk                (xclk),             // output receive clock, just to measure frequency
454 455 456 457 458

`ifdef USE_DATASCOPE
        .datascope_clk     (datascope_clk),     // output
        .datascope_waddr   (datascope_waddr),   // output[9:0] 
        .datascope_we      (datascope_we),      // output
459 460
        .datascope_di      (datascope0_di),      // output[31:0] 
        .datascope_trig    (ll_incom_invalidate ), // ll_frame_ackn),     // input datascope external trigger
461
//        .datascope_trig    (debug_link[4:0] == 'h0a), // state_send_eof // input datascope external trigger
462
///        .datascope_trig    (debug_link[4:0] == 'h02), // state_rcvr_goodcrc // input datascope external trigger
463
        //debug_link
464
`endif        
Andrey Filippov's avatar
Andrey Filippov committed
465 466 467 468 469 470 471 472 473 474 475

`ifdef USE_DRP
        .drp_rst           (drp_rst),           // input
        .drp_clk           (drp_clk),           // input
        .drp_en            (drp_en),            // input
        .drp_we            (drp_we),            // input
        .drp_addr          (drp_addr),          // input[14:0] 
        .drp_di            (drp_di),            // input[15:0] 
        .drp_rdy           (drp_rdy),           // output
        .drp_do            (drp_do),            // output[15:0] 
`endif 
476
        .debug_sata      (debug_phy0)  
Andrey Filippov's avatar
Andrey Filippov committed
477
        ,.debug_detected_alignp(debug_detected_alignp)
478 479 480 481 482 483
    );

    fifo_sameclock_control #(
        .WIDTH(9)
    ) fifo_h2d_control_i (
        .clk      (clk),                    // input
484
        .rst      (rst || pcmd_st_cleared), // input
485 486 487 488 489 490 491 492 493
        .wr       (h2d_fifo_wr),            // input
        .rd       (h2d_fifo_rd),            // input
        .nempty   (h2d_nempty),             // output
        .fill_in  (h2d_fill),               // output[9:0] 
        .mem_wa   (h2d_waddr),              // output[8:0] reg 
        .mem_ra   (h2d_raddr),              // output[8:0] reg 
        .mem_re   (h2d_fifo_re_regen[0]),   // output
        .mem_regen(h2d_fifo_re_regen[1]),   // output
        .over     (),                       // output reg 
494
        .under    () //h2d_under)               // output reg 
495 496 497 498 499 500 501
    );
    
    ram18p_var_w_var_r #(
        .REGISTERS    (1),
        .LOG2WIDTH_WR (5),
        .LOG2WIDTH_RD (5)
    ) fifo_h2d_i (
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
        .rclk     (clk),                                            // input
        .raddr    (h2d_raddr),                                      // input[8:0] 
        .ren      (h2d_fifo_re_regen[0]),                           // input
        .regen    (h2d_fifo_re_regen[1]),                           // input
        .data_out ({h2d_type_out, ll_h2d_mask_in, ll_h2d_data_in}), // output[35:0] 
        .wclk     (clk),                                            // input
        .waddr    (h2d_waddr),                                      // input[8:0] 
        .we       (h2d_fifo_wr),                                    // input
        .web      (4'hf),                                           // input[3:0] 
        .data_in  ({h2d_type,h2d_mask,h2d_data})                    // input[35:0] 
    );

    fifo_sameclock_control #(
        .WIDTH(9)
    ) fifo_d2h_control_i (
        .clk      (clk),                    // input
518
        .rst      (rst || pcmd_st_cleared), // input
519 520 521 522 523 524 525 526
        .wr       (d2h_fifo_wr),            // input
        .rd       (d2h_fifo_rd),            // input
        .nempty   (d2h_nempty),             // output
        .fill_in  (d2h_fill),               // output[9:0] 
        .mem_wa   (d2h_waddr),              // output[8:0] reg 
        .mem_ra   (d2h_raddr),              // output[8:0] reg 
        .mem_re   (d2h_fifo_re_regen[0]),   // output
        .mem_regen(d2h_fifo_re_regen[1]),   // output
527
        .over     (), //d2h_over),               // output reg 
528
        .under    ()                        // output reg 
529 530 531 532 533 534 535
    );

    ram18p_var_w_var_r #(
        .REGISTERS    (1),
        .LOG2WIDTH_WR (5),
        .LOG2WIDTH_RD (5)
    ) fifo_d2h_i (
536 537 538 539 540 541 542 543 544 545
        .rclk     (clk),                                            // input
        .raddr    (d2h_raddr),                                      // input[8:0] 
        .ren      (d2h_fifo_re_regen[0]),                           // input
        .regen    (d2h_fifo_re_regen[1]),                           // input
        .data_out ({d2h_type, d2h_mask, d2h_data}),                 // output[35:0] 
        .wclk     (clk),                                            // input
        .waddr    (d2h_waddr),                                      // input[8:0] 
        .we       (d2h_fifo_wr),                                    // input
        .web      (4'hf),                                           // input[3:0] 
        .data_in  ({d2h_type_in, ll_d2h_mask_out, ll_d2h_data_out}) // input[35:0] 
546 547
    );

548 549 550 551 552 553 554 555 556 557
    freq_meter #(
        .WIDTH    (FREQ_METER_WIDTH),
        .PRESCALE (1)
    ) freq_meter_i (
        .rst   (rst),        // input
        .clk   (clk),        // input
        .xclk  (xclk), // hclk), //xclk),       // input
        .dout  (xclk_period) // output[11:0] reg 
    );

558 559
endmodule