sata_phy.v 22.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*!
 * <b>Module:</b>sata_phy
 * @file sata_phy.v
 * @date  2015-07-11  
 * @author Alexey     
 *
 * @brief phy-level, including oob, clock generation and GTXE2 
 *
 * @copyright Copyright (c) 2015 Elphel, Inc.
 *
 * <b>License:</b>
12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * sata_phy.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.
 *
 * sata_phy.v file 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/> .
25 26 27 28 29 30 31 32 33 34 35 36 37
 *
 * Additional permission under GNU GPL version 3 section 7:
 * If you modify this Program, or any covered work, by linking or combining it
 * with independent modules provided by the FPGA vendor only (this permission
 * does not extend to any 3-rd party modules, "soft cores" or macros) under
 * different license terms solely for the purpose of generating binary "bitstream"
 * files and/or simulating the code, the copyright holders of this Program give
 * you the right to distribute the covered work without those independent modules
 * as long as the source code for them is available from the FPGA vendor free of
 * charge, and there is no dependence on any encrypted modules for simulating of
 * the combined code. This permission applies to you if the distributed code
 * contains all the components and scripts required to completely simulate it
 * with at least one of the Free Software programs.
38
 */
39 40
//`include "oob_ctrl.v"
//`include "gtx_wrap.v"
41
module sata_phy #(
42 43 44 45 46
`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        
47 48 49
    parameter   DATA_BYTE_WIDTH =     4,
    parameter ELASTIC_DEPTH =         4, //5, With 4/7 got infrequent overflows!
    parameter ELASTIC_OFFSET =        7 //  5 //10
50 51
)
(
Alexey Grebenkin's avatar
Alexey Grebenkin committed
52 53
    // initial reset, resets PLL. After pll is locked, an internal sata reset is generated.
    input   wire        extrst,
54
    // sata clk, generated in pll as usrclk2
55
    output  wire        clk, // 75MHz, bufg
Alexey Grebenkin's avatar
Alexey Grebenkin committed
56
    output  wire        rst,
57

58 59 60
    // reliable clock to source drp and cpll lock det circuits
    input   wire        reliable_clk,

61 62
    // state
    output  wire        phy_ready,
63 64 65
    // tmp output TODO
    output  wire        gtx_ready,
    output  wire  [11:0] debug_cnt,
66 67 68 69 70 71 72 73 74 75 76 77

    // top-level ifaces
    // 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,
    input   wire        rxn_in,

    // to link layer
78 79 80
    output  wire    [DATA_BYTE_WIDTH * 8 - 1:0] ll_data_out,
    output  wire    [DATA_BYTE_WIDTH - 1:0]     ll_charisk_out,
    output  wire    [DATA_BYTE_WIDTH - 1:0]     ll_err_out, // TODO!!!
81 82

    // from link layer
83
    input   wire    [DATA_BYTE_WIDTH * 8 - 1:0] ll_data_in,
84 85 86 87 88
    input   wire    [DATA_BYTE_WIDTH - 1:0]     ll_charisk_in,
    
    input                                       set_offline,     // electrically idle
    input                                       comreset_send,   // Not possible yet?
    output  wire                                cominit_got,
89
    output  wire                                comwake_got,
90 91 92 93 94
    
    // elastic buffer status
    output  wire                                rxelsfull,
    output  wire                                rxelsempty,

95 96
    output                                      cplllock_debug,
    output                                      usrpll_locked_debug,
Andrey Filippov's avatar
Andrey Filippov committed
97
    output                                      re_aligned,      // re-aligned after alignment loss
98
    output                                      xclk,            //  just to measure frequency to set the local clock
Andrey Filippov's avatar
Andrey Filippov committed
99
    
100 101 102 103 104 105 106 107 108 109
`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,
    input                                       datascope_trig, // external trigger event for the datascope     
    
`endif    
    
Andrey Filippov's avatar
Andrey Filippov committed
110 111 112 113 114 115 116 117 118 119
`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    
120
    output                               [31:0] debug_sata
