1 ------------------------------------------------------------------------------- 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. 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 ------------------------------------------------------------------------------- 42 use ieee.std_logic_1164.
all;
43 use ieee.std_logic_unsigned.
all;
44 use ieee.std_logic_arith.
all;
52 --! @ingroup protocols_rssi 73 -- Connection FSM indicating active connection 75 -- Closed state in connFSM (initialize seqN) 78 -- Fault injection corrupts header checksum 81 -- Various segment requests 88 -- Window buff size (Depends on the number of outstanding segments) 115 -- Initial sequence number 118 -- Tx data (input to header decoder module) 121 -- FSM outs for header and data flow control 129 -- Last acked number (Used in Rx FSM to determine if AcnN is valid) 132 -- Acknowledge mechanism 133 ack_i : in sl;
-- From receiver module when a segment with valid ACK is received 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 138 -- SSI Application side interface IN 142 -- SSI Transport side interface OUT 146 -- Errors (1 cc pulse) 150 -- Segment buffer indicator 155 architecture rtl
of TxFSM is
162 type TspStateType is ( 186 type AppStateType is ( 194 type AckStateType is ( 201 type RegType is record 203 -- Buffer window handling and acknowledgment control 204 ----------------------------------------- 210 lastAckSeqN : slv(7 downto 0);
211 --eackAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); 212 --eackIndex : integer; 218 ackState : AckStateType;
220 -- Application side FSM 221 ----------------------------------------- 232 appState : AppStateType;
234 -- Transport side FSM 235 ----------------------------------------- 238 nextSeqN : slv(7 downto 0);
240 txHeaderAddr : slv(7 downto 0);
269 tspState : tspStateType;
272 constant REG_INIT_C : RegType := ( 274 -- Buffer window handling and acknowledgment control 275 ----------------------------------------- 277 firstUnackAddr => (others => '0'), 278 lastSentAddr => (others => '0'), 279 nextSentAddr => (others => '0'), 281 lastAckSeqN => (others => '0'), 282 --eackAddr => (others => '0'), 291 -- Application side FSM 292 ----------------------------------------- 293 rxSegmentAddr => (others => '0'), 295 rxBufferAddr => (others => '0'), 300 appSsiMaster => SSI_MASTER_INIT_C, 301 appSsiSlave => SSI_SLAVE_NOTRDY_C, 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'), 330 injectFaultD1 => '0', 331 injectFaultReg => '0', 334 tspSsiMaster => SSI_MASTER_INIT_C, 335 tspSsiSlave => SSI_SLAVE_NOTRDY_C, 341 signal r : RegType := REG_INIT_C;
342 signal rin : RegType;
347 -- Send all 0 if checksum disabled 349 s_headerAndChksum <= rdHeaderData_i(63 downto 16) & s_chksum(15 downto 0);
351 ----------------------------------------------------------------------------------------------- 352 comb :
process (r,
rst_i,
appSsiMaster_i,
sndSyn_i,
sndAck_i,
connActive_i,
closed_i,
sndRst_i,
initSeqN_i,
windowSize_i,
headerRdy_i,
ack_i,
ackN_i,
bufferSize_i,
355 variable v : RegType;
360 -- ///////////////////////////////////////////////////////// 361 ------------------------------------------------------------ 362 -- Buffer window handling 363 ------------------------------------------------------------ 364 -- ///////////////////////////////////////////////////////// 366 ------------------------------------------------------------ 367 -- Buffer full if next slot is occupied 368 if ( r.windowArray(conv_integer(v.rxBufferAddr)).occupied = '1') then 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';
379 v.bufferEmpty := '0';
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';
390 -- Update last sent address when new segment is being sent 391 v.lastSentAddr := r.nextSentAddr;
393 v.windowArray := r.windowArray;
396 ------------------------------------------------------------ 397 -- When buffer is sent increase nextSentAddr 398 ------------------------------------------------------------ 399 if (r.buffSent = '1') then 402 v.nextSentAddr := r.nextSentAddr +1;
404 v.nextSentAddr := (others => '0');
408 v.nextSentAddr := r.nextSentAddr;
411 -- ///////////////////////////////////////////////////////// 412 ------------------------------------------------------------ 414 -- Acknowledgment mechanism to increment firstUnackAddr 415 -- Place out of order flags from EACK table (Not in Version 1) 416 ------------------------------------------------------------ 417 -- ///////////////////////////////////////////////////////// 420 ---------------------------------------------------------------------- 424 v.firstUnackAddr := r.firstUnackAddr;
425 v.lastAckSeqN := r.lastAckSeqN;
426 --v.eackAddr := r.firstUnackAddr; 430 -- Next state condition 431 if (ack_i = '1') then 434 ---------------------------------------------------------------------- 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 442 v.windowArray(conv_integer(r.firstUnackAddr)).occupied := '0';
443 v.firstUnackAddr := r.firstUnackAddr+1;
445 v.windowArray(conv_integer(r.firstUnackAddr)).occupied := '0';
446 v.firstUnackAddr := (others => '0');
449 --v.eackAddr := r.firstUnackAddr; 453 -- Next state condition 455 -- If the same ackN received 456 if (r.lastAckSeqN = ackN_i) then 459 v.ackState := IDLE_S;
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 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; 470 -- Go back to init when the acked seqN is found 471 v.ackState := IDLE_S;
474 ---------------------------------------------------------------------- 477 -- -- Increment EACK address from firstUnackAddr to nextSentAddr 478 -- if r.eackAddr < (windowSize_i-1) then 479 -- v.eackAddr := r.eackAddr+1; 481 -- v.eackAddr := (others => '0'); 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; 491 -- v.firstUnackAddr := r.firstUnackAddr; 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; 499 ---------------------------------------------------------------------- 502 v.firstUnackAddr := r.firstUnackAddr;
503 --v.eackAddr := r.firstUnackAddr; 507 -- Next state condition 508 v.ackState := IDLE_S;
509 ---------------------------------------------------------------------- 512 v.firstUnackAddr := r.firstUnackAddr;
513 -- v.eackAddr := r.firstUnackAddr; 517 -- Next state condition 518 v.ackState := IDLE_S;
519 ---------------------------------------------------------------------- 522 -- ///////////////////////////////////////////////////////// 523 ------------------------------------------------------------ 524 -- Application side FSM 525 ------------------------------------------------------------ 526 -- ///////////////////////////////////////////////////////// 528 -- Pipeline Master (DFF) 530 ------------------------------------------------------------ 532 ---------------------------------------------------------------------- 536 v.appSsiSlave := SSI_SLAVE_NOTRDY_C;
539 v.rxSegmentAddr := (others =>'0');
540 v.rxSegmentWe := '0';
541 v.rxBufferAddr := r.rxBufferAddr;
548 -- Wait if buffer full 549 if (v.bufferFull = '0') then 550 v.appState := WAIT_SOF_S;
552 ---------------------------------------------------------------------- 555 -- SSI Ready to receive data from APP 556 v.appSsiSlave := SSI_SLAVE_RDY_C;
559 v.rxSegmentAddr := (others =>'0');
560 v.rxSegmentWe := '0';
561 v.rxBufferAddr := r.rxBufferAddr;
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;
573 -- Increment the buffer window address because a NULL segment has filled the current spot 575 v.rxBufferAddr := r.rxBufferAddr+1;
577 v.rxBufferAddr := (others => '0');
580 -- Wait until receiving the first data 581 -- SOF and EOF received 582 -- Packet is only one word long go directly to ready! 585 -- First data already received at this point 586 v.rxSegmentAddr := r.rxSegmentAddr;
588 v.rxSegmentWe := '1';
590 -- Save packet tKeep of last data word 594 v.appState := SEG_RDY_S;
599 -- First data received 600 v.rxSegmentAddr := r.rxSegmentAddr;
602 v.rxSegmentWe := '1';
604 v.appState := SEG_RCV_S;
606 ---------------------------------------------------------------------- 610 v.appSsiSlave := SSI_SLAVE_RDY_C;
611 v.rxBufferAddr := r.rxBufferAddr;
613 -- Buffer write if data valid 615 v.rxSegmentAddr := r.rxSegmentAddr + 1;
616 v.rxSegmentWe := '1';
618 v.rxSegmentAddr := r.rxSegmentAddr;
619 v.rxSegmentWe := '0';
627 -- Wait until receiving EOF 630 -- Save packet tKeep of last data word 633 -- Save packet length (+1 because it has not incremented for EOF yet) 636 v.appState := SEG_RDY_S;
639 v.rxSegmentWe := '0';
640 v.appState := SEG_LEN_ERR;
642 v.rxSegmentWe := '0';
643 v.appState := SEG_LEN_ERR;
645 ---------------------------------------------------------------------- 649 v.appSsiSlave := SSI_SLAVE_NOTRDY_C;
651 v.rxSegmentAddr := (others =>'0');
652 v.rxSegmentWe := '0';
654 -- Request data at txFSM 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 664 v.rxBufferAddr := r.rxBufferAddr+1;
666 v.rxBufferAddr := (others => '0');
669 v.appState := IDLE_S;
671 ---------------------------------------------------------------------- 675 v.appSsiSlave := SSI_SLAVE_NOTRDY_C;
676 -- Overflow happened (packet too big) 679 v.rxSegmentAddr := (others =>'0');
680 v.rxSegmentWe := '0';
682 -- Request data at txFSM 688 v.appState := IDLE_S;
689 ---------------------------------------------------------------------- 694 -- Next state condition 695 v.appState := IDLE_S;
696 ---------------------------------------------------------------------- 700 -- ///////////////////////////////////////////////////////// 701 ------------------------------------------------------------ 702 -- Initialisation of the parameters when the connection is broken 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;
714 v.ackState := REG_INIT_C.ackState;
715 v.appState := REG_INIT_C.appState;
717 ------------------------------------------------------------ 718 -- ///////////////////////////////////////////////////////// 720 -- ///////////////////////////////////////////////////////// 721 ------------------------------------------------------------ 722 -- Arm fault injection on rising edge of injectFault_i 723 ------------------------------------------------------------ 724 -- /// ////////////////////////////////////////////////////// 728 v.injectFaultReg := '1';
730 v.injectFaultReg := r.injectFaultReg;
734 -- ///////////////////////////////////////////////////////// 735 ------------------------------------------------------------ 736 -- Transport side FSM 737 ------------------------------------------------------------ 738 -- ///////////////////////////////////////////////////////// 741 -- These flags will hold if not overidden 742 v.tspSsiMaster:= SSI_MASTER_INIT_C;
744 -- Pipeline incoming slave 748 ---------------------------------------------------------------------- 753 -- Register initial sequence number 755 v.seqN := r.nextSeqN;
757 -- Next state condition 759 v.tspState := DISS_CONN_S;
761 ---------------------------------------------------------------------- 764 v.nextSeqN := r.nextSeqN;
765 v.seqN := r.nextSeqN;
767 v.txHeaderAddr := (others => '0');
768 v.txSegmentAddr := (others => '0');
770 v.txBufferAddr := r.nextSentAddr;
785 v.tspSsiMaster:= SSI_MASTER_INIT_C;
787 -- Next state condition 789 v.tspState := SYN_H_S;
791 v.tspState := ACK_H_S;
793 v.tspState := RST_WE_S;
795 v.tspState := CONN_S;
797 v.tspState := INIT_S;
799 ---------------------------------------------------------------------- 802 v.nextSeqN := r.nextSeqN;
803 v.seqN := r.nextSeqN;
805 v.txHeaderAddr := (others => '0');
806 v.txSegmentAddr := (others => '0');
808 v.txBufferAddr := r.nextSentAddr;
825 v.tspSsiMaster:= SSI_MASTER_INIT_C;
827 -- Next state condition 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;
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;
839 v.tspState := INIT_S;
842 ---------------------------------------------------------------------- 844 ---------------------------------------------------------------------- 847 v.nextSeqN := r.nextSeqN;
848 v.seqN := r.nextSeqN;
850 v.txSegmentAddr := (others => '0');
851 v.txBufferAddr := r.nextSentAddr;
853 v.synH := '1';
-- Send SYN header 865 v.tspSsiMaster:= SSI_MASTER_INIT_C;
868 -- Send SOF with header address 0 869 if (r.txHeaderAddr = (r.txHeaderAddr'range => '0')) then 870 v.tspSsiMaster.sof := '1';
872 v.tspSsiMaster.sof := '0';
875 -- Increment address and generate strobe 877 v.tspSsiMaster.valid := '0';
878 v.txHeaderAddr := r.txHeaderAddr;
884 v.tspSsiMaster.valid := '1';
885 v.tspSsiMaster.eof := '1';
886 v.tspSsiMaster.eofe := '0';
888 v.nextSeqN := r.nextSeqN+1;
-- Increment SEQ number at the end of segment transmission 889 v.seqN := r.nextSeqN+1;
892 v.tspState := DISS_CONN_S;
895 v.tspSsiMaster.valid := '1';
896 v.txHeaderAddr := r.txHeaderAddr + 1;
899 v.tspSsiMaster.valid := '0';
900 v.txHeaderAddr := r.txHeaderAddr;
904 ---------------------------------------------------------------------- 906 ---------------------------------------------------------------------- 909 v.nextSeqN := r.nextSeqN;
910 v.seqN := r.nextSeqN;
912 v.txSegmentAddr := (others => '0');
913 v.txBufferAddr := r.nextSentAddr;
914 v.txHeaderAddr := (others => '0');
918 v.ackH := '1';
-- Send ack header 929 -- Strobe immediately after headerRdy 934 v.tspSsiMaster:= SSI_MASTER_INIT_C;
937 -- Next state condition (when chksum is ready) 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';
947 -- Add checksum to last two bytes 952 v.tspState := DISS_CONN_S;
954 v.tspState := CONN_S;
959 ---------------------------------------------------------------------- 961 ---------------------------------------------------------------------- 964 v.nextSeqN := r.nextSeqN;
965 v.seqN := r.nextSeqN;
967 v.txHeaderAddr := (others => '0');
968 v.txSegmentAddr := (others => '0');
970 v.txBufferAddr := r.nextSentAddr;
971 -- State control signals 974 v.rstH := '1';
-- Send reset header 980 v.buffWe := '0';
-- TODO (Check if this is ok) Ignore the buffer because the RST will not get retransmitted 986 v.tspSsiMaster:= SSI_MASTER_INIT_C;
988 -- Next State condition 989 v.tspState := RST_H_S;
990 ---------------------------------------------------------------------- 993 v.nextSeqN := r.nextSeqN;
994 v.seqN := r.nextSeqN;
996 v.txSegmentAddr := (others => '0');
997 v.txBufferAddr := r.nextSentAddr;
998 v.txHeaderAddr := (others => '0');
1003 v.rstH := '1';
-- Send reset header 1017 v.tspSsiMaster:= SSI_MASTER_INIT_C;
1020 -- Next state condition 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 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;
1039 ---------------------------------------------------------------------- 1041 ---------------------------------------------------------------------- 1044 v.nextSeqN := r.nextSeqN;
1045 v.seqN := r.nextSeqN;
1047 v.txHeaderAddr := (others => '0');
1048 v.txSegmentAddr := (others => '0');
1050 v.txBufferAddr := r.nextSentAddr;
1052 -- State control signals 1056 v.nullH := '1';
-- Send null header 1061 v.buffWe := '1';
-- Update buffer seqN and Type 1067 v.tspSsiMaster:= SSI_MASTER_INIT_C;
1069 -- Next State condition 1070 v.tspState := NULL_H_S;
1071 ---------------------------------------------------------------------- 1074 v.nextSeqN := r.nextSeqN;
1075 v.seqN := r.nextSeqN;
1076 v.txHeaderAddr := (others => '0');
1078 v.txSegmentAddr := (others => '0');
1079 v.txBufferAddr := r.nextSentAddr;
1085 v.nullH := '1';
-- Send null header 1098 -- Leave initialized v.tspSsiMaster 1101 -- Next state condition 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';
1111 -- Add checksum to last two bytes 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;
1121 ---------------------------------------------------------------------- 1123 ---------------------------------------------------------------------- 1126 v.nextSeqN := r.nextSeqN;
1127 v.seqN := r.nextSeqN;
1129 v.txHeaderAddr := (others => '0');
1130 v.txSegmentAddr := (others => '0');
1132 v.txBufferAddr := r.nextSentAddr;
1134 -- State control signals 1139 v.dataH := '1';
-- Send data header 1143 v.buffWe := '1';
-- Update buffer seqN and Type 1149 -- Leave initialised v.tspSsiMaster 1150 v.tspSsiMaster.data := r.tspSsiMaster.data;
1152 -- Next state condition 1153 v.tspState := DATA_H_S;
1154 ---------------------------------------------------------------------- 1157 v.nextSeqN := r.nextSeqN;
1158 v.seqN := r.nextSeqN;
1160 v.txSegmentAddr := (others => '0');
1161 v.txBufferAddr := r.nextSentAddr;
1167 v.dataH := '1';
-- Send data header 1175 -- if header data ready than 1176 -- strobe the checksum 1183 -- Next state condition 1184 -- Frame size is one word 1185 -- Wait for the chksum to be ready 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';
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! 1198 v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum);
-- Add checksum to last two bytes 1201 -- Set the fault reg to 0 1202 v.injectFaultReg := '0';
1204 v.tspState := DATA_S;
1207 ---------------------------------------------------------------------- 1210 v.nextSeqN := r.nextSeqN;
1211 v.seqN := r.nextSeqN;
1213 v.txHeaderAddr := (others => '0');
1214 v.txBufferAddr := r.nextSentAddr;
1215 v.txSegmentAddr := r.txSegmentAddr;
1223 v.dataD := '1';
-- Send data 1231 -- Other SSI parameters 1232 v.tspSsiMaster.sof := '0';
1233 v.tspSsiMaster.strb := (others => '1');
1234 v.tspSsiMaster.dest := (others => '0');
1237 -- Next state condition 1238 if (r.txSegmentAddr >= r.windowArray(conv_integer(r.txBufferAddr)).segSize) then 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;
1246 v.txSegmentAddr := r.txSegmentAddr;
1248 v.tspState := DATA_SENT_S;
1250 -- Increment segment address and assert valid only when not paused 1252 v.tspSsiMaster.valid := '1';
1253 v.txSegmentAddr := r.txSegmentAddr + 1;
1255 v.tspSsiMaster.valid := '0';
1256 v.txSegmentAddr := r.txSegmentAddr;
1259 ----------------------------------------------------------------------------- 1262 v.nextSeqN := r.nextSeqN+1;
-- Increment SEQ number at the end of segment transmission 1263 v.seqN := r.nextSeqN+1;
1265 v.txHeaderAddr := (others => '0');
1266 v.txSegmentAddr := (others => '0');
1268 v.txBufferAddr := r.nextSentAddr;
1281 v.buffSent := '1';
-- Increment buffer last sent address(txBuffer) 1283 -- SSI master (Initialise - stop transmission) 1284 v.tspSsiMaster := SSI_MASTER_INIT_C;
1287 v.tspState := CONN_S;
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;
1298 v.nextSeqN := r.nextSeqN;
-- Never increment seqN while resending 1299 v.seqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
1301 v.txHeaderAddr := (others => '0');
1302 v.txSegmentAddr := (others => '0');
1304 -- State control signals 1320 v.tspSsiMaster := SSI_MASTER_INIT_C;
1322 -- Next state condition 1323 v.tspState := RESEND_H_S;
1324 ---------------------------------------------------------------------- 1327 v.nextSeqN := r.nextSeqN;
-- Never increment seqN while resending 1328 v.seqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
1330 v.txSegmentAddr := (others => '0');
1331 v.txBufferAddr := r.txBufferAddr;
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);
1346 -- if header data ready than 1347 -- strobe the checksum 1354 -- Next state condition 1355 -- Frame size is one word 1356 -- Wait for chksumb ready 1358 v.tspSsiMaster.sof := '1';
1359 v.tspSsiMaster.valid := '1';
1360 v.tspSsiMaster.strb := (others => '1');
1361 v.tspSsiMaster.dest := (others => '0');
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! 1367 v.tspSsiMaster.data(RSSI_WORD_WIDTH_C*8-1 downto 0) := endianSwap64(s_headerAndChksum);
-- Add checksum to last two bytes 1370 -- Set the fault reg to 0 1371 v.injectFaultReg := '0';
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' 1378 -- Send EOF and start sending next packet 1379 v.tspSsiMaster.eof := '1';
1380 v.tspSsiMaster.eofe := '0';
1382 v.tspState := RESEND_PP_S;
1384 -- If DATA packet start sending data 1386 v.tspState := RESEND_DATA_S;
1389 ---------------------------------------------------------------------- 1390 when RESEND_DATA_S => 1392 v.nextSeqN := r.nextSeqN;
-- Never increment seqN while resending 1393 v.seqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
1395 v.txHeaderAddr := (others => '0');
1396 v.txBufferAddr := r.txBufferAddr;
1397 v.txSegmentAddr := r.txSegmentAddr;
1405 v.dataD := '1';
-- Send data 1417 -- Other SSI parameters 1418 v.tspSsiMaster.sof := '0';
1419 v.tspSsiMaster.strb := (others => '1');
1420 v.tspSsiMaster.dest := (others => '0');
1423 -- Next state condition 1424 if (r.txSegmentAddr >= r.windowArray(conv_integer(r.txBufferAddr)).segSize) then 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;
1432 v.txSegmentAddr := r.txSegmentAddr;
1434 v.tspState := RESEND_PP_S;
1436 -- Increment segment address only when Slave is ready 1438 v.tspSsiMaster.valid := '1';
1439 v.txSegmentAddr := r.txSegmentAddr + 1;
1441 v.tspSsiMaster.valid := '0';
1442 v.txSegmentAddr := r.txSegmentAddr;
1444 ---------------------------------------------------------------------- 1447 v.nextSeqN := r.nextSeqN;
-- Never increment seqN while resending 1448 v.seqN := r.windowArray(conv_integer(r.txBufferAddr)).seqN;
1450 v.txHeaderAddr := (others => '0');
1451 v.txSegmentAddr := (others => '0');
1453 -- Increment buffer address (circulary) 1455 v.txBufferAddr := r.txBufferAddr+1;
1457 v.txBufferAddr := (others => '0');
1460 -- State control signals 1477 v.tspSsiMaster := SSI_MASTER_INIT_C;
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;
1484 v.tspState := RESEND_H_S;
1486 ---------------------------------------------------------------------- 1490 ---------------------------------------------------------------------- 1493 -- Synchronous Reset 1494 if (rst_i = '1') then 1499 ----------------------------------------------------------- 1500 --------------------------------------------------------------------- 1503 -- Combine ram write address 1508 -- Slave out immediately 1518 ----------------------------------------------------------- 1519 --------------------------------------------------------------------- 1522 -- Combine ram read address 1537 -- Sequence number from buffer 1543 --------------------------------------------------------------------- 1546 seq :
process (
clk_i)
is 1548 if (rising_edge(clk_i)) then 1549 r <= rin after TPD_G;
1553 --------------------------------------------------------------------- 1554 end architecture rtl;
in chksum_islv( 15 downto 0)
out tspSsiMaster_oSsiMasterType
ACK_HEADER_SIZE_Gnatural := 8
in rdHeaderData_islv( RSSI_WORD_WIDTH_C* 8- 1 downto 0)
out wrBuffData_oslv( RSSI_WORD_WIDTH_C* 8- 1 downto 0)
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)
out txSeqN_oslv( 7 downto 0)
DATA_HEADER_SIZE_Gnatural := 8
WINDOW_ADDR_SIZE_Gpositive := 3
in rdBuffData_islv( RSSI_WORD_WIDTH_C* 8- 1 downto 0)
RST_HEADER_SIZE_Gnatural := 8
HEADER_CHKSUM_EN_Gboolean := true
out rdBuffAddr_oslv(( SEGMENT_ADDR_SIZE_G+ WINDOW_ADDR_SIZE_G)- 1 downto 0)
AxiStreamSlaveType :=(tReady => '0') AXI_STREAM_SLAVE_INIT_C
SEGMENT_ADDR_SIZE_Gpositive := 7
AxiStreamCtrlType :=(pause => '1',overflow => '0',idle => '0') AXI_STREAM_CTRL_INIT_C
in appSsiMaster_iSsiMasterType
NULL_HEADER_SIZE_Gnatural := 8
in windowSize_iinteger range 1 to 2**( WINDOW_ADDR_SIZE_G)
out appSsiSlave_oSsiSlaveType
in initSeqN_islv( 7 downto 0)
slv( SSI_TDEST_BITS_C- 1 downto 0) dest
AxiStreamSlaveType :=(tReady => '1') AXI_STREAM_SLAVE_FORCE_C
EACK_HEADER_SIZE_Gnatural := 8
out lastAckN_oslv( 7 downto 0)
SYN_HEADER_SIZE_Gnatural := 24
in ackN_islv( 7 downto 0)
in headerLength_ipositive
in bufferSize_iinteger range 1 to 2**( SEGMENT_ADDR_SIZE_G)
in tspSsiSlave_iSsiSlaveType
out wrBuffAddr_oslv(( SEGMENT_ADDR_SIZE_G+ WINDOW_ADDR_SIZE_G)- 1 downto 0)