sata_phy.v 22.5 KB
Newer Older
1 2 3 4
/*******************************************************************************
 * Module: sata_phy
 * Date: 2015-07-11  
 * Author: Alexey     
5
 * Description: phy-level, including oob, clock generation and GTXE2 
6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * Copyright (c) 2015 Elphel, Inc.
 * 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/> .
20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * 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.
33
 *******************************************************************************/
34 35
//`include "oob_ctrl.v"
//`include "gtx_wrap.v"
36
module sata_phy #(
37 38 39 40 41
`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        
42 43 44
    parameter   DATA_BYTE_WIDTH =     4,
    parameter ELASTIC_DEPTH =         4, //5, With 4/7 got infrequent overflows!
    parameter ELASTIC_OFFSET =        7 //  5 //10
45 46
)
(
Alexey Grebenkin's avatar
Alexey Grebenkin committed
47 48
    // initial reset, resets PLL. After pll is locked, an internal sata reset is generated.
    input   wire        extrst,
49
    // sata clk, generated in pll as usrclk2
50
    output  wire        clk, // 75MHz, bufg
Alexey Grebenkin's avatar
Alexey Grebenkin committed
51
    output  wire        rst,
52

53 54 55
    // reliable clock to source drp and cpll lock det circuits
    input   wire        reliable_clk,

56 57
    // state
    output  wire        phy_ready,
58 59 60
    // tmp output TODO
    output  wire        gtx_ready,
    output  wire  [11:0] debug_cnt,
61 62 63 64 65 66 67 68 69 70 71 72

    // 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
73 74 75
    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!!!
76 77

    // from link layer
78
    input   wire    [DATA_BYTE_WIDTH * 8 - 1:0] ll_data_in,
79 80 81 82 83
    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,
84
    output  wire                                comwake_got,
85 86 87 88 89
    
    // elastic buffer status
    output  wire                                rxelsfull,
    output  wire                                rxelsempty,

90 91
    output                                      cplllock_debug,
    output                                      usrpll_locked_debug,
Andrey Filippov's avatar
Andrey Filippov committed
92
    output                                      re_aligned,      // re-aligned after alignment loss
93
    output                                      xclk,            //  just to measure frequency to set the local clock
Andrey Filippov's avatar
Andrey Filippov committed
94
    
95 96 97 98 99 100 101 102 103 104
`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
105 106 107 108 109 110 111 112 113 114
`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    
115
    output                               [31:0] debug_sata
Andrey Filippov's avatar
Andrey Filippov committed
116 117
    ,output debug_detected_alignp
    
118 119
);

120 121 122 123 124 125 126 127
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;
128 129
wire    [DATA_BYTE_WIDTH - 1:0]     rxdisperr;
wire    [DATA_BYTE_WIDTH - 1:0]     rxnotintable;
130
wire                          [1:0] txbufstatus;                       
131 132 133
`ifdef DEBUG_ELASTIC
    wire [15:0]                     dbg_data_cntr; // output[11:0] reg 4 MSBs - got primitives during data receive