Andrey Filippov's avatar
Andrey Filippov committed
121 122
    ,output debug_detected_alignp
    
123 124
);

125 126 127 128 129 130 131 132
wire    [DATA_BYTE_WIDTH * 8 - 1:0] txdata;
wire    [DATA_BYTE_WIDTH * 8 - 1:0] rxdata;
wire    [DATA_BYTE_WIDTH * 8 - 1:0] rxdata_out;
wire    [DATA_BYTE_WIDTH * 8 - 1:0] txdata_in;
wire    [DATA_BYTE_WIDTH - 1:0]     txcharisk;
wire    [DATA_BYTE_WIDTH - 1:0]     rxcharisk;
wire    [DATA_BYTE_WIDTH - 1:0]     txcharisk_in;
wire    [DATA_BYTE_WIDTH - 1:0]     rxcharisk_out;
133 134
wire    [DATA_BYTE_WIDTH - 1:0]     rxdisperr;
wire    [DATA_BYTE_WIDTH - 1:0]     rxnotintable;
135
wire                          [1:0] txbufstatus;                       
136 137 138
`ifdef DEBUG_ELASTIC
    wire [15:0]                     dbg_data_cntr; // output[11:0] reg 4 MSBs - got primitives during data receive
`endif
139
assign  ll_err_out = rxdisperr | rxnotintable;
140 141 142 143 144 145 146

// once gtx_ready -> 1, gtx_configured latches
// after this point it's possible to perform additional resets and reconfigurations by higher-level logic
reg             gtx_configured;
// after external rst -> 0, after sata logic resets -> 1
wire            sata_reset_done;

147 148 149 150 151 152 153 154 155
wire            rxcomwakedet;
wire            rxcominitdet;
wire            cplllock;
wire            txcominit;
wire            txcomwake;
wire            rxreset;
wire            rxelecidle;
wire            txelecidle;
wire            rxbyteisaligned;
156 157
wire            txpcsreset_req;
wire            recal_tx_done;
158 159
wire            rxreset_req;
wire            rxreset_ack;
160 161 162 163
wire            clk_phase_align_req; 
wire            clk_phase_align_ack; 


164 165
wire            rxreset_oob;
// elastic buffer status signals TODO
166 167 168 169 170 171 172
//wire            rxelsfull;
//wire            rxelsempty;

wire            dbg_rxphaligndone;
wire            dbg_rx_clocks_aligned;
wire            dbg_rxcdrlock;
wire            dbg_rxdlysresetdone;
173

174
//wire            gtx_ready;
175 176
assign cominit_got = rxcominitdet; // For AHCI
assign comwake_got = rxcomwakedet; // For AHCI
177
wire dummy;
178 179 180



