x393  1.0
FPGAcodeforElphelNC393camera
oob.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 #(
46  parameter DATA_BYTE_WIDTH = 4,
47  parameter CLK_SPEED_GRADE = 1 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
48 )
49 (
50  output reg [11:0] debug,
51  input wire clk, // sata clk = usrclk2
52  input wire rst, // reset oob
53  // oob responses
54  input wire rxcominitdet_in,
55  input wire rxcomwakedet_in,
56  input wire rxelecidle_in,
57  // oob issues
58  output wire txcominit,
59  output wire txcomwake,
60  output wire txelecidle,
61  output wire txpcsreset_req, // partial tx reset
62  input wire recal_tx_done,
63  output wire rxreset_req, // rx reset (after rxelecidle -> 0)
64  input wire rxreset_ack,
65 
66  // Andrey: adding new signal and state - after RX is operational try re-align clock
67  output wire clk_phase_align_req, // Request GTX to align SIPO parallel clock and user- provided RXUSRCLK
68  input wire clk_phase_align_ack, // GTX aligned clock phase (DEBUG - not always clear when it works or not)
69 
70  input wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_in, // input data stream (if any data during OOB setting => ignored)
71  input wire [DATA_BYTE_WIDTH - 1:0] txcharisk_in,
72 
73  output wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_out, // output data stream to gtx
74  output wire [DATA_BYTE_WIDTH - 1:0] txcharisk_out,
75 
76  input wire [DATA_BYTE_WIDTH*8 - 1:0] rxdata_in, // input data from gtx
77  input wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_in,
78 
79  output wire [DATA_BYTE_WIDTH*8 - 1:0] rxdata_out, // bypassed data from gtx
80  output wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_out,
81 
82  input wire oob_start, // oob sequence needs to be issued
83  output wire oob_done, // connection established, all further data is valid
84  output wire oob_busy, // oob can't handle new start request
85  output wire link_up, // doc p265, link is established after 3back-to-back non-ALIGNp
86  output wire link_down, // link goes down - if rxelecidle
87  output wire cominit_req, // the device itself sends cominit
88  input wire cominit_allow, // allow to respond to cominit
89 
90  // status information to handle by a control block if any exists
91 
92  output wire oob_incompatible, // incompatible host-device speed grades (host cannot lock to alignp)
93  output wire oob_error, // timeout in an unexpected place
94  output wire oob_silence // noone responds to our cominits
95 
97 
98 `ifdef OOB_MULTISPEED
99  //TODO
100  // !!Implement it later on, ref to gen.adjustment fsm in the notebook!!
101 
102  // speed grade control
103  ,
104  // current speed grade, dynamic instead of static parameter
105  input wire [2:0] speed_grade,
106  // clock to be adjusted to best speed
107  input wire adj_clk,
108  // ask for slower protocol clock
109  output wire speed_down_req,
110  input wire speed_down_ack,
111  // reset speedgrade to the fastest one
112  output wire speed_rst_req,
113  input wire speed_rst_ack
114 `endif //OOB_MULTISPEED
115 );
118 
119 `ifdef SIMULATION
120  reg [639:0] HOST_OOB_TITLE ='bz; // to show human-readable state in the GTKWave
121 `endif
122 
124 
125 // 873.8 us error timer
126 // = 2621400 SATA2 serial ticks (period = 0.000333 us)
127 // = 131070 ticks @ 150Mhz
128 // = 65535 ticks @ 75Mhz
129 localparam [19:0] CLK_TO_TIMER_CONTRIB = CLK_SPEED_GRADE == 1 ? 20'h4 :
130  CLK_SPEED_GRADE == 2 ? 20'h2 :
131  CLK_SPEED_GRADE == 4 ? 20'h1 : 20'h1;
132 
133 localparam RXDLYSRESET_CYCLES = 5; // minimum - 50ns
135 
137 
138 `ifdef SIMULATION
139 localparam [19:0] TIMER_LIMIT = 19'd20000;
140 `else
141 localparam [19:0] TIMER_LIMIT = 19'd262140;
142 `endif
143 reg [19:0] timer;
144 wire timer_clr;
145 wire timer_fin;
147 // latching inputs from gtx
151 reg [DATA_BYTE_WIDTH*8 - 1:0] rxdata;
152 reg [DATA_BYTE_WIDTH - 1:0] rxcharisk;
154 // primitives detection
155 wire detected_alignp;
156 localparam NUM_CON_ALIGNS = 2; // just for debugging 1024;
157 reg [1:0] detected_alignp_cntr; // count detected ALIGNp - do not respond yet
158 ///localparam NUM_CON_ALIGNS = 1024; // just for debugging 1024;
159 ///reg [12:0] detected_alignp_cntr; // count detected ALIGNp - do not respond yet
160 reg detected_alignp_r; // debugging - N-th ALIGNp primitive
161 wire detected_syncp;
163 // wait until device's cominit is done
164 reg cominit_req_l;
165 reg rxcominitdet_l;
169 reg [9:0] rxcom_timer;
170 // for 75MHz : period of cominit = 426.7 ns = 32 ticks => need to wait x6 pulses + 1 as an insurance => 224 clock cycles. Same thoughts for comwake
171 localparam COMINIT_DONE_TIME = 896; // 300Mhz cycles
172 localparam COMWAKE_DONE_TIME = 448; // 300Mhz cycles
175 // wait until rxelecidle is not stable (more or less) deasserted
176 // let's say, if rxelecidle = 0 longer, than 2 comwake burst duration (2 * 106.7 ns), elecidle is stable and we're receiving some data
177 // 2 * 106.7ns = 64 clock cycles @ 300 MHz, 32 @ 150, 16 @ 75
178 // rxelecidle is synchronous to sata host clk, sooo some idle raises can occur insensibly. Still, it means line issues,
179 // not affecting the fact, oob was done and a stage when device sends alignps started
180 reg [7:0] eidle_timer;
183 // fsm, doc p265,266
192 reg state_wait_align2; // after clocks aligned
201 wire set_wait_rxrst;
203 wire set_wait_clk_align;
204 wire set_wait_align2;
205 wire set_wait_synp;
206 wire set_wait_linkup;
207 wire set_error;
208 wire clr_wait_cominit;
209 wire clr_wait_comwake;
210 wire clr_recal_tx;
211 wire clr_wait_eidle;
212 wire clr_wait_rxrst;
213 wire clr_wait_align;
214 wire clr_wait_clk_align;
215 wire clr_wait_align2;
216 wire clr_wait_synp;
217 wire clr_wait_linkup;
218 wire clr_error;
219 
220 always @ (posedge clk) begin
221  if (rst || rxelecidle) rxdlysreset_r <= 0;
222  else if (set_wait_clk_align) rxdlysreset_r <= ~0;
223  else rxdlysreset_r <= rxdlysreset_r << 1;
224 end
225 
226 
227 assign state_idle = ~state_wait_cominit &
232  ~state_wait_synp &
234  ~state_error &
235  ~state_recal_tx &
238 always @ (posedge clk)
239 begin
251 end
252 
261 
262 
263 
264 //assign set_wait_synp = state_wait_align & detected_alignp;
265 assign set_wait_synp = state_wait_align2 & (detected_alignp_r); // N previous were both ALIGNp
275  state_wait_synp/* | state_wait_linkup**/);
276 
286 assign clr_wait_linkup = state_wait_linkup; //TODO not so important, but still have to trace 3 back-to-back non alignp primitives
287 assign clr_error = state_error;
288 
289 // waiting timeout timer
290 assign timer_fin = timer == TIMER_LIMIT;
292 always @ (posedge clk)
293  timer <= rst | timer_clr ? 20'h0 : timer + CLK_TO_TIMER_CONTRIB;
294 
295 // something is wrong with speed grades if the host cannot lock to device's alignp stream
297 
298 // oob sequence is done, everything is okay
301 // noone responds to cominits
303 
304 // other timeouts
306 
307 // obvioud
308 assign oob_busy = ~state_idle;
309 
310 // ask for recalibration
313 // ask for rxreset
315 
316 // set gtx controls
317 reg txelecidle_r;
318 always @ (posedge clk)
319  txelecidle_r <= rst ? 1'b1 : /*clr_wait_cominit **/ clr_wait_comwake ? 1'b0 : set_wait_cominit ? 1'b1 : txelecidle_r;
320 
321 assign txcominit = set_wait_cominit;
324 
325 // indicate if link up condition was made
327 
328 // link goes down when line is idle
329 reg rxelecidle_r;
330 reg rxelecidle_rr;
331 always @ (posedge clk)
332 begin
335 end
336 
337 assign link_down = rxelecidle_rr;
338 
339 // indicate that device is requesting for oob
340 reg cominit_req_r;
341 wire cominit_req_set;
342 
344 always @ (posedge clk)
347 
348 // primitives
349 wire [63:0] alignp = {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100, 8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100};
350 wire [63:0] syncp = {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100, 8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100};
351 
352 // detect which primitives sends the device after comwake was done
353 generate
354  if (DATA_BYTE_WIDTH == 2)
355  begin
356  reg detected_alignp_f;
357  always @ (posedge clk)
358  detected_alignp_f <= rst | ~state_wait_align ? 1'b0 :
359  ~|(rxdata[15:0] ^ alignp[15:0]) & ~|(rxcharisk[1:0] ^ 2'b01); // {D10.2, K28.5}
360  assign detected_alignp = detected_alignp_f & ~|(rxdata[15:0] ^ alignp[31:16]) & ~|(rxcharisk[1:0] ^ 2'b00); // {D27.3, D10.2} // S uppressThisWarning VEditor -warning would be fixed in future releases
361 
362  reg detected_syncp_f;
363  always @ (posedge clk)
364  detected_syncp_f <= rst | ~state_wait_synp ? 1'b0 :
365  ~|(rxdata[15:0] ^ syncp[15:0]) & ~|(rxcharisk[1:0] ^ 2'b01); // {D21.4, K28.3}
366  assign detected_syncp = detected_syncp_f & ~|(rxdata[15:0] ^ syncp[31:16]) & ~|(rxcharisk[1:0] ^ 2'b00); // {D21.5, D21.5} // S uppressThisWarning VEditor -warning would be fixed in future releases
367  end
368  else
369  if (DATA_BYTE_WIDTH == 4)
370  begin
371  assign detected_alignp = ~|(rxdata[31:0] ^ alignp[31:0]) & ~|(rxcharisk[3:0] ^ 4'h1); // {D27.3, D10.2, D10.2, K28.5} // S uppressThisWarning VEditor -warning would be fixed in future releases
372  assign detected_syncp = ~|(rxdata[31:0] ^ syncp[31:0]) & ~|(rxcharisk[3:0] ^ 4'h1); // {D21.5, D21.5, D21.4, K28.3} // S uppressThisWarning VEditor -warning would be fixed in future releases
373  end
374  else
375  if (DATA_BYTE_WIDTH == 8)
376  begin
377  assign detected_alignp = ~|(rxdata[63:0] ^ alignp[63:0]) & ~|(rxcharisk[7:0] ^ 8'h11); // {D27.3, D10.2, D10.2, K28.5} // SuppressThisWarning VEditor -warning would be fixed in future releases
378  assign detected_syncp = ~|(rxdata[63:0] ^ syncp[63:0]) & ~|(rxcharisk[7:0] ^ 8'h11); // {D21.5, D21.5, D21.4, K28.3} // SuppressThisWarning VEditor -warning would be fixed in future releases
379  end
380  else
381  begin
382  always @ (posedge clk)
383  begin
384  $display("%m oob module works only with 16/32/64 gtx input data width");
385  $finish;
386  end
387  end
388 endgenerate
389 
390 // calculate an aproximate time when oob burst shall be done
393 
394 always @ (posedge clk) begin
398 end
400 // buf inputs from gtx
401 always @ (posedge clk)
402 begin
406  rxdata <= rxdata_in;
408 end
409 
410 // set data outputs to upper levels
411 assign rxdata_out = rxdata;
412 assign rxcharisk_out = rxcharisk;
413 
414 // as depicted @ doc, p264, figure 163, have to insert D10.2 and align primitives after
415 // getting comwake from device
416 reg [DATA_BYTE_WIDTH*8 - 1:0] txdata;
417 reg [DATA_BYTE_WIDTH - 1:0] txcharisk;
418 wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_d102;
419 wire [DATA_BYTE_WIDTH - 1:0] txcharisk_d102;
421 wire [DATA_BYTE_WIDTH - 1:0] txcharisk_align;
422 
423 always @ (posedge clk)
424 begin
431 end
432 
433 // Continious D10.2 primitive
434 assign txcharisk_d102 = {DATA_BYTE_WIDTH{1'b0}};
435 assign txdata_d102 = {DATA_BYTE_WIDTH{8'b01001010}}; // SuppressThisWarning VEditor -warning would be fixed in future releases
436 
437 // Align primitive: K28.5 + D10.2 + D10.2 + D27.3
438 generate
439  if (DATA_BYTE_WIDTH == 2)
440  begin
441  reg align_odd;
442  always @ (posedge clk)
443  align_odd <= rst | ~state_wait_synp ? 1'b0 : ~align_odd;
444 
445  assign txcharisk_align[DATA_BYTE_WIDTH - 1:0] = align_odd ? 2'b01 : 2'b00; // SuppressThisWarning VEditor -warning would be fixed in future releases
446  assign txdata_align[DATA_BYTE_WIDTH*8 - 1:0] = align_odd ? alignp[15:0] : // {D10.2, K28.5} // SuppressThisWarning VEditor -warning would be fixed in future releases
447  alignp[31:16]; // {D27.3, D10.2} // SuppressThisWarning VEditor -warning would be fixed in future releases
448  end
449  else
450  if (DATA_BYTE_WIDTH == 4)
451  begin
452  assign txcharisk_align[DATA_BYTE_WIDTH - 1:0] = 4'h1;
453  assign txdata_align[DATA_BYTE_WIDTH*8 - 1:0] = alignp[DATA_BYTE_WIDTH*8 - 1:0]; // {D27.3, D10.2, D10.2, K28.5}
454  end
455  else
456  if (DATA_BYTE_WIDTH == 8)
457  begin
458  assign txcharisk_align[DATA_BYTE_WIDTH - 1:0] = 8'h11; // SuppressThisWarning VEditor -warning would be fixed in future releases
459  assign txdata_align[DATA_BYTE_WIDTH*8 - 1:0] = alignp[DATA_BYTE_WIDTH*8 - 1:0]; // 2x{D27.3, D10.2, D10.2, K28.5}
460  end
461  else
462  always @ (posedge clk)
463  begin
464  $display("%m oob module works only with 16/32/64 gtx input data width");
465  $finish;
466  end
467 endgenerate
468 
469 `ifdef SIMULATION
470 // info msgs
471 always @ (posedge clk)
472 begin
473  if (txcominit) begin
474  HOST_OOB_TITLE = "Issued cominit";
475  $display("[Host] OOB: %s @%t",HOST_OOB_TITLE,$time);
476  end
477  if (txcomwake) begin
478  HOST_OOB_TITLE = "Issued comwake";
479  $display("[Host] OOB: %s @%t",HOST_OOB_TITLE,$time);
480  end
481  if (state_wait_linkup) begin
482  HOST_OOB_TITLE = "Link is up";
483  $display("[Host] OOB: %s @%t",HOST_OOB_TITLE,$time);
484  end
485  if (set_wait_synp) begin
486  HOST_OOB_TITLE = "Started continious align sending";
487  $display("[Host] OOB: %s @%t",HOST_OOB_TITLE,$time);
488  end
489 end
490 `endif
491 
492 always @ (posedge clk)
494 
495 // set data outputs to gtx
496 assign txdata_out = txdata;
497 assign txcharisk_out = txcharisk;
498 
499 // rxelectidle timer logic
500 assign eidle_timer_done = eidle_timer == 64;
501 always @ (posedge clk)
503 
504 always @ (posedge clk) begin
508 end
509 
510 always @ (posedge clk)
511  debug <= rst ? 12'h000 : {
512  state_idle,
521  state_error,
522  oob_start,
523  oob_error} | debug;
524 
525 
526 endmodule
527 
wire 15320oob_incompatible
Definition: oob.v:92
15333rxelecidlereg
Definition: oob.v:132
15381clr_wait_align2wire
Definition: oob.v:197
wire 15321oob_error
Definition: oob.v:93
wire 15314oob_done
Definition: oob.v:83
15396txdata_alignwire[DATA_BYTE_WIDTH*8-1:0]
Definition: oob.v:402
15390alignpwire[63:0]
Definition: oob.v:331
15375clr_wait_comwakewire
Definition: oob.v:191
wire 15301rxreset_req
Definition: oob.v:63
15361state_wait_linkupreg
Definition: oob.v:176
wire 15300recal_tx_done
Definition: oob.v:62
15384clr_errorwire
Definition: oob.v:200
wire 15315oob_busy
Definition: oob.v:84
15368set_wait_alignwire
Definition: oob.v:184
wire 15316link_up
Definition: oob.v:85
15374clr_wait_cominitwire
Definition: oob.v:190
15377clr_wait_eidlewire
Definition: oob.v:193
15385txelecidle_rreg
Definition: oob.v:299
wire 15322oob_silence
Definition: oob.v:94
wire 15298txelecidle
Definition: oob.v:60
15334rxdatareg[DATA_BYTE_WIDTH*8-1:0]
Definition: oob.v:133
15370set_wait_align2wire
Definition: oob.v:186
15346rxcom_timerreg[9:0]
Definition: oob.v:151
15397txcharisk_alignwire[DATA_BYTE_WIDTH-1:0]
Definition: oob.v:403
wire 15302rxreset_ack
Definition: oob.v:64
15356state_wait_rxrstreg
Definition: oob.v:171
wire [DATA_BYTE_WIDTH*8 - 1:0] 15307txdata_out
Definition: oob.v:73
15349eidle_timerreg[7:0]
Definition: oob.v:162
15360state_wait_synpreg
Definition: oob.v:175
15357state_wait_alignreg
Definition: oob.v:172
15342rxcominitdet_lreg
Definition: oob.v:147
15389cominit_req_setwire
Definition: oob.v:323
15394txdata_d102wire[DATA_BYTE_WIDTH*8-1:0]
Definition: oob.v:400
15288DATA_BYTE_WIDTH4
Definition: oob.v:46
wire 15299txpcsreset_req
Definition: oob.v:61
15336detected_alignpwire
Definition: oob.v:137
15373set_errorwire
Definition: oob.v:189
wire [DATA_BYTE_WIDTH - 1:0] 15312rxcharisk_out
Definition: oob.v:80
wire [DATA_BYTE_WIDTH*8 - 1:0] 15305txdata_in
Definition: oob.v:70
wire 15317link_down
Definition: oob.v:86
15364set_wait_comwakewire
Definition: oob.v:180
reg [11:0] 15290debug
Definition: oob.v:50
wire [DATA_BYTE_WIDTH - 1:0] 15310rxcharisk_in
Definition: oob.v:77
15367set_wait_rxrstwire
Definition: oob.v:183
15355state_wait_eidlereg
Definition: oob.v:170
15366set_wait_eidlewire
Definition: oob.v:182
15335rxchariskreg[DATA_BYTE_WIDTH-1:0]
Definition: oob.v:134
15353state_wait_comwakereg
Definition: oob.v:168
15347COMINIT_DONE_TIME896
Definition: oob.v:153
15393txchariskreg[DATA_BYTE_WIDTH-1:0]
Definition: oob.v:399
wire 15293rxcominitdet_in
Definition: oob.v:54
15326rxdlysreset_rreg[RXDLYSRESET_CYCLES-1:0]
Definition: oob.v:117
15325RXDLYSRESET_CYCLES5
Definition: oob.v:116
15337NUM_CON_ALIGNS2
Definition: oob.v:138
15350eidle_timer_donewire
Definition: oob.v:163
15289CLK_SPEED_GRADE1
Definition: oob.v:47
15339detected_alignp_rreg
Definition: oob.v:142
15348COMWAKE_DONE_TIME448
Definition: oob.v:154
15380clr_wait_clk_alignwire
Definition: oob.v:196
15340detected_syncpwire
Definition: oob.v:143
15369set_wait_clk_alignwire
Definition: oob.v:185
15328timerreg[19:0]
Definition: oob.v:125
wire 15313oob_start
Definition: oob.v:82
15341cominit_req_lreg
Definition: oob.v:146
wire [DATA_BYTE_WIDTH*8 - 1:0] 15309rxdata_in
Definition: oob.v:76
wire 15295rxelecidle_in
Definition: oob.v:56
wire 15292rst
Definition: oob.v:52
15372set_wait_linkupwire
Definition: oob.v:188
15358state_wait_clk_alignreg
Definition: oob.v:173
wire 15304clk_phase_align_ack
Definition: oob.v:68
15338detected_alignp_cntrreg[1:0]
Definition: oob.v:139
15363set_wait_cominitwire
Definition: oob.v:179
15371set_wait_synpwire
Definition: oob.v:187
15343rxcomwakedet_lreg
Definition: oob.v:148
15354state_recal_txreg
Definition: oob.v:169
wire 15297txcomwake
Definition: oob.v:59
15329timer_clrwire
Definition: oob.v:126
15392txdatareg[DATA_BYTE_WIDTH*8-1:0]
Definition: oob.v:398
15387rxelecidle_rrreg
Definition: oob.v:312
Definition: oob.v:45
wire 15294rxcomwakedet_in
Definition: oob.v:55
wire 15303clk_phase_align_req
Definition: oob.v:67
wire 15291clk
Definition: oob.v:51
15365set_recal_txwire
Definition: oob.v:181
wire 15296txcominit
Definition: oob.v:58
15382clr_wait_synpwire
Definition: oob.v:198
15323debug_detected_alignp
Definition: oob.v:96
15344rxcominit_donewire
Definition: oob.v:149
15376clr_recal_txwire
Definition: oob.v:192
15386rxelecidle_rreg
Definition: oob.v:311
15388cominit_req_rreg
Definition: oob.v:322
15352state_wait_cominitreg
Definition: oob.v:167
15331rxcominitdetreg
Definition: oob.v:130
wire 15318cominit_req
Definition: oob.v:87
[19:0] 15324CLK_TO_TIMER_CONTRIBCLK_SPEED_GRADE == 1 ? 20'h4 : CLK_SPEED_GRADE == 2 ? 20'h2 : CLK_SPEED_GRADE == 4 ? 20'h1 : 20'h1
Definition: oob.v:112
15330timer_finwire
Definition: oob.v:127
15383clr_wait_linkupwire
Definition: oob.v:199
15379clr_wait_alignwire
Definition: oob.v:195
wire 15319cominit_allow
Definition: oob.v:88
15378clr_wait_rxrstwire
Definition: oob.v:194
15332rxcomwakedetreg
Definition: oob.v:131
15359state_wait_align2reg
Definition: oob.v:174
wire [DATA_BYTE_WIDTH*8 - 1:0] 15311rxdata_out
Definition: oob.v:79
15345rxcomwake_donewire
Definition: oob.v:150
15362state_errorreg
Definition: oob.v:177
wire [DATA_BYTE_WIDTH - 1:0] 15308txcharisk_out
Definition: oob.v:74
[19:0] 15327TIMER_LIMIT19'd262140
Definition: oob.v:123
15395txcharisk_d102wire[DATA_BYTE_WIDTH-1:0]
Definition: oob.v:401
15351state_idlewire
Definition: oob.v:166
15391syncpwire[63:0]
Definition: oob.v:332
wire [DATA_BYTE_WIDTH - 1:0] 15306txcharisk_in
Definition: oob.v:71