`endif
134
assign  ll_err_out = rxdisperr | rxnotintable;
135 136 137 138 139 140 141

// 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;

142 143 144 145 146 147 148 149 150
wire            rxcomwakedet;
wire            rxcominitdet;
wire            cplllock;
wire            txcominit;
wire            txcomwake;
wire            rxreset;
wire            rxelecidle;
wire            txelecidle;
wire            rxbyteisaligned;
151 152
wire            txpcsreset_req;
wire            recal_tx_done;
153 154
wire            rxreset_req;
wire            rxreset_ack;
155 156 157 158
wire            clk_phase_align_req; 
wire            clk_phase_align_ack; 


159 160
wire            rxreset_oob;
// elastic buffer status signals TODO
161 162 163 164 165 166 167
//wire            rxelsfull;
//wire            rxelsempty;

wire            dbg_rxphaligndone;
wire            dbg_rx_clocks_aligned;
wire            dbg_rxcdrlock;
wire            dbg_rxdlysresetdone;
168

169
//wire            gtx_ready;
170 171
assign cominit_got = rxcominitdet; // For AHCI
assign comwake_got = rxcomwakedet; // For AHCI
172
wire dummy;
173 174 175



176
oob_ctrl oob_ctrl(
Andrey Filippov's avatar
Andrey Filippov committed
177 178 179
    .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
180
    .debug                ({dummy,debug_cnt[10:0]}),
181
    // oob responses
Andrey Filippov's avatar
Andrey Filippov committed
182 183 184
    .rxcominitdet_in      (rxcominitdet),          // input wire 
    .rxcomwakedet_in      (rxcomwakedet),          // input wire 
    .rxelecidle_in        (rxelecidle),            // input wire 
185
    // oob issues
Andrey Filippov's avatar
Andrey Filippov committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
    .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
205
    // To/from AHCI
Andrey Filippov's avatar
Andrey Filippov committed
206 207 208 209
    .set_offline          (set_offline),           // input
    .comreset_send        (comreset_send),         // input
    .re_aligned           (re_aligned)             // output reg 
    ,.debug_detected_alignp(debug_detected_alignp) // output 
210 211 212 213 214 215 216
);

wire    cplllockdetclk; // TODO
wire    cpllreset;
wire    gtrefclk;
wire    rxresetdone;
wire    txresetdone;
217
wire    txpcsreset;
218 219 220 221 222
wire    txreset;
wire    txuserrdy;
wire    rxuserrdy;
wire    txusrclk;
wire    txusrclk2;
223
//wire    rxusrclk;
224 225 226 227 228
wire    rxusrclk2;
wire    txp;
wire    txn;
wire    rxp;
wire    rxn;
229
wire    txoutclk; // comes out global from gtx_wrap
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
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
249 250 251 252
always @ (posedge gtrefclk) begin 
    if      (rxreset)          rxeyereset_cnt  <= 0;
    else if (!rxeyereset_done) rxeyereset_cnt  <= rxeyereset_cnt + 1;
end
253 254 255 256 257
/*
 * Resets
 */
wire    usrpll_locked;

258
// make tx/rxreset synchronous to gtrefclk - gather singals from different domains: async, aclk, usrclk2, gtrefclk
259
localparam [7:0] RST_TIMER_LIMIT = 8'b1000;
260 261 262 263 264 265
reg rxreset_f;
reg txreset_f;
reg rxreset_f_r;
reg txreset_f_r;
reg rxreset_f_rr;
reg txreset_f_rr;
266 267 268 269 270 271 272 273 274 275
//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];


276 277 278
assign cplllock_debug = cplllock;
assign usrpll_locked_debug = usrpll_locked;

Andrey Filippov's avatar
Andrey Filippov committed
279
always @ (posedge clk or  posedge sata_areset) begin
280 281 282 283
    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
284
reg cplllock_r;
285

286
always @ (posedge gtrefclk) begin
Andrey Filippov's avatar
Andrey Filippov committed
287 288 289
    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
290

291 292 293 294
    txreset_f_r <= txreset_f;
    rxreset_f_r <= rxreset_f;
    txreset_f_rr <= txreset_f_r;
    rxreset_f_rr <= rxreset_f_r;
295 296 297 298 299 300
    
    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));
    
301 302 303
end
assign  rxreset = rxreset_f_rr;
assign  txreset = txreset_f_rr;
Alexey Grebenkin's avatar
Alexey Grebenkin committed
304
assign  cpllreset = extrst;
305 306
assign  rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done & sata_reset_done;
assign  txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done & sata_reset_done;
307

Alexey Grebenkin's avatar
Alexey Grebenkin committed
308 309
assign  gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone;

310 311
// assert gtx_configured. Once gtx_ready -> 1, gtx_configured latches
always @ (posedge clk or posedge extrst)
312 313
    if (extrst) gtx_configured <= 0;
    else        gtx_configured <= gtx_ready | gtx_configured;
314 315


316 317 318 319




320 321
// 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
322 323 324 325 326 327 328 329 330
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;
331
    
332 333 334
    if      (rst)                          txpcsreset_cntr <= 0;
    else if (txpcsreset_req)               txpcsreset_cntr <= TXPCSRESET_CYCLES;
    else if (txpcsreset_cntr != 0)         txpcsreset_cntr <= txpcsreset_cntr - 1;
335
    
336 337 338
    if (rst || txelecidle || txpcsreset_r) recal_tx_done_r <= 0;
    else if (txresetdone)                  recal_tx_done_r <= 1;
end
339 340


341
// issue rx reset to restore functionality after oob sequence. Let it last 8 clock cycles
342 343 344 345 346 347 348 349
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)
350 351
    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;
352

Alexey Grebenkin's avatar
Alexey Grebenkin committed
353

354 355 356 357 358
/*
 * USRCLKs generation. USRCLK @ 150MHz, same as TXOUTCLK; USRCLK2 @ 75Mhz -> sata_clk === sclk
 * It's recommended to use MMCM instead of PLL, whatever
 */

359
wire usrclk_global;
360
wire    usrclk2;
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
// 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;
376 377 378 379 380 381 382

select_clk_buf #(
    .BUFFER_TYPE("BUFG")
) bufg_sclk (
    .o          (clk),  // output
    .i          (usrclk2),         // input
    .clr        (1'b0)            // input
383 384 385 386 387
);

/*
 * Padding for an external input clock @ 150 MHz
 */
388
 
389
localparam [1:0] CLKSWING_CFG = 2'b11;
390

391 392 393 394 395 396
IBUFDS_GTE2 #(
    .CLKRCV_TRST   ("TRUE"),
    .CLKCM_CFG      ("TRUE"),
    .CLKSWING_CFG   (CLKSWING_CFG)
)
ext_clock_buf(
397 398
    .I      (extclk_p),
    .IB     (extclk_n),
399 400 401 402
    .CEB    (1'b0),
    .O      (gtrefclk),
    .ODIV2  ()
);
403

404
gtx_wrap #(
405 406 407 408 409
`ifdef USE_DATASCOPE
    .ADDRESS_BITS        (ADDRESS_BITS),  // for datascope
    .DATASCOPE_START_BIT (DATASCOPE_START_BIT),
    .DATASCOPE_POST_MEAS (DATASCOPE_POST_MEAS),