181
oob_ctrl oob_ctrl(
Andrey Filippov's avatar
Andrey Filippov committed
182 183 184
    .clk                  (clk),                   // input wire         // sata clk = usrclk2
    .rst                  (rst),                   // input wire         // reset oob
    .gtx_ready            (gtx_ready),             // input wire         // gtx is ready = all resets are done
185
    .debug                ({dummy,debug_cnt[10:0]}),
186
    // oob responses
Andrey Filippov's avatar
Andrey Filippov committed
187 188 189
    .rxcominitdet_in      (rxcominitdet),          // input wire 
    .rxcomwakedet_in      (rxcomwakedet),          // input wire 
    .rxelecidle_in        (rxelecidle),            // input wire 
190
    // oob issues
Andrey Filippov's avatar
Andrey Filippov committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
    .txcominit            (txcominit),             // output wire 
    .txcomwake            (txcomwake),             // output wire 
    .txelecidle           (txelecidle),            // output wire 
    .txpcsreset_req       (txpcsreset_req),        // output wire 
    .recal_tx_done        (recal_tx_done),         // input wire 
    .rxreset_req          (rxreset_req),           // output wire 
    .rxreset_ack          (rxreset_ack),           // input wire 
    .clk_phase_align_req  (clk_phase_align_req),   // output wire 
    .clk_phase_align_ack  (clk_phase_align_ack),   // input wire 
    .txdata_in            (txdata_in),             // input[31:0] wire   // input data stream (if any data during OOB setting => ignored)
    .txcharisk_in         (txcharisk_in),          // input[3:0] wire    // same
    .txdata_out           (txdata),                // output[31:0] wire  // output data stream to gtx
    .txcharisk_out        (txcharisk),             // output[3:0] wire   // same
    .rxdata_in            (rxdata[31:0]),          // input[31:0] wire   // input data from gtx
    .rxcharisk_in         (rxcharisk[3:0]),        // input[3:0] wire    // same
    .rxdata_out           (rxdata_out),            // output[31:0] wire  // bypassed data from gtx
    .rxcharisk_out        (rxcharisk_out),         // output[3:0]wire    // same
    .rxbyteisaligned      (rxbyteisaligned),       // input wire         // receiving data is aligned
    .phy_ready            (phy_ready),             // output wire        // shows if channel is ready
210
    // To/from AHCI
Andrey Filippov's avatar
Andrey Filippov committed
211 212 213 214
    .set_offline          (set_offline),           // input
    .comreset_send        (comreset_send),         // input
    .re_aligned           (re_aligned)             // output reg 
    ,.debug_detected_alignp(debug_detected_alignp) // output 
215 216 217 218 219 220 221
);

wire    cplllockdetclk; // TODO
wire    cpllreset;
wire    gtrefclk;
wire    rxresetdone;
wire    txresetdone;
222
wire    txpcsreset;
223 224 225 226 227
wire    txreset;
wire    txuserrdy;
wire    rxuserrdy;
wire    txusrclk;
wire    txusrclk2;
228
//wire    rxusrclk;
229 230 231 232 233
wire    rxusrclk2;
wire    txp;
wire    txn;
wire    rxp;
wire    rxn;
234
wire    txoutclk; // comes out global from gtx_wrap
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
wire    txpmareset_done;
wire    rxeyereset_done;

// tx reset sequence; waves @ ug476 p67
localparam  TXPMARESET_TIME = 5'h1;
reg     [2:0]   txpmareset_cnt;
assign  txpmareset_done = txpmareset_cnt == TXPMARESET_TIME;
always @ (posedge gtrefclk)
    txpmareset_cnt  <= txreset ? 3'h0 : txpmareset_done ? txpmareset_cnt : txpmareset_cnt + 1'b1;

// rx reset sequence; waves @ ug476 p77
localparam  RXPMARESET_TIME     = 5'h11;
localparam  RXCDRPHRESET_TIME   = 5'h1;
localparam  RXCDRFREQRESET_TIME = 5'h1;
localparam  RXDFELPMRESET_TIME  = 7'hf;
localparam  RXISCANRESET_TIME   = 5'h1;
localparam  RXEYERESET_TIME     = 7'h0 + RXPMARESET_TIME + RXCDRPHRESET_TIME + RXCDRFREQRESET_TIME + RXDFELPMRESET_TIME + RXISCANRESET_TIME;
reg     [6:0]   rxeyereset_cnt;
assign  rxeyereset_done = rxeyereset_cnt == RXEYERESET_TIME;
Andrey Filippov's avatar
Andrey Filippov committed
254 255 256 257
always @ (posedge gtrefclk) begin 
    if      (rxreset)          rxeyereset_cnt  <= 0;
    else if (!rxeyereset_done) rxeyereset_cnt  <= rxeyereset_cnt + 1;
end
258 259 260 261 262
/*
 * Resets
 */
wire    usrpll_locked;

263
// make tx/rxreset synchronous to gtrefclk - gather singals from different domains: async, aclk, usrclk2, gtrefclk
264
localparam [7:0] RST_TIMER_LIMIT = 8'b1000;
265 266 267 268 269 270
reg rxreset_f;
reg txreset_f;
reg rxreset_f_r;
reg txreset_f_r;
reg rxreset_f_rr;
reg txreset_f_rr;
271 272 273 274 275 276 277 278 279 280
//reg pre_sata_reset_done;
reg sata_areset;
reg [2:0] sata_reset_done_r;
reg [7:0]   rst_timer;
//reg         rst_r = 1;
assign  rst = !sata_reset_done_r;

