SURF  1.0
RxFSM.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : RxFSM.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2015-06-11
5 -- Last update: 2016-06-23
6 -------------------------------------------------------------------------------
7 -- Description: Receiver FSM
8 -- Receiver has the following functionality:
9 -- Transport side FSM. Receive check and save segments to RX buffer.
10 -- - WAIT_SOF Waits for Transport side SOF,
11 -- - CHECK Determines the segment type and checks:
12 -- ACK, NULL, DATA, or RST segment
13 -- 1. Validates checksum (when valid),
14 -- 2. Header length (number of bytes),
15 -- 3. Sequence number (Only current seqN or lastSeqN+1 allowed)
16 -- 4. Acknowledgment number (Valid range is lastAckN to lastAckN + txWindowSize)
17 -- - CHECK_SYN Toggles through SYN header addresses and saves the RSSI parameters
18 -- Checks the following:
19 -- 1. Validates checksum (when valid),
20 -- 2. Validates Ack number if the ack is sent with the SYN segment
21 -- - DATA Receives the payload part of the DATA segment
22 -- - VALID Checks if next valid SEQn is received. If yes:
23 -- 1. increment the in order SEQn
24 -- 2. save seqN, type, and occupied to the window buffer at current rxBufferAddr
25 -- 3. increment rxBufferAddr
26 -- - DROP Just report dropped packet and got back to WAIT_SOF
27 -- Receiver side FSM. Send data to App side.
28 -- - CHECK_BUFFER and DATA Send the data frame to the Application
29 -- when the data at the next txSegmentAddr is ready.
30 -- - SENT Release the windowbuffer at txBufferAddr.
31 -- Increment txBufferAddr.
32 -- Register the received SeqN for acknowledgment.
33 -------------------------------------------------------------------------------
34 -- This file is part of 'SLAC Firmware Standard Library'.
35 -- It is subject to the license terms in the LICENSE.txt file found in the
36 -- top-level directory of this distribution and at:
37 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
38 -- No part of 'SLAC Firmware Standard Library', including this file,
39 -- may be copied, modified, propagated, or distributed except according to
40 -- the terms contained in the LICENSE.txt file.
41 -------------------------------------------------------------------------------
42 
43 library ieee;
44 use ieee.std_logic_1164.all;
45 use ieee.std_logic_unsigned.all;
46 use ieee.std_logic_arith.all;
47 
48 use work.StdRtlPkg.all;
49 use work.RssiPkg.all;
50 use work.SsiPkg.all;
51 use work.AxiStreamPkg.all;
52 
53 --! @see entity
54  --! @ingroup protocols_rssi
55 entity RxFSM is
56  generic (
57  TPD_G : time := 1 ns;
58  WINDOW_ADDR_SIZE_G : positive := 7; -- 2^WINDOW_ADDR_SIZE_G = Number of segments
59  HEADER_CHKSUM_EN_G : boolean := true;
60  SEGMENT_ADDR_SIZE_G : positive := 3 -- 2^SEGMENT_ADDR_SIZE_G = Number of 64 bit wide data words
61  );
62  port (
63  clk_i : in sl;
64  rst_i : in sl;
65 
66  -- Connection FSM indicating active connection
68 
69  -- Window size different for Rx and Tx
70  rxWindowSize_i : in integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G);
71  rxBufferSize_i : in integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_G);
72  txWindowSize_i : in integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G);
73 
74  -- Last acknowledged Sequence number connected to TX module
75  lastAckN_i : in slv(7 downto 0);
76 
77  -- Current received seqN
78  rxSeqN_o : out slv(7 downto 0);
79 
80  -- Current received ackN
81  rxAckN_o : out slv(7 downto 0);
82 
83  -- Last seqN received and sent to application (this is the ackN transmitted)
84  rxLastSeqN_o : out slv(7 downto 0);
85 
86  -- Valid Segment received (1 c-c)
88 
89  -- Segment dropped (1 c-c)
90  rxDropSeg_o : out sl;
91 
92  -- Last segment received flags (active until next segment is received)
94 
95  -- Parameters received from peer SYN packet
97 
98  -- Checksum control
103  chksumLength_o : out positive;
104 
105  -- Buffer write
106  wrBuffWe_o : out sl;
108  wrBuffData_o : out slv(RSSI_WORD_WIDTH_C*8-1 downto 0);
109 
110  -- Buffer read
112  rdBuffData_i : in slv(RSSI_WORD_WIDTH_C*8-1 downto 0);
113 
114  -- SSI Transport side interface IN
117 
118  -- SSI Application side interface OUT
121 
122  );
123 end entity RxFSM;
124 
125 architecture rtl of RxFSM is
126  -- Init SSI bus
127  constant SSI_MASTER_INIT_C : SsiMasterType := axis2SsiMaster(RSSI_AXIS_CONFIG_C, AXI_STREAM_MASTER_INIT_C);
128  constant SSI_SLAVE_NOTRDY_C : SsiSlaveType := axis2SsiSlave(RSSI_AXIS_CONFIG_C, AXI_STREAM_SLAVE_INIT_C, AXI_STREAM_CTRL_UNUSED_C);
129  constant SSI_SLAVE_RDY_C : SsiSlaveType := axis2SsiSlave(RSSI_AXIS_CONFIG_C, AXI_STREAM_SLAVE_FORCE_C, AXI_STREAM_CTRL_UNUSED_C);
130 
131  type tspStateType is (
132  --
133  WAIT_SOF_S,
134  CHECK_S,
135  SYN_CHECK_S,
136  VALID_S,
137  DROP_S,
138  DATA_S
139  );
140 
141  type AppStateType is (
142  --
143  CHECK_BUFFER_S,
144  DATA_S,
145  SENT_S
146  );
147 
148  type RegType is record
149 
150  -- Resception buffer window
151  windowArray : WindowTypeArray(0 to 2 ** WINDOW_ADDR_SIZE_G-1);
152 
153  -- Transport side FSM (Receive and check segments)
154  -----------------------------------------------------------
155 
156  -- Counters
157  inorderSeqN : slv(7 downto 0); -- Next expected seqN
158  rxHeaderAddr : slv(7 downto 0);
159  rxSegmentAddr : slv(SEGMENT_ADDR_SIZE_G downto 0);
160  rxBufferAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0);
161  --
162  segmentWe : sl;
163 
164  -- Packet flags
165  rxF : flagsType;
166 
167  -- Received RSSI parameters
168  rxParam : RssiParamType;
169 
170  rxHeadLen : slv(7 downto 0);
171  rxSeqN : slv(7 downto 0); -- Received seqN
172  rxAckN : slv(7 downto 0); -- Received ackN
173 
174  --
175  chkEn : sl;
176  chkStb : sl;
177  chkLen : positive;
178  --
179  segValid : sl;
180  segDrop : sl;
181  --
182  headerData : slv(RSSI_WORD_WIDTH_C*8-1 downto 0);
183 
184  -- SSI
185  tspSsiMaster : SsiMasterType;
186  tspSsiSlave : SsiSlaveType;
187 
188  -- State Machine
189  tspState : TspStateType;
190 
191  -- Application side FSM (Send segments when next in order received)
192  -----------------------------------------------------------
193  txSegmentAddr : slv(SEGMENT_ADDR_SIZE_G downto 0);
194  txBufferAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0);
195  rxLastSeqN : slv(7 downto 0);
196 
197  -- SSI
198  appSsiMaster : SsiMasterType;
199  appSsiSlave : SsiSlaveType;
200 
201  -- State Machine
202  appState : AppStateType;
203 
204  end record RegType;
205 
206  constant REG_INIT_C : RegType := (
207 
208  -- Rx buffer window
209  windowArray => (0 to 2 ** WINDOW_ADDR_SIZE_G-1 => WINDOW_INIT_C),
210 
211  -- Transport side FSM (Receive and check segments)
212  -----------------------------------------------------------
213  inorderSeqN => (others => '0'), -- Next expected seqN
214  rxHeaderAddr => (others => '0'),
215  rxSegmentAddr => (others => '0'),
216  rxBufferAddr => (others => '0'),
217 
218  --
219  segmentWe => '0',
220 
221  -- Packet flags
222  rxF => (others => ('0')),
223 
224  -- Received RSSI parameters
225  rxParam => RSSI_PARAM_INIT_C,
226 
227  rxHeadLen => (others => '0'), -- Received seqN
228  rxSeqN => (others => '0'), -- Received seqN
229  rxAckN => (others => '0'), -- Received ackN
230 
231  --
232  chkEn => '0',
233  chkStb => '0',
234  chkLen => 1,
235  --
236  segValid => '0',
237  segDrop => '0',
238  --
239  headerData => (others => '0'),
240 
241  -- SSI
242  tspSsiMaster => SSI_MASTER_INIT_C,
243  tspSsiSlave => SSI_SLAVE_NOTRDY_C,
244 
245  -- Transport side state
246  tspState => WAIT_SOF_S,
247 
248  -- Application side FSM (Send segments when received next in odrer received)
249  -----------------------------------------------------------
250  txBufferAddr => (others => '0'),
251  txSegmentAddr => (others => '0'),
252  rxLastSeqN => (others => '0'),
253 
254  -- SSI
255  appSsiMaster => SSI_MASTER_INIT_C,
256  appSsiSlave => SSI_SLAVE_NOTRDY_C,
257 
258  -- Application side state
259  appState => CHECK_BUFFER_S
260 
261  );
262 
263  signal r : RegType := REG_INIT_C;
264  signal rin : RegType;
265  signal s_chksumOk : sl;
266 
267 begin
268 
269  -- Override checksum check if checksum disabled
270  s_chksumOk <= ite(HEADER_CHKSUM_EN_G, chksumOk_i, '1');
271 
272  -----------------------------------------------------------------------------------------------
273  comb : process (r, rst_i, chksumValid_i, s_chksumOk, rxWindowSize_i, lastAckN_i, rxBufferSize_i,
275 
276  variable v : RegType;
277 
278  begin
279  v := r;
280 
281  ------------------------------------------------------------
282  -- RX Transport side FSM:
283  -- Receive the segment from the peer
284  -- Check the segment:
285  -- - register the parameters from SYN header
286  -- - seqN, ackN
287  -- - check header checksum
288  -- - increment in order received SeqN
289  ------------------------------------------------------------
290 
291  -- Pipeline the transport master
292  v.tspSsiMaster := tspSsiMaster_i;
293  v.headerData := endianSwap64(tspSsiMaster_i.data(63 downto 0));
294  case r.tspState is
295  ----------------------------------------------------------------------
296  when WAIT_SOF_S =>
297 
298  -- Counters to 0
299  v.rxHeaderAddr := (others => '0');
300  v.rxSegmentAddr := (others => '1'); -- "-1" so the first address after increment to be 0
301  v.segmentWe := '0';
302 
303  -- Ready until SOF received
304  -- Also flush any dropped or non SOF segments
305  v.tspSsiSlave := SSI_SLAVE_RDY_C;
306 
307  -- Checksum commands
308  v.chkEn := '0';
309  v.chkStb := '0';
310  v.chkLen := 1;
311  --
312  v.segValid := '0';
313  v.segDrop := '0';
314 
315  -- Next state condition
316  if (tspSsiMaster_i.sof = '1' and tspSsiMaster_i.valid = '1') then
317  v.chkEn := '1';
318  v.chkStb := '1';
319 
320  -- When SOF has been received dessert ready until package is checked
321  v.tspSsiSlave := SSI_SLAVE_RDY_C;
322 
323  -- If the packet is longer than one set the data flag
324  if (tspSsiMaster_i.eof = '1') then
325  v.rxF.data := '0';
326  else
327  v.rxF.data := '1';
328  end if;
329  --
330  v.tspState := CHECK_S;
331  --
332  end if;
333  ----------------------------------------------------------------------
334  when CHECK_S =>
335  --
336  v.segValid := '0';
337  v.segDrop := '0';
338  v.rxSegmentAddr := (others => '1');
339 
340  -- Hold incoming AXI stream
341  v.tspSsiSlave := SSI_SLAVE_NOTRDY_C;
342 
343  if (r.tspSsiMaster.valid = '1' and r.tspSsiMaster.sof = '1') then
344  -- Register flags, header length and SEQn
345  v.rxF.syn := r.headerData (63);
346  v.rxF.ack := r.headerData (62);
347  v.rxF.eack := r.headerData (61);
348  v.rxF.rst := r.headerData (60);
349  v.rxF.nul := r.headerData (59);
350  v.rxF.busy := r.headerData (56);
351 
352  v.rxHeadLen := r.headerData (55 downto 48);
353  v.rxSeqN := r.headerData (47 downto 40);
354  v.rxAckN := r.headerData (39 downto 32);
355  end if;
356 
357  -- Checksum commands
358  v.chkEn := '1';
359  v.chkStb := '0';
360 
361  -- Syn header received (header is 3 c-c long)
362  if (v.rxF.syn = '1') then
363 
364  -- Register SYN header word 0 parameters
365  v.chkLen := 3; -- TODO make generic
366  v.rxParam.version := r.headerData (31 downto 28);
367  v.rxParam.chksumEn := r.headerData (26 downto 26);
368  v.rxParam.maxOutsSeg := r.headerData (23 downto 16);
369  v.rxParam.maxSegSize := r.headerData (15 downto 0);
370 
371  --
372  if (v.rxF.ack = '1' and v.rxAckN /= lastAckN_i) then
373  -- Acknowledgment not valid
374  v.tspState := DROP_S;
375  elsif (v.rxF.eack = '1' or v.rxF.rst = '1' or v.rxF.busy = '1') then
376  -- Wrong flags
377  v.tspState := DROP_S;
378  else
379  -- Go to SYN_CHECK_S
380  v.tspState := SYN_CHECK_S;
381  end if;
382 
383  -- Segment is ACK, DATA, RST, or NULL
384  elsif (v.rxF.syn = '0' and v.rxF.eack = '0' and chksumValid_i = '1') then --
385 
386  -- Check header
387  if (
388  -- Checksum
389  s_chksumOk = '1' and
390  -- Check length
391  r.rxHeadLen = toSlv(8, 8) and
392  -- Check SeqN range
393  (r.rxSeqN - r.inOrderSeqN) <= 1 and
394  -- Check AckN range
395  (r.rxAckN - lastAckN_i) <= txWindowSize_i
396  ) then
397  -- Valid data segment
398  if (r.rxF.data = '1' and v.rxF.nul = '0' and v.rxF.rst = '0') then
399  -- Wait if the buffer full
400  -- Note: Deadlock possibility! If the peer is not accepting data!
401  if (r.windowArray(conv_integer(r.rxBufferAddr)).occupied = '0') then
402  -- Go to data segment
403  v.tspState := DATA_S;
404  else
405  -- Buffer is full -> drop segment
406  v.tspState := DROP_S;
407  end if;
408  elsif (r.rxF.data = '0') then
409  -- Valid non data segment
410  v.tspState := VALID_S;
411  else
412  -- Error: Data is attached to NUL or RST segment
413  v.tspState := DROP_S;
414  end if;
415  else
416  -- Header not valid
417  v.tspState := DROP_S;
418  end if;
419  end if;
420 
421  ----------------------------------------------------------------------
422  when SYN_CHECK_S =>
423  --
424  v.segValid := '0';
425  v.segDrop := '0';
426  v.rxSegmentAddr := (others => '1');
427 
428  -- Ready to receive further header data
429  v.tspSsiSlave := SSI_SLAVE_RDY_C;
430 
431  -- Get the rest of the SYN header
432  if (tspSsiMaster_i.valid = '1') then
433  v.chkStb := '1';
434  v.rxHeaderAddr := r.rxHeaderAddr + 1;
435  else
436  v.chkStb := '0';
437  v.rxHeaderAddr := r.rxHeaderAddr;
438  end if;
439 
440  -- Register SYN header word 1 parameters
441  if (r.rxHeaderAddr = x"01" and r.tspSsiMaster.valid = '1') then
442  -- Syn parameters
443  v.rxParam.retransTout := r.headerData (63 downto 48);
444  v.rxParam.cumulAckTout:= r.headerData (47 downto 32);
445  v.rxParam.nullSegTout := r.headerData (31 downto 16);
446  v.rxParam.maxRetrans := r.headerData (15 downto 8);
447  v.rxParam.maxCumAck := r.headerData ( 7 downto 0);
448  --
449  end if;
450 
451  -- Register SYN header word 2 parameters
452  if (r.rxHeaderAddr = x"02" ) then
453  v.chkStb := '0';
454  v.rxHeaderAddr := r.rxHeaderAddr;
455  v.tspSsiSlave := r.tspSsiSlave;
456 
457  if (r.tspSsiMaster.valid = '1') then
458 
459  -- Syn parameters
460  v.rxParam.maxOutofseq := r.headerData (63 downto 56);
461  v.rxParam.timeoutUnit := r.headerData (55 downto 48);
462  v.rxParam.connectionId(31 downto 0):= r.headerData (47 downto 16);
463 
464  -- Tsp parameters
465  v.tspSsiSlave := SSI_SLAVE_NOTRDY_C;
466  end if;
467 
468  -- Wait for checksum
469  if ( chksumValid_i = '1') then
470  -- Check received data header
471 
472  if (
473  -- Checksum
474  s_chksumOk = '1' and
475  -- Check length
476  r.rxHeadLen = toSlv(24, 8)
477  ) then
478  -- Header is valid
479  v.tspState := VALID_S;
480  else
481  -- Header not valid
482  v.tspState := DROP_S;
483  end if;
484  end if;
485  end if;
486  ----------------------------------------------------------------------
487  when DATA_S =>
488  --
489  v.segValid := '0';
490  v.segDrop := '0';
491  --
492  v.chkEn := '0';
493  v.chkStb := '0';
494 
495  -- Ready to receive further header data
496  v.tspSsiSlave := SSI_SLAVE_RDY_C;
497 
498  -- Write enable and segment address
499  if (tspSsiMaster_i.valid = '1') then
500  v.rxSegmentAddr := r.rxSegmentAddr + 1;
501  v.segmentWe := '1';
502  else
503  v.rxSegmentAddr := r.rxSegmentAddr;
504  v.segmentWe := '0';
505  end if;
506 
507  -- Wait until receiving EOF
508  if (tspSsiMaster_i.eof = '1' and tspSsiMaster_i.valid = '1') then
509 
510  -- Save tKeep of the last packet
511  v.windowArray(conv_integer(r.rxBufferAddr)).keep := tspSsiMaster_i.keep;
512 
513  -- Save packet length (+1 because it has not incremented for EOF yet)
514  v.windowArray(conv_integer(r.rxBufferAddr)).segSize := conv_integer(r.rxSegmentAddr(SEGMENT_ADDR_SIZE_G-1 downto 0))+1;
515 
516  -- Check EOF Error
517  if (tspSsiMaster_i.eofe = '0') then
518  v.tspState := VALID_S;
519  else
520  v.tspState := DROP_S;
521  end if;
522  elsif (r.tspSsiSlave.ready = '1' and r.rxSegmentAddr > rxBufferSize_i ) then
523  v.tspState := DROP_S;
524  elsif (r.tspSsiSlave.ready = '1' and r.rxSegmentAddr(SEGMENT_ADDR_SIZE_G) = '1' ) then
525  v.tspState := DROP_S;
526  end if;
527  ----------------------------------------------------------------------
528  when VALID_S =>
529  --
530  v.segValid := '1';
531  v.segDrop := '0';
532  --
533  v.chkEn := '0';
534  v.chkStb := '0';
535  v.segmentWe:= '0';
536  --
537  v.tspSsiSlave := SSI_SLAVE_NOTRDY_C;
538 
539  -- Initialize when valid SYN segment received
540  -- 1. Set the initial SeqN
541  -- 2. Initialize the buffer address
542  -- 3. Initialize window
543  if (connActive_i = '0' and r.rxF.syn = '1') then
544  v.rxF.ack := r.rxF.ack;
545  v.inOrderSeqN := r.rxSeqN;
546  v.rxBufferAddr := (others => '0');
547  v.windowArray := REG_INIT_C.windowArray;
548 
549  -- Check if next valid SEQn is received. If yes:
550  -- 1. increment the in order SEQn
551  -- 2. save seqN, type, and occupied to the current buffer address
552  -- 3. increase buffer
553  elsif ( (r.rxF.data = '1' or r.rxF.nul = '1' or r.rxF.rst = '1' ) and
554  -- Next seqN absolute difference is one
555  r.rxSeqN - r.inOrderSeqN = 1
556  ) then
557  --
558  v.windowArray(conv_integer(r.rxBufferAddr)).seqN := r.rxSeqN;
559  v.windowArray(conv_integer(r.rxBufferAddr)).segType(0) := r.rxF.data;
560  v.windowArray(conv_integer(r.rxBufferAddr)).segType(1) := r.rxF.nul;
561  v.windowArray(conv_integer(r.rxBufferAddr)).segType(2) := r.rxF.rst;
562  v.windowArray(conv_integer(r.rxBufferAddr)).occupied := '1';
563  --
564  v.inOrderSeqN := r.rxSeqN;
565  --
566  if r.rxBufferAddr < (rxWindowSize_i-1) then
567  v.rxBufferAddr := r.rxBufferAddr +1;
568  else
569  v.rxBufferAddr := (others => '0');
570  end if;
571  --
572  else
573  v.rxBufferAddr := r.rxBufferAddr;
574  v.inOrderSeqN := r.inOrderSeqN;
575  end if;
576 
577  -- Get ready to receive new packet
578  v.tspState := WAIT_SOF_S;
579 
580  ----------------------------------------------------------------------
581  when DROP_S =>
582  --
583  v.segValid := '0';
584  v.segDrop := '1';
585  --
586  v.chkEn := '0';
587  v.chkStb := '0';
588  v.segmentWe:= '0';
589  --
590  v.tspSsiSlave := SSI_SLAVE_NOTRDY_C;
591 
592  -- Get ready to receive new packet
593  v.tspState := WAIT_SOF_S;
594 
595  ----------------------------------------------------------------------
596  when others =>
597  --
598  v := REG_INIT_C;
599 
600  ----------------------------------------------------------------------
601  end case;
602 
603  ------------------------------------------------------------
604  -- TX Application side FSM:
605  -- Transmit the segments in correct order
606  -- Check the buffer if the next slot is available and send the buffer to APP
607  ------------------------------------------------------------
608 
609  -- Reset flags
610  -- These flags will hold if not overridden
611  v.appSsiMaster:= SSI_MASTER_INIT_C;
612 
613  -- Pipeline incomming slave
614  v.appSsiSlave:= appSsiSlave_i;
615 
616  case r.appState is
617  ----------------------------------------------------------------------
618  when CHECK_BUFFER_S =>
619 
620  -- Counters to 0
621  v.txSegmentAddr := (others => '0');
622  v.rxLastSeqN := r.rxLastSeqN;
623 
624  --
625  if connActive_i = '0' then
626  v.txBufferAddr := (others => '0');
627  v.rxLastSeqN := r.inOrderSeqN;
628  -- Data segment in buffer only one word long take TKEEP and apply EOF
629  elsif (r.windowArray(conv_integer(r.txBufferAddr)).occupied = '1' and
630  r.windowArray(conv_integer(r.txBufferAddr)).segType = "001" and -- Data segment type
631  r.windowArray(conv_integer(r.txBufferAddr)).segSize = 0
632  ) then
633  --
634  v.txBufferAddr := r.txBufferAddr;
635 
636  if (appSsiSlave_i.pause = '0') then
637 
638  v.appSsiMaster.sof := '1';
639  v.appSsiMaster.valid := '1';
640  v.appSsiMaster.strb := (others => '1');
641  v.appSsiMaster.dest := (others => '0');
642  v.appSsiMaster.keep := r.windowArray(conv_integer(r.txBufferAddr)).keep;
643  v.appSsiMaster.eof := '1';
644  v.appSsiMaster.eofe := '0';
645  v.appSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := rdBuffData_i;
646  v.txSegmentAddr := r.txSegmentAddr;
647 
648  v.appState := SENT_S;
649  end if;
650  -- Data segment in buffer longer than one word go to DATA_S
651  elsif (r.windowArray(conv_integer(r.txBufferAddr)).occupied = '1' and
652  r.windowArray(conv_integer(r.txBufferAddr)).segType = "001" -- Data segment type
653  ) then
654  --
655  v.txBufferAddr := r.txBufferAddr;
656 
657  if (appSsiSlave_i.pause = '0') then
658 
659  v.appSsiMaster.sof := '1';
660  v.appSsiMaster.valid := '1';
661  v.appSsiMaster.strb := (others => '1');
662  v.appSsiMaster.dest := (others => '0');
663  v.appSsiMaster.eof := '0';
664  v.appSsiMaster.eofe := '0';
665  v.appSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := rdBuffData_i;
666  v.txSegmentAddr := r.txSegmentAddr + 1;
667 
668  v.appState := DATA_S;
669  end if;
670  -- None data segment type (Go directly to SENT_S)
671  elsif (r.windowArray(conv_integer(r.txBufferAddr)).occupied = '1') then
672  --
673  v.txBufferAddr := r.txBufferAddr;
674  v.appState := SENT_S;
675  --
676  else
677  --
678  v.txBufferAddr := r.txBufferAddr;
679  v.appSsiMaster.valid := '0';
680  v.appState := CHECK_BUFFER_S;
681  end if;
682  ----------------------------------------------------------------------
683  when DATA_S =>
684 
685  -- Counters
686  v.txBufferAddr := r.txBufferAddr;
687  v.rxLastSeqN := r.rxLastSeqN;
688 
689  -- SSI parameters
690  v.appSsiMaster.sof := '0';
691  v.appSsiMaster.strb := (others => '1');
692  v.appSsiMaster.dest := (others => '0');
693  v.appSsiMaster.eof := '0';
694  v.appSsiMaster.eofe := '0';
695  v.appSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := rdBuffData_i;
696 
697  -- Next state condition
698  -- When segment address reaches segment size then go to SENT_S
699  if (r.txSegmentAddr >= r.windowArray(conv_integer(r.txBufferAddr)).segSize) then
700 
701  -- Send EOF at the end of the segment
702  v.appSsiMaster.valid := '1';
703  v.appSsiMaster.eof := '1';
704  v.appSsiMaster.keep := r.windowArray(conv_integer(r.txBufferAddr)).keep;
705  v.appSsiMaster.eofe := '0';
706  v.txSegmentAddr := r.txSegmentAddr;
707 
708  v.appState := SENT_S;
709 
710  -- Increment segment address only when not pausing
711  elsif (appSsiSlave_i.pause = '0') then
712  v.appSsiMaster.valid := '1';
713  v.txSegmentAddr := r.txSegmentAddr + 1;
714  elsif (connActive_i = '0') then
715  v.appSsiMaster.valid := '0';
716  v.appSsiMaster.eof := '1';
717  v.appState := CHECK_BUFFER_S;
718  else
719  v.appSsiMaster.valid := '0';
720  v.txSegmentAddr := r.txSegmentAddr;
721  end if;
722  ----------------------------------------------------------------------
723  when SENT_S =>
724 
725  -- Register the sent SeqN (this means that the place has been freed and the SeqN can be Acked)
726  v.rxLastSeqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
727 
728  -- Counters
729  if r.txBufferAddr < (rxWindowSize_i-1) then
730  v.txBufferAddr := r.txBufferAddr+1; -- Increment once
731  else
732  v.txBufferAddr := (others => '0');
733  end if;
734 
735  v.windowArray(conv_integer(r.txBufferAddr)).occupied := '0'; -- Release buffer
736 
737  v.txSegmentAddr := (others => '0');
738 
739 
740  -- SSI parameters
741  -- Init the master no SSI communication
742  v.appSsiMaster := SSI_MASTER_INIT_C;
743 
744  -- Next state immediately
745  v.appState := CHECK_BUFFER_S;
746 
747  ----------------------------------------------------------------------
748  when others =>
749  --
750  v := REG_INIT_C;
751 
752  ----------------------------------------------------------------------
753  end case;
754 
755  -- Synchronous Reset
756  if (rst_i = '1') then
757  v := REG_INIT_C;
758  end if;
759 
760  rin <= v;
761 
762  ---------------------------------------------------------------------
763  -- Write and read ports
764  wrBuffAddr_o <= r.rxBufferAddr & r.rxSegmentAddr(SEGMENT_ADDR_SIZE_G-1 downto 0);
765  wrBuffWe_o <= r.segmentWe;
766  wrBuffData_o <= r.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0);
767  rdBuffAddr_o <= v.txBufferAddr & v.txSegmentAddr(SEGMENT_ADDR_SIZE_G-1 downto 0);
768 
769  -- Assign outputs
770  rxFlags_o <= r.rxF;
771  rxSeqN_o <= r.rxSeqN;
772  rxLastSeqN_o <= r.rxLastSeqN;
773  rxAckN_o <= r.rxAckN;
774  rxValidSeg_o <= r.segValid;
775  rxDropSeg_o <= r.segDrop;
776  chksumEnable_o <= r.chkEn;
777  chksumStrobe_o <= r.chkStb;
778  chksumLength_o <= r.chkLen;
779  rxParam_o <= r.rxParam;
780 
781  -- Transport side SSI output
782  tspSsiSlave_o <= v.tspSsiSlave;
783 
784  -- Application side SSI output
785  appSsiMaster_o <= r.appSsiMaster;
786  -----------------------------------------------------------
787  end process comb;
788 
789  seq : process (clk_i) is
790  begin
791  if (rising_edge(clk_i)) then
792  r <= rin after TPD_G;
793  end if;
794  end process seq;
795  ---------------------------------------------------------------------
796 end architecture rtl;
in rst_isl
Definition: RxFSM.vhd:64
out appSsiMaster_oSsiMasterType
Definition: RxFSM.vhd:119
out rxFlags_oflagsType
Definition: RxFSM.vhd:93
out rxDropSeg_osl
Definition: RxFSM.vhd:90
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 nul
Definition: RssiPkg.vhd:91
sl occupied
Definition: RssiPkg.vhd:102
in appSsiSlave_iSsiSlaveType
Definition: RxFSM.vhd:122
sl sof
Definition: SsiPkg.vhd:72
out wrBuffData_oslv( RSSI_WORD_WIDTH_C* 8- 1 downto 0)
Definition: RxFSM.vhd:108
std_logic sl
Definition: StdRtlPkg.vhd:28
out rxSeqN_oslv( 7 downto 0)
Definition: RxFSM.vhd:78
slv( 3 downto 0) version
Definition: RssiPkg.vhd:53
in lastAckN_islv( 7 downto 0)
Definition: RxFSM.vhd:75
out chksumLength_opositive
Definition: RxFSM.vhd:103
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
slv( 31 downto 0) connectionId
Definition: RssiPkg.vhd:69
out chksumEnable_osl
Definition: RxFSM.vhd:101
in txWindowSize_iinteger range 1 to 2**( WINDOW_ADDR_SIZE_G)
Definition: RxFSM.vhd:72
slv( 15 downto 0) strb
Definition: SsiPkg.vhd:68
WINDOW_ADDR_SIZE_Gpositive := 7
Definition: RxFSM.vhd:58
slv( 15 downto 0) keep
Definition: RssiPkg.vhd:100
slv( 15 downto 0) nullSegTout
Definition: RssiPkg.vhd:62
sl rst
Definition: RssiPkg.vhd:90
in connActive_isl
Definition: RxFSM.vhd:67
positive := 8 RSSI_WORD_WIDTH_C
Definition: RssiPkg.vhd:32
slv( 7 downto 0) seqN
Definition: RssiPkg.vhd:98
sl syn
Definition: RssiPkg.vhd:87
RssiParamType :=(version =>( others => '0'),chksumEn =>( others => '0'),timeoutUnit =>( others => '0'),maxOutsSeg =>( others => '0'),maxSegSize =>( others => '0'),retransTout =>( others => '0'),cumulAckTout =>( others => '0'),nullSegTout =>( others => '0'),maxRetrans =>( others => '0'),maxCumAck =>( others => '0'),maxOutofseq =>( others => '0'),connectionId =>( others => '0')) RSSI_PARAM_INIT_C
Definition: RssiPkg.vhd:72
in rxWindowSize_iinteger range 1 to 2**( WINDOW_ADDR_SIZE_G)
Definition: RxFSM.vhd:70
out rxValidSeg_osl
Definition: RxFSM.vhd:87
in clk_isl
Definition: RxFSM.vhd:63
slv( 7 downto 0) maxRetrans
Definition: RssiPkg.vhd:64
sl data
Definition: RssiPkg.vhd:92
out rxLastSeqN_oslv( 7 downto 0)
Definition: RxFSM.vhd:84
flagsType
Definition: RssiPkg.vhd:86
slv( 7 downto 0) maxOutofseq
Definition: RssiPkg.vhd:67
out wrBuffWe_osl
Definition: RxFSM.vhd:106
in rdBuffData_islv( RSSI_WORD_WIDTH_C* 8- 1 downto 0)
Definition: RxFSM.vhd:112
SsiMasterType
Definition: SsiPkg.vhd:65
slv( 15 downto 0) retransTout
Definition: RssiPkg.vhd:60
slv( 7 downto 0) maxCumAck
Definition: RssiPkg.vhd:65
HEADER_CHKSUM_EN_Gboolean := true
Definition: RxFSM.vhd:59
slv( 2 downto 0) segType
Definition: RssiPkg.vhd:99
out rdBuffAddr_oslv(( SEGMENT_ADDR_SIZE_G+ WINDOW_ADDR_SIZE_G)- 1 downto 0)
Definition: RxFSM.vhd:111
SsiSlaveType
Definition: SsiPkg.vhd:77
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
Definition: RxFSM.vhd:55
sl eofe
Definition: RssiPkg.vhd:94
out tspSsiSlave_oSsiSlaveType
Definition: RxFSM.vhd:116
slv( 15 downto 0) cumulAckTout
Definition: RssiPkg.vhd:61
slv( 7 downto 0) maxOutsSeg
Definition: RssiPkg.vhd:57
sl ack
Definition: RssiPkg.vhd:88
SEGMENT_ADDR_SIZE_Gpositive := 3
Definition: RxFSM.vhd:61
in tspSsiMaster_iSsiMasterType
Definition: RxFSM.vhd:115
TPD_Gtime := 1 ns
Definition: RxFSM.vhd:57
sl eack
Definition: RssiPkg.vhd:89
slv( 15 downto 0) maxSegSize
Definition: RssiPkg.vhd:58
sl valid
Definition: SsiPkg.vhd:66
slv( SSI_TDEST_BITS_C- 1 downto 0) dest
Definition: SsiPkg.vhd:70
in rxBufferSize_iinteger range 1 to 2**( SEGMENT_ADDR_SIZE_G)
Definition: RxFSM.vhd:71
AxiStreamCtrlType :=(pause => '0',overflow => '0',idle => '1') AXI_STREAM_CTRL_UNUSED_C
sl ready
Definition: SsiPkg.vhd:78
out chksumStrobe_osl
Definition: RxFSM.vhd:102
RssiParamType
Definition: RssiPkg.vhd:52
sl pause
Definition: SsiPkg.vhd:79
in chksumValid_isl
Definition: RxFSM.vhd:99
slv( 0 downto 0) chksumEn
Definition: RssiPkg.vhd:54
AxiStreamSlaveType :=(tReady => '1') AXI_STREAM_SLAVE_FORCE_C
natural segSize
Definition: RssiPkg.vhd:101
array(natural range <> ) of WindowType WindowTypeArray
Definition: RssiPkg.vhd:113
out rxParam_oRssiParamType
Definition: RxFSM.vhd:96
out rxAckN_oslv( 7 downto 0)
Definition: RxFSM.vhd:81
sl eof
Definition: SsiPkg.vhd:73
in chksumOk_isl
Definition: RxFSM.vhd:100
sl busy
Definition: RssiPkg.vhd:93
_library_ ieeeieee
Definition: RssiPkg.vhd:18
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: RxFSM.vhd:107
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
slv( 7 downto 0) timeoutUnit
Definition: RssiPkg.vhd:55