40 For now both device and host shall be set up to SATA2 speeds. 41 Need to think how to change speed grades on fly (either to broaden 42 data iface width or to change RXRATE/TXRATE) 44 // All references to doc = to SerialATA_Revision_2_6_Gold.pdf 68 // output data stream to gtx 71 // input data from gtx 99 assign align = {
8'b01111011,
8'b01001010,
8'b01001010,
8'b10111100};
// {D27.3, D10.2, D10.2, K28.5} 100 assign sync = {
8'b10110101,
8'b10110101,
8'b10010101,
8'b01111100};
// {D21.5, D21.5, D21.4, K28.3} 125 // buf inputs from gtx 144 assign aligndet = ~|(
rxdata ^ {
8'b01111011,
8'b01001010,
8'b01001010,
8'b10111100}) & ~|(
rxcharisk ^
4'h1);
// {D27.3, D10.2, D10.2, K28.5} 145 assign syncdet = ~|(
rxdata ^ {
8'b10110101,
8'b10110101,
8'b10010101,
8'b01111100}) & ~|(
rxcharisk ^
4'h1);
// {D21.5, D21.5, D21.4, K28.3} 208 // txcomwake period = 213.333 ns times let's say 10 pulses => 2133.333 ns = 160 cycles of 75Mhz 347 // 873.8 us error timer 348 // = 2621400 SATA2 serial ticks (period = 0.000333 us) 349 // = 131070 ticks @ 150Mhz 350 // = 65535 ticks @ 75Mhz 351 localparam [19:0] CLK_TO_TIMER_CONTRIB = CLK_SPEED_GRADE == 1 ? 20'h4 : 352 CLK_SPEED_GRADE == 2 ? 20'h2 : 353 CLK_SPEED_GRADE == 4 ? 20'h1 : 20'h1; 355 localparam [19:0] TIMER_LIMIT = 19'd200; 357 localparam [19:0] TIMER_LIMIT = 19'd262140; 363 // latching inputs from gtx 367 reg [DATA_BYTE_WIDTH*8 - 1:0] rxdata; 368 reg [DATA_BYTE_WIDTH - 1:0] rxcharisk; 370 // primitives detection 371 wire detected_alignp; 376 reg state_wait_cominit; 377 reg state_wait_comwake; 378 reg state_wait_align; 380 reg state_wait_linkup; 383 wire set_wait_cominit; 384 wire set_wait_comwake; 387 wire set_wait_linkup; 389 wire clr_wait_cominit; 390 wire clr_wait_comwake; 393 wire clr_wait_linkup; 396 assign state_idle = ~state_wait_cominit & ~state_wait_comwake & ~state_wait_align & ~state_wait_synp & ~state_wait_linkup & ~state_error; 397 always @ (posedge clk) 399 state_wait_cominit <= (state_wait_cominit | set_wait_cominit) & ~clr_wait_cominit & ~rst; 400 state_wait_comwake <= (state_wait_comwake | set_wait_comwake) & ~clr_wait_comwake & ~rst; 401 state_wait_align <= (state_wait_align | set_wait_align ) & ~clr_wait_align & ~rst; 402 state_wait_synp <= (state_wait_synp | set_wait_synp ) & ~clr_wait_synp & ~rst; 403 state_wait_linkup <= (state_wait_linkup | set_wait_linkup ) & ~clr_wait_linkup & ~rst; 404 state_error <= (state_error | set_error ) & ~clr_error & ~rst; 407 assign set_wait_cominit = state_idle & oob_start & ~cominit_req; 408 assign set_wait_comwake = state_idle & cominit_req & cominit_allow | state_wait_cominit & rxcominitdet; 409 assign set_wait_align = state_wait_comwake & rxcomwakedet; 410 assign set_wait_synp = state_wait_align & detected_alignp; 411 assign set_wait_linkup = state_wait_synp & detected_syncp; 412 assign set_error = timer_fin & (state_wait_cominit | state_wait_comwake | state_wait_align | state_wait_synp); 413 assign clr_wait_cominit = set_wait_comwake | set_error; 414 assign clr_wait_comwake = set_wait_align | set_error; 415 assign clr_wait_align = set_wait_synp | set_error; 416 assign clr_wait_synp = set_wait_linkup | set_error; 417 assign clr_wait_linkup = state_wait_linkup; //TODO not so important, but still have to trace 3 back-to-back non alignp primitives 418 assign clr_error = state_error; 420 // waiting timeout timer 421 assign timer_fin = timer == TIMER_LIMIT; 422 assign timer_clr = set_error | state_error | state_idle; 423 always @ (posedge clk) 424 timer <= rst | timer_clr ? 20'h0 : timer + CLK_TO_TIMER_CONTRIB; 426 // something is wrong with speed grades if the host cannot lock to device's alignp stream 427 assign oob_incompatible = state_wait_align & set_error; 429 // oob sequence is done, everything is okay 430 assign oob_done = set_wait_linkup; 432 // noone responds to cominits 433 assign oob_silence = set_error & state_wait_cominit; 436 assign oob_error = set_error & ~oob_silence & ~oob_incompatible; 439 assign oob_busy = ~state_idle; 443 always @ (posedge clk) 444 txelecidle_r <= rst ? 1'b1 : clr_wait_cominit ? 1'b0 : set_wait_cominit ? 1'b1 : txelecidle_r; 446 assign txcominit = set_wait_cominit; 447 assign txcomwake = set_wait_comwake; 448 assign txelecidle = set_wait_cominit | txelecidle_r; 450 // indicate if link up condition was made 451 assign link_up = clr_wait_linkup; 453 // link goes down when line is idle 456 always @ (posedge clk) 458 rxelecidle_rr <= rxelecidle_r; 459 rxelecidle_r <= rxelecidle; 462 assign link_down = rxelecidle_rr; 464 // indicate that device is requesting for oob 466 wire cominit_req_set; 468 assign cominit_req_set = state_idle & rxcominitdet; 469 always @ (posedge clk) 470 cominit_req_r <= (cominit_req_r | cominit_req_set) & ~(cominit_allow & cominit_req) & ~rst; 471 assign cominit_req = cominit_req_set | cominit_req_r; 473 // detect which primitives sends the device after comwake was done 475 if (DATA_BYTE_WIDTH == 2) 477 reg detected_alignp_f; 478 always @ (posedge clk) 479 detected_alignp_f <= rst | ~state_wait_align ? 1'b0 : 480 ~|(rxdata ^ {8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 2'b01); // {D10.2, K28.5} 481 assign detected_alignp = detected_alignp_f & ~|(rxdata ^ {8'b01111011, 8'b01001010}) & ~|(rxcharisk ^ 2'b00); // {D27.3, D10.2} 483 reg detected_syncp_f; 484 always @ (posedge clk) 485 detected_syncp_f <= rst | ~state_wait_synp ? 1'b0 : 486 ~|(rxdata ^ {8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 2'b01); // {D21.4, K28.3} 487 assign detected_syncp = detected_syncp_f & ~|(rxdata ^ {8'b10110101, 8'b10110101}) & ~|(rxcharisk ^ 2'b00); // {D21.5, D21.5} 490 if (DATA_BYTE_WIDTH == 4) 492 assign detected_alignp = ~|(rxdata ^ {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 4'h1); // {D27.3, D10.2, D10.2, K28.5} 493 assign detected_syncp = ~|(rxdata ^ {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 4'h1); // {D21.5, D21.5, D21.4, K28.3} 496 if (DATA_BYTE_WIDTH == 8) 498 assign detected_alignp = ~|(rxdata ^ {2{8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}}) & ~|(rxcharisk ^ 8'h11); // {D27.3, D10.2, D10.2, K28.5} 499 assign detected_syncp = ~|(rxdata ^ {2{8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}}) & ~|(rxcharisk ^ 8'h11); // {D21.5, D21.5, D21.4, K28.3} 503 always @ (posedge clk) 505 $display("%m oob module works only with 16/32/64 gtx input data width"); 511 // buf inputs from gtx 512 always @ (posedge clk) 514 rxcominitdet <= rxcominitdet_in; 515 rxcomwakedet <= rxcomwakedet_in; 516 rxelecidle <= rxelecidle_in; 518 rxcharisk <= rxcharisk_in; 521 // set data outputs to upper levels 522 assign rxdata_out = rxdata; 523 assign rxcharisk_out = rxcharisk; 525 // as depicted @ doc, p264, figure 163, have to insert D10.2 and align primitives after 526 // getting comwake from device 527 reg [DATA_BYTE_WIDTH*8 - 1:0] txdata; 528 reg [DATA_BYTE_WIDTH - 1:0] txcharisk; 529 wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_d102; 530 wire [DATA_BYTE_WIDTH - 1:0] txcharisk_d102; 531 wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_align; 532 wire [DATA_BYTE_WIDTH - 1:0] txcharisk_align; 534 always @ (posedge clk) 536 txdata <= state_wait_align ? txdata_d102 : 537 state_wait_synp ? txdata_align : txdata_in; 538 txcharisk <= state_wait_align ? txcharisk_d102 : 539 state_wait_synp ? txcharisk_align : txcharisk_in; 542 // Continious D10.2 primitive 543 assign txcharisk_d102 = {DATA_BYTE_WIDTH{1'b0}}; 544 assign txdata_d102 = {DATA_BYTE_WIDTH{8'b01001010}}; 546 // Align primitive: K28.5 + D10.2 + D10.2 + D27.3 548 if (DATA_BYTE_WIDTH == 2) 551 always @ (posedge clk) 552 align_odd <= rst | ~state_wait_synp ? 1'b0 : ~align_odd; 554 assign txcharisk_align = align_odd ? 2'b01 : 2'b00; 555 assign txdata_align = align_odd ? {8'b01001010, 8'b10111100} : // {D10.2, K28.5} 556 {8'b01111011, 8'b01001010}; // {D27.3, D10.2} 559 if (DATA_BYTE_WIDTH == 4) 561 assign txcharisk_align = 4'h1; 562 assign txdata_align = {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}; // {D27.3, D10.2, D10.2, K28.5} 565 if (DATA_BYTE_WIDTH == 8) 567 assign txcharisk_align = 8'h11; 568 assign txdata_align = {2{8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}}; // 2x{D27.3, D10.2, D10.2, K28.5} 571 always @ (posedge clk) 573 $display("%m oob module works only with 16/32/64 gtx input data width"); 578 // set data outputs to gtx 579 assign txdata_out = txdata; 580 assign txcharisk_out = txcharisk; wire [DATA_BYTE_WIDTH - 1:0] 14386rxcharisk_in
14403wait_interval_elapsedwire
14391STATE_AWAITNOCOMWAKE3
14408retry_timerreg[31:0]
wire [DATA_BYTE_WIDTH*8 - 1:0] 14383txdata_out
wire [DATA_BYTE_WIDTH - 1:0] 14384txcharisk_out
wire [DATA_BYTE_WIDTH*8 - 1:0] 14385rxdata_in
14402retry_interval_elapsedwire
wire 14376rxcomwakedet_in
14407nocomwake_timerreg[31:0]
14417txelecidle_cntreg[9:0]
wire 14375rxcominitdet_in