x393  1.0
FPGAcodeforElphelNC393camera
link.v
Go to the documentation of this file.
1 
39 //`include "scrambler.v"
40 //`include "crc.v"
41 module link #(
42  // 4 = dword. 4-bytes aligned data transfers TODO 2 = word - easy, 8 = qword - difficult
43  parameter DATA_BYTE_WIDTH = 4,
44 `ifdef SIMULATION
45 // parameter ALIGNES_PERIOD = 10 // period of sending ALIGNp pairs
46  parameter ALIGNES_PERIOD = 100 // period of sending ALIGNp pairs
47 `else
48  parameter ALIGNES_PERIOD = 252 // period of sending ALIGNp pairs
49 `endif
50 )
51 (
52  // TODO insert watchdogs
53  input wire rst,
54  input wire clk,
55 
56  // data inputs from transport layer
57  // input data stream (if any data during OOB setting => ignored)
58  input wire [DATA_BYTE_WIDTH*8 - 1:0] data_in,
59  // in case of strange data aligments and size (1st mentioned @ doc, p.310, odd number of words case)
60  // Actually, only last data bundle shall be masked, others are always valid.
61  // Mask could be encoded into 3 bits instead of 4 for qword, but encoding+decoding aren't worth the bit
62 
63  input wire [DATA_BYTE_WIDTH/2 - 1:0] data_mask_in, // TODO, for now not supported, all mask bits are assumed to be set
64  output wire data_strobe_out, // buffer read strobe
65  input wire data_last_in, // transaction's last data budle pulse
66  input wire data_val_in, // read data is valid (if 0 while last pulse wasn't received => need to hold the line)
67  // data outputs to transport layer
68  output wire [DATA_BYTE_WIDTH*8 - 1:0] data_out, // read data, same as related inputs
69  output wire [DATA_BYTE_WIDTH/2 - 1:0] data_mask_out, // same thing - all 1s for now. TODO
70  output wire data_val_out, // count every data bundle read by transport layer, even if busy flag is set
71  // let the transport layer handle oveflows by itself
72  input wire data_busy_in, // transport layer tells if its inner buffer is almost full
73  output wire data_last_out,
74  input wire frame_req, // request for a new frame transition
75 // a little bit of overkill with the cound of response signals, think of throwing out 1 of them
76  output wire frame_busy, // LL tells back if it cant handle the request for now
77  output wire frame_ack, // LL tells if the request is transmitting
78  output wire frame_rej, // or if it was cancelled because of simultanious incoming transmission
79  output wire frame_done_good, // Tell TL if the outcoming transaction is done and how it was done
80  output wire frame_done_bad,
81  output wire incom_start, // if started an incoming transaction
82  output wire incom_done, // if incoming transition was completed
83  output wire incom_invalidate, // if incoming transition had errors
84  output wire incom_sync_escape, // particular type - got sync escape
85  input wire incom_ack_good, // transport layer responds on a completion of a FIS
86  input wire incom_ack_bad, // Reject frame even if it had good CRC (Bad will be responded automatically)
87  // It is OK to send extra incom_ack_bad from transport - it will be discarded
88  input wire link_reset, // oob sequence is reinitiated and link now is not established or rxelecidle
89  input wire sync_escape_req, // TL demands to brutally cancel current transaction
90  output wire sync_escape_ack, // acknowlegement of a successful reception
91  input wire incom_stop_req, // TL demands to stop current recieving session
92  output link_established, // received 3 back-to-back non-align primitives.
93  output reg link_bad_crc, // got bad crc at EOF
94  // inputs from phy
95  input wire phy_ready, // phy is ready - link is established
96  input wire [DATA_BYTE_WIDTH*8 - 1:0] phy_data_in, // data-primitives stream from phy
97  input wire [DATA_BYTE_WIDTH - 1:0] phy_isk_in, // charisk
98  input wire [DATA_BYTE_WIDTH - 1:0] phy_err_in, // disperr | notintable
99  // to phy
100  output wire [DATA_BYTE_WIDTH*8 - 1:0] phy_data_out,
101  output wire [DATA_BYTE_WIDTH - 1:0] phy_isk_out, // charisk
102  // debug
103  output [31:0] debug_out //
104 );
105 `ifdef SIMULATION
106  reg [639:0] HOST_LINK_TITLE; // to show human-readable state in the GTKWave
107  reg [31:0] HOST_LINK_DATA;
108 `endif
110 // latching data-primitives stream from phy
112 reg [DATA_BYTE_WIDTH - 1:0] phy_isk_in_r; // charisk
113 reg [DATA_BYTE_WIDTH - 1:0] phy_err_in_r; // disperr | notintable
114 //one extra layer to process CONTp
116 reg [DATA_BYTE_WIDTH - 1:0] phy_isk_in_r0; // charisk
117 reg [DATA_BYTE_WIDTH - 1:0] phy_err_in_r0; // disperr | notintable
118 
119 reg [DATA_BYTE_WIDTH*8 - 1:0] last_not_cont_di; // last primitive dword, but not CONTp
120 reg rcv_junk; // receiving CONTp junk data
121 wire is_non_cont_non_align_p_w; // got primitive other than CONTp and ALIGNp (early by 1)
122 wire is_cont_p_w; // got CONTp primitive (early by 1)
123 wire is_align_p_w; // got ALIGNp primitive (early by 1)
125 //CONTp should pass ALIGNp
128 // scrambled data
130 wire dec_err; // doc, p.311
131 // while receiving session shows crc check status
132 wire crc_good;
133 wire crc_bad;
134 // current crc
135 wire [31:0] crc_dword;
136 // Removing - state_align is handled by OOB
137 ///reg link_established_r; // received 3 back-to-back non-align primitives.
138 ///reg [1:0] non_align_cntr;
139 ///assign link_established = link_established_r;
140 assign link_established = phy_ready;
141 // send primitives variety count, including CRC and DATA as primitives
142 localparam PRIM_NUM = 16; // 15;
143 wire [PRIM_NUM - 1:0] rcvd_dword; // shows current processing primitive (or just data dword)
144 wire dword_val; // any valid primitive/data
145 wire dword_val_na; // any valid primitive but ALIGNp
146 // list of bits of rcvd_dword
147 localparam CODE_DATA = 0; // DATA
148 localparam CODE_CRC = 1; // CRC
149 localparam CODE_SYNCP = 2; // SYNCp
150 localparam CODE_ALIGNP = 3; // ALIGNp PHY layer control
151 localparam CODE_XRDYP = 4; // X_RDYp Transmission data ready
152 localparam CODE_SOFP = 5; // SOFp Start of Frame
153 localparam CODE_HOLDAP = 6; // HOLDAp HOLD acknowledge
154 localparam CODE_HOLDP = 7; // HOLDp Hold data transmission
155 localparam CODE_EOFP = 8; // EOFp End Of Frame
156 localparam CODE_WTRMP = 9; // WTRMp Wait for frame termination
157 localparam CODE_RRDYP = 10; // R_RDYp Receiver ready
158 localparam CODE_IPP = 11; // R_IPp - Reception in progress
159 localparam CODE_DMATP = 12; // DMATp - DMA terminate
160 localparam CODE_OKP = 13; // R_OKp - Reception with no error
161 localparam CODE_ERRP = 14; // R_ERRp - Reception with Error
162 localparam CODE_CONTP = 15; // CONTp - Continue repeating
163 
164 // processing CONTp/junk, delaying everything by 1 clock
165 always @ (posedge clk) begin
169 
170  if (is_non_cont_non_align_p_w) last_not_cont_di <= phy_data_in_r0; // last_not_cont_di - primitive to repeat instead of junk
171 
173  else if (is_cont_p_w) rcv_junk <= 1;
174 
176  phy_data_in_r <= last_not_cont_di; // last non-cont/non-align primitive will be sent instead of junk
177  phy_isk_in_r <= 1; // it was always primitive (4'b0001)
178  end else begin
179  phy_data_in_r <= phy_data_in_r0; // data and ALIGNp will go through
180  phy_isk_in_r <= phy_isk_in_r0; // data and ALIGNp will go through
181  end
183 
184 end
185 // When switching from state_rcvr_shold to state_rcvr_data we need to know that it will be data 1 cycle ahead
187 
188 reg data_txing_r; // if there are still some data to transmit and the transaction wasn't cancelled
190 // Make it safe
191 always @ (posedge clk) begin
192  if (rst) data_txing_r <= 0;
193  else if (frame_req) data_txing_r <= 1;
194  else if (state_send_crc) data_txing_r <= 0;
195 end
197 
198 // states and transitions are taken from the doc, "Link Layer State Machine" chapter
199 // power mode states are not implemented. TODO insert them as an additional branch of fsm
201 // !!!IMPORTANT!!! If add/remove any states, dont forget to change this parameter value
202 localparam STATES_COUNT = 23;
203 // idle state
204 wire state_idle;
205 reg state_sync_esc; // SyncEscape
206 reg state_nocommerr; // NoComErr
207 reg state_nocomm; // NoComm
208 reg state_align; // SendAlign - not used, handled by OOB
209 reg state_reset; // RESET
210 // tranmitter branch
211 reg state_send_rdy; // SendChkRdy
212 reg state_send_sof; // SendSOF
213 reg state_send_data; // SendData
214 reg state_send_rhold; // RcvrHold - hold initiated by current data reciever
215 reg state_send_shold; // SendHold - hold initiated by current data sender
216 reg state_send_crc; // SendCVC
217 reg state_send_eof; // SendEOF
218 reg state_wait; // Wait
219 // receiver branch
220 reg state_rcvr_wait; // RcvWaitFifo
221 reg state_rcvr_rdy; // RcvChkRdy
222 reg state_rcvr_data; // RcvData
223 reg state_rcvr_rhold; // Hold - hold initiated by current data reciever
224 reg state_rcvr_shold; // RcvHold - hold initiated by current data sender
225 reg state_rcvr_eof; // RcvEOF
226 reg state_rcvr_goodcrc; // GoodCRC
227 reg state_rcvr_goodend; // GoodEnd
228 reg state_rcvr_badend; // BadEnd
229 
230 // handling single-cycle incom_ack_good/incom_ack_bad when they arrive at alignes_pair
249 wire set_wait;
253 wire set_rcvr_rhold;
259 
272 wire clr_wait;
276 wire clr_rcvr_rhold;
277 wire clr_rcvr_shold;
278 wire clr_rcvr_eof;
279 wire clr_rcvr_goodcrc;
280 wire clr_rcvr_goodend;
281 wire clr_rcvr_badend;
282 
283 assign state_idle = ~state_sync_esc
284  & ~state_nocommerr
285  & ~state_nocomm
286  & ~state_align
287  & ~state_reset
288  & ~state_send_rdy
289  & ~state_send_sof
290  & ~state_send_data
293  & ~state_send_crc
294  & ~state_send_eof
295  & ~state_wait
296  & ~state_rcvr_wait
297  & ~state_rcvr_rdy
298  & ~state_rcvr_data
301  & ~state_rcvr_eof
305 
306 // got an escaping primitive = request to cancel the transmission
307 // may be 1 cycle, need to extend over alignes_pair
308 wire got_escape = dword_val & rcvd_dword[CODE_SYNCP]; // can wait over alignes pair
309 reg sync_escape_req_r; // ahci sends 1 single-clock pulse, it may hit alignes_pair
310 always @ (posedge clk) begin
312 end
314 // escaping is done
316 
318 reg alignes_pair; // pauses every state go give a chance to insert 2 align primitives on a line at least every 256 dwords due to spec
319 reg [8:0] alignes_timer;
320 
321 reg alignes_pair_0; // time for 1st align primitive
322 
323 always @ (posedge clk) begin
324  if (!phy_ready || select_prim[CODE_ALIGNP]) alignes_timer <= ALIGNES_PERIOD;
328 
329 end
330 
331 always @ (posedge clk) begin
333 
335  else if (!state_rcvr_goodcrc) incom_ack_good_pend <= 0;
336 
338  else if (!state_rcvr_goodcrc) incom_ack_bad_pend <= 0; // didn't like it even with good crc
339 end
340 
341 // Whole transitions table, literally from doc pages 311-328 (Andrey: now modified, may be not true)
342 assign set_sync_esc = sync_escape_req || sync_escape_req_r; // extended over alignes_pair
344 assign set_nocomm = state_nocommerr;
345 assign set_align = 0; // never, as this state is handled by OOB
346 assign set_reset = link_reset;
347 
349 
351 
355 
358 
360 
363 
365 
367 
368 // receiver's branch
371 
373 
376  | state_rcvr_shold & next_will_be_data // So it will not be align
377  | state_rcvr_data & next_will_be_data; // to skip over single-cycle CODE_HOLDP
378 //next_will_be_data
380 
383 
387 
389 
390 assign set_rcvr_goodend = state_rcvr_goodcrc& incom_ack_good_or_pend; // incom_ack_good; // may arrive at aligns_pair
391 
393  | state_rcvr_eof & crc_bad // Got bad CRC
394  | state_rcvr_goodcrc& incom_ack_bad_or_pend; // incom_ack_bad; // Transport didn't like it (may arrive at aligns_pair)
395 
398 assign clr_nocomm = set_reset | set_align;
399 ///assign clr_align = set_nocommerr | set_reset | phy_ready;
400 ///assign clr_align = set_nocommerr | set_reset | link_established_r; // Not phy_ready !!!
401 assign clr_align = 0; // never - this state is handled in OOB
402 assign clr_reset = ~link_reset;
403 ///assign clr_reset = set_align;
405 assign clr_send_sof = set_nocommerr | set_reset | set_sync_esc | set_send_data; // | got_escape;
409 assign clr_send_crc = set_nocommerr | set_reset | set_sync_esc | set_send_eof; // | got_escape;
410 assign clr_send_eof = set_nocommerr | set_reset | set_sync_esc | set_wait; // | got_escape;
411 assign clr_wait = set_nocommerr | set_reset | set_sync_esc | frame_done; // | got_escape;
412 
413 assign clr_rcvr_wait = set_nocommerr | set_reset | set_sync_esc /*| set_rcvr_rdy **/ | (dword_val_na & ~rcvd_dword[CODE_XRDYP]);
415 assign clr_rcvr_data = set_nocommerr | set_reset | set_sync_esc /*| set_rcvr_rhold | set_rcvr_shold | set_rcvr_eof **/ | set_rcvr_badend; // | got_escape;
416 assign clr_rcvr_rhold = set_nocommerr | set_reset | set_sync_esc /*| set_rcvr_data | set_rcvr_eof | set_rcvr_shold **/; // | got_escape;
417 assign clr_rcvr_shold = set_nocommerr | set_reset | set_sync_esc /*| set_rcvr_data | set_rcvr_eof **/; // | got_escape;
418 assign clr_rcvr_eof = set_nocommerr | set_reset | set_sync_esc /*|set_rcvr_goodcrc | set_rcvr_badend**/;
419 assign clr_rcvr_goodcrc = set_nocommerr | set_reset | set_sync_esc /*set_rcvr_goodend | set_rcvr_badend |**/; // | got_escape;
420 
421 assign clr_rcvr_goodend = set_nocommerr | set_reset | set_sync_esc; // | got_escape; // can be 1 cycle only
422 assign clr_rcvr_badend = set_nocommerr | set_reset | set_sync_esc; // | got_escape;
423 
424 // the only truely asynchronous transaction between states is -> state_ reset. It shall not be delayed by sending alignes
425 // Luckily, while in that state, the line is off, so we dont need to care about merging alignes and state-bounded primitives
426 // Others transitions are straightforward
427 always @ (posedge clk)
428 begin
432  // state_align is not used, it is handled by OOB
443  // Andrey: most receiver states can not wait for transmitting aligns_pair. What host sends in this states matters when confirmed by the device
444  // So it seems OK if alignes_pair will just overwrite whatever host was going to send in these state.
445  // Care should be taken only for transitions between these states and others (transmit) that need to wait for alignes_pair to finish
446  // set_* are considered fast (no wait), clr_* - slow (to non-receive states), next opeartors use OR-ed "set_*" in immediate transitions
447  // to other states, clr_* - to other states
448  // rdy->data, data->eof
450 
452 
455  set_rcvr_eof |
457 
460  set_rcvr_eof |
462 
464  set_rcvr_eof |
466 
469 
473 
475 
477 
478 end
479 
480 // flag if incoming request to terminate current transaction came from TL
481 reg incom_stop_f;
482 always @ (posedge clk)
483 // incom_stop_f <= rst | incom_done | ~frame_busy ? 1'b0 : incom_stop_req ? 1'b1 : incom_stop_f;
484  if (rst) incom_stop_f <= 0;
485  else if (incom_stop_req) incom_stop_f <= 1;
486  else if (incom_done | ~frame_busy) incom_stop_f <= 0;
487 
489 // form data to phy
492 // TODO implement CONTP
493 localparam [15:0] PRIM_SYNCP_HI = {3'd5, 5'd21, 3'd5, 5'd21};
494 localparam [15:0] PRIM_SYNCP_LO = {3'd4, 5'd21, 3'd3, 5'd28};
495 localparam [15:0] PRIM_ALIGNP_HI = {3'd3, 5'd27, 3'd2, 5'd10};
496 localparam [15:0] PRIM_ALIGNP_LO = {3'd2, 5'd10, 3'd5, 5'd28};
497 localparam [15:0] PRIM_XRDYP_HI = {3'd2, 5'd23, 3'd2, 5'd23};
498 localparam [15:0] PRIM_XRDYP_LO = {3'd5, 5'd21, 3'd3, 5'd28};
499 localparam [15:0] PRIM_SOFP_HI = {3'd1, 5'd23, 3'd1, 5'd23};
500 localparam [15:0] PRIM_SOFP_LO = {3'd5, 5'd21, 3'd3, 5'd28};
501 localparam [15:0] PRIM_HOLDAP_HI = {3'd4, 5'd21, 3'd4, 5'd21};
502 localparam [15:0] PRIM_HOLDAP_LO = {3'd5, 5'd10, 3'd3, 5'd28};
503 localparam [15:0] PRIM_HOLDP_HI = {3'd6, 5'd21, 3'd6, 5'd21};
504 localparam [15:0] PRIM_HOLDP_LO = {3'd5, 5'd10, 3'd3, 5'd28};
505 localparam [15:0] PRIM_EOFP_HI = {3'd6, 5'd21, 3'd6, 5'd21};
506 localparam [15:0] PRIM_EOFP_LO = {3'd5, 5'd21, 3'd3, 5'd28};
507 localparam [15:0] PRIM_WTRMP_HI = {3'd2, 5'd24, 3'd2, 5'd24};
508 localparam [15:0] PRIM_WTRMP_LO = {3'd5, 5'd21, 3'd3, 5'd28};
509 localparam [15:0] PRIM_RRDYP_HI = {3'd2, 5'd10, 3'd2, 5'd10};
510 localparam [15:0] PRIM_RRDYP_LO = {3'd4, 5'd21, 3'd3, 5'd28};
511 localparam [15:0] PRIM_IPP_HI = {3'd2, 5'd21, 3'd2, 5'd21};
512 localparam [15:0] PRIM_IPP_LO = {3'd5, 5'd21, 3'd3, 5'd28};
513 localparam [15:0] PRIM_DMATP_HI = {3'd1, 5'd22, 3'd1, 5'd22};
514 localparam [15:0] PRIM_DMATP_LO = {3'd5, 5'd21, 3'd3, 5'd28};
515 localparam [15:0] PRIM_OKP_HI = {3'd1, 5'd21, 3'd1, 5'd21};
516 localparam [15:0] PRIM_OKP_LO = {3'd5, 5'd21, 3'd3, 5'd28};
517 localparam [15:0] PRIM_ERRP_HI = {3'd2, 5'd22, 3'd2, 5'd22};
518 localparam [15:0] PRIM_ERRP_LO = {3'd5, 5'd21, 3'd3, 5'd28};
519 //The transmission of CONTp is optional, but the ability to receive and properly process CONTp is required.
520 localparam [15:0] PRIM_CONTP_HI = {3'd4, 5'd25, 3'd4, 5'd25};
521 localparam [15:0] PRIM_CONTP_LO = {3'd5, 5'd10, 3'd3, 5'd28};
522 
523 
524 wire [DATA_BYTE_WIDTH*8 - 1:0] prim_data [PRIM_NUM - 1:0];
525 
526 // fill all possible output primitives to choose from them after
527 generate
528 if (DATA_BYTE_WIDTH == 2)
529 begin
530  reg prim_word; // word counter in a primitive TODO logic
531  assign prim_data[CODE_SYNCP] [15:0] = prim_word ? PRIM_SYNCP_HI : PRIM_SYNCP_LO;
532  assign prim_data[CODE_ALIGNP][15:0] = prim_word ? PRIM_ALIGNP_HI : PRIM_ALIGNP_LO;
533  assign prim_data[CODE_XRDYP] [15:0] = prim_word ? PRIM_XRDYP_HI : PRIM_XRDYP_LO;
534  assign prim_data[CODE_SOFP] [15:0] = prim_word ? PRIM_SOFP_HI : PRIM_SOFP_LO;
535  assign prim_data[CODE_DATA] [15:0] = scrambler_out[15:0];
536  assign prim_data[CODE_HOLDAP][15:0] = prim_word ? PRIM_HOLDAP_HI : PRIM_HOLDAP_LO;
537  assign prim_data[CODE_HOLDP] [15:0] = prim_word ? PRIM_HOLDP_HI : PRIM_HOLDP_LO;
538  assign prim_data[CODE_CRC] [15:0] = scrambler_out[15:0];
539  assign prim_data[CODE_EOFP] [15:0] = prim_word ? PRIM_EOFP_HI : PRIM_EOFP_LO;
540  assign prim_data[CODE_WTRMP] [15:0] = prim_word ? PRIM_WTRMP_HI : PRIM_WTRMP_LO;
541  assign prim_data[CODE_RRDYP] [15:0] = prim_word ? PRIM_RRDYP_HI : PRIM_RRDYP_LO;
542  assign prim_data[CODE_IPP] [15:0] = prim_word ? PRIM_IPP_HI : PRIM_IPP_LO;
543  assign prim_data[CODE_DMATP] [15:0] = prim_word ? PRIM_DMATP_HI : PRIM_DMATP_LO;
544  assign prim_data[CODE_OKP] [15:0] = prim_word ? PRIM_OKP_HI : PRIM_OKP_LO;
545  assign prim_data[CODE_ERRP] [15:0] = prim_word ? PRIM_ERRP_HI : PRIM_ERRP_LO;
546  assign prim_data[CODE_CONTP] [15:0] = prim_word ? PRIM_CONTP_HI : PRIM_CONTP_LO;
547  always @ (posedge clk)
548  begin
549  $display("%m: unsupported data width");
550  $finish;
551  end
552 end
553 else
554 if (DATA_BYTE_WIDTH == 4)
555 begin
563  assign prim_data[CODE_CRC] = scrambler_out;
572 end
573 else
574 begin
575  always @ (posedge clk)
576  begin
577  $display("%m: unsupported data width");
578  $finish;
579  end
580 end
581 endgenerate
582 
583 // select which primitive shall be sent
584 wire [PRIM_NUM - 1:0] select_prim;
589 assign select_prim[CODE_DATA] = ~alignes_pair & (state_send_data & ~set_send_shold); // if there's no data availible for a transmission, fsm still = state_send_data. Need to explicitly count this case.
591 assign select_prim[CODE_HOLDP] = ~alignes_pair & (state_send_shold | state_rcvr_rhold | state_send_data & set_send_shold); // the case mentioned 2 lines upper
600 // No sending of CONTp
601 
602 // primitive selector MUX
603 always @ (posedge clk)
604  to_phy_data <= rst ? {DATA_BYTE_WIDTH*8{1'b0}}:
620 
621 always @ (posedge clk)
622  to_phy_isk <= rst | ~select_prim[CODE_DATA] & ~select_prim[CODE_CRC] ? {{(DATA_BYTE_WIDTH - 1){1'b0}}, 1'b1} : {DATA_BYTE_WIDTH{1'b0}} ;
623 
624 // incoming data is data
625 wire inc_is_data;
627 //wire inc_is_crc = dword_val_na & rcvd_dword[CODE_CRC] & (state_rcvr_data | state_rcvr_rhold);
628 /*
629  Scrambler can work both as a scrambler and a descramler, because data stream could be
630  one direction at a time
631  */
634  .clk (clk),
640 );
641 
642 /*
643  Same as for scrambler, crc computation for both directions
644  */
645 crc crc(
646  .clk (clk),
650  .crc_out (crc_dword)
651 );
652 
653 // the output of crc module shall be 0 if 1 tick later reciever got a crc checksum and no errors occured
657 // to TL data outputs assigment
658 // delay outputs so the last data would be marked
659 reg [31:0] data_out_r;
661 reg [31:0] data_out_rr;
662 reg data_val_out_rr;
663 // if current == EOF => _r == CRC and _rr == last data piece
664 reg data_held; // some data is held in data_out_r over primitives - to be restored if not EOF
665 // no need to check for set_rcvr_eof - last dword will be always lost
666 always @ (posedge clk) begin
668  else if (inc_is_data) data_held <= 1;
669 
672 
674 
676 
677 end
678 
679 
680 assign data_out = data_out_rr;
681 assign data_mask_out = 2'b11;//{DATA_BYTE_WIDTH/2{1'b1}};
683 assign data_last_out = set_rcvr_eof;
685 // from TL data
686 // gives a strobe everytime data is present and we're at a corresponding state.
688 
689 // Just to make output signals single-cycel regardless of alignes_pair and remove dependence on SM code
693 wire incom_invalidate_w;
694 
695 reg frame_rej_r;
696 reg incom_start_r;
697 reg incom_done_r;
700 assign frame_rej = frame_rej_w && !frame_rej_r;
702 assign incom_done = incom_done_w && ! incom_done_r;
704 
705 always @ (posedge clk) begin
710 end
711 
712 // assign phy data outputs
713 assign phy_data_out = to_phy_data;
714 assign phy_isk_out = to_phy_isk;
715 
716 assign frame_busy = ~state_idle;
717 assign frame_ack = state_send_sof;
718 assign frame_rej_w = set_rcvr_wait & state_send_rdy; // & ~alignes_pair; // OK to mask with
719 
720 // incoming fises detected
721 assign incom_start_w = set_rcvr_wait; // & ~alignes_pair;
722 // ... and processed
723 assign incom_done_w = set_rcvr_goodcrc; // & ~alignes_pair;
724 // or the FIS had errors
725 // Separating different types of errors, sync_escape from other problems. TODO: route individual errors to set SERR bits
726 assign incom_invalidate_w = (state_rcvr_eof & crc_bad) | // CRC mismatch
727  (state_rcvr_data & dword_val & rcvd_dword[CODE_WTRMP]); // missed EOF?
730 
731 // shows that incoming primitive or data is ready to be processed // TODO somehow move alignes_pair into dword_val_na
732 
733 assign dword_val = |rcvd_dword & phy_ready; // any valid primitive/data
734 assign dword_val_na = |rcvd_dword & phy_ready & ~rcvd_dword[CODE_ALIGNP]; // any valid primitive/data but ALIGNp
735 // determine imcoming primitive type
736 assign rcvd_dword[CODE_DATA] = ~|phy_isk_in_r;
737 assign rcvd_dword[CODE_CRC] = 1'b0;
751 // was missing
753 
754 // CONTp (*_r0 is one cycle ahead of *_r)
755 // Following is processed one cycle ahead of the others to replace CONTp junk with the replaced repeated primitives
760 
761 
762 // phy level errors handling TODO
763 assign dec_err = |phy_err_in_r;
764 
765 // form a response to transport layer
769 
770 // Handling 3 non-align primitives - removed, this is (should be) done by OOB
771 
772 // =========== Debug code ===================
773 wire [PRIM_NUM - 1:0] rcvd_dword0; // at least oce received after reset
774 
776 assign rcvd_dword0[CODE_CRC] = 1'b0;
792 reg [PRIM_NUM - 1:0] debug_rcvd_dword; // at least once received after reset
799 reg [15:0] debug_num_aligns;
800 reg [15:0] debug_num_syncs;
802 reg other_prim_r;
803 reg [15:0] debug_num_other; // other primitives - not aligh, sync or cont
804 reg [31:0] debug_unknown_dword;
806 
807 wire [STATES_COUNT - 1:0] debug_states_concat = {
808  state_idle
811  , state_nocomm
812  , state_align
813  , state_reset
821  , state_wait
831  };
832 reg [4:0] debug_states_encoded;
833 
835 
836 always @ (posedge clk) begin
838 
839  if (rst) debug_first_alignp <= 0;
840  else if (is_align_p_w) debug_first_alignp <= 1;
841 
842  if (rst) debug_first_syncp <= 0;
844 
845  if (rst) debug_first_error <= 0;
846  else if (dec_err && debug_first_syncp) debug_first_error <= 1;
847 
848 
849  if (rst) debug_first_nonsyncp <= 0;
851 
852  if (rst) debug_first_unknown <= 0;
853  else if ((rcvd_dword0 ==0) && debug_first_alignp) debug_first_unknown <= 1;
854 
855 
856 
857  if (rst) debug_to_first_err <= 0;
859 
860  if (rst) debug_num_aligns <= 0;
862 
863  if (rst) debug_num_syncs <= 0;
865 
866  if (rst) debug_num_later_aligns <= 0;
868 
869  if (rst) debug_num_other <= 0;
871 
872  if (rst) debug_unknown_dword <= 0;
874 
875  if (rst) debug_rcvd_dword <= 0;
877 
878  if (rst) debug_states_visited <= 0;
880 
881 
883  |debug_states_concat[15: 8],
884  (|debug_states_concat[22:20]) | (|debug_states_concat[15:12]) | (|debug_states_concat[7:4]),
885  debug_states_concat[22] | (|debug_states_concat[19:18]) | (|debug_states_concat[15:14]) |
886  (|debug_states_concat[11:10]) | (|debug_states_concat[7:6]) | (|debug_states_concat[3:2]),
890 
891 end
902 reg debug_was_wait;
903 reg debug_was_idle;
908 // frame_done | got_escape
909 
910 always @(posedge clk) begin
911  if (data_strobe_out) begin
919  end
920 
922 
923  if (frame_req) debug_was_OK_ERR <= 0;
925 
928 
930 
932 
936  end
937 
938 end
939 
940 assign debug_out[ 4: 0] = debug_states_encoded;
941 assign debug_out[7: 5] = {
944  alignes_pair};
945 assign debug_out[31] = rcvd_dword[CODE_ALIGNP];
946 assign debug_out[30] = set_send_sof;
947 assign debug_out[29] = clr_send_rdy;
948 assign debug_out[28] = state_send_rdy;
949 assign debug_out[27] = state_send_sof;
950 assign debug_out[26] = state_idle;
951 assign debug_out[25] = state_send_data;
953 assign debug_out[23] = (clr_send_sof & ~alignes_pair);
954 assign debug_out[22] = set_rcvr_wait; // start logging input
955 
956 //assign debug_out[15: 5] = debug_to_first_err[14:4];
957 assign debug_out[21:16] = debug_rcvd_dword[5:0];
958 
959 assign debug_out[15: 8] = {
960  debug_was_wait, // state was wait when last CODE_ERRP/CODE_OKP was received
961  debug_was_idle, // state was idle when last CODE_ERRP/CODE_OKP was received
962  debug_was_OK_ERR[1:0],
966 
967 /* debug_data_last_in_r[1],
968  debug_alignes_pair_r[1],
969  debug_state_send_data_r[1],
970  debug_state_send_data_r[0],
971  debug_data_val_in[1],
972 
973  debug_data_val_in[0],
974  debug_set_send_crc[1],
975 */
976 // debug_dword_val_na[1],
977  ~debug_CODE_SYNCP[1]};
978 
979 /*
980  state_send_sof <= (state_send_sof | set_send_sof & ~alignes_pair) & ~(clr_send_sof & ~alignes_pair) & ~rst;
981 
982 
983 
984 _send_crc = state_send_data & data_txing & data_val_in & data_last_in & dword_val_na & ~rcvd_dword[CODE_SYNCP]
985  | state_send_data & dword_val_na & rcvd_dword[CODE_DMATP];
986 
987 */
988 
989 
990 
991 //assign debug_out[STATES_COUNT - 1:0] = debug_states_visited;
992 
993 /*
994 //assign debug_out[PRIM_NUM - 1:0] = debug_rcvd_dword;
995 assign debug_out[ 7: 0] = debug_rcvd_dword[7:0];
996 assign debug_out[15: 8] = debug_alignes;
997 assign debug_out[23:16] = debug_data_primitives;
998 assign debug_out[30:24] = debug_notaligned_primitives[6:0]; // now count state_reset _/~
999 assign debug_out[31] = debug_state_reset_r[0];
1000 */
1001 `ifdef CHECKERS_ENABLED
1002 // incoming primitives
1003 always @ (posedge clk)
1004  if (~|rcvd_dword & phy_ready)
1005  begin
1006  $display("%m: invalid primitive received : %h, conrol : %h, err : %h", phy_data_in_r, phy_isk_in_r, phy_err_in_r);
1007  #500;
1008  $finish;
1009  end
1010 // States checker
1011 reg [STATES_COUNT - 1:0] sim_states_concat;
1012 always @ (posedge clk)
1013  if (~rst)
1014  if (( 32'h0
1015  + state_idle
1016  + state_sync_esc
1017  + state_nocommerr
1018  + state_nocomm
1019  + state_align
1020  + state_reset
1021  + state_send_rdy
1022  + state_send_sof
1023  + state_send_data
1024  + state_send_rhold
1025  + state_send_shold
1026  + state_send_crc
1027  + state_send_eof
1028  + state_wait
1029  + state_rcvr_wait
1030  + state_rcvr_rdy
1031  + state_rcvr_data
1032  + state_rcvr_rhold
1033  + state_rcvr_shold
1034  + state_rcvr_eof
1035  + state_rcvr_goodcrc
1036  + state_rcvr_goodend
1037  + state_rcvr_badend
1038  ) != 1)
1039  begin
1040  sim_states_concat = {
1041  state_idle
1042  , state_sync_esc
1043  , state_nocommerr
1044  , state_nocomm
1045  , state_align
1046  , state_reset
1047  , state_send_rdy
1048  , state_send_sof
1049  , state_send_data
1050  , state_send_rhold
1051  , state_send_shold
1052  , state_send_crc
1053  , state_send_eof
1054  , state_wait
1055  , state_rcvr_wait
1056  , state_rcvr_rdy
1057  , state_rcvr_data
1058  , state_rcvr_rhold
1059  , state_rcvr_shold
1060  , state_rcvr_eof
1061  , state_rcvr_goodcrc
1062  , state_rcvr_goodend
1063  , state_rcvr_badend
1064  };
1065  $display("%m: invalid states: %b", sim_states_concat);
1066 // $finish;
1067  end
1068 `endif
1069 
1070 `ifdef SIMULATION
1071 integer sim_cnt;
1072 always @ (posedge clk) begin
1073  if (incom_start) begin
1074  HOST_LINK_TITLE = "Incoming start";
1075  $display("[Host] LINK: %s @%t", HOST_LINK_TITLE, $time);
1076  sim_cnt = 0;
1077  end
1078  if (data_val_out) begin
1079  HOST_LINK_TITLE = "From device - received data";
1080  HOST_LINK_DATA = data_out;
1081  $display("[Host] LINK: %s = %h (#%d)@%t", HOST_LINK_TITLE, HOST_LINK_DATA, sim_cnt, $time);
1082  sim_cnt = sim_cnt + 1;
1083  end
1084  if (incom_done) begin
1085  HOST_LINK_TITLE = "Incoming end";
1086  $display("[Host] LINK: %s @%t", HOST_LINK_TITLE, $time);
1087  sim_cnt = 0;
1088  end
1089  if (incom_invalidate) begin
1090  HOST_LINK_TITLE = "Incoming invalidate";
1091  $display("[Host] LINK: %s @%t", HOST_LINK_TITLE, $time);
1092  sim_cnt = 0;
1093  end
1094  if (incom_sync_escape) begin
1095  HOST_LINK_TITLE = "Incoming sync_escape";
1096  $display("[Host] LINK: %s @%t", HOST_LINK_TITLE, $time);
1097  sim_cnt = 0;
1098  end
1099  if (incom_ack_good) begin
1100  HOST_LINK_TITLE = "Incoming ack_good";
1101  $display("[Host] LINK: %s @%t", HOST_LINK_TITLE, $time);
1102  sim_cnt = 0;
1103  end
1104  if (incom_ack_bad) begin
1105  HOST_LINK_TITLE = "Incoming ack_bad";
1106  $display("[Host] LINK: %s @%t", HOST_LINK_TITLE, $time);
1107  sim_cnt = 0;
1108  end
1109 // if (inc_is_data) begin
1110 // $display("[Host] LINK: From device - received raw data = %h", phy_data_in);
1111 // end
1112 end
1113 
1114 `endif
1115 
1116 endmodule
1117 
wire [DATA_BYTE_WIDTH*8 - 1:0] 14618crc_out
Definition: crc.v:50
wire [DATA_BYTE_WIDTH*8 - 1:0] 15594data_in
Definition: scrambler.v:51
wire [DATA_BYTE_WIDTH*8 - 1:0] 15595data_out
Definition: scrambler.v:52
wire 15591clk
Definition: scrambler.v:47
wire 14615rst
Definition: crc.v:46
wire 15593val_in
Definition: scrambler.v:50
wire 15592rst
Definition: scrambler.v:48
wire [DATA_BYTE_WIDTH*8 - 1:0] 14617data_in
Definition: crc.v:49
wire 14614clk
Definition: crc.v:45
wire 14616val_in
Definition: crc.v:48