x393  1.0
FPGAcodeforElphelNC393camera
oob_dev.v
Go to the documentation of this file.
1 
39 /*
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)
43  */
44 // All references to doc = to SerialATA_Revision_2_6_Gold.pdf
45 module oob_dev #(
46  parameter DATA_BYTE_WIDTH = 4,
47  parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
48 )
49 (
50  // sata clk = usrclk2
51  input wire clk,
52  // reset oob
53  input wire rst,
54 
55  input wire gtx_ready,
56  // oob responses
57  input wire rxcominitdet_in,
58  input wire rxcomwakedet_in,
59  input wire rxelecidle_in,
60  // oob issues
61  output reg txcominit,
62  output reg txcomwake,
63  output reg txelecidle,
64 
65  output wire txpcsreset_req,
66  input wire recal_tx_done,
67 
68  // output data stream to gtx
69  output wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_out,
70  output wire [DATA_BYTE_WIDTH - 1:0] txcharisk_out,
71  // input data from gtx
72  input wire [DATA_BYTE_WIDTH*8 - 1:0] rxdata_in,
73  input wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_in,
74 
75  output wire link_up
76 );
77 
78 localparam STATE_RESET = 0;
79 localparam STATE_COMINIT = 1;
80 localparam STATE_AWAITCOMWAKE = 2;
81 localparam STATE_AWAITNOCOMWAKE = 3;
82 localparam STATE_CALIBRATE = 4;
83 localparam STATE_COMWAKE = 5;
84 localparam STATE_RECAL = 55;
85 localparam STATE_SENDALIGN = 6;
86 localparam STATE_READY = 7;
87 localparam STATE_PARTIAL = 8;
88 localparam STATE_SLUMBER = 9;
89 localparam STATE_REDUCESPEED = 10;
90 localparam STATE_ERROR = 11;
91 
92 reg [9:0] state;
95 wire nocomwake;
96 wire [31:0] align;
97 wire [31:0] sync;
98 
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}
101 
102 reg [31:0] nocomwake_timer;
103 assign nocomwake = nocomwake_timer == 32'd38;
104 always @ (posedge clk)
106 
107 reg [31:0] retry_timer;
108 assign retry_interval_elapsed = retry_timer == 32'd1000;
109 always @ (posedge clk)
110  retry_timer <= rst | ~(state == STATE_AWAITCOMWAKE) ? 32'h0 : retry_timer + 1'b1;
111 
112 reg [31:0] wait_timer;
113 assign wait_interval_elapsed = wait_timer == 32'd4096;
114 always @ (posedge clk)
115  wait_timer <= rst | ~(state == STATE_SENDALIGN) ? 32'h0 : wait_timer + 1'b1;
116 
117 reg [31:0] data;
118 reg [3:0] isk;
119 
120 assign link_up = state == STATE_READY;
121 
122 assign txdata_out = data;
123 assign txcharisk_out = isk;
124 
125 // buf inputs from gtx
129 reg [31:0] rxdata;
130 reg [3:0] rxcharisk;
131 always @ (posedge clk)
132 begin
136  rxdata <= rxdata_in;
138 end
139 
140 reg [9:0] txelecidle_cnt;
141 
142 wire aligndet;
143 wire syncdet;
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}
146 
147 assign txpcsreset_req = state == STATE_RECAL & (txelecidle_cnt == 10'd160);
148 
149 always @ (posedge clk)
150  if (rst | (~gtx_ready & ~(state == STATE_RECAL)))
151  begin
152  state <= STATE_RESET;
153  txelecidle <= 1'b1;
154  txcominit <= 1'b0;
155  txcomwake <= 1'b0;
156  txelecidle_cnt <= 10'h0;
157  end
158  else
159  case (state)
160  STATE_RESET:
161  begin
162  if (rxcominitdet) begin
163  txelecidle_cnt <= 10'h0;
164  state <= STATE_COMINIT;
165  txelecidle <= 1'b1;
166  txcominit <= 1'b0;
167  txcomwake <= 1'b0;
168  end
169  end
171  begin
173  txcominit <= 1'b1;
174  end
176  begin
177  txcominit <= 1'b0;
178  if (rxcomwakedet)
180  else
182  state <= STATE_RESET;
183  else
185  end
187  begin
188  if (nocomwake)
189  begin
191  end
192  end
194  begin
195  state <= STATE_COMWAKE;
196  end
198  begin
199  txcomwake <= 1'b1;
200  state <= STATE_RECAL;
201  txelecidle_cnt <= 10'h0;
202  end
203  STATE_RECAL:
204  begin
205  data <= align;
206  isk <= 4'h1;
207  txcomwake <= 1'b0;
208  // txcomwake period = 213.333 ns times let's say 10 pulses => 2133.333 ns = 160 cycles of 75Mhz
209  if (txelecidle_cnt == 10'd160) begin
210  txelecidle <= 1'b0;
211  end
212  else begin
213  txelecidle_cnt <= txelecidle_cnt + 1'b1;
214  end
215  if (recal_tx_done) begin
217  end
218  end
220  begin
221  data <= align;
222  isk <= 4'h1;
223  if (aligndet)
224  state <= STATE_READY;
225  else
227  state <= STATE_ERROR;
228  else
230  end
231  STATE_READY:
232  begin
233  txelecidle <= 1'b0;
234  data <= sync;
235  isk <= 4'h1;
236  if (rxelecidle_in)
237  state <= STATE_ERROR;
238  end
239  STATE_ERROR:
240  begin
241  txelecidle <= 1'b0;
242  state <= STATE_RESET;
243  end
244  endcase
245 
246 
247 
248 
249 
250 
251 
252 
253 
254 
255 
256 
257 
258 
259 
260 
261 
262 
263 
264 
265 
266 
267 
268 
269 
270 
271 
272 
273 
274 
275 
276 
277 
278 
279 
280 
281 
282 
283 
284 
285 
286 
287 
288 
289 
290 
291 
292 
293 
294 
295 
296 
297 
298 
299 
300 
301 
302 
303 
304 
305 
306 
307 
308 
309 
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 
337 
338 
339 
340 
341 
342 
343 /*
344 
345 
346 
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;
354 `ifdef SIMULATION
355 localparam [19:0] TIMER_LIMIT = 19'd200;
356 `else
357 localparam [19:0] TIMER_LIMIT = 19'd262140;
358 `endif
359 reg [19:0] timer;
360 wire timer_clr;
361 wire timer_fin;
362 
363 // latching inputs from gtx
364 reg rxcominitdet;
365 reg rxcomwakedet;
366 reg rxelecidle;
367 reg [DATA_BYTE_WIDTH*8 - 1:0] rxdata;
368 reg [DATA_BYTE_WIDTH - 1:0] rxcharisk;
369 
370 // primitives detection
371 wire detected_alignp;
372 wire detected_syncp;
373 
374 // fsm, doc p265,266
375 wire state_idle;
376 reg state_wait_cominit;
377 reg state_wait_comwake;
378 reg state_wait_align;
379 reg state_wait_synp;
380 reg state_wait_linkup;
381 reg state_error;
382 
383 wire set_wait_cominit;
384 wire set_wait_comwake;
385 wire set_wait_align;
386 wire set_wait_synp;
387 wire set_wait_linkup;
388 wire set_error;
389 wire clr_wait_cominit;
390 wire clr_wait_comwake;
391 wire clr_wait_align;
392 wire clr_wait_synp;
393 wire clr_wait_linkup;
394 wire clr_error;
395 
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)
398 begin
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;
405 end
406 
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;
419 
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;
425 
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;
428 
429 // oob sequence is done, everything is okay
430 assign oob_done = set_wait_linkup;
431 
432 // noone responds to cominits
433 assign oob_silence = set_error & state_wait_cominit;
434 
435 // other timeouts
436 assign oob_error = set_error & ~oob_silence & ~oob_incompatible;
437 
438 // obvioud
439 assign oob_busy = ~state_idle;
440 
441 // set gtx controls
442 reg txelecidle_r;
443 always @ (posedge clk)
444  txelecidle_r <= rst ? 1'b1 : clr_wait_cominit ? 1'b0 : set_wait_cominit ? 1'b1 : txelecidle_r;
445 
446 assign txcominit = set_wait_cominit;
447 assign txcomwake = set_wait_comwake;
448 assign txelecidle = set_wait_cominit | txelecidle_r;
449 
450 // indicate if link up condition was made
451 assign link_up = clr_wait_linkup;
452 
453 // link goes down when line is idle
454 reg rxelecidle_r;
455 reg rxelecidle_rr;
456 always @ (posedge clk)
457 begin
458  rxelecidle_rr <= rxelecidle_r;
459  rxelecidle_r <= rxelecidle;
460 end
461 
462 assign link_down = rxelecidle_rr;
463 
464 // indicate that device is requesting for oob
465 reg cominit_req_r;
466 wire cominit_req_set;
467 
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;
472 
473 // detect which primitives sends the device after comwake was done
474 generate
475  if (DATA_BYTE_WIDTH == 2)
476  begin
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}
482 
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}
488  end
489  else
490  if (DATA_BYTE_WIDTH == 4)
491  begin
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}
494  end
495  else
496  if (DATA_BYTE_WIDTH == 8)
497  begin
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}
500  end
501  else
502  begin
503  always @ (posedge clk)
504  begin
505  $display("%m oob module works only with 16/32/64 gtx input data width");
506  $finish;
507  end
508  end
509 endgenerate
510 
511 // buf inputs from gtx
512 always @ (posedge clk)
513 begin
514  rxcominitdet <= rxcominitdet_in;
515  rxcomwakedet <= rxcomwakedet_in;
516  rxelecidle <= rxelecidle_in;
517  rxdata <= rxdata_in;
518  rxcharisk <= rxcharisk_in;
519 end
520 
521 // set data outputs to upper levels
522 assign rxdata_out = rxdata;
523 assign rxcharisk_out = rxcharisk;
524 
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;
533 
534 always @ (posedge clk)
535 begin
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;
540 end
541 
542 // Continious D10.2 primitive
543 assign txcharisk_d102 = {DATA_BYTE_WIDTH{1'b0}};
544 assign txdata_d102 = {DATA_BYTE_WIDTH{8'b01001010}};
545 
546 // Align primitive: K28.5 + D10.2 + D10.2 + D27.3
547 generate
548  if (DATA_BYTE_WIDTH == 2)
549  begin
550  reg align_odd;
551  always @ (posedge clk)
552  align_odd <= rst | ~state_wait_synp ? 1'b0 : ~align_odd;
553 
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}
557  end
558  else
559  if (DATA_BYTE_WIDTH == 4)
560  begin
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}
563  end
564  else
565  if (DATA_BYTE_WIDTH == 8)
566  begin
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}
569  end
570  else
571  always @ (posedge clk)
572  begin
573  $display("%m oob module works only with 16/32/64 gtx input data width");
574  $finish;
575  end
576 endgenerate
577 
578 // set data outputs to gtx
579 assign txdata_out = txdata;
580 assign txcharisk_out = txcharisk;
581 */
582 endmodule
wire [DATA_BYTE_WIDTH - 1:0] 14386rxcharisk_in
Definition: oob_dev.v:73
14400STATE_ERROR11
Definition: oob_dev.v:90
14403wait_interval_elapsedwire
Definition: oob_dev.v:94
14391STATE_AWAITNOCOMWAKE3
Definition: oob_dev.v:81
14370DATA_BYTE_WIDTH4
Definition: oob_dev.v:46
wire 14381txpcsreset_req
Definition: oob_dev.v:65
14408retry_timerreg[31:0]
Definition: oob_dev.v:107
14416rxchariskreg[3:0]
Definition: oob_dev.v:130
14419syncdetwire
Definition: oob_dev.v:143
14409wait_timerreg[31:0]
Definition: oob_dev.v:112
14389STATE_COMINIT1
Definition: oob_dev.v:79
reg 14378txcominit
Definition: oob_dev.v:61
14412rxcominitdetreg
Definition: oob_dev.v:126
wire [DATA_BYTE_WIDTH*8 - 1:0] 14383txdata_out
Definition: oob_dev.v:69
wire [DATA_BYTE_WIDTH - 1:0] 14384txcharisk_out
Definition: oob_dev.v:70
14371CLK_SPEED_GRADE2
Definition: oob_dev.v:47
wire [DATA_BYTE_WIDTH*8 - 1:0] 14385rxdata_in
Definition: oob_dev.v:72
14402retry_interval_elapsedwire
Definition: oob_dev.v:93
14394STATE_RECAL55
Definition: oob_dev.v:84
wire 14376rxcomwakedet_in
Definition: oob_dev.v:58
14395STATE_SENDALIGN6
Definition: oob_dev.v:85
14404nocomwakewire
Definition: oob_dev.v:95
reg 14380txelecidle
Definition: oob_dev.v:63
14388STATE_RESET0
Definition: oob_dev.v:78
14392STATE_CALIBRATE4
Definition: oob_dev.v:82
14406syncwire[31:0]
Definition: oob_dev.v:97
14405alignwire[31:0]
Definition: oob_dev.v:96
14393STATE_COMWAKE5
Definition: oob_dev.v:83
14407nocomwake_timerreg[31:0]
Definition: oob_dev.v:102
14398STATE_SLUMBER9
Definition: oob_dev.v:88
14397STATE_PARTIAL8
Definition: oob_dev.v:87
14401statereg[9:0]
Definition: oob_dev.v:92
wire 14373rst
Definition: oob_dev.v:53
14414rxelecidlereg
Definition: oob_dev.v:128
14415rxdatareg[31:0]
Definition: oob_dev.v:129
14399STATE_REDUCESPEED10
Definition: oob_dev.v:89
14413rxcomwakedetreg
Definition: oob_dev.v:127
14411iskreg[3:0]
Definition: oob_dev.v:118
wire 14372clk
Definition: oob_dev.v:51
14396STATE_READY7
Definition: oob_dev.v:86
reg 14379txcomwake
Definition: oob_dev.v:62
14390STATE_AWAITCOMWAKE2
Definition: oob_dev.v:80
wire 14382recal_tx_done
Definition: oob_dev.v:66
14410datareg[31:0]
Definition: oob_dev.v:117
wire 14377rxelecidle_in
Definition: oob_dev.v:59
14418aligndetwire
Definition: oob_dev.v:142
14417txelecidle_cntreg[9:0]
Definition: oob_dev.v:140
wire 14374gtx_ready
Definition: oob_dev.v:55
wire 14375rxcominitdet_in
Definition: oob_dev.v:57
wire 14387link_up
Definition: oob_dev.v:75