assign  sata_reset_done = sata_reset_done_r[1];


281 282 283
assign cplllock_debug = cplllock;
assign usrpll_locked_debug = usrpll_locked;

Andrey Filippov's avatar
Andrey Filippov committed
284
always @ (posedge clk or  posedge sata_areset) begin
285 286 287 288
    if      (sata_areset)  sata_reset_done_r <= 0;
    else                   sata_reset_done_r <= {sata_reset_done_r[1:0], 1'b1};
end

Andrey Filippov's avatar
Andrey Filippov committed
289
reg cplllock_r;
290

291
always @ (posedge gtrefclk) begin
Andrey Filippov's avatar
Andrey Filippov committed
292 293 294
    cplllock_r <= cplllock;
    rxreset_f <= ~cplllock_r | ~cplllock | cpllreset | rxreset_oob & gtx_configured;
    txreset_f <= ~cplllock_r | ~cplllock | cpllreset;
Andrey Filippov's avatar
Andrey Filippov committed
295

296 297 298 299
    txreset_f_r <= txreset_f;
    rxreset_f_r <= rxreset_f;
    txreset_f_rr <= txreset_f_r;
    rxreset_f_rr <= rxreset_f_r;
300 301 302 303 304 305
    
    if (!(cplllock  && usrpll_locked)) rst_timer <= RST_TIMER_LIMIT;
    else if (|rst_timer)               rst_timer <= rst_timer - 1;
    
    sata_areset <= !(cplllock  &&  usrpll_locked && !(|rst_timer));
    
306 307 308
end
assign  rxreset = rxreset_f_rr;
assign  txreset = txreset_f_rr;
Alexey Grebenkin's avatar
Alexey Grebenkin committed
309
assign  cpllreset = extrst;
310 311
assign  rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done & sata_reset_done;
assign  txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done & sata_reset_done;
312

Alexey Grebenkin's avatar
Alexey Grebenkin committed
313 314
assign  gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone;

315 316
// assert gtx_configured. Once gtx_ready -> 1, gtx_configured latches
always @ (posedge clk or posedge extrst)
317 318
    if (extrst) gtx_configured <= 0;
    else        gtx_configured <= gtx_ready | gtx_configured;
319 320


321 322 323 324




325 326
// issue partial tx reset to restore functionality after oob sequence. Let it lasts 8 clock cycles
// Not enough or too early (after txelctidle?) txbufstatus shows overflow
327 328 329 330 331 332 333 334 335
localparam TXPCSRESET_CYCLES = 100;
reg       txpcsreset_r;
reg [7:0] txpcsreset_cntr;
reg       recal_tx_done_r;
assign    recal_tx_done = recal_tx_done_r;
assign    txpcsreset = txpcsreset_r;     
always @ (posedge clk) begin
    if (rst || (txpcsreset_cntr == 0))     txpcsreset_r <= 0; 
    else if (txpcsreset_req)               txpcsreset_r <= 1;
336
    
337 338 339
    if      (rst)                          txpcsreset_cntr <= 0;
    else if (txpcsreset_req)               txpcsreset_cntr <= TXPCSRESET_CYCLES;
    else if (txpcsreset_cntr != 0)         txpcsreset_cntr <= txpcsreset_cntr - 1;
340
    
341 342 343
    if (rst || txelecidle || txpcsreset_r) recal_tx_done_r <= 0;
    else if (txresetdone)                  recal_tx_done_r <= 1;
end
344 345


346
// issue rx reset to restore functionality after oob sequence. Let it last 8 clock cycles
347 348 349 350 351 352 353 354
reg [3:0]   rxreset_oob_cnt;
wire        rxreset_oob_stop;

assign  rxreset_oob_stop = rxreset_oob_cnt[3];
assign  rxreset_oob      = rxreset_req & ~rxreset_oob_stop;
assign  rxreset_ack      = rxreset_oob_stop & gtx_ready;

always @ (posedge clk or posedge extrst)
355 356
    if (extrst) rxreset_oob_cnt <= 1; 
    else        rxreset_oob_cnt <= rst | ~rxreset_req ? 4'h0 : rxreset_oob_stop ? rxreset_oob_cnt : rxreset_oob_cnt + 1'b1;
357

Alexey Grebenkin's avatar
Alexey Grebenkin committed
358

359 360 361 362 363
/*
 * USRCLKs generation. USRCLK @ 150MHz, same as TXOUTCLK; USRCLK2 @ 75Mhz -> sata_clk === sclk
 * It's recommended to use MMCM instead of PLL, whatever
 */

364
wire usrclk_global;
365
wire    usrclk2;
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
// divide txoutclk (global) by 2, then make global. Does not need to be phase-aligned - will use FIFO
reg usrclk2_r;
always @ (posedge txoutclk) begin
    if (~cplllock) usrclk2_r <= 0;
    else           usrclk2_r <= ~usrclk2;
end
assign txusrclk  =     txoutclk; // 150MHz, was already global
assign usrclk_global = txoutclk; // 150MHz, was already global
assign usrclk2 =       usrclk2_r;
assign usrpll_locked = cplllock;

assign txusrclk  = usrclk_global; // 150MHz
assign txusrclk2 = clk;           // usrclk2;
//assign rxusrclk  = usrclk_global; // 150MHz
assign rxusrclk2 = clk;           // usrclk2;
381 382 383 384 385 386 387

select_clk_buf #(
    .BUFFER_TYPE("BUFG")
) bufg_sclk (
    .o          (clk),  // output
    .i          (usrclk2),         // input
    .clr        (1'b0)            // input
388 389 390 391 392
);

/*
 * Padding for an external input clock @ 150 MHz
 */
393
 
394
localparam [1:0] CLKSWING_CFG = 2'b11;
395

396 397 398 399 400 401
IBUFDS_GTE2 #(
    .CLKRCV_TRST   ("TRUE"),
    .CLKCM_CFG      ("TRUE"),
    .CLKSWING_CFG   (CLKSWING_CFG)
)
ext_clock_buf(
402 403
    .I      (extclk_p),
    .IB     (extclk_n),
404 405 406 407
    .CEB    (1'b0),
    .O      (gtrefclk),
    .ODIV2  ()
);
408

409
gtx_wrap #(
410 411 412 413 414
`ifdef USE_DATASCOPE
    .ADDRESS_BITS        (ADDRESS_BITS),  // for datascope
    .DATASCOPE_START_BIT (DATASCOPE_START_BIT),
    .DATASCOPE_POST_MEAS (DATASCOPE_POST_MEAS),
`endif
415 416 417 418 419 420
    .DATA_BYTE_WIDTH        (DATA_BYTE_WIDTH),
    .TXPMARESET_TIME        (TXPMARESET_TIME),
    .RXPMARESET_TIME        (RXPMARESET_TIME),
    .RXCDRPHRESET_TIME      (RXCDRPHRESET_TIME),
    .RXCDRFREQRESET_TIME    (RXCDRFREQRESET_TIME),
    .RXDFELPMRESET_TIME     (RXDFELPMRESET_TIME),
421 422 423 424
    .RXISCANRESET_TIME      (RXISCANRESET_TIME),
    .ELASTIC_DEPTH          (ELASTIC_DEPTH), // with 4/7 infrequent full !
    .ELASTIC_OFFSET         (ELASTIC_OFFSET)
    
425 426 427
)
gtx_wrap
(
Andrey Filippov's avatar
Andrey Filippov committed
428 429 430 431 432 433 434
    .debug              (debug_cnt[11]),   // output reg 
    .cplllock           (cplllock),        // output wire 
    .cplllockdetclk     (cplllockdetclk),  // input wire 
    .cpllreset          (cpllreset),       // input wire 
    .gtrefclk           (gtrefclk),        // input wire 
    .rxuserrdy          (rxuserrdy),       // input wire 
    .txuserrdy          (txuserrdy),       // input wire 
435
//    .rxusrclk           (rxusrclk),        // input wire 
Andrey Filippov's avatar
Andrey Filippov committed
436 437 438 439 440 441 442 443 444
    .rxusrclk2          (rxusrclk2),       // input wire 
    .rxp                (rxp),             // input wire 
    .rxn                (rxn),             // input wire 
    .rxbyteisaligned    (rxbyteisaligned), // output wire
    .rxreset            (rxreset),         // input wire 
    .rxcomwakedet       (rxcomwakedet),    // output wire
    .rxcominitdet       (rxcominitdet),    // output wire
    .rxelecidle         (rxelecidle),      // output wire
    .rxresetdone        (rxresetdone),     // output wire
445 446 447 448 449
    .txreset            (txreset),         // input wire

    .clk_phase_align_req(clk_phase_align_req), // output wire 
    .clk_phase_align_ack(clk_phase_align_ack), // input wire 
     
Andrey Filippov's avatar
Andrey Filippov committed
450 451 452 453 454
    .txusrclk           (txusrclk),        // input wire 
    .txusrclk2          (txusrclk2),       // input wire 
    .txelecidle         (txelecidle),      // input wire 
    .txp                (txp),             // output wire
    .txn                (txn),             // output wire
455
    .txoutclk           (txoutclk),        // output wire // made global inside
Andrey Filippov's avatar
Andrey Filippov committed
456 457 458 459
    .txpcsreset         (txpcsreset),      // input wire 
    .txresetdone        (txresetdone),     // output wire
    .txcominit          (txcominit),       // input wire 
    .txcomwake          (txcomwake),       // input wire 
460
    .txcomfinish        (),                // output wire
Andrey Filippov's avatar
Andrey Filippov committed
461 462 463 464 465 466 467
    .rxelsfull          (rxelsfull),       // output wire
    .rxelsempty         (rxelsempty),      // output wire
    .txdata             (txdata),          // input [31:0] wire 
    .txcharisk          (txcharisk),       // input [3:0] wire 
    .rxdata             (rxdata),          // output[31:0] wire 
    .rxcharisk          (rxcharisk),       // output[3:0] wire 
    .rxdisperr          (rxdisperr),       // output[3:0] wire 
468
    .rxnotintable       (rxnotintable),     // output[3:0] wire
469 470 471 472 473 474
    .dbg_rxphaligndone     (dbg_rxphaligndone),
    .dbg_rx_clocks_aligned (dbg_rx_clocks_aligned),
    .dbg_rxcdrlock         (dbg_rxcdrlock)    ,
    .dbg_rxdlysresetdone   (dbg_rxdlysresetdone),
    .txbufstatus           (txbufstatus[1:0]),
    .xclk                  (xclk)             // output receive clock, just to measure frequency // global
475 476 477 478 479
`ifdef USE_DATASCOPE
       ,.datascope_clk     (datascope_clk),     // output
        .datascope_waddr   (datascope_waddr),   // output[9:0] 
        .datascope_we      (datascope_we),      // output
        .datascope_di      (datascope_di),      // output[31:0] 
480
        .datascope_trig    (datascope_trig)     // input // external trigger event for the datascope     
481 482
`endif
    
Andrey Filippov's avatar
Andrey Filippov committed
483 484 485 486 487 488 489 490 491 492
`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 
493 494 495
`ifdef DEBUG_ELASTIC
        ,.dbg_data_cntr (dbg_data_cntr) // output[11:0] reg 
`endif
Andrey Filippov's avatar
Andrey Filippov committed
496
    
497
);
Andrey Filippov's avatar
Andrey Filippov committed
498 499 500



501 502 503
/*
 * Interfaces
 */
504
assign  cplllockdetclk  = reliable_clk; //gtrefclk;
505 506 507

assign  rxn             = rxn_in;
assign  rxp             = rxp_in;
Alexey Grebenkin's avatar
Alexey Grebenkin committed
508
assign  txn_out         = txn;
509 510 511 512 513
assign  txp_out         = txp;
assign  ll_data_out     = rxdata_out;
assign  ll_charisk_out  = rxcharisk_out;
assign  txdata_in       = ll_data_in;
assign  txcharisk_in    = ll_charisk_in;
514

515 516 517 518
reg [3:0] debug_cntr1;
reg [3:0] debug_cntr2;
reg [3:0] debug_cntr3;
reg [3:0] debug_cntr4;
Andrey Filippov's avatar
Andrey Filippov committed
519 520 521 522
reg [15:0] debug_cntr5;
reg [15:0] debug_cntr6;
reg [1:0] debug_rxbyteisaligned_r;
reg       debug_error_r;
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
//txoutclk
always @ (posedge gtrefclk) begin
    if (extrst) debug_cntr1 <= 0;
    else        debug_cntr1 <= debug_cntr1 + 1;
end

always @ (posedge clk) begin
    if (rst) debug_cntr2 <= 0;
    else        debug_cntr2 <= debug_cntr2 + 1;
end

always @ (posedge reliable_clk) begin
    if (extrst) debug_cntr3 <= 0;
    else        debug_cntr3 <= debug_cntr3 + 1;
end

always @ (posedge txoutclk) begin
    if (extrst) debug_cntr4 <= 0;
    else        debug_cntr4 <= debug_cntr4 + 1;
end

Andrey Filippov's avatar
Andrey Filippov committed
544 545 546 547 548 549 550 551 552 553
always @ (posedge clk) begin
    debug_rxbyteisaligned_r <= {debug_rxbyteisaligned_r[0],rxbyteisaligned};
    debug_error_r <= |ll_err_out;
    if      (rst)                             debug_cntr5 <= 0;
    else if (debug_rxbyteisaligned_r==1)      debug_cntr5 <= debug_cntr5 + 1;

    if      (rst)                             debug_cntr6 <= 0;
    else if (debug_error_r)                   debug_cntr6 <= debug_cntr6 + 1;
end

554 555 556
reg [15:0] dbg_clk_align_cntr;
reg        dbg_clk_align_wait;

557
reg [11:0] error_count;
558
always @ (posedge clk) begin
559 560 561 562
    if      (rxelecidle)                 error_count <= 0;
    else if (phy_ready && (|ll_err_out)) error_count <= error_count + 1;
    

563 564 565 566 567 568 569
    if      (rxelecidle || clk_phase_align_ack) dbg_clk_align_wait <= 0;
    else if (clk_phase_align_req)                         dbg_clk_align_wait <= 1;

    if      (rxelecidle)                                  dbg_clk_align_cntr <= 0;
    else if (dbg_clk_align_wait)                          dbg_clk_align_cntr <= dbg_clk_align_cntr +1;

end
570 571


572
`ifdef USE_DATASCOPE
573 574 575 576 577 578 579 580 581 582 583
    `ifdef DEBUG_ELASTIC
        assign debug_sata = {dbg_data_cntr[15:0], // latched at error from previous FIS (@sof) (otherwise overwritten by h2d rfis)
                             error_count[3:0],
                             2'b0,
                             datascope_waddr[9:0]};
    `else //DEBUG_ELASTIC
        assign debug_sata = {8'b0,
                             error_count[11:0],
                             2'b0,
                             datascope_waddr[9:0]};
    `endif //`else DEBUG_ELASTIC
584 585
//dbg_data_cntr                         
                         
586 587 588
`else
    assign debug_sata = {8'b0, dbg_clk_align_cntr, txbufstatus[1:0], rxelecidle, dbg_rxcdrlock, rxelsfull, rxelsempty, dbg_rxphaligndone, dbg_rx_clocks_aligned};
`endif
589

Andrey Filippov's avatar
Andrey Filippov committed
590
 
591
endmodule