SURF  1.0
TxFSM.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : TxFSM.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-08-09
5 -- Last update: 2016-01-27
6 -------------------------------------------------------------------------------
7 -- Description: Transmitter FSM
8 -- Transmitter has the following functionality:
9 -- Handle buffer addresses and buffer window (firstUnackAddr,nextSentAddr,lastSentAddr, bufferFull, bufferEmpty)
10 -- Application side FSM. Receive SSI frame and store into TX data buffer.
11 -- - IDLE Waits until buffer window is free (not bufferFull),
12 -- - Waits for Application side SOF,
13 -- - Save the segment to Rx buffer at nextSentAddr. Disable sending of NULL segments with appBusy flag,
14 -- - When EOF received save segment length and keep flags. Check length error,
15 -- - Request data send at Transport side FSM and increment nextSentAddr
16 -- - Wait until the data is processed and data segment sent by Transport side FSM
17 -- - Release appBusy flag and go back to INIT.
18 -- Acknowledgment FSM.
19 -- - IDLE Waits for ack_i (ack request) and ackN_i(ack number)(from RxFSM),
20 -- - Increments firstUnackAddr until the ackN_i is found in Window buffer,
21 -- - If it does not find the SEQ number it reports Ack Error,
22 -- - Goes back to IDLE.
23 -- Transport side FSM. Send and resend various segments to Transport side.
24 -- - INIT Initializes seqN to initSeqN. Waits until new connection requested. ConnFSM goin out od Closed state.
25 -- - DISS_CONN allows sending SYN, ACK, or RST segments. Goes to CONN when connection becomes active.
26 -- - CONN allows sending DATA, NULL, ACK, or RST segments.
27 -- In Resend procedure the FSM resends all the unacknowledged (DATA, NULL, RST) segments in the buffer window.
28 --
29 -- Note:Sequence number is incremented with sending SYN, DATA, NULL, and RST segments.
30 -- Note:Only the following segments are saved into Tx buffer DATA, NULL, and RST.
31 -------------------------------------------------------------------------------
32 -- This file is part of 'SLAC Firmware Standard Library'.
33 -- It is subject to the license terms in the LICENSE.txt file found in the
34 -- top-level directory of this distribution and at:
35 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
36 -- No part of 'SLAC Firmware Standard Library', including this file,
37 -- may be copied, modified, propagated, or distributed except according to
38 -- the terms contained in the LICENSE.txt file.
39 -------------------------------------------------------------------------------
40 
41 library ieee;
42 use ieee.std_logic_1164.all;
43 use ieee.std_logic_unsigned.all;
44 use ieee.std_logic_arith.all;
45 
46 use work.StdRtlPkg.all;
47 use work.RssiPkg.all;
48 use work.SsiPkg.all;
49 use work.AxiStreamPkg.all;
50 
51 --! @see entity
52  --! @ingroup protocols_rssi
53 entity TxFSM is
54  generic (
55  TPD_G : time := 1 ns;
56 
57  WINDOW_ADDR_SIZE_G : positive := 3; -- 2^WINDOW_ADDR_SIZE_G = Number of segments
58  SEGMENT_ADDR_SIZE_G : positive := 7; -- 2^SEGMENT_ADDR_SIZE_G = Number of 64 bit wide data words
59 
60  SYN_HEADER_SIZE_G : natural := 24;
61  ACK_HEADER_SIZE_G : natural := 8;
62  EACK_HEADER_SIZE_G : natural := 8;
63  RST_HEADER_SIZE_G : natural := 8;
64  NULL_HEADER_SIZE_G : natural := 8;
65  DATA_HEADER_SIZE_G : natural := 8;
66 
67  HEADER_CHKSUM_EN_G : boolean := true
68  );
69  port (
70  clk_i : in sl;
71  rst_i : in sl;
72 
73  -- Connection FSM indicating active connection
75  -- Closed state in connFSM (initialize seqN)
76  closed_i : in sl;
77 
78  -- Fault injection corrupts header checksum
80 
81  -- Various segment requests
82  sndSyn_i : in sl;
83  sndAck_i : in sl;
84  sndRst_i : in sl;
86  sndNull_i : in sl;
87 
88  -- Window buff size (Depends on the number of outstanding segments)
89  windowSize_i : in integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G);
90  bufferSize_i : in integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_G);
91 
92  -- Buffer write
93  wrBuffWe_o : out sl;
95  wrBuffData_o : out slv(RSSI_WORD_WIDTH_C*8-1 downto 0);
96 
97  -- Buffer read
99  rdBuffData_i : in slv(RSSI_WORD_WIDTH_C*8-1 downto 0);
100 
101  -- Header read
102  rdHeaderAddr_o : out slv(7 downto 0);
104  --
106  headerLength_i : in positive; -- Unconnected for now will be used when EACK
107 
108  -- Checksum control
112  --
113  chksum_i : in slv(15 downto 0);
114 
115  -- Initial sequence number
116  initSeqN_i : in slv(7 downto 0);
117 
118  -- Tx data (input to header decoder module)
119  txSeqN_o : out slv(7 downto 0);
120 
121  -- FSM outs for header and data flow control
125  dataSt_o : out sl;
128 
129  -- Last acked number (Used in Rx FSM to determine if AcnN is valid)
130  lastAckN_o : out slv(7 downto 0);
131 
132  -- Acknowledge mechanism
133  ack_i : in sl; -- From receiver module when a segment with valid ACK is received
134  ackN_i : in slv(7 downto 0); -- Number being ACKed
135  --eack_i : in sl; -- From receiver module when a segment with valid EACK is received
136  --eackSeqnArr_i : in Slv8Array(0 to MAX_RX_NUM_OUTS_SEG_G-1); -- Array of sequence numbers received out of order
137 
138  -- SSI Application side interface IN
141 
142  -- SSI Transport side interface OUT
145 
146  -- Errors (1 cc pulse)
147  lenErr_o : out sl;
148  ackErr_o : out sl;
149 
150  -- Segment buffer indicator
151  bufferEmpty_o : out sl
152  );
153 end entity TxFSM;
154 
155 architecture rtl of TxFSM is
156 
157  -- Init SSI bus
158  constant SSI_MASTER_INIT_C : SsiMasterType := axis2SsiMaster(RSSI_AXIS_CONFIG_C, AXI_STREAM_MASTER_INIT_C);
159  constant SSI_SLAVE_NOTRDY_C : SsiSlaveType := axis2SsiSlave(RSSI_AXIS_CONFIG_C, AXI_STREAM_SLAVE_INIT_C, AXI_STREAM_CTRL_INIT_C);
160  constant SSI_SLAVE_RDY_C : SsiSlaveType := axis2SsiSlave(RSSI_AXIS_CONFIG_C, AXI_STREAM_SLAVE_FORCE_C, AXI_STREAM_CTRL_INIT_C);
161 
162  type TspStateType is (
163  --
164  INIT_S,
165  DISS_CONN_S,
166  CONN_S,
167  --
168  SYN_H_S,
169  ACK_H_S,
170  RST_H_S,
171  NULL_H_S,
172  DATA_H_S,
173  DATA_S,
174  DATA_SENT_S,
175  --
176  RST_WE_S,
177  DATA_WE_S,
178  NULL_WE_S,
179  --
180  RESEND_INIT_S,
181  RESEND_H_S,
182  RESEND_DATA_S,
183  RESEND_PP_S
184  );
185 
186  type AppStateType is (
187  IDLE_S,
188  WAIT_SOF_S,
189  SEG_RCV_S,
190  SEG_RDY_S,
191  SEG_LEN_ERR
192  );
193 
194  type AckStateType is (
195  IDLE_S,
196  ERR_S,
197  ACK_S
198  --EACK_S,
199  );
200 
201  type RegType is record
202 
203  -- Buffer window handling and acknowledgment control
204  -----------------------------------------
205  windowArray : WindowTypeArray(0 to 2 ** WINDOW_ADDR_SIZE_G-1);
206  firstUnackAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0);
207  nextSentAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0);
208  lastSentAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0);
209 
210  lastAckSeqN : slv(7 downto 0);
211  --eackAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0);
212  --eackIndex : integer;
213  bufferFull : sl;
214  bufferEmpty : sl;
215  ackErr : sl;
216 
217  -- State Machine
218  ackState : AckStateType;
219 
220  -- Application side FSM
221  -----------------------------------------
222  rxSegmentAddr : slv(SEGMENT_ADDR_SIZE_G downto 0); -- One address bit more to check the overflow
223  rxBufferAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0);
224  rxSegmentWe : sl;
225  sndData : sl;
226  lenErr : sl;
227  appBusy : sl;
228 
229  appSsiMaster : SsiMasterType;
230  appSsiSlave : SsiSlaveType;
231 
232  appState : AppStateType;
233 
234  -- Transport side FSM
235  -----------------------------------------
236 
237  -- Counters
238  nextSeqN : slv(7 downto 0);
239  seqN : slv(7 downto 0);
240  txHeaderAddr : slv(7 downto 0);
241  txSegmentAddr : slv(SEGMENT_ADDR_SIZE_G downto 0);
242  txBufferAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0);
243 
244  -- Data mux flags
245  synH : sl;
246  ackH : sl;
247  rstH : sl;
248  nullH : sl;
249  dataH : sl;
250  dataD : sl;
251  resend: sl;
252 
253  -- Varionus controls
254  txRdy : sl;
255  buffWe : sl;
256  buffSent : sl;
257  chkEn : sl;
258  chkStb : sl;
259 
260  -- Fault injection
261  injectFaultD1 : sl;
262  injectFaultReg : sl;
263 
264  -- SSI master
265  tspSsiMaster : SsiMasterType;
266  tspSsiSlave : SsiSlaveType;
267 
268  -- State Machine
269  tspState : tspStateType;
270  end record RegType;
271 
272  constant REG_INIT_C : RegType := (
273 
274  -- Buffer window handling and acknowledgment control
275  -----------------------------------------
276  -- Window control
277  firstUnackAddr => (others => '0'),
278  lastSentAddr => (others => '0'),
279  nextSentAddr => (others => '0'),
280 
281  lastAckSeqN => (others => '0'),
282  --eackAddr => (others => '0'),
283  --eackIndex => 0,
284  bufferFull => '0',
285  bufferEmpty => '1',
286  windowArray => (0 to 2 ** WINDOW_ADDR_SIZE_G-1 => WINDOW_INIT_C),
287  ackErr => '0',
288 
289  ackState => IDLE_S,
290 
291  -- Application side FSM
292  -----------------------------------------
293  rxSegmentAddr => (others => '0'),
294  rxSegmentWe => '0',
295  rxBufferAddr => (others => '0'),
296  sndData => '0',
297  lenErr => '0',
298  appBusy => '0',
299 
300  appSsiMaster => SSI_MASTER_INIT_C,
301  appSsiSlave => SSI_SLAVE_NOTRDY_C,
302 
303  appState => IDLE_S,
304 
305  -- Transport side FSM
306  -----------------------------------------
307  nextSeqN => (others => '0'),
308  seqN => (others => '0'),
309  txHeaderAddr => (others => '0'),
310  txSegmentAddr => (others => '0'),
311  txBufferAddr => (others => '0'),
312 
313  --
314  synH => '0',
315  ackH => '0',
316  rstH => '0',
317  nullH => '0',
318  dataH => '0',
319  dataD => '0',
320  resend => '0',
321 
322  --
323  txRdy => '0',
324  buffWe => '0',
325  buffSent => '0',
326  chkEn => '0',
327  chkStb => '0',
328 
329  -- Fault injection
330  injectFaultD1 => '0',
331  injectFaultReg => '0',
332 
333  -- SSI master
334  tspSsiMaster => SSI_MASTER_INIT_C,
335  tspSsiSlave => SSI_SLAVE_NOTRDY_C,
336 
337  -- State Machine
338  tspState => INIT_S
339  );
340 
341  signal r : RegType := REG_INIT_C;
342  signal rin : RegType;
343  signal s_chksum : slv(chksum_i'range);
344  signal s_headerAndChksum : slv(RSSI_WORD_WIDTH_C*8-1 downto 0);
345 begin
346 
347  -- Send all 0 if checksum disabled
348  s_chksum <= ite(HEADER_CHKSUM_EN_G, chksum_i, (chksum_i'range=>'0') );
349  s_headerAndChksum <= rdHeaderData_i(63 downto 16) & s_chksum(15 downto 0);
350 
351  -----------------------------------------------------------------------------------------------
354 
355  variable v : RegType;
356 
357  begin
358  v := r;
359 
360  -- /////////////////////////////////////////////////////////
361  ------------------------------------------------------------
362  -- Buffer window handling
363  ------------------------------------------------------------
364  -- /////////////////////////////////////////////////////////
365 
366  ------------------------------------------------------------
367  -- Buffer full if next slot is occupied
368  if ( r.windowArray(conv_integer(v.rxBufferAddr)).occupied = '1') then
369  v.bufferFull := '1';
370  else
371  v.bufferFull := '0';
372  end if;
373 
374  ------------------------------------------------------------
375  -- Buffer empty if next unacknowledged slot is unoccupied
376  if ( r.windowArray(conv_integer(r.firstUnackAddr)).occupied = '0') then
377  v.bufferEmpty := '1';
378  else
379  v.bufferEmpty := '0';
380  end if;
381 
382  ------------------------------------------------------------
383  -- Write seqN and segment type to window array
384  ------------------------------------------------------------
385  if (r.buffWe = '1') then
386  v.windowArray(conv_integer(r.nextSentAddr)).seqN := r.nextSeqN;
387  v.windowArray(conv_integer(r.nextSentAddr)).segType := r.rstH & r.nullH & r.dataH;
388  v.windowArray(conv_integer(r.nextSentAddr)).occupied := '1';
389 
390  -- Update last sent address when new segment is being sent
391  v.lastSentAddr := r.nextSentAddr;
392  else
393  v.windowArray := r.windowArray;
394  end if;
395 
396  ------------------------------------------------------------
397  -- When buffer is sent increase nextSentAddr
398  ------------------------------------------------------------
399  if (r.buffSent = '1') then
400 
401  if r.nextSentAddr < (windowSize_i-1) then
402  v.nextSentAddr := r.nextSentAddr +1;
403  else
404  v.nextSentAddr := (others => '0');
405  end if;
406 
407  else
408  v.nextSentAddr := r.nextSentAddr;
409  end if;
410 
411  -- /////////////////////////////////////////////////////////
412  ------------------------------------------------------------
413  -- ACK FSM
414  -- Acknowledgment mechanism to increment firstUnackAddr
415  -- Place out of order flags from EACK table (Not in Version 1)
416  ------------------------------------------------------------
417  -- /////////////////////////////////////////////////////////
418 
419  case r.ackState is
420  ----------------------------------------------------------------------
421  when IDLE_S =>
422 
423  -- Hold ACK address
424  v.firstUnackAddr := r.firstUnackAddr;
425  v.lastAckSeqN := r.lastAckSeqN;
426  --v.eackAddr := r.firstUnackAddr;
427  --v.eackIndex := 0;
428  v.ackErr := '0';
429 
430  -- Next state condition
431  if (ack_i = '1') then
432  v.ackState := ACK_S;
433  end if;
434  ----------------------------------------------------------------------
435  when ACK_S =>
436 
437  -- If the same ackN received do nothing
438  if (r.lastAckSeqN = ackN_i) then
439  v.firstUnackAddr := r.firstUnackAddr;
440  -- Increment ACK address until seqN is found next received
441  elsif r.firstUnackAddr < (windowSize_i-1) then
442  v.windowArray(conv_integer(r.firstUnackAddr)).occupied := '0';
443  v.firstUnackAddr := r.firstUnackAddr+1;
444  else
445  v.windowArray(conv_integer(r.firstUnackAddr)).occupied := '0';
446  v.firstUnackAddr := (others => '0');
447  end if;
448 
449  --v.eackAddr := r.firstUnackAddr;
450  -- v.eackIndex := 0;
451  v.ackErr := '0';
452 
453  -- Next state condition
454 
455  -- If the same ackN received
456  if (r.lastAckSeqN = ackN_i) then
457 
458  -- Go back to IDLE
459  v.ackState := IDLE_S;
460 
461  elsif (r.firstUnackAddr = r.lastSentAddr and r.windowArray(conv_integer(r.firstUnackAddr)).seqN /= ackN_i) then
462  -- If the acked seqN is not found go to error state
463  v.ackState := ERR_S;
464  elsif (r.windowArray(conv_integer(r.firstUnackAddr)).seqN = ackN_i) then
465  v.lastAckSeqN := ackN_i; -- Save the last Acked seqN
466  --if eack_i = '1' then
467  -- Go back to init when the acked seqN is found
468  -- v.ackState := EACK_S;
469  --else
470  -- Go back to init when the acked seqN is found
471  v.ackState := IDLE_S;
472  --end if;
473  end if;
474  ----------------------------------------------------------------------
475  -- when EACK_S =>
476 
477  -- -- Increment EACK address from firstUnackAddr to nextSentAddr
478  -- if r.eackAddr < (windowSize_i-1) then
479  -- v.eackAddr := r.eackAddr+1;
480  -- else
481  -- v.eackAddr := (others => '0');
482  -- end if;
483 
484  -- -- For every address check if the sequence number equals value from eackSeqnArr_i array.
485  -- -- If it matches mark the eack field at the address and compare the next value from the table.
486  -- if r.windowArray(conv_integer(r.eackAddr)).seqN = eackSeqnArr_i(r.eackIndex) then
487  -- v.windowArray(conv_integer(r.eackAddr)).eacked := '1';
488  -- v.eackIndex := r.eackIndex + 1;
489  -- end if;
490 
491  -- v.firstUnackAddr := r.firstUnackAddr;
492  -- v.ackErr := '0';
493 
494  -- -- Next state condition
495  -- if (r.eackAddr = r.nextSentAddr) then
496  -- -- If the acked seqN is not found go to error state
497  -- v.appState := IDLE_S;
498  -- end if;
499  ----------------------------------------------------------------------
500  when ERR_S =>
501  -- Outputs
502  v.firstUnackAddr := r.firstUnackAddr;
503  --v.eackAddr := r.firstUnackAddr;
504  --v.eackIndex := 0;
505  v.ackErr := '1';
506 
507  -- Next state condition
508  v.ackState := IDLE_S;
509  ----------------------------------------------------------------------
510  when others =>
511  -- Outputs
512  v.firstUnackAddr := r.firstUnackAddr;
513  -- v.eackAddr := r.firstUnackAddr;
514  -- v.eackIndex := 0;
515  v.ackErr := '1';
516 
517  -- Next state condition
518  v.ackState := IDLE_S;
519  ----------------------------------------------------------------------
520  end case;
521 
522  -- /////////////////////////////////////////////////////////
523  ------------------------------------------------------------
524  -- Application side FSM
525  ------------------------------------------------------------
526  -- /////////////////////////////////////////////////////////
527 
528  -- Pipeline Master (DFF)
529  v.appSsiMaster := appSsiMaster_i;
530  ------------------------------------------------------------
531  case r.appState is
532  ----------------------------------------------------------------------
533  when IDLE_S =>
534 
535  -- SSI
536  v.appSsiSlave := SSI_SLAVE_NOTRDY_C;
537 
538  -- Buffer write ctl
539  v.rxSegmentAddr := (others =>'0');
540  v.rxSegmentWe := '0';
541  v.rxBufferAddr := r.rxBufferAddr;
542 
543  -- txFSM
544  v.sndData := '0';
545  v.lenErr := '0';
546  v.appBusy := '1';
547 
548  -- Wait if buffer full
549  if (v.bufferFull = '0') then
550  v.appState := WAIT_SOF_S;
551  end if;
552  ----------------------------------------------------------------------
553  when WAIT_SOF_S =>
554 
555  -- SSI Ready to receive data from APP
556  v.appSsiSlave := SSI_SLAVE_RDY_C;
557 
558  -- Buffer write ctl
559  v.rxSegmentAddr := (others =>'0');
560  v.rxSegmentWe := '0';
561  v.rxBufferAddr := r.rxBufferAddr;
562 
563  -- txFSM
564  v.sndData := '0';
565  v.lenErr := '0';
566  v.appBusy := '0';
567 
568  -- If other segment (NULL, or RST) is requested return to IDLE_S to
569  -- check if buffer is still available (not full)
570  if (r.buffWe = '1') then
571  v.appState := IDLE_S;
572 
573  -- Increment the buffer window address because a NULL segment has filled the current spot
574  if r.rxBufferAddr < (windowSize_i-1) then
575  v.rxBufferAddr := r.rxBufferAddr+1;
576  else
577  v.rxBufferAddr := (others => '0');
578  end if;
579 
580  -- Wait until receiving the first data
581  -- SOF and EOF received
582  -- Packet is only one word long go directly to ready!
583  elsif (appSsiMaster_i.sof = '1' and appSsiMaster_i.valid = '1' and appSsiMaster_i.eof = '1' ) then
584 
585  -- First data already received at this point
586  v.rxSegmentAddr := r.rxSegmentAddr;
587  v.appBusy := '1';
588  v.rxSegmentWe := '1';
589 
590  -- Save packet tKeep of last data word
591  v.windowArray(conv_integer(r.rxBufferAddr)).keep := appSsiMaster_i.keep;
592  v.windowArray(conv_integer(r.rxBufferAddr)).segSize := conv_integer(r.rxSegmentAddr(SEGMENT_ADDR_SIZE_G-1 downto 0));
593 
594  v.appState := SEG_RDY_S;
595 
596  -- SOF received
597  elsif (appSsiMaster_i.sof = '1' and appSsiMaster_i.valid = '1') then
598 
599  -- First data received
600  v.rxSegmentAddr := r.rxSegmentAddr;
601  v.appBusy := '1';
602  v.rxSegmentWe := '1';
603 
604  v.appState := SEG_RCV_S;
605  end if;
606  ----------------------------------------------------------------------
607  when SEG_RCV_S =>
608 
609  -- SSI
610  v.appSsiSlave := SSI_SLAVE_RDY_C;
611  v.rxBufferAddr := r.rxBufferAddr;
612 
613  -- Buffer write if data valid
614  if (appSsiMaster_i.valid = '1') then
615  v.rxSegmentAddr := r.rxSegmentAddr + 1;
616  v.rxSegmentWe := '1';
617  else
618  v.rxSegmentAddr := r.rxSegmentAddr;
619  v.rxSegmentWe := '0';
620  end if;
621 
622  -- txFSM
623  v.sndData := '0';
624  v.lenErr := '0';
625  v.appBusy := '1';
626 
627  -- Wait until receiving EOF
628  if (appSsiMaster_i.eof = '1' and appSsiMaster_i.valid = '1') then
629 
630  -- Save packet tKeep of last data word
631  v.windowArray(conv_integer(r.rxBufferAddr)).keep := appSsiMaster_i.keep;
632 
633  -- Save packet length (+1 because it has not incremented for EOF yet)
634  v.windowArray(conv_integer(r.rxBufferAddr)).segSize := conv_integer(r.rxSegmentAddr(SEGMENT_ADDR_SIZE_G-1 downto 0))+1;
635 
636  v.appState := SEG_RDY_S;
637  --
638  elsif (r.rxSegmentAddr > bufferSize_i ) then
639  v.rxSegmentWe := '0';
640  v.appState := SEG_LEN_ERR;
641  elsif (r.rxSegmentAddr(SEGMENT_ADDR_SIZE_G) = '1' ) then
642  v.rxSegmentWe := '0';
643  v.appState := SEG_LEN_ERR;
644  end if;
645  ----------------------------------------------------------------------
646  when SEG_RDY_S =>
647 
648  -- SSI
649  v.appSsiSlave := SSI_SLAVE_NOTRDY_C;
650 
651  v.rxSegmentAddr := (others =>'0');
652  v.rxSegmentWe := '0';
653 
654  -- Request data at txFSM
655  v.sndData := '1';
656  v.lenErr := '0';
657  v.appBusy := '1';
658 
659  -- Hold request until accepted
660  -- And not in resend process
661  if (v.dataH = '1' and v.resend = '0' ) then
662  -- Increment the rxBuffer
663  if r.rxBufferAddr < (windowSize_i-1) then
664  v.rxBufferAddr := r.rxBufferAddr+1;
665  else
666  v.rxBufferAddr := (others => '0');
667  end if;
668 
669  v.appState := IDLE_S;
670  end if;
671  ----------------------------------------------------------------------
672  when SEG_LEN_ERR =>
673 
674  -- SSI
675  v.appSsiSlave := SSI_SLAVE_NOTRDY_C;
676  -- Overflow happened (packet too big)
677  v.appSsiSlave.overflow := '1';
678 
679  v.rxSegmentAddr := (others =>'0');
680  v.rxSegmentWe := '0';
681 
682  -- Request data at txFSM
683  v.sndData := '0';
684  v.lenErr := '1';
685  v.appBusy := '1';
686 
687  -- Go back to idle
688  v.appState := IDLE_S;
689  ----------------------------------------------------------------------
690  when others =>
691  -- Outs
692  v := REG_INIT_C;
693 
694  -- Next state condition
695  v.appState := IDLE_S;
696  ----------------------------------------------------------------------
697  end case;
698 
699 
700  -- /////////////////////////////////////////////////////////
701  ------------------------------------------------------------
702  -- Initialisation of the parameters when the connection is broken
703  if (connActive_i = '0') then
704  v.firstUnackAddr := REG_INIT_C.firstUnackAddr;
705  v.lastSentAddr := REG_INIT_C.lastSentAddr;
706  v.nextSentAddr := REG_INIT_C.nextSentAddr;
707  v.rxBufferAddr := REG_INIT_C.rxBufferAddr;
708  v.bufferFull := REG_INIT_C.bufferFull;
709  v.bufferEmpty := REG_INIT_C.bufferEmpty;
710  v.windowArray := REG_INIT_C.windowArray;
711 
712  v.lastAckSeqN := initSeqN_i;
713 
714  v.ackState := REG_INIT_C.ackState;
715  v.appState := REG_INIT_C.appState;
716  end if;
717  ------------------------------------------------------------
718  -- /////////////////////////////////////////////////////////
719 
720  -- /////////////////////////////////////////////////////////
721  ------------------------------------------------------------
722  -- Arm fault injection on rising edge of injectFault_i
723  ------------------------------------------------------------
724  -- /// //////////////////////////////////////////////////////
725  v.injectFaultD1 := injectFault_i;
726 
727  if (injectFault_i = '1' and r.injectFaultD1 = '0') then
728  v.injectFaultReg := '1';
729  else
730  v.injectFaultReg := r.injectFaultReg;
731  end if;
732 
733 
734  -- /////////////////////////////////////////////////////////
735  ------------------------------------------------------------
736  -- Transport side FSM
737  ------------------------------------------------------------
738  -- /////////////////////////////////////////////////////////
739 
740  -- Reset flags
741  -- These flags will hold if not overidden
742  v.tspSsiMaster:= SSI_MASTER_INIT_C;
743 
744  -- Pipeline incoming slave
745  v.tspSsiSlave := tspSsiSlave_i;
746 
747  case r.tspState is
748  ----------------------------------------------------------------------
749  when INIT_S =>
750  -- Initialize all
751  v := REG_INIT_C;
752 
753  -- Register initial sequence number
754  v.nextSeqN := initSeqN_i;
755  v.seqN := r.nextSeqN;
756 
757  -- Next state condition
758  if (closed_i = '0') then
759  v.tspState := DISS_CONN_S;
760  end if;
761  ----------------------------------------------------------------------
762  when DISS_CONN_S =>
763  -- Counters
764  v.nextSeqN := r.nextSeqN;
765  v.seqN := r.nextSeqN;
766 
767  v.txHeaderAddr := (others => '0');
768  v.txSegmentAddr := (others => '0');
769 
770  v.txBufferAddr := r.nextSentAddr;
771  --
772  v.synH := '0';
773  v.ackH := '0';
774  v.rstH := '0';
775  v.nullH := '0';
776  v.dataH := '0';
777  v.dataD := '0';
778  --
779  v.txRdy := '1';
780  v.buffWe := '0';
781  v.buffSent := '0';
782  v.chkEn := '0';
783  v.chkStb := '0';
784 
785  v.tspSsiMaster:= SSI_MASTER_INIT_C;
786 
787  -- Next state condition
788  if (sndSyn_i = '1') then
789  v.tspState := SYN_H_S;
790  elsif (sndAck_i = '1') then
791  v.tspState := ACK_H_S;
792  elsif (sndRst_i = '1') then
793  v.tspState := RST_WE_S;
794  elsif (connActive_i = '1') then
795  v.tspState := CONN_S;
796  elsif (closed_i = '1') then
797  v.tspState := INIT_S;
798  end if;
799  ----------------------------------------------------------------------
800  when CONN_S =>
801  -- Counters
802  v.nextSeqN := r.nextSeqN;
803  v.seqN := r.nextSeqN;
804 
805  v.txHeaderAddr := (others => '0');
806  v.txSegmentAddr := (others => '0');
807 
808  v.txBufferAddr := r.nextSentAddr;
809  --
810  v.synH := '0';
811  v.ackH := '0';
812  v.rstH := '0';
813  v.nullH := '0';
814  v.dataH := '0';
815  v.dataD := '0';
816  v.resend := '0';
817 
818  --
819  v.txRdy := '1';
820  v.buffWe := '0';
821  v.buffSent := '0';
822  v.chkEn := '0';
823  v.chkStb := '0';
824 
825  v.tspSsiMaster:= SSI_MASTER_INIT_C;
826 
827  -- Next state condition
828  if (sndRst_i = '1') then
829  v.tspState := RST_WE_S;
830  elsif (r.sndData = '1' and r.bufferFull = '0') then
831  v.tspState := DATA_WE_S;
832  elsif (sndResend_i = '1' and r.bufferEmpty = '0') then
833  v.tspState := RESEND_INIT_S;
834  elsif (sndAck_i = '1') then
835  v.tspState := ACK_H_S;
836  elsif (sndNull_i = '1' and r.bufferFull = '0' and r.appBusy = '0') then
837  v.tspState := NULL_WE_S;
838  elsif (connActive_i = '0') then
839  v.tspState := INIT_S;
840  end if;
841 
842  ----------------------------------------------------------------------
843  -- SYN packet
844  ----------------------------------------------------------------------
845  when SYN_H_S =>
846  -- Counters
847  v.nextSeqN := r.nextSeqN;
848  v.seqN := r.nextSeqN;
849 
850  v.txSegmentAddr := (others => '0');
851  v.txBufferAddr := r.nextSentAddr;
852  --
853  v.synH := '1'; -- Send SYN header
854  v.ackH := '0';
855  v.rstH := '0';
856  v.nullH := '0';
857  v.dataH := '0';
858  v.dataD := '0';
859  --
860  v.txRdy := '0';
861  v.buffWe := '0';
862  v.buffSent := '0';
863  v.chkEn := '1';
864 
865  v.tspSsiMaster:= SSI_MASTER_INIT_C;
866  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(rdHeaderData_i);
867 
868  -- Send SOF with header address 0
869  if (r.txHeaderAddr = (r.txHeaderAddr'range => '0')) then
870  v.tspSsiMaster.sof := '1';
871  else
872  v.tspSsiMaster.sof := '0';
873  end if;
874 
875  -- Increment address and generate strobe
876  if (r.txHeaderAddr = headerLength_i-1 and headerRdy_i = '1') then
877  v.tspSsiMaster.valid := '0';
878  v.txHeaderAddr := r.txHeaderAddr;
879  v.chkStb := '1';
880 
881  if (chksumValid_i = '1') then
882  -- Add checksum
883  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum);
884  v.tspSsiMaster.valid := '1';
885  v.tspSsiMaster.eof := '1';
886  v.tspSsiMaster.eofe := '0';
887 
888  v.nextSeqN := r.nextSeqN+1; -- Increment SEQ number at the end of segment transmission
889  v.seqN := r.nextSeqN+1;
890 
891  -- Next state
892  v.tspState := DISS_CONN_S;
893  end if;
894  elsif (tspSsiSlave_i.pause = '0' and headerRdy_i = '1') then
895  v.tspSsiMaster.valid := '1';
896  v.txHeaderAddr := r.txHeaderAddr + 1;
897  v.chkStb := '1';
898  else
899  v.tspSsiMaster.valid := '0';
900  v.txHeaderAddr := r.txHeaderAddr;
901  v.chkStb := '0';
902  end if;
903 
904  ----------------------------------------------------------------------
905  -- ACK packet
906  ----------------------------------------------------------------------
907  when ACK_H_S =>
908  -- Counters
909  v.nextSeqN := r.nextSeqN;
910  v.seqN := r.nextSeqN;
911 
912  v.txSegmentAddr := (others => '0');
913  v.txBufferAddr := r.nextSentAddr;
914  v.txHeaderAddr := (others => '0');
915 
916  --
917  v.synH := '0';
918  v.ackH := '1'; -- Send ack header
919  v.rstH := '0';
920  v.nullH := '0';
921  v.dataH := '0';
922  v.dataD := '0';
923  --
924  v.txRdy := '0';
925  v.buffWe := '0';
926  v.buffSent := '0';
927  v.chkEn := '1';
928 
929  -- Strobe immediately after headerRdy
930  if (headerRdy_i = '1') then
931  v.chkStb := '1';
932  end if;
933 
934  v.tspSsiMaster:= SSI_MASTER_INIT_C;
935  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(rdHeaderData_i);
936 
937  -- Next state condition (when chksum is ready)
938  if (chksumValid_i = '1' and tspSsiSlave_i.pause = '0') then -- Frame size is one word
939  v.tspSsiMaster.valid := '1';
940  v.tspSsiMaster.sof := '1';
941  v.tspSsiMaster.strb := (others => '1');
942  v.tspSsiMaster.keep := (others => '1');
943  v.tspSsiMaster.dest := (others => '0');
944  v.tspSsiMaster.eof := '1';
945  v.tspSsiMaster.eofe := '0';
946 
947  -- Add checksum to last two bytes
948  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum);
949 
950  --
951  if connActive_i = '0' then
952  v.tspState := DISS_CONN_S;
953  else
954  v.tspState := CONN_S;
955  end if;
956 
957  end if;
958 
959  ----------------------------------------------------------------------
960  -- RST packet
961  ----------------------------------------------------------------------
962  when RST_WE_S =>
963  -- Counters
964  v.nextSeqN := r.nextSeqN;
965  v.seqN := r.nextSeqN;
966 
967  v.txHeaderAddr := (others => '0');
968  v.txSegmentAddr := (others => '0');
969 
970  v.txBufferAddr := r.nextSentAddr;
971  -- State control signals
972  v.synH := '0';
973  v.ackH := '0';
974  v.rstH := '1'; -- Send reset header
975  v.nullH := '0';
976  v.dataH := '0';
977  v.dataD := '0';
978  --
979  v.txRdy := '0';
980  v.buffWe := '0'; -- TODO (Check if this is ok) Ignore the buffer because the RST will not get retransmitted
981  v.buffSent := '0';
982  v.chkEn := '0';
983  v.chkStb := '0';
984 
985  -- SSI master
986  v.tspSsiMaster:= SSI_MASTER_INIT_C;
987 
988  -- Next State condition
989  v.tspState := RST_H_S;
990  ----------------------------------------------------------------------
991  when RST_H_S =>
992  --
993  v.nextSeqN := r.nextSeqN;
994  v.seqN := r.nextSeqN;
995 
996  v.txSegmentAddr := (others => '0');
997  v.txBufferAddr := r.nextSentAddr;
998  v.txHeaderAddr := (others => '0');
999 
1000  -- Flags
1001  v.synH := '0';
1002  v.ackH := '0';
1003  v.rstH := '1'; -- Send reset header
1004  v.nullH := '0';
1005  v.dataH := '0';
1006  v.dataD := '0';
1007  --
1008  v.txRdy := '0';
1009  v.buffWe := '0';
1010  v.buffSent := '0';
1011  v.chkEn := '1';
1012 
1013  if (headerRdy_i = '1') then
1014  v.chkStb := '1';
1015  end if;
1016 
1017  v.tspSsiMaster:= SSI_MASTER_INIT_C;
1018  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(rdHeaderData_i);
1019 
1020  -- Next state condition
1021  if (chksumValid_i = '1' and tspSsiSlave_i.pause = '0' ) then -- Frame size is one word
1022  v.tspSsiMaster.valid := '1';
1023  v.tspSsiMaster.sof := '1';
1024  v.tspSsiMaster.strb := (others => '1');
1025  v.tspSsiMaster.keep := (others => '1');
1026  v.tspSsiMaster.dest := (others => '0');
1027  v.tspSsiMaster.eof := '1';
1028  v.tspSsiMaster.eofe := '0';
1029  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum); -- Add header to last two bytes
1030 
1031  -- Increment seqN
1032  v.nextSeqN := r.nextSeqN+1; -- Increment SEQ number at the end of segment transmission
1033  v.seqN := r.nextSeqN+1;
1034  v.buffSent := '0'; -- Ignore the buffer because the RST will not get retransmitted
1035  v.tspState := CONN_S;
1036  --
1037  end if;
1038 
1039  ----------------------------------------------------------------------
1040  -- NULL packet
1041  ----------------------------------------------------------------------
1042  when NULL_WE_S =>
1043  -- Counters
1044  v.nextSeqN := r.nextSeqN;
1045  v.seqN := r.nextSeqN;
1046 
1047  v.txHeaderAddr := (others => '0');
1048  v.txSegmentAddr := (others => '0');
1049 
1050  v.txBufferAddr := r.nextSentAddr;
1051 
1052  -- State control signals
1053  v.synH := '0';
1054  v.ackH := '0';
1055  v.rstH := '0';
1056  v.nullH := '1'; -- Send null header
1057  v.dataH := '0';
1058  v.dataD := '0';
1059  --
1060  v.txRdy := '0';
1061  v.buffWe := '1'; -- Update buffer seqN and Type
1062  v.buffSent := '0';
1063  v.chkEn := '0';
1064  v.chkStb := '0';
1065 
1066  -- SSI master
1067  v.tspSsiMaster:= SSI_MASTER_INIT_C;
1068 
1069  -- Next State condition
1070  v.tspState := NULL_H_S;
1071  ----------------------------------------------------------------------
1072  when NULL_H_S =>
1073  -- Counters
1074  v.nextSeqN := r.nextSeqN;
1075  v.seqN := r.nextSeqN;
1076  v.txHeaderAddr := (others => '0');
1077 
1078  v.txSegmentAddr := (others => '0');
1079  v.txBufferAddr := r.nextSentAddr;
1080 
1081  -- Flags
1082  v.synH := '0';
1083  v.ackH := '0';
1084  v.rstH := '0';
1085  v.nullH := '1'; -- Send null header
1086  v.dataH := '0';
1087  v.dataD := '0';
1088  --
1089  v.txRdy := '0';
1090  v.buffWe := '0';
1091  v.buffSent := '0';
1092  v.chkEn := '1';
1093 
1094  if (headerRdy_i = '1') then
1095  v.chkStb := '1';
1096  end if;
1097 
1098  -- Leave initialized v.tspSsiMaster
1099  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(rdHeaderData_i);
1100 
1101  -- Next state condition
1102  if (chksumValid_i = '1' and tspSsiSlave_i.pause = '0' ) then -- Frame size is one word
1103  v.tspSsiMaster.valid := '1';
1104  v.tspSsiMaster.sof := '1';
1105  v.tspSsiMaster.strb := (others => '1');
1106  v.tspSsiMaster.keep := (others => '1');
1107  v.tspSsiMaster.dest := (others => '0');
1108  v.tspSsiMaster.eof := '1';
1109  v.tspSsiMaster.eofe := '0';
1110 
1111  -- Add checksum to last two bytes
1112  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum);
1113 
1114  -- Increment seqN
1115  v.nextSeqN := r.nextSeqN+1; -- Increment SEQ number at the end of segment transmission
1116  v.seqN := r.nextSeqN+1;
1117  v.buffSent := '1'; -- Increment the sent buffer
1118  v.tspState := CONN_S;
1119  end if;
1120 
1121  ----------------------------------------------------------------------
1122  -- DATA packet
1123  ----------------------------------------------------------------------
1124  when DATA_WE_S =>
1125  -- Counters
1126  v.nextSeqN := r.nextSeqN;
1127  v.seqN := r.nextSeqN;
1128 
1129  v.txHeaderAddr := (others => '0');
1130  v.txSegmentAddr := (others => '0');
1131 
1132  v.txBufferAddr := r.nextSentAddr;
1133 
1134  -- State control signals
1135  v.synH := '0';
1136  v.ackH := '0';
1137  v.rstH := '0';
1138  v.nullH := '0';
1139  v.dataH := '1'; -- Send data header
1140  v.dataD := '0';
1141  --
1142  v.txRdy := '0';
1143  v.buffWe := '1'; -- Update buffer seqN and Type
1144  v.buffSent := '0';
1145  v.chkEn := '0';
1146  v.chkStb := '0';
1147 
1148  -- SSI master
1149  -- Leave initialised v.tspSsiMaster
1150  v.tspSsiMaster.data := r.tspSsiMaster.data;
1151 
1152  -- Next state condition
1153  v.tspState := DATA_H_S;
1154  ----------------------------------------------------------------------
1155  when DATA_H_S =>
1156  -- Counters
1157  v.nextSeqN := r.nextSeqN;
1158  v.seqN := r.nextSeqN;
1159 
1160  v.txSegmentAddr := (others => '0');
1161  v.txBufferAddr := r.nextSentAddr;
1162  --
1163  v.synH := '0';
1164  v.ackH := '0';
1165  v.rstH := '0';
1166  v.nullH := '0';
1167  v.dataH := '1'; -- Send data header
1168  v.dataD := '0';
1169  --
1170  v.txRdy := '0';
1171  v.buffWe := '0';
1172  v.buffSent := '0';
1173  v.chkEn := '1';
1174 
1175  -- if header data ready than
1176  -- strobe the checksum
1177  if (headerRdy_i = '1') then
1178  v.chkStb := '1';
1179  end if;
1180 
1181  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(rdHeaderData_i);
1182 
1183  -- Next state condition
1184  -- Frame size is one word
1185  -- Wait for the chksum to be ready
1186  if (chksumValid_i = '1' and tspSsiSlave_i.pause = '0') then
1187  v.tspSsiMaster.valid := '1';
1188  v.tspSsiMaster.sof := '1';
1189  v.tspSsiMaster.strb := (others => '1');
1190  v.tspSsiMaster.dest := (others => '0');
1191  v.tspSsiMaster.eof := '0';
1192  v.tspSsiMaster.eofe := '0';
1193 
1194  -- Inject fault into checksum
1195  if (r.injectFaultReg = '1') then
1196  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum) xor (s_headerAndChksum'range => '1'); -- Flip bits in checksum! Point of fault injection!
1197  else
1198  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum); -- Add checksum to last two bytes
1199  end if;
1200 
1201  -- Set the fault reg to 0
1202  v.injectFaultReg := '0';
1203 
1204  v.tspState := DATA_S;
1205  --
1206  end if;
1207  ----------------------------------------------------------------------
1208  when DATA_S =>
1209  -- Counters
1210  v.nextSeqN := r.nextSeqN;
1211  v.seqN := r.nextSeqN;
1212 
1213  v.txHeaderAddr := (others => '0');
1214  v.txBufferAddr := r.nextSentAddr;
1215  v.txSegmentAddr := r.txSegmentAddr;
1216 
1217  --
1218  v.synH := '0';
1219  v.ackH := '0';
1220  v.rstH := '0';
1221  v.nullH := '0';
1222  v.dataH := '0';
1223  v.dataD := '1'; -- Send data
1224  --
1225  v.txRdy := '0';
1226  v.buffWe := '0';
1227  v.buffSent := '0';
1228  v.chkEn := '0';
1229  v.chkStb := '0';
1230 
1231  -- Other SSI parameters
1232  v.tspSsiMaster.sof := '0';
1233  v.tspSsiMaster.strb := (others => '1');
1234  v.tspSsiMaster.dest := (others => '0');
1235  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := rdBuffData_i;
1236 
1237  -- Next state condition
1238  if (r.txSegmentAddr >= r.windowArray(conv_integer(r.txBufferAddr)).segSize) then
1239 
1240  -- Send EOF at the end of the segment
1241  v.tspSsiMaster.valid := '1';
1242  v.tspSsiMaster.eof := '1';
1243  v.tspSsiMaster.eofe := '0';
1244  v.tspSsiMaster.keep := r.windowArray(conv_integer(r.txBufferAddr)).keep;
1245  --
1246  v.txSegmentAddr := r.txSegmentAddr;
1247  --
1248  v.tspState := DATA_SENT_S;
1249 
1250  -- Increment segment address and assert valid only when not paused
1251  elsif (tspSsiSlave_i.pause = '0') then
1252  v.tspSsiMaster.valid := '1';
1253  v.txSegmentAddr := r.txSegmentAddr + 1;
1254  else
1255  v.tspSsiMaster.valid := '0';
1256  v.txSegmentAddr := r.txSegmentAddr;
1257  end if;
1258 
1259  -----------------------------------------------------------------------------
1260  when DATA_SENT_S =>
1261  -- Outputs
1262  v.nextSeqN := r.nextSeqN+1; -- Increment SEQ number at the end of segment transmission
1263  v.seqN := r.nextSeqN+1;
1264 
1265  v.txHeaderAddr := (others => '0');
1266  v.txSegmentAddr := (others => '0');
1267 
1268  v.txBufferAddr := r.nextSentAddr;
1269  --
1270  v.synH := '0';
1271  v.ackH := '0';
1272  v.rstH := '0';
1273  v.nullH := '0';
1274  v.dataH := '0';
1275  v.dataD := '0';
1276  v.chkEn := '0';
1277  v.chkStb := '0';
1278  --
1279  v.txRdy := '0';
1280  v.buffWe := '0';
1281  v.buffSent := '1'; -- Increment buffer last sent address(txBuffer)
1282 
1283  -- SSI master (Initialise - stop transmission)
1284  v.tspSsiMaster := SSI_MASTER_INIT_C;
1285 
1286  -- Next state
1287  v.tspState := CONN_S;
1288 
1289  ----------------------------------------------------------------------
1290  -- Resend all packets from the buffer
1291  -- Packets between r.firstUnackAddr and r.lastSentAddr
1292  ----------------------------------------------------------------------
1293  when RESEND_INIT_S =>
1294  -- Start from first unack address
1295  v.txBufferAddr := r.firstUnackAddr;
1296 
1297  -- Counters
1298  v.nextSeqN := r.nextSeqN; -- Never increment seqN while resending
1299  v.seqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
1300 
1301  v.txHeaderAddr := (others => '0');
1302  v.txSegmentAddr := (others => '0');
1303 
1304  -- State control signals
1305  v.synH := '0';
1306  v.ackH := '0';
1307  v.rstH := '0';
1308  v.nullH := '0';
1309  v.dataH := '0';
1310  v.dataD := '0';
1311  v.resend := '1';
1312  --
1313  v.txRdy := '0';
1314  v.buffWe := '0';
1315  v.buffSent := '0';
1316  v.chkEn := '0';
1317  v.chkStb := '0';
1318 
1319  -- SSI master
1320  v.tspSsiMaster := SSI_MASTER_INIT_C;
1321 
1322  -- Next state condition
1323  v.tspState := RESEND_H_S;
1324  ----------------------------------------------------------------------
1325  when RESEND_H_S =>
1326  -- Counters
1327  v.nextSeqN := r.nextSeqN; -- Never increment seqN while resending
1328  v.seqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
1329 
1330  v.txSegmentAddr := (others => '0');
1331  v.txBufferAddr := r.txBufferAddr;
1332  --
1333  v.synH := '0';
1334  v.ackH := '0';
1335  v.rstH := r.windowArray(conv_integer(r.txBufferAddr)).segType(2);
1336  v.nullH := r.windowArray(conv_integer(r.txBufferAddr)).segType(1);
1337  v.dataH := r.windowArray(conv_integer(r.txBufferAddr)).segType(0);
1338  v.dataD := '0';
1339  v.resend := '1';
1340  --
1341  v.txRdy := '0';
1342  v.buffWe := '0';
1343  v.buffSent := '0';
1344  v.chkEn := '1';
1345 
1346  -- if header data ready than
1347  -- strobe the checksum
1348  if (headerRdy_i = '1') then
1349  v.chkStb := '1';
1350  end if;
1351 
1352  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(rdHeaderData_i);
1353 
1354  -- Next state condition
1355  -- Frame size is one word
1356  -- Wait for chksumb ready
1357  if (chksumValid_i = '1' and tspSsiSlave_i.pause = '0') then
1358  v.tspSsiMaster.sof := '1';
1359  v.tspSsiMaster.valid := '1';
1360  v.tspSsiMaster.strb := (others => '1');
1361  v.tspSsiMaster.dest := (others => '0');
1362 
1363  -- Inject fault into checksum
1364  if (r.injectFaultReg = '1') then
1365  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum) xor (s_headerAndChksum'range => '1'); -- Flip bits in checksum! Point of fault injection!
1366  else
1367  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum); -- Add checksum to last two bytes
1368  end if;
1369 
1370  -- Set the fault reg to 0
1371  v.injectFaultReg := '0';
1372 
1373  -- Null or Rst packet
1374  if (r.windowArray(conv_integer(r.txBufferAddr)).segType(2) = '1' or
1375  r.windowArray(conv_integer(r.txBufferAddr)).segType(1) = '1'
1376  ) then
1377 
1378  -- Send EOF and start sending next packet
1379  v.tspSsiMaster.eof := '1';
1380  v.tspSsiMaster.eofe := '0';
1381  --
1382  v.tspState := RESEND_PP_S;
1383 
1384  -- If DATA packet start sending data
1385  else
1386  v.tspState := RESEND_DATA_S;
1387  end if;
1388  end if;
1389  ----------------------------------------------------------------------
1390  when RESEND_DATA_S =>
1391  -- Counters
1392  v.nextSeqN := r.nextSeqN; -- Never increment seqN while resending
1393  v.seqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
1394 
1395  v.txHeaderAddr := (others => '0');
1396  v.txBufferAddr := r.txBufferAddr;
1397  v.txSegmentAddr := r.txSegmentAddr;
1398 
1399  --
1400  v.synH := '0';
1401  v.ackH := '0';
1402  v.rstH := '0';
1403  v.nullH := '0';
1404  v.dataH := '0';
1405  v.dataD := '1'; -- Send data
1406  v.resend := '1';
1407 
1408  --
1409  v.txRdy := '0';
1410  v.buffWe := '0';
1411  v.buffSent := '0';
1412  v.chkEn := '0';
1413  v.chkStb := '0';
1414 
1415  -- SSI Control
1416 
1417  -- Other SSI parameters
1418  v.tspSsiMaster.sof := '0';
1419  v.tspSsiMaster.strb := (others => '1');
1420  v.tspSsiMaster.dest := (others => '0');
1421  v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := rdBuffData_i;
1422 
1423  -- Next state condition
1424  if (r.txSegmentAddr >= r.windowArray(conv_integer(r.txBufferAddr)).segSize) then
1425 
1426  -- Send EOF at the end of the segment
1427  v.tspSsiMaster.valid := '1';
1428  v.tspSsiMaster.eof := '1';
1429  v.tspSsiMaster.eofe := '0';
1430  v.tspSsiMaster.keep := r.windowArray(conv_integer(r.txBufferAddr)).keep;
1431  --
1432  v.txSegmentAddr := r.txSegmentAddr;
1433  --
1434  v.tspState := RESEND_PP_S;
1435 
1436  -- Increment segment address only when Slave is ready
1437  elsif (tspSsiSlave_i.pause = '0') then
1438  v.tspSsiMaster.valid := '1';
1439  v.txSegmentAddr := r.txSegmentAddr + 1;
1440  else
1441  v.tspSsiMaster.valid := '0';
1442  v.txSegmentAddr := r.txSegmentAddr;
1443  end if;
1444  ----------------------------------------------------------------------
1445  when RESEND_PP_S =>
1446  -- Counters
1447  v.nextSeqN := r.nextSeqN; -- Never increment seqN while resending
1448  v.seqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
1449 
1450  v.txHeaderAddr := (others => '0');
1451  v.txSegmentAddr := (others => '0');
1452 
1453  -- Increment buffer address (circulary)
1454  if r.txBufferAddr < (windowSize_i-1) then
1455  v.txBufferAddr := r.txBufferAddr+1;
1456  else
1457  v.txBufferAddr := (others => '0');
1458  end if;
1459 
1460  -- State control signals
1461  v.rstH := '0';
1462  v.nullH := '0';
1463  v.dataH := '0';
1464  v.nullH := '0';
1465  v.dataH := '0';
1466  v.dataD := '0';
1467  v.resend := '1';
1468 
1469  --
1470  v.txRdy := '0';
1471  v.buffWe := '0';
1472  v.buffSent := '0';
1473  v.chkEn := '0';
1474  v.chkStb := '0';
1475 
1476  -- SSI master
1477  v.tspSsiMaster := SSI_MASTER_INIT_C;
1478 
1479  -- Next state condition
1480  -- Go back to CONN_S when the last sent address reached
1481  if (r.txBufferAddr = r.lastSentAddr) then
1482  v.tspState := CONN_S;
1483  else
1484  v.tspState := RESEND_H_S;
1485  end if;
1486  ----------------------------------------------------------------------
1487  when others =>
1488  --
1489  v := REG_INIT_C;
1490  ----------------------------------------------------------------------
1491  end case;
1492 
1493  -- Synchronous Reset
1494  if (rst_i = '1') then
1495  v := REG_INIT_C;
1496  end if;
1497 
1498  rin <= v;
1499  -----------------------------------------------------------
1500  ---------------------------------------------------------------------
1501  -- APP side
1502 
1503  -- Combine ram write address
1504  wrBuffAddr_o <= r.rxBufferAddr & r.rxSegmentAddr(SEGMENT_ADDR_SIZE_G-1 downto 0);
1505  wrBuffData_o <= r.AppSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0);
1506  wrBuffWe_o <= r.rxSegmentWe;
1507 
1508  -- Slave out immediately
1509  appSsiSlave_o <= v.appSsiSlave;
1510 
1511  -- Errors
1512  ackErr_o <= r.ackErr;
1513  lenErr_o <= r.lenErr;
1514 
1515  --
1516  bufferEmpty_o <= r.bufferEmpty;
1517 
1518  -----------------------------------------------------------
1519  ---------------------------------------------------------------------
1520  -- TSP side
1521 
1522  -- Combine ram read address
1523  rdBuffAddr_o <= v.txBufferAddr & v.txSegmentAddr(SEGMENT_ADDR_SIZE_G-1 downto 0);
1524  rdHeaderAddr_o <= v.txHeaderAddr;
1525 
1526  -- State assignment
1527  synHeadSt_o <= r.synH;
1528  ackHeadSt_o <= r.ackH;
1529  dataHeadSt_o <= r.dataH;
1530  dataSt_o <= r.dataD;
1531  rstHeadSt_o <= r.rstH;
1532  nullHeadSt_o <= r.nullH;
1533 
1534  chksumEnable_o <= r.chkEn;
1535  chksumStrobe_o <= r.chkStb;
1536 
1537  -- Sequence number from buffer
1538  txSeqN_o <= r.seqN;
1539  tspSsiMaster_o <= r.tspSsiMaster;
1540 
1541  --
1542  lastAckN_o <= r.lastAckSeqN;
1543  ---------------------------------------------------------------------
1544  end process comb;
1545 
1546  seq : process (clk_i) is
1547  begin
1548  if (rising_edge(clk_i)) then
1549  r <= rin after TPD_G;
1550  end if;
1551  end process seq;
1552 
1553  ---------------------------------------------------------------------
1554 end architecture rtl;
out rstHeadSt_osl
Definition: TxFSM.vhd:126
in rst_isl
Definition: TxFSM.vhd:71
in chksum_islv( 15 downto 0)
Definition: TxFSM.vhd:113
in injectFault_isl
Definition: TxFSM.vhd:79
out tspSsiMaster_oSsiMasterType
Definition: TxFSM.vhd:144
AxiStreamConfigType :=ssiAxiStreamConfig(dataBytes => RSSI_WORD_WIDTH_C,tKeepMode => TKEEP_COMP_C,tUserMode => TUSER_FIRST_LAST_C,tDestBits => 0,tUserBits => 2) RSSI_AXIS_CONFIG_C
Definition: RssiPkg.vhd:33
sl occupied
Definition: RssiPkg.vhd:102
ACK_HEADER_SIZE_Gnatural := 8
Definition: TxFSM.vhd:61
in rdHeaderData_islv( RSSI_WORD_WIDTH_C* 8- 1 downto 0)
Definition: TxFSM.vhd:103
sl sof
Definition: SsiPkg.vhd:72
out wrBuffData_oslv( RSSI_WORD_WIDTH_C* 8- 1 downto 0)
Definition: TxFSM.vhd:95
std_logic sl
Definition: StdRtlPkg.vhd:28
AxiStreamMasterType :=(tValid => '0',tData =>( others => '0'),tStrb =>( others => '1'),tKeep =>( others => '1'),tLast => '0',tDest =>( others => '0'),tId =>( others => '0'),tUser =>( others => '0')) AXI_STREAM_MASTER_INIT_C
out rdHeaderAddr_oslv( 7 downto 0)
Definition: TxFSM.vhd:102
out dataHeadSt_osl
Definition: TxFSM.vhd:124
out dataSt_osl
Definition: TxFSM.vhd:125
out txSeqN_oslv( 7 downto 0)
Definition: TxFSM.vhd:119
out chksumEnable_osl
Definition: TxFSM.vhd:110
in ack_isl
Definition: TxFSM.vhd:133
slv( 15 downto 0) strb
Definition: SsiPkg.vhd:68
slv( 15 downto 0) keep
Definition: RssiPkg.vhd:100
in sndRst_isl
Definition: TxFSM.vhd:84
sl overflow
Definition: SsiPkg.vhd:80
in connActive_isl
Definition: TxFSM.vhd:74
positive := 8 RSSI_WORD_WIDTH_C
Definition: RssiPkg.vhd:32
slv( 7 downto 0) seqN
Definition: RssiPkg.vhd:98
out nullHeadSt_osl
Definition: TxFSM.vhd:127
Definition: TxFSM.vhd:53
in clk_isl
Definition: TxFSM.vhd:70
out ackErr_osl
Definition: TxFSM.vhd:148
sl data
Definition: RssiPkg.vhd:92
in headerRdy_isl
Definition: TxFSM.vhd:105
DATA_HEADER_SIZE_Gnatural := 8
Definition: TxFSM.vhd:65
WINDOW_ADDR_SIZE_Gpositive := 3
Definition: TxFSM.vhd:57
out synHeadSt_osl
Definition: TxFSM.vhd:122
out bufferEmpty_osl
Definition: TxFSM.vhd:152
out wrBuffWe_osl
Definition: TxFSM.vhd:93
in rdBuffData_islv( RSSI_WORD_WIDTH_C* 8- 1 downto 0)
Definition: TxFSM.vhd:99
SsiMasterType
Definition: SsiPkg.vhd:65
in sndAck_isl
Definition: TxFSM.vhd:83
RST_HEADER_SIZE_Gnatural := 8
Definition: TxFSM.vhd:63
in sndResend_isl
Definition: TxFSM.vhd:85
HEADER_CHKSUM_EN_Gboolean := true
Definition: TxFSM.vhd:68
out rdBuffAddr_oslv(( SEGMENT_ADDR_SIZE_G+ WINDOW_ADDR_SIZE_G)- 1 downto 0)
Definition: TxFSM.vhd:98
slv( 2 downto 0) segType
Definition: RssiPkg.vhd:99
SsiSlaveType
Definition: SsiPkg.vhd:77
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
SEGMENT_ADDR_SIZE_Gpositive := 7
Definition: TxFSM.vhd:58
AxiStreamCtrlType :=(pause => '1',overflow => '0',idle => '0') AXI_STREAM_CTRL_INIT_C
_library_ ieeeieee
Definition: RxFSM.vhd:43
sl eofe
Definition: RssiPkg.vhd:94
in appSsiMaster_iSsiMasterType
Definition: TxFSM.vhd:139
NULL_HEADER_SIZE_Gnatural := 8
Definition: TxFSM.vhd:64
TPD_Gtime := 1 ns
Definition: TxFSM.vhd:55
in sndSyn_isl
Definition: TxFSM.vhd:82
in windowSize_iinteger range 1 to 2**( WINDOW_ADDR_SIZE_G)
Definition: TxFSM.vhd:89
out appSsiSlave_oSsiSlaveType
Definition: TxFSM.vhd:140
in initSeqN_islv( 7 downto 0)
Definition: TxFSM.vhd:116
sl valid
Definition: SsiPkg.vhd:66
slv( SSI_TDEST_BITS_C- 1 downto 0) dest
Definition: SsiPkg.vhd:70
in closed_isl
Definition: TxFSM.vhd:76
out chksumStrobe_osl
Definition: TxFSM.vhd:111
in sndNull_isl
Definition: TxFSM.vhd:86
sl pause
Definition: SsiPkg.vhd:79
in chksumValid_isl
Definition: TxFSM.vhd:109
AxiStreamSlaveType :=(tReady => '1') AXI_STREAM_SLAVE_FORCE_C
EACK_HEADER_SIZE_Gnatural := 8
Definition: TxFSM.vhd:62
out lastAckN_oslv( 7 downto 0)
Definition: TxFSM.vhd:130
out lenErr_osl
Definition: TxFSM.vhd:147
SYN_HEADER_SIZE_Gnatural := 24
Definition: TxFSM.vhd:60
natural segSize
Definition: RssiPkg.vhd:101
in ackN_islv( 7 downto 0)
Definition: TxFSM.vhd:134
array(natural range <> ) of WindowType WindowTypeArray
Definition: RssiPkg.vhd:113
sl eof
Definition: SsiPkg.vhd:73
in headerLength_ipositive
Definition: TxFSM.vhd:106
in bufferSize_iinteger range 1 to 2**( SEGMENT_ADDR_SIZE_G)
Definition: TxFSM.vhd:90
in tspSsiSlave_iSsiSlaveType
Definition: TxFSM.vhd:143
WindowType :=(seqN =>( others => '0'),segType =>( others => '0'),keep =>( others => '1'),segSize => 0,occupied => '0') WINDOW_INIT_C
Definition: RssiPkg.vhd:105
out wrBuffAddr_oslv(( SEGMENT_ADDR_SIZE_G+ WINDOW_ADDR_SIZE_G)- 1 downto 0)
Definition: TxFSM.vhd:94
out ackHeadSt_osl
Definition: TxFSM.vhd:123
std_logic_vector slv
Definition: StdRtlPkg.vhd:29