`endif
410 411 412 413 414 415
    .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),
416 417 418 419
    .RXISCANRESET_TIME      (RXISCANRESET_TIME),
    .ELASTIC_DEPTH          (ELASTIC_DEPTH), // with 4/7 infrequent full !
    .ELASTIC_OFFSET         (ELASTIC_OFFSET)
    
420 421 422
)
gtx_wrap
(
Andrey Filippov's avatar
Andrey Filippov committed
423 424 425 426 427 428 429
    .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 
430
//    .rxusrclk           (rxusrclk),        // input wire 
Andrey Filippov's avatar
Andrey Filippov committed
431 432 433 434 435 436 437 438 439
    .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
440 441 442 443 444
    .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
445 446 447 448 449
    .txusrclk           (txusrclk),        // input wire 
    .txusrclk2          (txusrclk2),       // input wire 
    .txelecidle         (txelecidle),      // input wire 
    .txp                (txp),             // output wire
    .txn                (txn),             // output wire
450
    .txoutclk           (txoutclk),        // output wire // made global inside
Andrey Filippov's avatar
Andrey Filippov committed
451 452 453 454
    .txpcsreset         (txpcsreset),      // input wire 
    .txresetdone        (txresetdone),     // output wire
    .txcominit          (txcominit),       // input wire 
    .txcomwake          (txcomwake),       // input wire 
455
    .txcomfinish        (),                // output wire
Andrey Filippov's avatar
Andrey Filippov committed
456 457 458 459 460 461 462
    .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 
463
    .rxnotintable       (rxnotintable),     // output[3:0] wire
464 465 466 467 468 469
    .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
470 471 472 473 474
`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] 
475
        .datascope_trig    (datascope_trig)     // input // external trigger event for the datascope     
476 477
`endif
    
Andrey Filippov's avatar
Andrey Filippov committed
478 479 480 481 482 483 484 485 486 487
`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 
488 489 490
`ifdef DEBUG_ELASTIC
        ,.dbg_data_cntr (dbg_data_cntr) // output[11:0] reg 
`endif
Andrey Filippov's avatar
Andrey Filippov committed
491
    
492
);
Andrey Filippov's avatar
Andrey Filippov committed
493 494 495



496 497 498
/*
 * Interfaces
 */
499
assign  cplllockdetclk  = reliable_clk; //gtrefclk;
500 501 502

assign  rxn             = rxn_in;
assign  rxp             = rxp_in;
Alexey Grebenkin's avatar
Alexey Grebenkin committed
503
assign  txn_out         = txn;
504 505 506 507 508
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;
509

510 511 512 513
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
514 515 516 517
reg [15:0] debug_cntr5;
reg [15:0] debug_cntr6;
reg [1:0] debug_rxbyteisaligned_r;
reg       debug_error_r;
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
//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
539 540 541 542 543 544 545 546 547 548
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

549 550 551
reg [15:0] dbg_clk_align_cntr;
reg        dbg_clk_align_wait;

552
reg [11:0] error_count;
553
always @ (posedge clk) begin
554 555 556 557
    if      (rxelecidle)                 error_count <= 0;
    else if (phy_ready && (|ll_err_out)) error_count <= error_count + 1;
    

558 559 560 561 562 563 564
    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
565 566


567
`ifdef USE_DATASCOPE
568 569 570 571 572 573 574 575 576 577 578
    `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
579 580
//dbg_data_cntr                         
                         
581 582 583
`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
584

Andrey Filippov's avatar
Andrey Filippov committed
585
 
586
endmodule