diff --git a/protocols/rssi/ruckus.tcl b/protocols/rssi/ruckus.tcl index 874eace8c2..d39448dff2 100644 --- a/protocols/rssi/ruckus.tcl +++ b/protocols/rssi/ruckus.tcl @@ -2,4 +2,3 @@ source $::env(RUCKUS_PROC_TCL) loadRuckusTcl "$::DIR_PATH/v1" -loadRuckusTcl "$::DIR_PATH/v1b" diff --git a/protocols/rssi/v1b/rtl/AxiRssiCore.vhd b/protocols/rssi/v1b/rtl/AxiRssiCore.vhd deleted file mode 100644 index 8535904878..0000000000 --- a/protocols/rssi/v1b/rtl/AxiRssiCore.vhd +++ /dev/null @@ -1,684 +0,0 @@ -------------------------------------------------------------------------------- --- Title : RSSI Protocol: https://confluence.slac.stanford.edu/x/1IyfD -------------------------------------------------------------------------------- --- Company : SLAC National Accelerator Laboratory -------------------------------------------------------------------------------- --- Description: The module is based upon RUDP (Cisco implementation) RFC-908, RFC-1151, draft-ietf-sigtran-reliable-udp-00. --- The specifications in the drafts are modified by internal simplifications and improvements. --- --- Interfaces to transport and application side through AxiStream ports --- The AxiStream IO port widths can be adjusted (AxiStream FIFOs added to IO) --- Optional AxiLite Register interface. More info on registers is in RssiAxiLiteRegItf.vhd --- The module can act as Server or Client: --- - Server: - Passively listens for connection request from client, --- - Monitors connection activity NULL segment timeouts --- - Client: - Actively requests connection --- - Sends NULL packages if there is no incoming data --- Status register: --- statusReg_o(0) : Connection Active --- statusReg_o(1) : Maximum retransmissions exceeded r.retransMax and --- statusReg_o(2) : Null timeout reached (server) r.nullTout; --- statusReg_o(3) : Error in acknowledgment mechanism --- statusReg_o(4) : SSI Frame length too long --- statusReg_o(5) : Connection to peer timed out --- statusReg_o(6) : Client rejected the connection (parameters out of range) --- Server proposed new parameters (parameters out of range) -------------------------------------------------------------------------------- --- This file is part of 'SLAC Firmware Standard Library'. --- It is subject to the license terms in the LICENSE.txt file found in the --- top-level directory of this distribution and at: --- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. --- No part of 'SLAC Firmware Standard Library', including this file, --- may be copied, modified, propagated, or distributed except according to --- the terms contained in the LICENSE.txt file. -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.std_logic_arith.all; -use ieee.math_real.all; - - -library surf; -use surf.StdRtlPkg.all; -use surf.AxiPkg.all; -use surf.AxiStreamPkg.all; -use surf.AxiLitePkg.all; -use surf.AxiRssiPkg.all; -use surf.RssiPkg.all; -use surf.SsiPkg.all; - -entity AxiRssiCore is - generic ( - TPD_G : time := 1 ns; - SERVER_G : boolean := true; --! Module is server or client - -- AXI Configurations - MAX_SEG_SIZE_G : positive := 1024; --! max. payload size (units of bytes) - AXI_CONFIG_G : AxiConfigType; --! Defines the AXI configuration but ADDR_WIDTH_C should be defined as the space for RSSI and maybe not the entire memory address space - -- AXIS Configurations - APP_AXIS_CONFIG_G : AxiStreamConfigType; - TSP_AXIS_CONFIG_G : AxiStreamConfigType; - -- RSSI Timeouts - CLK_FREQUENCY_G : real := 156.25E+6; --! In units of Hz - TIMEOUT_UNIT_G : real := 1.0E-3; --! In units of seconds - ACK_TOUT_G : positive := 25; --! unit depends on TIMEOUT_UNIT_G - RETRANS_TOUT_G : positive := 50; --! unit depends on TIMEOUT_UNIT_G (Recommended >= MAX_NUM_OUTS_SEG_C*Data segment transmission time) - NULL_TOUT_G : positive := 200; --! unit depends on TIMEOUT_UNIT_G (Recommended >= 4*RETRANS_TOUT_G) - RETRANSMIT_ENABLE_G : boolean := true; --! Enable/Disable retransmissions in tx module - -- Version and connection ID - INIT_SEQ_N_G : natural := 16#80#; - CONN_ID_G : positive := 16#12345678#; - VERSION_G : positive := 1; - HEADER_CHKSUM_EN_G : boolean := true; - -- Counters - MAX_RETRANS_CNT_G : positive := 8; - MAX_CUM_ACK_CNT_G : positive := 3); - port ( - clk : in sl; - rst : in sl; - -- AXI TX Segment Buffer Interface - txAxiOffset : in slv(63 downto 0); --! Used to apply an address offset to the master AXI transactions - txAxiWriteMaster : out AxiWriteMasterType; - txAxiWriteSlave : in AxiWriteSlaveType; - txAxiReadMaster : out AxiReadMasterType; - txAxiReadSlave : in AxiReadSlaveType; - -- AXI RX Segment Buffer Interface - rxAxiOffset : in slv(63 downto 0); --! Used to apply an address offset to the master AXI transactions - rxAxiWriteMaster : out AxiWriteMasterType; - rxAxiWriteSlave : in AxiWriteSlaveType; - rxAxiReadMaster : out AxiReadMasterType; - rxAxiReadSlave : in AxiReadSlaveType; - -- High level Application side interface - openRq : in sl := '0'; - closeRq : in sl := '0'; - inject : in sl := '0'; - -- SSI Application side - sAppAxisMaster : in AxiStreamMasterType; - sAppAxisSlave : out AxiStreamSlaveType; - mAppAxisMaster : out AxiStreamMasterType; - mAppAxisSlave : in AxiStreamSlaveType; - -- SSI Transport side - sTspAxisMaster : in AxiStreamMasterType; - sTspAxisSlave : out AxiStreamSlaveType; - mTspAxisMaster : out AxiStreamMasterType; - mTspAxisSlave : in AxiStreamSlaveType; - -- AXI-Lite Register Interface - sAxilReadMaster : in AxiLiteReadMasterType := AXI_LITE_READ_MASTER_INIT_C; - sAxilReadSlave : out AxiLiteReadSlaveType; - sAxilWriteMaster : in AxiLiteWriteMasterType := AXI_LITE_WRITE_MASTER_INIT_C; - sAxilWriteSlave : out AxiLiteWriteSlaveType; - -- Internal statuses - statusReg : out slv(6 downto 0); - maxSegSize : out slv(15 downto 0)); -end entity AxiRssiCore; - -architecture rtl of AxiRssiCore is - - constant MAX_SEGS_BITS_C : positive := bitSize(MAX_SEG_SIZE_G-1); - constant SEGMENT_ADDR_SIZE_C : positive := (MAX_SEGS_BITS_C-3); --! 2^SEGMENT_ADDR_SIZE_C = Number of 64 bit wide data words - constant WINDOW_ADDR_SIZE_C : positive := (AXI_CONFIG_G.ADDR_WIDTH_C-MAX_SEGS_BITS_C); --! 2^WINDOW_ADDR_SIZE_C = Max number of segments in buffer - constant MAX_NUM_OUTS_SEG_C : positive := (2**WINDOW_ADDR_SIZE_C); --! MAX_NUM_OUTS_SEG_C=(2**WINDOW_ADDR_SIZE_C) - constant AXI_BURST_BYTES_C : positive := ite((MAX_SEG_SIZE_G > 4096), 4096, 2**MAX_SEGS_BITS_C); -- Enforce power of 2 and up to 4kB AXI burst - - -- RSSI Parameters - signal s_appRssiParam : RssiParamType; - signal s_rxRssiParam : RssiParamType; - signal s_rssiParam : RssiParamType; - - -- Monitor input signals - signal s_txBufferEmpty : sl; - signal s_lenErr : sl; - signal s_ackErr : sl; - signal s_peerConnTout : sl; - signal s_paramReject : sl; - - -- Connection control and parameters - signal s_initSeqN : slv(7 downto 0); - signal s_connActive : sl; - signal s_closeRq : sl; - signal s_closed : sl; - signal s_openRq : sl; - signal s_intCloseRq : sl; - signal s_txAckF : sl; - - -- Fault injection - signal s_injectFaultReg : sl; - signal s_injectFault : sl; - - -- Header states - signal s_synHeadSt : sl; - signal s_rstHeadSt : sl; - signal s_dataHeadSt : sl; - signal s_nullHeadSt : sl; - signal s_ackHeadSt : sl; - - -- Tx Segment requests - signal s_sndResend : sl; - signal s_sndSyn : sl; - signal s_sndAck : sl; - signal s_sndAckMon : sl; - signal s_sndAckCon : sl; - signal s_sndRst : sl; - signal s_sndNull : sl; - - -- Current transmitted or received SeqN and AckN - signal s_txSeqN : slv(7 downto 0); - signal s_txAckN : slv(7 downto 0); - signal s_rxSeqN : slv(7 downto 0); - signal s_rxLastSeqN : slv(7 downto 0); - signal s_rxAckN : slv(7 downto 0); - signal s_rxLastAckN : slv(7 downto 0); - - -- Tx Header Interface - signal s_headerAddr : slv(7 downto 0); - signal s_headerData : slv(RSSI_WORD_WIDTH_C*8-1 downto 0); - signal s_headerRdy : sl; - signal s_headerLength : positive; - - -- Rx Statuses - signal s_rxValidSeg : sl; - signal s_rxDropSeg : sl; - signal s_rxFlags : flagsType; - signal s_rxAck : sl; -- Acknowledge pulse when valid segment with acknowledge flag received - signal s_rxBuffBusy : sl; - - -- Rx segment buffer - signal s_rxBufferSize : integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_C); - signal s_rxWindowSize : integer range 1 to 2 ** (WINDOW_ADDR_SIZE_C); - - -- Tx segment buffer - signal s_txBufferSize : integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_C); - signal s_txWindowSize : integer range 1 to 2 ** (WINDOW_ADDR_SIZE_C); - - -- AXIS Application Interface - signal s_sAppAxisMaster : AxiStreamMasterType; - signal s_sAppAxisSlave : AxiStreamSlaveType; - signal s_mAppAxisMaster : AxiStreamMasterType; - signal s_mAppAxisSlave : AxiStreamSlaveType; - - -- AXIS Transport Interface - signal s_sTspAxisMaster : AxiStreamMasterType; - signal s_sTspAxisSlave : AxiStreamSlaveType; - signal s_mTspAxisMaster : AxiStreamMasterType; - signal s_mTspAxisSlave : AxiStreamSlaveType; - - -- AXI-Lite Control/Config Interface - signal s_openRqReg : sl; - signal s_closeRqReg : sl; - signal s_modeReg : sl; -- '0': Use internal parameters from generics, '1': Use parameters from Axil - signal s_initSeqNReg : slv(7 downto 0); - signal s_appRssiParamReg : RssiParamType; - - -- AXI-Lite Status/Monitoring Interface - signal s_statusReg : slv(statusReg'range); - signal s_dropCntReg : slv(31 downto 0); - signal s_validCntReg : slv(31 downto 0); - signal s_reconCntReg : slv(31 downto 0); - signal s_resendCntReg : slv(31 downto 0); - signal s_monMasters : AxiStreamMasterArray(1 downto 0); - signal s_monSlaves : AxiStreamSlaveArray(1 downto 0); - signal s_frameRate : Slv32Array(1 downto 0); - signal s_bandwidth : Slv64Array(1 downto 0); - -begin - - assert (MAX_NUM_OUTS_SEG_C <= 256) - report "AxiRssiCore: MAX_NUM_OUTS_SEG_C must be <= 256" severity failure; - - statusReg <= s_statusReg; - maxSegSize <= s_rxRssiParam.maxSegSize; - - --------------------- - -- Register interface - --------------------- - U_Reg : entity surf.RssiAxiLiteRegItf - generic map ( - TPD_G => TPD_G, - COMMON_CLK_G => true, - TIMEOUT_UNIT_G => TIMEOUT_UNIT_G, - SEGMENT_ADDR_SIZE_G => SEGMENT_ADDR_SIZE_C, - INIT_SEQ_N_G => INIT_SEQ_N_G, - CONN_ID_G => CONN_ID_G, - VERSION_G => VERSION_G, - HEADER_CHKSUM_EN_G => HEADER_CHKSUM_EN_G, - MAX_NUM_OUTS_SEG_G => MAX_NUM_OUTS_SEG_C, - MAX_SEG_SIZE_G => MAX_SEG_SIZE_G, - RETRANS_TOUT_G => RETRANS_TOUT_G, - ACK_TOUT_G => ACK_TOUT_G, - NULL_TOUT_G => NULL_TOUT_G, - MAX_RETRANS_CNT_G => MAX_RETRANS_CNT_G, - MAX_CUM_ACK_CNT_G => MAX_CUM_ACK_CNT_G, - MAX_OUT_OF_SEQUENCE_G => 0) - port map ( - axiClk_i => clk, - axiRst_i => rst, - axilReadMaster => sAxilReadMaster, - axilReadSlave => sAxilReadSlave, - axilWriteMaster => sAxilWriteMaster, - axilWriteSlave => sAxilWriteSlave, - -- DevClk domain - devClk_i => clk, - devRst_i => rst, - -- Control - openRq_o => s_openRqReg, - closeRq_o => s_closeRqReg, - mode_o => s_modeReg, - initSeqN_o => s_initSeqNReg, - appRssiParam_o => s_appRssiParamReg, - negRssiParam_i => s_rssiParam, - injectFault_o => s_injectFaultReg, - -- Status (RO) - frameRate_i => s_frameRate, - bandwidth_i => s_bandwidth, - status_i => s_statusReg, - dropCnt_i => s_dropCntReg, - validCnt_i => s_validCntReg, - resendCnt_i => s_resendCntReg, - reconCnt_i => s_reconCntReg); - - s_injectFault <= s_injectFaultReg or inject; - - PACKET_RATE : - for i in 1 downto 0 generate - U_AxiStreamMon : entity surf.AxiStreamMon - generic map ( - TPD_G => TPD_G, - COMMON_CLK_G => true, - AXIS_CLK_FREQ_G => CLK_FREQUENCY_G, - AXIS_CONFIG_G => APP_AXIS_CONFIG_G) - port map ( - -- AXIS Stream Interface - axisClk => clk, - axisRst => rst, - axisMaster => s_monMasters(i), - axisSlave => s_monSlaves(i), - -- Status Interface - statusClk => clk, - statusRst => rst, - frameRate => s_frameRate(i), - bandwidth => s_bandwidth(i)); - end generate PACKET_RATE; - - ---------------------------------------------------------------------------- - -- Connection, Auto Negotiation and Monitoring -- - ---------------------------------------------------------------------------- - - ----------------------- - -- Parameter assignment - ----------------------- - process (closeRq, openRq, s_appRssiParamReg, s_closeRqReg, s_initSeqNReg, - s_intCloseRq, s_modeReg, s_openRqReg) is - begin - if (s_modeReg = '0') then - - -- Use external requests - s_closeRq <= s_closeRqReg or closeRq or s_intCloseRq; - s_openRq <= s_openRqReg or openRq; - - -- Assign application side RSSI parameters from generics - s_appRssiParam.maxOutsSeg <= toSlv(MAX_NUM_OUTS_SEG_C, 8); - s_appRssiParam.maxSegSize <= toSlv(MAX_SEG_SIZE_G, 16); - s_appRssiParam.retransTout <= toSlv(RETRANS_TOUT_G, 16); - s_appRssiParam.cumulAckTout <= toSlv(ACK_TOUT_G, 16); - s_appRssiParam.nullSegTout <= toSlv(NULL_TOUT_G, 16); - s_appRssiParam.maxRetrans <= toSlv(MAX_RETRANS_CNT_G, 8); - s_appRssiParam.maxCumAck <= toSlv(MAX_CUM_ACK_CNT_G, 8); - s_appRssiParam.maxOutofseq <= toSlv(0, 8); - s_appRssiParam.version <= toSlv(VERSION_G, 4); - s_appRssiParam.connectionId <= toSlv(CONN_ID_G, 32); - s_appRssiParam.chksumEn <= ite(HEADER_CHKSUM_EN_G, "1", "0"); - s_appRssiParam.timeoutUnit <= toSlv(integer(0.0 - (ieee.math_real.log(TIMEOUT_UNIT_G)/ieee.math_real.log(10.0))), 8); - s_initSeqN <= toSlv(INIT_SEQ_N_G, 8); - - else - - -- Use AXI-Lite register requests - s_closeRq <= s_closeRqReg or s_intCloseRq; - s_openRq <= s_openRqReg; - - -- Assign application side RSSI parameters from AXI-Lite registers - s_appRssiParam <= s_appRssiParamReg; - s_initSeqN <= s_initSeqNReg; - - end if; - end process; - - ---------------------------------- - -- Connection Finite State Machine - ---------------------------------- - U_ConnFSM : entity surf.RssiConnFsm - generic map ( - TPD_G => TPD_G, - SERVER_G => SERVER_G, - TIMEOUT_UNIT_G => TIMEOUT_UNIT_G, - CLK_FREQUENCY_G => CLK_FREQUENCY_G, - RETRANS_TOUT_G => RETRANS_TOUT_G, - MAX_RETRANS_CNT_G => MAX_RETRANS_CNT_G, - WINDOW_ADDR_SIZE_G => WINDOW_ADDR_SIZE_C, - SEGMENT_ADDR_SIZE_G => SEGMENT_ADDR_SIZE_C) - port map ( - clk_i => clk, - rst_i => rst, - connRq_i => s_openRq, - closeRq_i => s_closeRq, - closed_o => s_closed, - rxRssiParam_i => s_rxRssiParam, - appRssiParam_i => s_appRssiParam, - rssiParam_o => s_rssiParam, - rxFlags_i => s_rxFlags, - rxValid_i => s_rxValidSeg, - synHeadSt_i => s_synHeadSt, - ackHeadSt_i => s_ackHeadSt, - rstHeadSt_i => s_rstHeadSt, - connActive_o => s_connActive, - sndSyn_o => s_sndSyn, - sndAck_o => s_sndAckCon, - sndRst_o => s_sndRst, - txAckF_o => s_txAckF, - rxBufferSize_o => s_rxBufferSize, - rxWindowSize_o => s_rxWindowSize, - txBufferSize_o => s_txBufferSize, - txWindowSize_o => s_txWindowSize, - peerTout_o => s_peerConnTout, - paramReject_o => s_paramReject); - - ------------------------------- - -- Connection Monitoring Module - ------------------------------- - U_Monitor : entity surf.RssiMonitor - generic map ( - TPD_G => TPD_G, - CLK_FREQUENCY_G => CLK_FREQUENCY_G, - TIMEOUT_UNIT_G => TIMEOUT_UNIT_G, - SERVER_G => SERVER_G, - WINDOW_ADDR_SIZE_G => WINDOW_ADDR_SIZE_C, - RETRANSMIT_ENABLE_G => RETRANSMIT_ENABLE_G) - port map ( - clk_i => clk, - rst_i => rst, - connActive_i => s_connActive, - rxBuffBusy_i => s_rxBuffBusy, - rssiParam_i => s_rssiParam, - rxFlags_i => s_rxFlags, - rxValid_i => s_rxValidSeg, - rxDrop_i => s_rxDropSeg, - ackHeadSt_i => s_ackHeadSt, - rstHeadSt_i => s_rstHeadSt, - dataHeadSt_i => s_dataHeadSt, - nullHeadSt_i => s_nullHeadSt, - rxLastSeqN_i => s_rxLastSeqN, - rxWindowSize_i => s_rxWindowSize, - lenErr_i => s_lenErr, - ackErr_i => s_ackErr, - peerConnTout_i => s_peerConnTout, - paramReject_i => s_paramReject, - txBufferEmpty_i => s_txBufferEmpty, - sndResend_o => s_sndResend, - sndAck_o => s_sndAckMon, - sndNull_o => s_sndNull, - closeRq_o => s_intCloseRq, - statusReg_o => s_statusReg, - dropCnt_o => s_dropCntReg, - validCnt_o => s_validCntReg, - resendCnt_o => s_resendCntReg, - reconCnt_o => s_reconCntReg); - - ------------------------------------ - -- Outbound Header Generation Module - ------------------------------------ - U_HeaderReg : entity surf.RssiHeaderReg - generic map ( - TPD_G => TPD_G, - SYN_HEADER_SIZE_G => SYN_HEADER_SIZE_C, - ACK_HEADER_SIZE_G => ACK_HEADER_SIZE_C, - EACK_HEADER_SIZE_G => EACK_HEADER_SIZE_C, - RST_HEADER_SIZE_G => RST_HEADER_SIZE_C, - NULL_HEADER_SIZE_G => NULL_HEADER_SIZE_C, - DATA_HEADER_SIZE_G => DATA_HEADER_SIZE_C) - port map ( - clk_i => clk, - rst_i => rst, - synHeadSt_i => s_synHeadSt, - rstHeadSt_i => s_rstHeadSt, - dataHeadSt_i => s_dataHeadSt, - nullHeadSt_i => s_nullHeadSt, - ackHeadSt_i => s_ackHeadSt, - busyHeadSt_i => s_rxBuffBusy, - ack_i => s_txAckF, -- Connected to ConnectFSM - txSeqN_i => s_txSeqN, - rxAckN_i => s_rxLastSeqN, - headerValues_i => s_rssiParam, - addr_i => s_headerAddr, - headerData_o => s_headerData, - ready_o => s_headerRdy, - headerLength_o => s_headerLength); - - s_sndAck <= s_sndAckCon or s_sndAckMon; - - ---------------------------------------------------------------------------- - -- From Application layer to Transport Layer -- - ---------------------------------------------------------------------------- - - -------------------- - -- Application Layer - -------------------- - U_AppIn : entity surf.AxiStreamResize - generic map ( - -- General Configurations - TPD_G => TPD_G, - READY_EN_G => true, - -- AXI Stream Port Configurations - SLAVE_AXI_CONFIG_G => APP_AXIS_CONFIG_G, - MASTER_AXI_CONFIG_G => RSSI_AXIS_CONFIG_C) - port map ( - -- Clock and reset - axisClk => clk, - axisRst => rst, - -- Slave Port - sAxisMaster => s_monMasters(0), - sAxisSlave => s_monSlaves(0), - -- Master Port - mAxisMaster => s_mAppAxisMaster, - mAxisSlave => s_mAppAxisSlave); - - s_monMasters(0) <= sAppAxisMaster; - sAppAxisSlave <= s_monSlaves(0); - - ----------------------------------- - -- Transmitter Finite State Machine - ----------------------------------- - U_TxFSM : entity surf.AxiRssiTxFsm - generic map ( - TPD_G => TPD_G, - AXI_CONFIG_G => AXI_CONFIG_G, - BURST_BYTES_G => AXI_BURST_BYTES_C, - WINDOW_ADDR_SIZE_G => WINDOW_ADDR_SIZE_C, - SEGMENT_ADDR_SIZE_G => SEGMENT_ADDR_SIZE_C, - HEADER_CHKSUM_EN_G => HEADER_CHKSUM_EN_G) - port map ( - clk_i => clk, - rst_i => rst, - -- AXI Segment Buffer Interface - axiOffset_i => txAxiOffset, - mAxiWriteMaster_o => txAxiWriteMaster, - mAxiWriteSlave_i => txAxiWriteSlave, - mAxiReadMaster_o => txAxiReadMaster, - mAxiReadSlave_i => txAxiReadSlave, - -- Inbound Application Interface - appMaster_i => s_mAppAxisMaster, - appSlave_o => s_mAppAxisSlave, - -- Outbound Transport Interface - tspMaster_o => s_sTspAxisMaster, - tspSlave_i => s_sTspAxisSlave, - -- Connection FSM indicating active connection - connActive_i => s_connActive, - -- Closed state in connFSM (initialize seqN) - closed_i => s_closed, - -- Fault injection corrupts header checksum - injectFault_i => s_injectFault, - -- Various segment requests - sndSyn_i => s_sndSyn, - sndAck_i => s_sndAck, - sndRst_i => s_sndRst, - sndResend_i => s_sndResend, - sndNull_i => s_sndNull, - -- Window buff size (Depends on the number of outstanding segments) - windowSize_i => s_txWindowSize, - bufferSize_i => s_txBufferSize, - -- Header read - rdHeaderAddr_o => s_headerAddr, - rdHeaderData_i => s_headerData, - -- Initial sequence number - initSeqN_i => s_initSeqN, - -- Tx data (input to header decoder module) - txSeqN_o => s_txSeqN, - -- FSM outs for header and data flow control - synHeadSt_o => s_synHeadSt, - ackHeadSt_o => s_ackHeadSt, - dataHeadSt_o => s_dataHeadSt, - dataSt_o => open, -- may be used in the future otherwise remove - rstHeadSt_o => s_rstHeadSt, - nullHeadSt_o => s_nullHeadSt, - -- Last acked number (Used in Rx FSM to determine if AcnN is valid) - lastAckN_o => s_rxLastAckN, - -- Acknowledge mechanism - ack_i => s_rxAck, - ackN_i => s_rxAckN, - ---------------------------------- - --eack_i => s_rxEack_i, -- From receiver module when a segment with valid EACK is received - --eackSeqnArr_i => s_rxEackSeqnArr, -- Array of sequence numbers received out of order - ---------------------------------- - -- Errors (1 cc pulse) - lenErr_o => s_lenErr, - ackErr_o => s_ackErr, - -- Segment buffer indicator - bufferEmpty_o => s_txBufferEmpty); - - ------------------ - -- Transport Layer - ------------------ - U_TspOut : entity surf.AxiStreamResize - generic map ( - -- General Configurations - TPD_G => TPD_G, - READY_EN_G => true, - -- AXI Stream Port Configurations - SLAVE_AXI_CONFIG_G => RSSI_AXIS_CONFIG_C, - MASTER_AXI_CONFIG_G => TSP_AXIS_CONFIG_G) - port map ( - -- Clock and reset - axisClk => clk, - axisRst => rst, - -- Slave Port - sAxisMaster => s_sTspAxisMaster, - sAxisSlave => s_sTspAxisSlave, - -- Master Port - mAxisMaster => mTspAxisMaster, - mAxisSlave => mTspAxisSlave); - - ---------------------------------------------------------------------------- - -- From Transport layer to Application Layer -- - ---------------------------------------------------------------------------- - - ------------------ - -- Transport Layer - ------------------ - U_TspIn : entity surf.AxiStreamResize - generic map ( - -- General Configurations - TPD_G => TPD_G, - READY_EN_G => true, - -- AXI Stream Port Configurations - SLAVE_AXI_CONFIG_G => TSP_AXIS_CONFIG_G, - MASTER_AXI_CONFIG_G => RSSI_AXIS_CONFIG_C) - port map ( - -- Clock and reset - axisClk => clk, - axisRst => rst, - -- Slave Port - sAxisMaster => sTspAxisMaster, - sAxisSlave => sTspAxisSlave, - -- Master Port - mAxisMaster => s_mTspAxisMaster, - mAxisSlave => s_mTspAxisSlave); - - -------------------------------- - -- Receiver Finite State Machine - -------------------------------- - U_RxFSM : entity surf.AxiRssiRxFsm - generic map ( - TPD_G => TPD_G, - AXI_CONFIG_G => AXI_CONFIG_G, - BURST_BYTES_G => AXI_BURST_BYTES_C, - WINDOW_ADDR_SIZE_G => WINDOW_ADDR_SIZE_C, - HEADER_CHKSUM_EN_G => HEADER_CHKSUM_EN_G, - SEGMENT_ADDR_SIZE_G => SEGMENT_ADDR_SIZE_C) - port map ( - clk_i => clk, - rst_i => rst, - -- AXI Segment Buffer Interface - axiOffset_i => rxAxiOffset, - mAxiWriteMaster_o => rxAxiWriteMaster, - mAxiWriteSlave_i => rxAxiWriteSlave, - mAxiReadMaster_o => rxAxiReadMaster, - mAxiReadSlave_i => rxAxiReadSlave, - -- Inbound Transport Interface - tspMaster_i => s_mTspAxisMaster, - tspSlave_o => s_mTspAxisSlave, - -- Outbound Application Interface - appMaster_o => s_sAppAxisMaster, - appSlave_i => s_sAppAxisSlave, - -- RX Buffer Full - rxBuffBusy_o => s_rxBuffBusy, - -- Connection FSM indicating active connection - connActive_i => s_connActive, - -- Window size different for Rx and Tx - rxWindowSize_i => s_rxWindowSize, - rxBufferSize_i => s_rxBufferSize, - txWindowSize_i => s_txWindowSize, - -- Last acknowledged Sequence number connected to TX module - lastAckN_i => s_rxLastAckN, - -- Current received seqN - rxSeqN_o => s_rxSeqN, - -- Current received ackN - rxLastSeqN_o => s_rxLastSeqN, - -- Last seqN received and sent to application (this is the ackN transmitted) - rxAckN_o => s_rxAckN, - -- Valid Segment received (1 c-c) - rxValidSeg_o => s_rxValidSeg, - -- Segment dropped (1 c-c) - rxDropSeg_o => s_rxDropSeg, - -- Last segment received flags (active until next segment is received) - rxFlags_o => s_rxFlags, - -- Parameters received from peer SYN packet - rxParam_o => s_rxRssiParam); - - s_rxAck <= s_rxValidSeg and s_rxFlags.ack and s_connActive; -- Acknowledge valid packet - - -------------------- - -- Application Layer - -------------------- - U_AppOut : entity surf.AxiStreamResize - generic map ( - -- General Configurations - TPD_G => TPD_G, - READY_EN_G => true, - -- AXI Stream Port Configurations - SLAVE_AXI_CONFIG_G => RSSI_AXIS_CONFIG_C, - MASTER_AXI_CONFIG_G => APP_AXIS_CONFIG_G) - port map ( - -- Clock and reset - axisClk => clk, - axisRst => rst, - -- Slave Port - sAxisMaster => s_sAppAxisMaster, - sAxisSlave => s_sAppAxisSlave, - -- Master Port - mAxisMaster => s_monMasters(1), - mAxisSlave => s_monSlaves(1)); - - mAppAxisMaster <= s_monMasters(1); - s_monSlaves(1) <= mAppAxisSlave; - -end architecture rtl; diff --git a/protocols/rssi/v1b/rtl/AxiRssiCoreWrapper.vhd b/protocols/rssi/v1b/rtl/AxiRssiCoreWrapper.vhd deleted file mode 100644 index feee8f05b9..0000000000 --- a/protocols/rssi/v1b/rtl/AxiRssiCoreWrapper.vhd +++ /dev/null @@ -1,323 +0,0 @@ -------------------------------------------------------------------------------- --- Title : RSSI Protocol: https://confluence.slac.stanford.edu/x/1IyfD -------------------------------------------------------------------------------- --- Company : SLAC National Accelerator Laboratory -------------------------------------------------------------------------------- --- Description: Wrapper for RSSI + AXIS packetizer -------------------------------------------------------------------------------- --- This file is part of 'SLAC Firmware Standard Library'. --- It is subject to the license terms in the LICENSE.txt file found in the --- top-level directory of this distribution and at: --- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. --- No part of 'SLAC Firmware Standard Library', including this file, --- may be copied, modified, propagated, or distributed except according to --- the terms contained in the LICENSE.txt file. -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.std_logic_arith.all; - - -library surf; -use surf.StdRtlPkg.all; -use surf.AxiPkg.all; -use surf.AxiStreamPkg.all; -use surf.AxiLitePkg.all; -use surf.AxiRssiPkg.all; -use surf.RssiPkg.all; -use surf.SsiPkg.all; - -entity AxiRssiCoreWrapper is - generic ( - TPD_G : time := 1 ns; - SERVER_G : boolean := true; --! Module is server or client - JUMBO_G : boolean := false; --! true=8192 byte payload, false=1024 byte payload - AXI_CONFIG_G : AxiConfigType; --! Defines the AXI configuration but ADDR_WIDTH_C should be defined as the space for RSSI and "maybe" not the entire memory address space available - -- AXIS Configurations - APP_STREAMS_G : positive := 1; - APP_STREAM_ROUTES_G : Slv8Array := (0 => "--------"); - APP_AXIS_CONFIG_G : AxiStreamConfigArray; - TSP_AXIS_CONFIG_G : AxiStreamConfigType; - -- RSSI Timeouts - CLK_FREQUENCY_G : real := 156.25E+6; -- In units of Hz - TIMEOUT_UNIT_G : real := 1.0E-3; -- In units of seconds - ACK_TOUT_G : positive := 25; -- unit depends on TIMEOUT_UNIT_G - RETRANS_TOUT_G : positive := 50; -- unit depends on TIMEOUT_UNIT_G (Recommended >= MAX_NUM_OUTS_SEG_G*Data segment transmission time) - NULL_TOUT_G : positive := 200; -- unit depends on TIMEOUT_UNIT_G (Recommended >= 4*RETRANS_TOUT_G) - -- Counters - MAX_RETRANS_CNT_G : positive := 8; - MAX_CUM_ACK_CNT_G : positive := 3); - port ( - -- Clock and Reset - clk : in sl; - rst : in sl; - -- AXI TX Segment Buffer Interface - txAxiOffset : in slv(63 downto 0); --! Used to apply an address offset to the master AXI transactions - txAxiWriteMaster : out AxiWriteMasterType; - txAxiWriteSlave : in AxiWriteSlaveType; - txAxiReadMaster : out AxiReadMasterType; - txAxiReadSlave : in AxiReadSlaveType; - -- AXI RX Segment Buffer Interface - rxAxiOffset : in slv(63 downto 0); --! Used to apply an address offset to the master AXI transactions - rxAxiWriteMaster : out AxiWriteMasterType; - rxAxiWriteSlave : in AxiWriteSlaveType; - rxAxiReadMaster : out AxiReadMasterType; - rxAxiReadSlave : in AxiReadSlaveType; - -- SSI Application side - sAppAxisMasters : in AxiStreamMasterArray(APP_STREAMS_G-1 downto 0); - sAppAxisSlaves : out AxiStreamSlaveArray(APP_STREAMS_G-1 downto 0); - mAppAxisMasters : out AxiStreamMasterArray(APP_STREAMS_G-1 downto 0); - mAppAxisSlaves : in AxiStreamSlaveArray(APP_STREAMS_G-1 downto 0); - -- SSI Transport side - sTspAxisMaster : in AxiStreamMasterType; - sTspAxisSlave : out AxiStreamSlaveType; - mTspAxisMaster : out AxiStreamMasterType; - mTspAxisSlave : in AxiStreamSlaveType; - -- High level Application side interface - openRq : in sl := '0'; - closeRq : in sl := '0'; - inject : in sl := '0'; - linkUp : out sl; - -- Optional AXI-Lite Register Interface - sAxilReadMaster : in AxiLiteReadMasterType := AXI_LITE_READ_MASTER_INIT_C; - sAxilReadSlave : out AxiLiteReadSlaveType; - sAxilWriteMaster : in AxiLiteWriteMasterType := AXI_LITE_WRITE_MASTER_INIT_C; - sAxilWriteSlave : out AxiLiteWriteSlaveType); -end entity AxiRssiCoreWrapper; - -architecture mapping of AxiRssiCoreWrapper is - - constant PACKETIZER_AXIS_CONFIG_C : AxiStreamConfigType := ( - TSTRB_EN_C => false, - TDATA_BYTES_C => 8, - TDEST_BITS_C => 8, - TID_BITS_C => 8, - TKEEP_MODE_C => TKEEP_COMP_C, - TUSER_BITS_C => 8, - TUSER_MODE_C => TUSER_FIRST_LAST_C); - - constant MAX_SEG_SIZE_C : positive := ite(JUMBO_G, 8192, 1024); - constant MAX_SEGS_BITS_C : positive := bitSize(MAX_SEG_SIZE_C); - - signal maxSegs : slv(MAX_SEGS_BITS_C-1 downto 0) := toSlv(MAX_SEG_SIZE_C, MAX_SEGS_BITS_C); - signal maxObSegSize : slv(15 downto 0) := toSlv(MAX_SEG_SIZE_C, 16); - signal ileaveRearb : slv(11 downto 0); - - signal status : slv(6 downto 0) := (others => '0'); - signal rssiNotConnected : sl := '1'; - signal rssiConnected : sl := '1'; - - signal rxMasters : AxiStreamMasterArray(APP_STREAMS_G-1 downto 0); - signal rxSlaves : AxiStreamSlaveArray(APP_STREAMS_G-1 downto 0); - - signal depacketizerMasters : AxiStreamMasterArray(1 downto 0); - signal depacketizerSlaves : AxiStreamSlaveArray(1 downto 0); - - signal packetizerMasters : AxiStreamMasterArray(1 downto 0); - signal packetizerSlaves : AxiStreamSlaveArray(1 downto 0); - - signal txMasters : AxiStreamMasterArray(APP_STREAMS_G-1 downto 0); - signal txSlaves : AxiStreamSlaveArray(APP_STREAMS_G-1 downto 0); - -begin - - -- Register to help with timing - process(clk) - begin - if rising_edge(clk) then - linkUp <= status(0) after TPD_G; - rssiConnected <= status(0) after TPD_G; - rssiNotConnected <= not(rssiConnected) after TPD_G; - if (maxObSegSize >= MAX_SEG_SIZE_C) then - maxSegs <= toSlv(MAX_SEG_SIZE_C, MAX_SEGS_BITS_C) after TPD_G; - else - maxSegs <= maxObSegSize(maxSegs'range) after TPD_G; - end if; - ileaveRearb <= resize(maxSegs(MAX_SEGS_BITS_C-1 downto 3), 12) - 3 after TPD_G; -- # of tValid minus AxiStreamPacketizer2.PROTO_WORDS_C=3 - end if; - end process; - - GEN_RX : - for i in (APP_STREAMS_G-1) downto 0 generate - U_Rx : entity surf.AxiStreamResize - generic map ( - -- General Configurations - TPD_G => TPD_G, - READY_EN_G => true, - -- AXI Stream Port Configurations - SLAVE_AXI_CONFIG_G => APP_AXIS_CONFIG_G(i), - MASTER_AXI_CONFIG_G => PACKETIZER_AXIS_CONFIG_C) - port map ( - -- Clock and reset - axisClk => clk, - axisRst => rst, - -- Slave Port - sAxisMaster => sAppAxisMasters(i), - sAxisSlave => sAppAxisSlaves(i), - -- Master Port - mAxisMaster => rxMasters(i), - mAxisSlave => rxSlaves(i)); - end generate GEN_RX; - - U_AxiStreamMux : entity surf.AxiStreamMux - generic map ( - TPD_G => TPD_G, - NUM_SLAVES_G => APP_STREAMS_G, - MODE_G => "ROUTED", - TDEST_ROUTES_G => APP_STREAM_ROUTES_G, - ILEAVE_EN_G => true, - ILEAVE_ON_NOTVALID_G => true, -- Because of ILEAVE_REARB_G value != power of 2, forcing rearb on not(tValid) - ILEAVE_REARB_G => (MAX_SEG_SIZE_C/PACKETIZER_AXIS_CONFIG_C.TDATA_BYTES_C) - 3, -- AxiStreamPacketizer2.PROTO_WORDS_C=3 - PIPE_STAGES_G => 1) - port map ( - -- Clock and reset - axisClk => clk, - axisRst => rst, - -- Slaves - sAxisMasters => rxMasters, - sAxisSlaves => rxSlaves, - ileaveRearb => ileaveRearb, - -- Master - mAxisMaster => packetizerMasters(0), - mAxisSlave => packetizerSlaves(0)); - - U_Packetizer : entity surf.AxiStreamPacketizer2 - generic map ( - TPD_G => TPD_G, - MEMORY_TYPE_G => "block", - REG_EN_G => true, - CRC_MODE_G => "FULL", - CRC_POLY_G => x"04C11DB7", - TDEST_BITS_G => 8, - MAX_PACKET_BYTES_G => MAX_SEG_SIZE_C, - INPUT_PIPE_STAGES_G => 0, - OUTPUT_PIPE_STAGES_G => 1) - port map ( - axisClk => clk, - axisRst => rst, - maxPktBytes => maxSegs, - sAxisMaster => packetizerMasters(0), - sAxisSlave => packetizerSlaves(0), - mAxisMaster => packetizerMasters(1), - mAxisSlave => packetizerSlaves(1)); - - U_RssiCore : entity surf.AxiRssiCore - generic map ( - TPD_G => TPD_G, - SERVER_G => SERVER_G, - -- AXI Configurations - MAX_SEG_SIZE_G => MAX_SEG_SIZE_C, - AXI_CONFIG_G => AXI_CONFIG_G, - -- AXIS Configurations - APP_AXIS_CONFIG_G => PACKETIZER_AXIS_CONFIG_C, - TSP_AXIS_CONFIG_G => TSP_AXIS_CONFIG_G, - -- RSSI Timeouts - CLK_FREQUENCY_G => CLK_FREQUENCY_G, - TIMEOUT_UNIT_G => TIMEOUT_UNIT_G, - ACK_TOUT_G => ACK_TOUT_G, - RETRANS_TOUT_G => RETRANS_TOUT_G, - NULL_TOUT_G => NULL_TOUT_G, - -- Counters - MAX_RETRANS_CNT_G => MAX_RETRANS_CNT_G, - MAX_CUM_ACK_CNT_G => MAX_CUM_ACK_CNT_G) - port map ( - -- Clock and Reset - clk => clk, - rst => rst, - -- AXI TX Segment Buffer Interface - txAxiOffset => txAxiOffset, - txAxiWriteMaster => txAxiWriteMaster, - txAxiWriteSlave => txAxiWriteSlave, - txAxiReadMaster => txAxiReadMaster, - txAxiReadSlave => txAxiReadSlave, - -- AXI RX Segment Buffer Interface - rxAxiOffset => rxAxiOffset, - rxAxiWriteMaster => rxAxiWriteMaster, - rxAxiWriteSlave => rxAxiWriteSlave, - rxAxiReadMaster => rxAxiReadMaster, - rxAxiReadSlave => rxAxiReadSlave, - -- SSI Application side - sAppAxisMaster => packetizerMasters(1), - sAppAxisSlave => packetizerSlaves(1), - mAppAxisMaster => depacketizerMasters(1), - mAppAxisSlave => depacketizerSlaves(1), - -- SSI Transport side - sTspAxisMaster => sTspAxisMaster, - sTspAxisSlave => sTspAxisSlave, - mTspAxisMaster => mTspAxisMaster, - mTspAxisSlave => mTspAxisSlave, - -- High level Application side interface - openRq => openRq, - closeRq => closeRq, - inject => inject, - -- AXI-Lite Register Interface - sAxilReadMaster => sAxilReadMaster, - sAxilReadSlave => sAxilReadSlave, - sAxilWriteMaster => sAxilWriteMaster, - sAxilWriteSlave => sAxilWriteSlave, - -- Internal statuses - statusReg => status, - maxSegSize => maxObSegSize); - - U_Depacketizer : entity surf.AxiStreamDepacketizer2 - generic map ( - TPD_G => TPD_G, - MEMORY_TYPE_G => "block", - REG_EN_G => true, - CRC_MODE_G => "FULL", - CRC_POLY_G => x"04C11DB7", - TDEST_BITS_G => 8, - INPUT_PIPE_STAGES_G => 0, -- No need for input stage, RSSI output is already pipelined - OUTPUT_PIPE_STAGES_G => 1) - port map ( - axisClk => clk, - axisRst => rst, - linkGood => rssiConnected, - sAxisMaster => depacketizerMasters(1), - sAxisSlave => depacketizerSlaves(1), - mAxisMaster => depacketizerMasters(0), - mAxisSlave => depacketizerSlaves(0)); - - U_AxiStreamDeMux : entity surf.AxiStreamDeMux - generic map ( - TPD_G => TPD_G, - PIPE_STAGES_G => 1, - NUM_MASTERS_G => APP_STREAMS_G, - MODE_G => "ROUTED", - TDEST_ROUTES_G => APP_STREAM_ROUTES_G) - port map ( - -- Clock and reset - axisClk => clk, - axisRst => rst, - -- Slaves - sAxisMaster => depacketizerMasters(0), - sAxisSlave => depacketizerSlaves(0), - -- Master - mAxisMasters => txMasters, - mAxisSlaves => txSlaves); - - GEN_TX : - for i in (APP_STREAMS_G-1) downto 0 generate - U_Tx : entity surf.AxiStreamResize - generic map ( - -- General Configurations - TPD_G => TPD_G, - READY_EN_G => true, - -- AXI Stream Port Configurations - SLAVE_AXI_CONFIG_G => PACKETIZER_AXIS_CONFIG_C, - MASTER_AXI_CONFIG_G => APP_AXIS_CONFIG_G(i)) - port map ( - -- Clock and reset - axisClk => clk, - axisRst => rst, - -- Slave Port - sAxisMaster => txMasters(i), - sAxisSlave => txSlaves(i), - -- Master Port - mAxisMaster => mAppAxisMasters(i), - mAxisSlave => mAppAxisSlaves(i)); - end generate GEN_TX; - -end architecture mapping; diff --git a/protocols/rssi/v1b/rtl/AxiRssiPkg.vhd b/protocols/rssi/v1b/rtl/AxiRssiPkg.vhd deleted file mode 100644 index c3c3164b55..0000000000 --- a/protocols/rssi/v1b/rtl/AxiRssiPkg.vhd +++ /dev/null @@ -1,95 +0,0 @@ -------------------------------------------------------------------------------- --- Title : RSSI Protocol: https://confluence.slac.stanford.edu/x/1IyfD -------------------------------------------------------------------------------- --- Company : SLAC National Accelerator Laboratory -------------------------------------------------------------------------------- --- Description: RSSI Package File -------------------------------------------------------------------------------- --- This file is part of 'SLAC Firmware Standard Library'. --- It is subject to the license terms in the LICENSE.txt file found in the --- top-level directory of this distribution and at: --- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. --- No part of 'SLAC Firmware Standard Library', including this file, --- may be copied, modified, propagated, or distributed except according to --- the terms contained in the LICENSE.txt file. -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.std_logic_arith.all; - - -library surf; -use surf.StdRtlPkg.all; -use surf.AxiPkg.all; - -package AxiRssiPkg is - - --! Default RSSI AXI configuration - constant RSSI_AXI_CONFIG_C : AxiConfigType := ( - ADDR_WIDTH_C => 13, -- 2^13 = 8kB buffer - DATA_BYTES_C => 8, -- 8 bytes = 64-bits - ID_BITS_C => 2, - LEN_BITS_C => 7); -- Up to 1kB bursting - - procedure GetRssiCsum ( -- 2 clock cycle latency calculation - -- Input - init : in sl; - header : in slv(63 downto 0); - accumReg : in slv(20 downto 0); - -- Results - accumVar : inout slv(20 downto 0); - chksumOk : inout sl; - checksum : inout slv(15 downto 0)); - -end AxiRssiPkg; - - -package body AxiRssiPkg is - - procedure GetRssiCsum ( - -- Input - init : in sl; - header : in slv(63 downto 0); - accumReg : in slv(20 downto 0); - -- Results - accumVar : inout slv(20 downto 0); - chksumOk : inout sl; - checksum : inout slv(15 downto 0)) is - variable hdrSum : slv(20 downto 0); - variable summ0 : slv(16 downto 0); - variable summ1 : slv(15 downto 0); - begin - - -- Summation of the header - hdrSum := resize(header(63 downto 48), 21) + - resize(header(47 downto 32), 21) + - resize(header(31 downto 16), 21) + - resize(header(15 downto 0), 21); - - -- Check for initializing - if (init = '1') then - accumVar := hdrSum; - else - -- Add new word sum - accumVar := hdrSum + accumReg; - end if; - - -- Add the sum carry bits - summ0 := resize(accumReg(15 downto 0), 17) + resize(accumReg(20 downto 16), 17); - summ1 := summ0(15 downto 0) + resize(summ0(16 downto 16), 16); - - -- Checksum's Ones complement output (only used in TX FSM) - checksum := not(summ1); - - -- Output the checksum status (only used in RX FSM) - if (checksum = 0) then - chksumOk := '1'; - else - chksumOk := '0'; - end if; - - end procedure; - -end package body AxiRssiPkg; diff --git a/protocols/rssi/v1b/rtl/AxiRssiRxFsm.vhd b/protocols/rssi/v1b/rtl/AxiRssiRxFsm.vhd deleted file mode 100644 index b835108ff0..0000000000 --- a/protocols/rssi/v1b/rtl/AxiRssiRxFsm.vhd +++ /dev/null @@ -1,766 +0,0 @@ -------------------------------------------------------------------------------- --- Title : RSSI Protocol: https://confluence.slac.stanford.edu/x/1IyfD -------------------------------------------------------------------------------- --- Company : SLAC National Accelerator Laboratory -------------------------------------------------------------------------------- --- Description: Receiver FSM --- Receiver has the following functionality: --- Transport side FSM. Receive check and save segments to RX buffer. --- - WAIT_SOF Waits for Transport side SOF, --- - CHECK Determines the segment type and checks: --- ACK, NULL, DATA, or RST segment --- 1. Validates checksum (when valid), --- 2. Header length (number of bytes), --- 3. Sequence number (Only current seqN or lastSeqN+1 allowed) --- 4. Acknowledgment number (Valid range is lastAckN to lastAckN + txWindowSize) --- - CHECK_SYN Toggles through SYN header addresses and saves the RSSI parameters --- Checks the following: --- 1. Validates checksum (when valid), --- 2. Validates Ack number if the ack is sent with the SYN segment --- - DATA Receives the payload part of the DATA segment --- - VALID Checks if next valid SEQn is received. If yes: --- 1. increment the in order SEQn --- 2. save seqN, type, and occupied to the window buffer at current rxBufferAddr --- 3. increment rxBufferAddr --- - DROP Just report dropped packet and got back to WAIT_SOF --- Receiver side FSM. Send data to App side. --- - CHECK_BUFFER and DATA Send the data frame to the Application --- when the data at the next txSegmentAddr is ready. --- - SENT Release the windowbuffer at txBufferAddr. --- Increment txBufferAddr. --- Register the received SeqN for acknowledgment. -------------------------------------------------------------------------------- --- This file is part of 'SLAC Firmware Standard Library'. --- It is subject to the license terms in the LICENSE.txt file found in the --- top-level directory of this distribution and at: --- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. --- No part of 'SLAC Firmware Standard Library', including this file, --- may be copied, modified, propagated, or distributed except according to --- the terms contained in the LICENSE.txt file. -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.std_logic_arith.all; - - -library surf; -use surf.StdRtlPkg.all; -use surf.AxiStreamPkg.all; -use surf.AxiPkg.all; -use surf.AxiDmaPkg.all; -use surf.AxiRssiPkg.all; -use surf.RssiPkg.all; -use surf.SsiPkg.all; - -entity AxiRssiRxFsm is - generic ( - TPD_G : time := 1 ns; - AXI_CONFIG_G : AxiConfigType; - BURST_BYTES_G : positive := 1024; - WINDOW_ADDR_SIZE_G : positive := 7; -- 2^WINDOW_ADDR_SIZE_G = Number of segments - HEADER_CHKSUM_EN_G : boolean := true; - SEGMENT_ADDR_SIZE_G : positive := 3); -- 2^SEGMENT_ADDR_SIZE_G = Number of 64 bit wide data words - port ( - clk_i : in sl; - rst_i : in sl; - -- AXI Segment Buffer Interface - axiOffset_i : in slv(63 downto 0); - mAxiWriteMaster_o : out AxiWriteMasterType; - mAxiWriteSlave_i : in AxiWriteSlaveType; - mAxiReadMaster_o : out AxiReadMasterType; - mAxiReadSlave_i : in AxiReadSlaveType; - -- Inbound Transport Interface - tspMaster_i : in AxiStreamMasterType; - tspSlave_o : out AxiStreamSlaveType; - -- Outbound Application Interface - appMaster_o : out AxiStreamMasterType; - appSlave_i : in AxiStreamSlaveType; - -- RX Buffer Full - rxBuffBusy_o : out sl; - -- Connection FSM indicating active connection - connActive_i : in sl; - -- Window size different for Rx and Tx - rxWindowSize_i : in integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G); - rxBufferSize_i : in integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_G); -- Units of 64-bit words - txWindowSize_i : in integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G); - -- Last acknowledged Sequence number connected to TX module - lastAckN_i : in slv(7 downto 0); - -- Current received seqN - rxSeqN_o : out slv(7 downto 0); - -- Current received ackN - rxAckN_o : out slv(7 downto 0); - -- Last seqN received and sent to application (this is the ackN transmitted) - rxLastSeqN_o : out slv(7 downto 0); - -- Valid Segment received (1 c-c) - rxValidSeg_o : out sl; - -- Segment dropped (1 c-c) - rxDropSeg_o : out sl; - -- Last segment received flags (active until next segment is received) - rxFlags_o : out flagsType; - -- Parameters received from peer SYN packet - rxParam_o : out RssiParamType); -end entity AxiRssiRxFsm; - -architecture rtl of AxiRssiRxFsm is - - type tspStateType is ( - IDLE_S, - SYN_WAIT0_S, - SYN_WAIT1_S, - SYN_CHECK_S, - NSYN_CHECK_S, - DATA_S, - VALID_S); - - type AppStateType is ( - IDLE_S, - DATA_S, - SENT_S); - - type RegType is record - -- Reception buffer window - windowArray : WindowTypeArray(0 to 2 ** WINDOW_ADDR_SIZE_G-1); - pending : slv(WINDOW_ADDR_SIZE_G downto 0); - -------------------------------------------------- - -- Transport side FSM (Receive and check segments) - -------------------------------------------------- - wrReq : AxiWriteDmaReqType; - -- Counters - inorderSeqN : slv(7 downto 0); -- Next expected seqN - rxBufferAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); - -- Packet flags - rxF : flagsType; - -- Received RSSI parameters - rxParam : RssiParamType; - rxHeadLen : slv(7 downto 0); - rxSeqN : slv(7 downto 0); -- Received seqN - rxAckN : slv(7 downto 0); -- Received ackN - -- Checksum Calculation - csumAccum : slv(20 downto 0); - chksumOk : sl; - chksumRdy : sl; - checksum : slv(15 downto 0); - -- Strobing status flags - segValid : sl; - segDrop : sl; - simErrorDet : sl; - -- Inbound Transport Interface - tspSlave : AxiStreamSlaveType; - -- State Machine - tspState : TspStateType; - -- Application side FSM (Send segments when next in order received) - ----------------------------------------------------------- - rdReq : AxiReadDmaReqType; - txBufferAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); - rxLastSeqN : slv(7 downto 0); - -- State Machine - appState : AppStateType; - end record RegType; - - constant REG_INIT_C : RegType := ( - -- Rx buffer window - windowArray => (0 to 2 ** WINDOW_ADDR_SIZE_G-1 => WINDOW_INIT_C), - pending => (others => '0'), - -------------------------------------------------- - -- Transport side FSM (Receive and check segments) - -------------------------------------------------- - wrReq => AXI_WRITE_DMA_REQ_INIT_C, - -- Counters - inorderSeqN => (others => '0'), -- Next expected seqN - rxBufferAddr => (others => '0'), - -- Packet flags - rxF => (others => ('0')), - -- Received RSSI parameters - rxParam => RSSI_PARAM_INIT_C, - rxHeadLen => (others => '0'), -- Received seqN - rxSeqN => (others => '0'), -- Received seqN - rxAckN => (others => '0'), -- Received ackN - -- Checksum Calculation - csumAccum => (others => '0'), - chksumOk => '0', - chksumRdy => '0', - checksum => (others => '0'), - -- Strobing status flags - segValid => '0', - segDrop => '0', - simErrorDet => '0', - -- Inbound Transport Interface - tspSlave => AXI_STREAM_SLAVE_INIT_C, - -- Transport side state - tspState => IDLE_S, - ---------------------------------------------------------------------------- - -- Application side FSM (Send segments when received next in order received) - ---------------------------------------------------------------------------- - rdReq => AXI_READ_DMA_REQ_INIT_C, - txBufferAddr => (others => '0'), - rxLastSeqN => (others => '0'), - -- Application side state - appState => IDLE_S); - - signal r : RegType := REG_INIT_C; - signal rin : RegType; - - signal wrAck : AxiWriteDmaAckType; - signal rdAck : AxiReadDmaAckType; - - signal wrDmaMaster : AxiStreamMasterType; - signal wrDmaSlave : AxiStreamSlaveType; - - -- attribute dont_touch : string; - -- attribute dont_touch of r : signal is "TRUE"; - -begin - - U_DmaWrite : entity surf.AxiStreamDmaWrite - generic map ( - TPD_G => TPD_G, - AXI_READY_EN_G => true, - AXIS_CONFIG_G => RSSI_AXIS_CONFIG_C, - AXI_CONFIG_G => AXI_CONFIG_G, - BURST_BYTES_G => BURST_BYTES_G, - AXI_BURST_G => "01", -- INCR - AXI_CACHE_G => "0011", -- Cacheable - SW_CACHE_EN_G => false, - ACK_WAIT_BVALID_G => true, - PIPE_STAGES_G => 0, - BYP_SHIFT_G => true, - BYP_CACHE_G => true) - port map ( - -- Clock/Reset - axiClk => clk_i, - axiRst => rst_i, - -- DMA Control Interface - dmaReq => r.wrReq, - dmaAck => wrAck, - -- Streaming Interface - axisMaster => wrDmaMaster, - axisSlave => wrDmaSlave, - -- AXI Interface - axiWriteMaster => mAxiWriteMaster_o, - axiWriteSlave => mAxiWriteSlave_i); - - U_DmaRead : entity surf.AxiStreamDmaRead - generic map ( - TPD_G => TPD_G, - AXIS_READY_EN_G => true, - AXIS_CONFIG_G => RSSI_AXIS_CONFIG_C, - AXI_CONFIG_G => AXI_CONFIG_G, - AXI_BURST_G => "01", -- INCR - AXI_CACHE_G => "0011", -- Cacheable - SW_CACHE_EN_G => false, - PIPE_STAGES_G => 0, - PEND_THRESH_G => 0, -- In units of bytes - BYP_SHIFT_G => true) - port map ( - -- Clock/Reset - axiClk => clk_i, - axiRst => rst_i, - -- DMA Control Interface - dmaReq => r.rdReq, - dmaAck => rdAck, - -- Streaming Interface - axisMaster => appMaster_o, - axisSlave => appSlave_i, - axisCtrl => AXI_STREAM_CTRL_UNUSED_C, - -- AXI Interface - axiReadMaster => mAxiReadMaster_o, - axiReadSlave => mAxiReadSlave_i); - - ----------------------------------------------------------------------------------------------- - comb : process (axiOffset_i, connActive_i, lastAckN_i, r, rdAck, rst_i, - rxBufferSize_i, rxWindowSize_i, tspMaster_i, txWindowSize_i, - wrAck, wrDmaSlave) is - - variable v : RegType; - variable headerData : slv(63 downto 0); - variable maxSegSize : natural; - variable rxBufIdx : natural; - variable txBufIdx : natural; - begin - -- Latch the current value - v := r; - - -- Reset strobes - v.tspSlave := AXI_STREAM_SLAVE_INIT_C; - v.segValid := '0'; - v.segDrop := '0'; - v.chksumRdy := '0'; - - -- Endian swap the header - headerData := endianSwap64(tspMaster_i.tData(63 downto 0)); - - -- Convert to bytes - maxSegSize := 8*rxBufferSize_i; - - -- Calculate the next DMA write transaction - rxBufIdx := conv_integer(r.rxBufferAddr); - v.wrReq.address := axiOffset_i + toSlv((rxBufIdx*maxSegSize), 64); - v.wrReq.maxSize := toSlv(maxSegSize, 32); - - ------------------------------------------------------------ - -- RX Transport side FSM: - -- Receive the segment from the peer - -- Check the segment: - -- register the parameters from SYN header - -- seqN, ackN - -- check header checksum - -- increment in order received SeqN - ------------------------------------------------------------ - case r.tspState is - ---------------------------------------------------------------------- - when IDLE_S => - - -- Calculate the checksum - GetRssiCsum( - -- Input - '1', -- init - headerData, -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - - -- Check for data - if (tspMaster_i.tValid = '1') then - - -- Accept the data - v.tspSlave.tReady := '1'; - - -- Check if SOF - if (ssiGetUserSof(RSSI_AXIS_CONFIG_C, tspMaster_i) = '1') then - - -- Register flags, header length and SEQn - v.rxF.syn := headerData(63); - v.rxF.ack := headerData(62); - v.rxF.eack := headerData(61); - v.rxF.rst := headerData(60); - v.rxF.nul := headerData(59); - v.rxF.busy := headerData(56); - v.rxHeadLen := headerData(55 downto 48); - v.rxSeqN := headerData(47 downto 40); - v.rxAckN := headerData(39 downto 32); - - -- Syn header received (header is 3 c-c long) - if (v.rxF.syn = '1') then - - -- Register SYN header word 0 parameters - v.rxParam.version := headerData(31 downto 28); - v.rxParam.chksumEn := headerData(26 downto 26); - v.rxParam.maxOutsSeg := headerData(23 downto 16); - v.rxParam.maxSegSize := headerData(15 downto 0); - - -- Check for early EOF - if (tspMaster_i.tLast = '1') then - -- Set the flag - v.segDrop := '1'; - else - -- Next State - v.tspState := SYN_WAIT0_S; - end if; - - else - -- Set the flag - v.rxF.data := not(tspMaster_i.tLast); - -- Next State - v.tspState := NSYN_CHECK_S; - end if; - - end if; - - end if; - ---------------------------------------------------------------------- - when SYN_WAIT0_S => - -- Check for data - if (tspMaster_i.tValid = '1') then - - -- Accept the data - v.tspSlave.tReady := '1'; - - -- Calculate the checksum - GetRssiCsum( - -- Input - '0', -- init - headerData, -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - - -- Syn parameters - v.rxParam.retransTout := headerData(63 downto 48); - v.rxParam.cumulAckTout := headerData(47 downto 32); - v.rxParam.nullSegTout := headerData(31 downto 16); - v.rxParam.maxRetrans := headerData(15 downto 8); - v.rxParam.maxCumAck := headerData(7 downto 0); - - -- Check for early EOF - if (tspMaster_i.tLast = '1') then - -- Set the flag - v.segDrop := '1'; - -- Next State - v.tspState := IDLE_S; - else - -- Next State - v.tspState := SYN_WAIT1_S; - end if; - - end if; - - ---------------------------------------------------------------------- - when SYN_WAIT1_S => - -- Check for data - if (tspMaster_i.tValid = '1') then - - -- Accept the data - v.tspSlave.tReady := '1'; - - -- Calculate the checksum - GetRssiCsum( - -- Input - '0', -- init - headerData, -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - - -- Syn parameters - v.rxParam.maxOutofseq := headerData(63 downto 56); - v.rxParam.timeoutUnit := headerData(55 downto 48); - v.rxParam.connectionId(31 downto 0) := headerData(47 downto 16); - - -- Check for no EOF - if (tspMaster_i.tLast = '0') then - -- Set the flag - v.segDrop := '1'; - -- Next State - v.tspState := IDLE_S; - else - -- Next State - v.tspState := SYN_CHECK_S; - end if; - - end if; - ---------------------------------------------------------------------- - when SYN_CHECK_S => - - -- Last cycle of pipeline - v.chksumRdy := '1'; - GetRssiCsum( - -- Input - '0', -- init - (others => '0'), -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - - if (r.chksumRdy = '1') then - - -- Check the header - if ((HEADER_CHKSUM_EN_G = false) or (r.chksumOk = '1')) and (r.rxHeadLen = toSlv(24, 8)) then - -- Next State - v.tspState := VALID_S; - else - - -- Set the flag - v.segDrop := '1'; - - -- Next State - v.tspState := IDLE_S; - - end if; - - end if; - ---------------------------------------------------------------------- - when NSYN_CHECK_S => - -- Last cycle of pipeline - v.chksumRdy := '1'; - GetRssiCsum( - -- Input - '0', -- init - (others => '0'), -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - - if (r.chksumRdy = '1') then - - -- Check the header - if ( - ((HEADER_CHKSUM_EN_G = false) or (r.chksumOk = '1')) and - -- Check length - r.rxHeadLen = toSlv(8, 8) and - -- Check SeqN range - (r.rxSeqN - r.inOrderSeqN) <= 1 and - -- Check AckN range - (r.rxAckN - lastAckN_i) <= txWindowSize_i - ) then - - -- Valid data segment - if (r.rxF.data = '1' and v.rxF.nul = '0' and v.rxF.rst = '0') then - - -- Wait if the buffer full - -- Note: Deadlock possibility! If the peer is not accepting data! - if (r.windowArray(rxBufIdx).occupied = '0') then - -- Start the DMA write transaction - v.wrReq.request := '1'; - -- Next State - v.tspState := DATA_S; - - -- Buffer is full -> drop segment - else - -- Set the flag - v.segDrop := '1'; - -- Next State - v.tspState := IDLE_S; - end if; - - -- Valid non data segment - elsif (r.rxF.data = '0') then - -- Next State - v.tspState := VALID_S; - - -- Undefined condition - else - -- Set the flag - v.segDrop := '1'; - -- Next State - v.tspState := IDLE_S; - end if; - - -- Else failed header checking - else - -- Set the flag - v.segDrop := '1'; - -- Next State - v.tspState := IDLE_S; - end if; - - end if; - ---------------------------------------------------------------------- - when DATA_S => - -- Latch the segment size - v.windowArray(rxBufIdx).segSize := conv_integer(wrAck.size); - - -- Check if DMA write completed - if (wrAck.done = '1') then - - -- Reset the flag - v.wrReq.request := '0'; - - -- Check for error - if (wrAck.writeError = '1') or (wrAck.overflow = '1') then - -- Set the flag - v.segDrop := '1'; - -- Next State - v.tspState := IDLE_S; - else - -- Next State - v.tspState := VALID_S; - end if; - - end if; - ---------------------------------------------------------------------- - when VALID_S => - -- Set the flag - v.segValid := '1'; - - -- Initialize when valid SYN segment received - -- 1. Set the initial SeqN - -- 2. Initialize the buffer address - -- 3. Initialize window - if (connActive_i = '0') and (r.rxF.syn = '1') then - - -- Initialize for FSM internal signals - v.rxF.ack := r.rxF.ack; - v.inOrderSeqN := r.rxSeqN; - v.rxBufferAddr := (others => '0'); - v.windowArray := REG_INIT_C.windowArray; - v.pending := (others => '0'); - - -- Check if next valid SEQn is received. If yes: - -- 1. increment the in order SEQn - -- 2. save seqN, type, and occupied to the current buffer address - -- 3. increase buffer - elsif ((r.rxF.data = '1' or r.rxF.nul = '1' or r.rxF.rst = '1') and - -- Next seqN absolute difference is one - r.rxSeqN - r.inOrderSeqN = 1 - ) then - - -- Fill in the window array buffer - v.windowArray(rxBufIdx).seqN := r.rxSeqN; - v.windowArray(rxBufIdx).segType(0) := r.rxF.data; - v.windowArray(rxBufIdx).segType(1) := r.rxF.nul; - v.windowArray(rxBufIdx).segType(2) := r.rxF.rst; - v.windowArray(rxBufIdx).occupied := '1'; - - -- Update the in-order sequence index - v.inOrderSeqN := r.rxSeqN; - - -- Increment the RX buffer index - if r.rxBufferAddr < (rxWindowSize_i-1) then - v.rxBufferAddr := r.rxBufferAddr +1; - else - v.rxBufferAddr := (others => '0'); - end if; - - -- Increment the pending counter - if v.pending < rxWindowSize_i then - v.pending := v.pending + 1; - end if; - - end if; - - -- Next State - v.tspState := IDLE_S; - ---------------------------------------------------------------------- - end case; - - -- Calculate the next DMA read transaction - txBufIdx := conv_integer(r.txBufferAddr); - v.rdReq.address := axiOffset_i + toSlv((txBufIdx*maxSegSize), 64); - v.rdReq.size := toSlv(r.windowArray(txBufIdx).segSize, 32); - v.rdReq.firstUser(SSI_SOF_C) := '1'; -- SOF - - ---------------------------------------------------------------------------- - -- TX Application side FSM: - -- Transmit the segments in correct order - -- Check the buffer if the next slot is available and send the buffer to APP - ---------------------------------------------------------------------------- - case r.appState is - ---------------------------------------------------------------------- - when IDLE_S => - -- Check if not connected - if (connActive_i = '0') then - -- Reset the index pointers - v.txBufferAddr := (others => '0'); - v.rxLastSeqN := r.inOrderSeqN; - - -- Check for occupied buffer - elsif (r.windowArray(txBufIdx).occupied = '1') then - - -- Check for a data segment - if (r.windowArray(txBufIdx).segType(0) = '1') then - - -- Check if ready to move data - if (rdAck.idle = '1') then - -- Start the DMA read transaction - v.rdReq.request := '1'; - - -- Next State - v.appState := DATA_S; - end if; - - else - -- Next State - v.appState := SENT_S; - end if; - - end if; - ---------------------------------------------------------------------- - when DATA_S => - -- Check if DMA write completed - if (rdAck.done = '1') then - - -- Reset the flag - v.rdReq.request := '0'; - - -- Next State - v.appState := SENT_S; - - end if; - ---------------------------------------------------------------------- - when SENT_S => - -- Register the sent SeqN (this means that the place has been freed and the SeqN can be Acked) - v.rxLastSeqN := r.windowArray(txBufIdx).seqN; - - -- Release buffer - v.windowArray(txBufIdx).occupied := '0'; - - -- Increment the TX buffer index - if r.txBufferAddr < (rxWindowSize_i-1) then - v.txBufferAddr := r.txBufferAddr+1; -- Increment once - else - v.txBufferAddr := (others => '0'); - end if; - - -- Decrement the pending counter - if v.pending /= 0 then - v.pending := v.pending - 1; - end if; - - -- Next State - v.appState := IDLE_S; - ---------------------------------------------------------------------- - end case; - - v.simErrorDet := (r.segDrop or wrAck.overflow or wrAck.writeError or rdAck.readError); - -- if r.simErrorDet = '1' then - -- assert false - -- report "Simulation Failed!" severity failure; - -- end if; - - ---------------------------------------------------------------------- - -- Outputs -- - ---------------------------------------------------------------------- - - -- Inbound Transport Interface - wrDmaMaster <= tspMaster_i; - wrDmaMaster.tValid <= tspMaster_i.tValid and r.wrReq.request; - tspSlave_o.tReady <= v.tspSlave.tReady or wrDmaSlave.tReady; - - -- RX Buffer Full - if (r.pending > 1) then - rxBuffBusy_o <= '1'; - else - rxBuffBusy_o <= '0'; - end if; - - -- Current received seqN - rxSeqN_o <= r.rxSeqN; - - -- Current received ackN - rxAckN_o <= r.rxAckN; - - -- Last seqN received and sent to application (this is the ackN transmitted) - rxLastSeqN_o <= r.rxLastSeqN; - - -- Valid Segment received (1 c-c) - rxValidSeg_o <= r.segValid; - - -- Segment dropped (1 c-c) - rxDropSeg_o <= r.segDrop; - - -- Last segment received flags (active until next segment is received) - rxFlags_o <= r.rxF; - - -- Parameters received from peer SYN packet - rxParam_o <= r.rxParam; - - -- Reset - if (rst_i = '1') then - v := REG_INIT_C; - end if; - - -- Register the variable for next clock cycle - rin <= v; - - end process comb; - - seq : process (clk_i) is - begin - if (rising_edge(clk_i)) then - r <= rin after TPD_G; - end if; - end process seq; - -end architecture rtl; diff --git a/protocols/rssi/v1b/rtl/AxiRssiTxFsm.vhd b/protocols/rssi/v1b/rtl/AxiRssiTxFsm.vhd deleted file mode 100644 index e02bf719e9..0000000000 --- a/protocols/rssi/v1b/rtl/AxiRssiTxFsm.vhd +++ /dev/null @@ -1,1163 +0,0 @@ -------------------------------------------------------------------------------- --- Title : RSSI Protocol: https://confluence.slac.stanford.edu/x/1IyfD -------------------------------------------------------------------------------- --- Company : SLAC National Accelerator Laboratory -------------------------------------------------------------------------------- --- Description: Transmitter FSM --- Transmitter has the following functionality: --- Handle buffer addresses and buffer window (firstUnackAddr,nextSentAddr,lastSentAddr, bufferFull, bufferEmpty) --- Application side FSM. Receive SSI frame and store into TX data buffer. --- - IDLE Waits until buffer window is free (not bufferFull), --- - Waits for Application side SOF, --- - Save the segment to Rx buffer at nextSentAddr. Disable sending of NULL segments with appBusy flag, --- - When EOF received save segment length and keep flags. Check length error, --- - Request data send at Transport side FSM and increment nextSentAddr --- - Wait until the data is processed and data segment sent by Transport side FSM --- - Release appBusy flag and go back to INIT. --- Acknowledgment FSM. --- - IDLE Waits for ack_i (ack request) and ackN_i(ack number)(from RxFSM), --- - Increments firstUnackAddr until the ackN_i is found in Window buffer, --- - If it does not find the SEQ number it reports Ack Error, --- - Goes back to IDLE. --- Transport side FSM. Send and resend various segments to Transport side. --- - INIT Initializes seqN to initSeqN. Waits until new connection requested. ConnFSM goin out od Closed state. --- - DISS_CONN allows sending SYN, ACK, or RST segments. Goes to CONN when connection becomes active. --- - CONN allows sending DATA, NULL, ACK, or RST segments. --- In Resend procedure the FSM resends all the unacknowledged (DATA, NULL, RST) segments in the buffer window. --- --- Note:Sequence number is incremented with sending SYN, DATA, NULL, and RST segments. --- Note:Only the following segments are saved into Tx buffer DATA, NULL, and RST. -------------------------------------------------------------------------------- --- This file is part of 'SLAC Firmware Standard Library'. --- It is subject to the license terms in the LICENSE.txt file found in the --- top-level directory of this distribution and at: --- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. --- No part of 'SLAC Firmware Standard Library', including this file, --- may be copied, modified, propagated, or distributed except according to --- the terms contained in the LICENSE.txt file. -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.std_logic_arith.all; - - -library surf; -use surf.StdRtlPkg.all; -use surf.AxiStreamPkg.all; -use surf.AxiPkg.all; -use surf.AxiDmaPkg.all; -use surf.AxiRssiPkg.all; -use surf.RssiPkg.all; -use surf.SsiPkg.all; - -entity AxiRssiTxFsm is - generic ( - TPD_G : time := 1 ns; - AXI_CONFIG_G : AxiConfigType; - BURST_BYTES_G : positive := 1024; - WINDOW_ADDR_SIZE_G : positive := 3; -- 2^WINDOW_ADDR_SIZE_G = Number of segments - SEGMENT_ADDR_SIZE_G : positive := 7; -- 2^SEGMENT_ADDR_SIZE_G = Number of 64 bit wide data words - HEADER_CHKSUM_EN_G : boolean := true); - port ( - clk_i : in sl; - rst_i : in sl; - -- AXI Segment Buffer Interface - axiOffset_i : in slv(63 downto 0); - mAxiWriteMaster_o : out AxiWriteMasterType; - mAxiWriteSlave_i : in AxiWriteSlaveType; - mAxiReadMaster_o : out AxiReadMasterType; - mAxiReadSlave_i : in AxiReadSlaveType; - -- Inbound Application Interface - appMaster_i : in AxiStreamMasterType; - appSlave_o : out AxiStreamSlaveType; - -- Outbound Transport Interface - tspMaster_o : out AxiStreamMasterType; - tspSlave_i : in AxiStreamSlaveType; - -- Connection FSM indicating active connection - connActive_i : in sl; - -- Closed state in connFSM (initialize seqN) - closed_i : in sl; - -- Fault injection corrupts header checksum - injectFault_i : in sl; - -- Various segment requests - sndSyn_i : in sl; - sndAck_i : in sl; - sndRst_i : in sl; - sndResend_i : in sl; - sndNull_i : in sl; - -- Window buff size (Depends on the number of outstanding segments) - windowSize_i : in integer range 1 to 2 ** (WINDOW_ADDR_SIZE_G); - bufferSize_i : in integer range 1 to 2 ** (SEGMENT_ADDR_SIZE_G); - -- Header read - rdHeaderAddr_o : out slv(7 downto 0); - rdHeaderData_i : in slv(RSSI_WORD_WIDTH_C*8-1 downto 0); - -- Initial sequence number - initSeqN_i : in slv(7 downto 0); - -- Tx data (input to header decoder module) - txSeqN_o : out slv(7 downto 0); - -- FSM outs for header and data flow control - synHeadSt_o : out sl; - ackHeadSt_o : out sl; - dataHeadSt_o : out sl; - dataSt_o : out sl; - rstHeadSt_o : out sl; - nullHeadSt_o : out sl; - -- Last acked number (Used in Rx FSM to determine if AcnN is valid) - lastAckN_o : out slv(7 downto 0); - -- Acknowledge mechanism - ack_i : in sl; -- From receiver module when a segment with valid ACK is received - ackN_i : in slv(7 downto 0); -- Number being ACKed - --eack_i : in sl; -- From receiver module when a segment with valid EACK is received - --eackSeqnArr_i : in Slv8Array(0 to MAX_RX_NUM_OUTS_SEG_G-1); -- Array of sequence numbers received out of order - -- Errors (1 cc pulse) - lenErr_o : out sl; - ackErr_o : out sl; - -- Segment buffer indicator - bufferEmpty_o : out sl); -end entity AxiRssiTxFsm; - -architecture rtl of AxiRssiTxFsm is - - type TspStateType is ( - -- - INIT_S, - DISS_CONN_S, - CONN_S, - -- - SYN_H_S, - SYN_XSUM_S, - NSYN_H_S, - NSYN_XSUM_S, - DATA_H_S, - DATA_XSUM_S, - DATA_S, - -- - RESEND_INIT_S, - RESEND_H_S, - RESEND_XSUM_S, - RESEND_PP_S); - - type AppStateType is ( - IDLE_S, - WAIT_SOF_S, - DATA_S, - SEG_RDY_S); - - type AckStateType is ( - IDLE_S, - ERR_S, - -- EACK_S, - ACK_S); - - type RegType is record - ---------------------------------------------------- - -- Buffer window handling and acknowledgment control - ---------------------------------------------------- - windowArray : WindowTypeArray(0 to 2 ** WINDOW_ADDR_SIZE_G-1); - firstUnackAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); - nextSentAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); - lastSentAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); - lastAckSeqN : slv(7 downto 0); - --eackAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); - --eackIndex : integer; - bufferFull : sl; - bufferEmpty : sl; - ackErr : sl; - -- State Machine - ackState : AckStateType; - ----------------------- - -- Application side FSM - ----------------------- - wrReq : AxiWriteDmaReqType; - rxBufferAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); - rxSegmentWe : sl; - sndData : sl; - lenErr : sl; - appBusy : sl; - appSlave : AxiStreamSlaveType; - appState : AppStateType; - --------------------- - -- Transport side FSM - --------------------- - rdReq : AxiReadDmaReqType; - -- Checksum Calculation - csumAccum : slv(20 downto 0); - chksumOk : sl; - checksum : slv(15 downto 0); - -- Counters - nextSeqN : slv(7 downto 0); - seqN : slv(7 downto 0); - txHeaderAddr : slv(7 downto 0); - txBufferAddr : slv(WINDOW_ADDR_SIZE_G-1 downto 0); - -- Data mux flags - synH : sl; - ackH : sl; - rstH : sl; - nullH : sl; - dataH : sl; - dataD : sl; - resend : sl; - ackSndData : sl; - hdrAmrmed : sl; - simErrorDet : sl; - -- Various controls - buffWe : sl; - buffSent : sl; - -- Fault injection - injectFaultD1 : sl; - injectFaultReg : sl; - -- Transport Interface - rdDmaSlave : AxiStreamSlaveType; - tspMaster : AxiStreamMasterType; - -- State Machine - tspState : tspStateType; - end record RegType; - - constant REG_INIT_C : RegType := ( - ---------------------------------------------------- - -- Buffer window handling and acknowledgment control - ---------------------------------------------------- - -- Window control - firstUnackAddr => (others => '0'), - lastSentAddr => (others => '0'), - nextSentAddr => (others => '0'), - lastAckSeqN => (others => '0'), - --eackAddr => (others => '0'), - --eackIndex => 0, - bufferFull => '0', - bufferEmpty => '1', - windowArray => (0 to 2 ** WINDOW_ADDR_SIZE_G-1 => WINDOW_INIT_C), - ackErr => '0', - ackState => IDLE_S, - ----------------------- - -- Application side FSM - ----------------------- - wrReq => AXI_WRITE_DMA_REQ_INIT_C, - rxSegmentWe => '0', - rxBufferAddr => (others => '0'), - sndData => '0', - lenErr => '0', - appBusy => '0', - appSlave => AXI_STREAM_SLAVE_INIT_C, - appState => IDLE_S, - ---------------------- - -- Transport side FSM - ---------------------- - rdReq => AXI_READ_DMA_REQ_INIT_C, - -- - csumAccum => (others => '0'), - chksumOk => '0', - checksum => (others => '0'), - -- - nextSeqN => (others => '0'), - seqN => (others => '0'), - txHeaderAddr => (others => '0'), - txBufferAddr => (others => '0'), - -- - synH => '0', - ackH => '0', - rstH => '0', - nullH => '0', - dataH => '0', - dataD => '0', - resend => '0', - ackSndData => '0', - hdrAmrmed => '0', - simErrorDet => '0', - -- - buffWe => '0', - buffSent => '0', - -- Fault injection - injectFaultD1 => '0', - injectFaultReg => '0', - -- Transport Interface - rdDmaSlave => AXI_STREAM_SLAVE_INIT_C, - tspMaster => AXI_STREAM_MASTER_INIT_C, - -- State Machine - tspState => INIT_S); - - signal r : RegType := REG_INIT_C; - signal rin : RegType; - - signal wrAck : AxiWriteDmaAckType; - signal rdAck : AxiReadDmaAckType; - - signal wrDmaMaster : AxiStreamMasterType; - signal wrDmaSlave : AxiStreamSlaveType; - - signal rdDmaMaster : AxiStreamMasterType; - signal rdDmaSlave : AxiStreamSlaveType; - - -- attribute dont_touch : string; - -- attribute dont_touch of r : signal is "TRUE"; - -begin - - U_DmaWrite : entity surf.AxiStreamDmaWrite - generic map ( - TPD_G => TPD_G, - AXI_READY_EN_G => true, - AXIS_CONFIG_G => RSSI_AXIS_CONFIG_C, - AXI_CONFIG_G => AXI_CONFIG_G, - BURST_BYTES_G => BURST_BYTES_G, - AXI_BURST_G => "01", -- INCR - AXI_CACHE_G => "0011", -- Cacheable - SW_CACHE_EN_G => false, - ACK_WAIT_BVALID_G => true, - PIPE_STAGES_G => 0, - BYP_SHIFT_G => true, - BYP_CACHE_G => true) - port map ( - -- Clock/Reset - axiClk => clk_i, - axiRst => rst_i, - -- DMA Control Interface - dmaReq => r.wrReq, - dmaAck => wrAck, - -- Streaming Interface - axisMaster => wrDmaMaster, - axisSlave => wrDmaSlave, - -- AXI Interface - axiWriteMaster => mAxiWriteMaster_o, - axiWriteSlave => mAxiWriteSlave_i); - - U_DmaRead : entity surf.AxiStreamDmaRead - generic map ( - TPD_G => TPD_G, - AXIS_READY_EN_G => true, - AXIS_CONFIG_G => RSSI_AXIS_CONFIG_C, - AXI_CONFIG_G => AXI_CONFIG_G, - AXI_BURST_G => "01", -- INCR - AXI_CACHE_G => "0011", -- Cacheable - SW_CACHE_EN_G => false, - PIPE_STAGES_G => 0, - PEND_THRESH_G => 0, -- In units of bytes - BYP_SHIFT_G => true) - port map ( - -- Clock/Reset - axiClk => clk_i, - axiRst => rst_i, - -- DMA Control Interface - dmaReq => r.rdReq, - dmaAck => rdAck, - -- Streaming Interface - axisMaster => rdDmaMaster, - axisSlave => rdDmaSlave, - axisCtrl => AXI_STREAM_CTRL_UNUSED_C, - -- AXI Interface - axiReadMaster => mAxiReadMaster_o, - axiReadSlave => mAxiReadSlave_i); - - - ----------------------------------------------------------------------------------------------- - comb : process (ackN_i, ack_i, appMaster_i, axiOffset_i, bufferSize_i, - closed_i, connActive_i, initSeqN_i, injectFault_i, r, rdAck, - rdDmaMaster, rdHeaderData_i, rst_i, sndAck_i, sndNull_i, - sndResend_i, sndRst_i, sndSyn_i, tspSlave_i, windowSize_i, - wrAck, wrDmaSlave) is - - variable v : RegType; - variable maxSegSize : natural; - variable rxBufIdx : natural; - variable txBufIdx : natural; - begin - -- Latch the current value - v := r; - - -- Convert to bytes - maxSegSize := 8*bufferSize_i; - - -- Reset strobes - v.appSlave := AXI_STREAM_SLAVE_INIT_C; - v.ackSndData := '0'; - v.sndData := '0'; - v.lenErr := '0'; - - -- ///////////////////////////////////////////////////////// - ------------------------------------------------------------ - -- Buffer window handling - ------------------------------------------------------------ - -- ///////////////////////////////////////////////////////// - - ------------------------------------------------------------ - -- Buffer full if next slot is occupied - if (r.windowArray(conv_integer(v.rxBufferAddr)).occupied = '1') then - v.bufferFull := '1'; - else - v.bufferFull := '0'; - end if; - - ------------------------------------------------------------ - -- Buffer empty if next unacknowledged slot is unoccupied - if (r.windowArray(conv_integer(r.firstUnackAddr)).occupied = '0') then - v.bufferEmpty := '1'; - else - v.bufferEmpty := '0'; - end if; - - ------------------------------------------------------------ - -- Write seqN and segment type to window array - ------------------------------------------------------------ - if (r.buffWe = '1') then - v.windowArray(conv_integer(r.nextSentAddr)).seqN := r.nextSeqN; - v.windowArray(conv_integer(r.nextSentAddr)).segType := r.rstH & r.nullH & r.dataH; - v.windowArray(conv_integer(r.nextSentAddr)).occupied := '1'; - - -- Update last sent address when new segment is being sent - v.lastSentAddr := r.nextSentAddr; - else - v.windowArray := r.windowArray; - end if; - - ------------------------------------------------------------ - -- When buffer is sent increase nextSentAddr - ------------------------------------------------------------ - if (r.buffSent = '1') then - - if r.nextSentAddr < (windowSize_i-1) then - v.nextSentAddr := r.nextSentAddr +1; - else - v.nextSentAddr := (others => '0'); - end if; - - else - v.nextSentAddr := r.nextSentAddr; - end if; - - -- ///////////////////////////////////////////////////////// - ------------------------------------------------------------ - -- ACK FSM - -- Acknowledgment mechanism to increment firstUnackAddr - -- Place out of order flags from EACK table (Not in Version 1) - ------------------------------------------------------------ - -- ///////////////////////////////////////////////////////// - - case r.ackState is - ---------------------------------------------------------------------- - when IDLE_S => - - -- Hold ACK address - v.firstUnackAddr := r.firstUnackAddr; - v.lastAckSeqN := r.lastAckSeqN; - --v.eackAddr := r.firstUnackAddr; - --v.eackIndex := 0; - v.ackErr := '0'; - - -- Next state condition - if (ack_i = '1') then - v.ackState := ACK_S; - end if; - ---------------------------------------------------------------------- - when ACK_S => - - -- If the same ackN received do nothing - if (r.lastAckSeqN = ackN_i) then - v.firstUnackAddr := r.firstUnackAddr; - -- Increment ACK address until seqN is found next received - elsif r.firstUnackAddr < (windowSize_i-1) then - v.windowArray(conv_integer(r.firstUnackAddr)).occupied := '0'; - v.firstUnackAddr := r.firstUnackAddr+1; - else - v.windowArray(conv_integer(r.firstUnackAddr)).occupied := '0'; - v.firstUnackAddr := (others => '0'); - end if; - - --v.eackAddr := r.firstUnackAddr; - -- v.eackIndex := 0; - v.ackErr := '0'; - - -- Next state condition - - -- If the same ackN received - if (r.lastAckSeqN = ackN_i) then - - -- Go back to IDLE - v.ackState := IDLE_S; - - elsif (r.firstUnackAddr = r.lastSentAddr and r.windowArray(conv_integer(r.firstUnackAddr)).seqN /= ackN_i) then - -- If the acked seqN is not found go to error state - v.ackState := ERR_S; - elsif (r.windowArray(conv_integer(r.firstUnackAddr)).seqN = ackN_i) then - v.lastAckSeqN := ackN_i; -- Save the last Acked seqN - --if eack_i = '1' then - -- Go back to init when the acked seqN is found - -- v.ackState := EACK_S; - --else - -- Go back to init when the acked seqN is found - v.ackState := IDLE_S; - --end if; - end if; - ---------------------------------------------------------------------- - -- when EACK_S => - - -- -- Increment EACK address from firstUnackAddr to nextSentAddr - -- if r.eackAddr < (windowSize_i-1) then - -- v.eackAddr := r.eackAddr+1; - -- else - -- v.eackAddr := (others => '0'); - -- end if; - - -- -- For every address check if the sequence number equals value from eackSeqnArr_i array. - -- -- If it matches mark the eack field at the address and compare the next value from the table. - -- if r.windowArray(conv_integer(r.eackAddr)).seqN = eackSeqnArr_i(r.eackIndex) then - -- v.windowArray(conv_integer(r.eackAddr)).eacked := '1'; - -- v.eackIndex := r.eackIndex + 1; - -- end if; - - -- v.firstUnackAddr := r.firstUnackAddr; - -- v.ackErr := '0'; - - -- -- Next state condition - -- if (r.eackAddr = r.nextSentAddr) then - -- -- If the acked seqN is not found go to error state - -- v.ackState := IDLE_S; - -- end if; - ---------------------------------------------------------------------- - when ERR_S => - -- Outputs - v.firstUnackAddr := r.firstUnackAddr; - --v.eackAddr := r.firstUnackAddr; - --v.eackIndex := 0; - v.ackErr := '1'; - - -- Next state condition - v.ackState := IDLE_S; - ---------------------------------------------------------------------- - end case; - - -- ///////////////////////////////////////////////////////// - ------------------------------------------------------------ - -- Application side FSM - ------------------------------------------------------------ - -- ///////////////////////////////////////////////////////// - - -- Calculate the next DMA write transaction - rxBufIdx := conv_integer(r.rxBufferAddr); - v.wrReq.address := axiOffset_i + toSlv((rxBufIdx*maxSegSize), 64); - v.wrReq.maxSize := toSlv(maxSegSize, 32); - - ------------------------------------------------------------ - case r.appState is - ---------------------------------------------------------------------- - when IDLE_S => - -- Set the flag - v.appBusy := '1'; - -- Check if buffer if not full - if (v.bufferFull = '0') then - -- Next state - v.appState := WAIT_SOF_S; - end if; - ---------------------------------------------------------------------- - when WAIT_SOF_S => - -- Set the flag - v.appBusy := '0'; - -- If other segment (NULL, or RST) is requested return to IDLE_S to - -- check if buffer is still available (not full) - if (r.buffWe = '1') then - -- Increment the buffer window address because a NULL segment has filled the current spot - if r.rxBufferAddr < (windowSize_i-1) then - v.rxBufferAddr := r.rxBufferAddr+1; - else - v.rxBufferAddr := (others => '0'); - end if; - -- Set the flag - v.appBusy := '1'; - -- Next state - v.appState := IDLE_S; - -- Check for data - elsif (appMaster_i.tValid = '1') then - -- Check if SOF - if (ssiGetUserSof(RSSI_AXIS_CONFIG_C, appMaster_i) = '1') then - -- Set the flag - v.appBusy := '1'; - -- Start the DMA write transaction - v.wrReq.request := '1'; - -- Next State - v.appState := DATA_S; - else - -- Blow off the data - v.appSlave.tReady := '1'; - end if; - end if; - ---------------------------------------------------------------------- - when DATA_S => - -- Latch the segment size - v.windowArray(rxBufIdx).segSize := conv_integer(wrAck.size); - -- Check if DMA write completed - if (wrAck.done = '1') then - -- Reset the flag - v.wrReq.request := '0'; - -- Check for error - if (wrAck.writeError = '1') or (wrAck.overflow = '1') then - -- Set the flag - v.lenErr := '1'; - -- Next state - v.appState := IDLE_S; - else - -- Next state - v.appState := SEG_RDY_S; - end if; - end if; - ---------------------------------------------------------------------- - when SEG_RDY_S => - -- Request data transfer - v.sndData := '1'; - -- Hold request until accepted and not in resend process - if (r.ackSndData = '1') and (v.resend = '0') then - -- Increment the rxBuffer - if r.rxBufferAddr < (windowSize_i-1) then - v.rxBufferAddr := r.rxBufferAddr+1; - else - v.rxBufferAddr := (others => '0'); - end if; - -- Next state - v.appState := IDLE_S; - end if; - ---------------------------------------------------------------------- - end case; - - - -- ///////////////////////////////////////////////////////// - ------------------------------------------------------------ - -- Initialization of the parameters when the connection is broken - if (connActive_i = '0') then - v.firstUnackAddr := REG_INIT_C.firstUnackAddr; - v.lastSentAddr := REG_INIT_C.lastSentAddr; - v.nextSentAddr := REG_INIT_C.nextSentAddr; - v.rxBufferAddr := REG_INIT_C.rxBufferAddr; - v.bufferFull := REG_INIT_C.bufferFull; - v.bufferEmpty := REG_INIT_C.bufferEmpty; - v.windowArray := REG_INIT_C.windowArray; - v.lastAckSeqN := initSeqN_i; - v.ackState := REG_INIT_C.ackState; - v.appState := REG_INIT_C.appState; - end if; - ------------------------------------------------------------ - -- ///////////////////////////////////////////////////////// - - -- ///////////////////////////////////////////////////////// - ------------------------------------------------------------ - -- Arm fault injection on rising edge of injectFault_i - ------------------------------------------------------------ - -- /// ////////////////////////////////////////////////////// - v.injectFaultD1 := injectFault_i; - - if (injectFault_i = '1' and r.injectFaultD1 = '0') then - v.injectFaultReg := '1'; - else - v.injectFaultReg := r.injectFaultReg; - end if; - - - -- ///////////////////////////////////////////////////////// - ------------------------------------------------------------ - -- Transport side FSM - ------------------------------------------------------------ - -- ///////////////////////////////////////////////////////// - - -- Reset strobes - v.buffWe := '0'; - v.buffSent := '0'; - v.rdDmaSlave := AXI_STREAM_SLAVE_INIT_C; - if (tspSlave_i.tReady = '1') then - v.tspMaster.tValid := '0'; - v.tspMaster.tLast := '0'; - v.tspMaster.tUser := (others => '0'); - v.tspMaster.tKeep := (others => '1'); - end if; - - -- Calculate the next DMA read transaction - txBufIdx := conv_integer(r.txBufferAddr); - v.rdReq.address := axiOffset_i + toSlv((txBufIdx*maxSegSize), 64); - v.rdReq.size := toSlv(r.windowArray(txBufIdx).segSize, 32); - - -- Update the pipeline - GetRssiCsum( - -- Input - '0', -- init - (others => '0'), -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - - - case r.tspState is - ---------------------------------------------------------------------- - when INIT_S => - -- Initialize all - v := REG_INIT_C; - -- Register initial sequence number - v.nextSeqN := initSeqN_i; - v.seqN := r.nextSeqN; - -- Next state condition - if (closed_i = '0') then - -- Next state - v.tspState := DISS_CONN_S; - end if; - ---------------------------------------------------------------------- - when DISS_CONN_S => - -- Update the sequence indexes - v.nextSeqN := r.nextSeqN; - v.seqN := r.nextSeqN; - -- Update TX buffer address - v.txBufferAddr := r.nextSentAddr; - -- Reset RSSI flags - v.synH := '0'; - v.ackH := '0'; - v.rstH := '0'; - v.nullH := '0'; - v.dataH := '0'; - v.dataD := '0'; - v.resend := '0'; - v.hdrAmrmed := '0'; - -- Check for SYN - if (sndSyn_i = '1') then - -- Set the flag - v.synH := '1'; - -- Next state - v.tspState := SYN_H_S; - -- Check for ACK - elsif (sndAck_i = '1') then - -- Set the flag - v.ackH := '1'; - -- Next state - v.tspState := NSYN_H_S; - -- Check for RST - elsif (sndRst_i = '1') then - -- Set the flag - v.rstH := '1'; - -- Next state - v.tspState := NSYN_H_S; - -- Check for link up - elsif (connActive_i = '1') then - -- Next state - v.tspState := CONN_S; - -- Check for link down - elsif (closed_i = '1') then - -- Next state - v.tspState := INIT_S; - end if; - ---------------------------------------------------------------------- - when CONN_S => - -- Update TX buffer address - v.txBufferAddr := r.nextSentAddr; - -- Reset RSSI flags - v.synH := '0'; - v.ackH := '0'; - v.rstH := '0'; - v.nullH := '0'; - v.dataH := '0'; - v.dataD := '0'; - v.resend := '0'; - v.hdrAmrmed := '0'; - -- Check for RST - if (sndRst_i = '1') then - -- Set the flags - v.rstH := '1'; - -- Next state - v.tspState := NSYN_H_S; - -- Check for DATA - elsif (r.sndData = '1') and (r.bufferFull = '0') then - -- Set the flags - v.ackSndData := '1'; - v.dataH := '1'; - v.buffWe := '1'; -- Update buffer seqN and Type - -- Start the DMA read transaction - v.rdReq.request := '1'; - -- Next state - v.tspState := DATA_H_S; - -- Check for RESEND - elsif (sndResend_i = '1') and (r.bufferEmpty = '0') then - -- Next state - v.tspState := RESEND_INIT_S; - -- Check for ACK - elsif (sndAck_i = '1') then - -- Set the flag - v.ackH := '1'; - -- Next state - v.tspState := NSYN_H_S; - -- Check for NULL - elsif (sndNull_i = '1') and (r.bufferFull = '0') and (r.appBusy = '0') then - -- Set flags - v.nullH := '1'; - v.buffWe := '1'; -- Update buffer seqN and Type - -- Next state - v.tspState := NSYN_H_S; - -- Check for link down - elsif (connActive_i = '0') then - -- Next state - v.tspState := INIT_S; - end if; - ---------------------------------------------------------------------- - when SYN_H_S => - -- Set the flag - v.hdrAmrmed := '1'; - -- Check if ready to move data - if (r.tspMaster.tValid = '0') and (r.hdrAmrmed = '1') then -- Using registered value to help relax timing - -- Move the data - v.tspMaster.tValid := '1'; - v.tspMaster.tData(63 downto 0) := endianSwap64(rdHeaderData_i); - -- Increment the counter - v.txHeaderAddr := r.txHeaderAddr + 1; - -- Check for SOF - if (r.txHeaderAddr = 0) then - -- Set the SOF flag - ssiSetUserSof(RSSI_AXIS_CONFIG_C, v.tspMaster, '1'); - -- Calculate the checksum - GetRssiCsum( - -- Input - '1', -- init - rdHeaderData_i, -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - elsif (r.txHeaderAddr = 1) or (r.txHeaderAddr = 2) then - -- Calculate the checksum - GetRssiCsum( - -- Input - '0', -- init - rdHeaderData_i, -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - if (r.txHeaderAddr = 2) then - -- Keep counter value - v.txHeaderAddr := r.txHeaderAddr; - -- Hold off write - v.tspMaster.tValid := '0'; - -- Reset the flag - v.hdrAmrmed := '0'; - -- Next state - v.tspState := SYN_XSUM_S; - end if; - end if; - end if; - ---------------------------------------------------------------------- - when SYN_XSUM_S => - -- Set the flag - v.hdrAmrmed := '1'; - -- Check if ready to move data (r.tspMaster.tValid already '0' from previous state) - if (r.hdrAmrmed = '1') then -- Using registered value to help relax timing - -- Reset counter - v.txHeaderAddr := (others => '0'); - -- Move the data - v.tspMaster.tValid := '1'; - -- Set EOF flag - v.tspMaster.tLast := '1'; - -- Check if header checksum enable generic set - if (HEADER_CHKSUM_EN_G) then - -- Insert the checksum - v.tspMaster.tData(63 downto 56) := r.checksum(7 downto 0); - v.tspMaster.tData(55 downto 48) := r.checksum(15 downto 8); - end if; - -- Increment SEQ number at the end of segment transmission - v.nextSeqN := r.nextSeqN+1; - v.seqN := r.nextSeqN+1; - -- Next state - v.tspState := DISS_CONN_S; - end if; - ---------------------------------------------------------------------- - when NSYN_H_S => -- RST/ACK/NULL messages - -- Set the flag - v.hdrAmrmed := '1'; - -- Check if ready to move data - if (r.tspMaster.tValid = '0') and (r.hdrAmrmed = '1') then -- Using registered value to help relax timing - -- Set the data - v.tspMaster.tData(63 downto 0) := endianSwap64(rdHeaderData_i); - -- Calculate the checksum - GetRssiCsum( - -- Input - '1', -- init - rdHeaderData_i, -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - -- Reset the flag - v.hdrAmrmed := '0'; - -- Next state - v.tspState := NSYN_XSUM_S; - end if; - ---------------------------------------------------------------------- - when NSYN_XSUM_S => - -- Set the flag - v.hdrAmrmed := '1'; - -- Check if ready to move data (r.tspMaster.tValid already '0' from previous state) - if (r.hdrAmrmed = '1') then -- Using registered value to help relax timing - -- Move the data - v.tspMaster.tValid := '1'; - -- Set the SOF flag - ssiSetUserSof(RSSI_AXIS_CONFIG_C, v.tspMaster, '1'); - -- Set EOF flag - v.tspMaster.tLast := '1'; - -- Check if header checksum enable generic set - if (HEADER_CHKSUM_EN_G) then - -- Insert the checksum - v.tspMaster.tData(63 downto 56) := r.checksum(7 downto 0); - v.tspMaster.tData(55 downto 48) := r.checksum(15 downto 8); - end if; - -- Check for RST or NULL - if (r.rstH = '1') or (r.nullH = '1') then - -- Increment seqN - v.nextSeqN := r.nextSeqN+1; -- Increment SEQ number at the end of segment transmission - v.seqN := r.nextSeqN+1; - end if; - -- Increment the sent buffer - v.buffSent := r.nullH; - -- Check if link up - if connActive_i = '0' then - -- Next state - v.tspState := DISS_CONN_S; - else - -- Next state - v.tspState := CONN_S; - end if; - end if; - ---------------------------------------------------------------------- - when DATA_H_S => - -- Set the flag - v.hdrAmrmed := '1'; - -- Check if ready to move data - if (r.tspMaster.tValid = '0') and (r.hdrAmrmed = '1') then -- Using registered value to help relax timing - -- Set the data - v.tspMaster.tData(63 downto 0) := endianSwap64(rdHeaderData_i); - -- Calculate the checksum - GetRssiCsum( - -- Input - '1', -- init - rdHeaderData_i, -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - -- Reset the flag - v.hdrAmrmed := '0'; - -- Next state - v.tspState := DATA_XSUM_S; - end if; - ---------------------------------------------------------------------- - when DATA_XSUM_S => - -- Set the flag - v.hdrAmrmed := '1'; - -- Check if ready to move data (r.tspMaster.tValid already '0' from previous state) - if (r.hdrAmrmed = '1') then -- Using registered value to help relax timing - -- Move the data - v.tspMaster.tValid := '1'; - -- Set the SOF flag - ssiSetUserSof(RSSI_AXIS_CONFIG_C, v.tspMaster, '1'); - -- Check if header checksum enable generic set - if (HEADER_CHKSUM_EN_G) then - -- Inject fault into checksum - if (r.injectFaultReg = '1') then - -- Flip bits in checksum! Point of fault injection! - v.tspMaster.tData(63 downto 56) := not(r.checksum(7 downto 0)); - v.tspMaster.tData(55 downto 48) := not(r.checksum(15 downto 8)); - else - -- Insert the checksum - v.tspMaster.tData(63 downto 56) := r.checksum(7 downto 0); - v.tspMaster.tData(55 downto 48) := r.checksum(15 downto 8); - end if; - end if; - -- Set the fault reg to 0 - v.injectFaultReg := '0'; - -- Update the flags - v.dataH := '0'; - v.dataD := '1'; -- Send data - -- Next state - v.tspState := DATA_S; - end if; - ---------------------------------------------------------------------- - when DATA_S => - -- Check if ready to move data - if (v.tspMaster.tValid = '0') and (rdDmaMaster.tValid = '1') then - -- Accept the data - v.rdDmaSlave.tReady := '1'; - -- Move the data - v.tspMaster := rdDmaMaster; - -- Check for last transfer - if (rdDmaMaster.tLast = '1') then - -- Reset the flag - v.rdReq.request := '0'; - -- Check if not resending - if (r.resend = '0') then - -- Increment SEQ number at the end of segment transmission - v.nextSeqN := r.nextSeqN+1; - v.seqN := r.nextSeqN+1; - -- Increment buffer last sent address(txBuffer) - v.buffSent := '1'; - -- Next state - v.tspState := CONN_S; - else - -- Next state - v.tspState := RESEND_PP_S; - end if; - end if; - end if; - ---------------------------------------------------------------------- - -- Resend all packets from the buffer - -- Packets between r.firstUnackAddr and r.lastSentAddr - ---------------------------------------------------------------------- - when RESEND_INIT_S => - -- Check if first segment iteration of resending - if (r.resend = '0') then - -- Start from first unack address - v.txBufferAddr := r.firstUnackAddr; - -- Update the sequence indexes - v.nextSeqN := r.nextSeqN; -- Never increment seqN while resending - v.seqN := r.windowArray(conv_integer(r.firstUnackAddr)).seqN; - end if; - -- Update the RSSI flags - v.synH := '0'; - v.ackH := '0'; - v.rstH := r.windowArray(conv_integer(r.firstUnackAddr)).segType(2); - v.nullH := r.windowArray(conv_integer(r.firstUnackAddr)).segType(1); - v.dataH := r.windowArray(conv_integer(r.firstUnackAddr)).segType(0); - v.dataD := '0'; - v.resend := '1'; - -- Reset the flag - v.hdrAmrmed := '0'; - -- Next state condition - v.tspState := RESEND_H_S; - ---------------------------------------------------------------------- - when RESEND_H_S => - -- Set the flag - v.hdrAmrmed := '1'; - -- Check if ready to move data - if (r.tspMaster.tValid = '0') and (r.hdrAmrmed = '1') then -- Using registered value to help relax timing - -- Set the data - v.tspMaster.tData(63 downto 0) := endianSwap64(rdHeaderData_i); - -- Calculate the checksum - GetRssiCsum( - -- Input - '1', -- init - rdHeaderData_i, -- header - r.csumAccum, -- accumReg - -- Results - v.csumAccum, -- accumVar - v.chksumOk, -- chksumOk - v.checksum); -- checksum - -- Reset the flag - v.hdrAmrmed := '0'; - -- Next state - v.tspState := RESEND_XSUM_S; - end if; - ---------------------------------------------------------------------- - when RESEND_XSUM_S => - -- Set the flag - v.hdrAmrmed := '1'; - -- Check if ready to move data (r.tspMaster.tValid already '0' from previous state) - if (r.hdrAmrmed = '1') then -- Using registered value to help relax timing - -- Move the data - v.tspMaster.tValid := '1'; - -- Set the SOF flag - ssiSetUserSof(RSSI_AXIS_CONFIG_C, v.tspMaster, '1'); - -- Check if header checksum enable generic set - if (HEADER_CHKSUM_EN_G) then - -- Insert the checksum - v.tspMaster.tData(63 downto 56) := r.checksum(7 downto 0); - v.tspMaster.tData(55 downto 48) := r.checksum(15 downto 8); - end if; - -- Check for a Null or Rst packet - if (r.windowArray(txBufIdx).segType(2) = '1') or (r.windowArray(txBufIdx).segType(1) = '1') then - -- Set EOF flag - v.tspMaster.tLast := '1'; - -- Next state - v.tspState := RESEND_PP_S; - -- else resend the DATA packet start sending data - else - -- Start the DMA read transaction - v.rdReq.request := '1'; - -- Next state - v.tspState := DATA_S; - end if; - end if; - ---------------------------------------------------------------------- - when RESEND_PP_S => - -- Increment buffer address (circular) - if r.txBufferAddr < (windowSize_i-1) then - v.txBufferAddr := r.txBufferAddr+1; - else - v.txBufferAddr := (others => '0'); - end if; - -- Go back to CONN_S when the last sent address reached - if (r.txBufferAddr = r.lastSentAddr) then - -- Next state - v.tspState := CONN_S; - else - -- Next state - v.tspState := RESEND_INIT_S; - end if; - ---------------------------------------------------------------------- - end case; - - v.simErrorDet := (wrAck.overflow or wrAck.writeError or rdAck.readError); - -- if r.simErrorDet = '1' then - -- assert false - -- report "Simulation Failed!" severity failure; - -- end if; - - ---------------------------------------------------------------------- - -- Outputs -- - ---------------------------------------------------------------------- - - -- Inbound Application Interface - wrDmaMaster <= appMaster_i; - wrDmaMaster.tValid <= appMaster_i.tValid and r.wrReq.request; - appSlave_o.tReady <= v.appSlave.tReady or wrDmaSlave.tReady; - - -- Outbound Transport Interface - tspMaster_o <= r.tspMaster; - - -- DMA Read Interface - rdDmaSlave <= v.rdDmaSlave; - - -- Tx data (input to header decoder module) - txSeqN_o <= r.seqN; - - -- FSM outs for header and data flow control - rdHeaderAddr_o <= v.txHeaderAddr; - synHeadSt_o <= r.synH; - ackHeadSt_o <= r.ackH; - dataHeadSt_o <= r.dataH; - dataSt_o <= r.dataD; - rstHeadSt_o <= r.rstH; - nullHeadSt_o <= r.nullH; - - -- Last acked number (Used in Rx FSM to determine if AcnN is valid) - lastAckN_o <= r.lastAckSeqN; - - -- Errors (1 cc pulse) - ackErr_o <= r.ackErr; - lenErr_o <= r.lenErr; - - -- Segment buffer indicator - bufferEmpty_o <= r.bufferEmpty; - - -- Reset - if (rst_i = '1') then - v := REG_INIT_C; - end if; - - -- Register the variable for next clock cycle - rin <= v; - - end process comb; - - seq : process (clk_i) is - begin - if (rising_edge(clk_i)) then - r <= rin after TPD_G; - end if; - end process seq; - -end architecture rtl; diff --git a/protocols/rssi/v1b/ruckus.tcl b/protocols/rssi/v1b/ruckus.tcl deleted file mode 100644 index 7e52f14a5b..0000000000 --- a/protocols/rssi/v1b/ruckus.tcl +++ /dev/null @@ -1,8 +0,0 @@ -# Load RUCKUS library -source $::env(RUCKUS_PROC_TCL) - -# Load Source Code -loadSource -lib surf -dir "$::DIR_PATH/rtl" - -# Load Simulation -loadSource -lib surf -sim_only -dir "$::DIR_PATH/tb" diff --git a/protocols/rssi/v1b/tb/AxiRssiCoreTb.vhd b/protocols/rssi/v1b/tb/AxiRssiCoreTb.vhd deleted file mode 100644 index 007b9fcad8..0000000000 --- a/protocols/rssi/v1b/tb/AxiRssiCoreTb.vhd +++ /dev/null @@ -1,329 +0,0 @@ -------------------------------------------------------------------------------- --- Title : RSSI Protocol: https://confluence.slac.stanford.edu/x/1IyfD -------------------------------------------------------------------------------- --- Company : SLAC National Accelerator Laboratory -------------------------------------------------------------------------------- --- Description: Simulation Testbed for testing the AxiRssiCore -------------------------------------------------------------------------------- --- This file is part of 'SLAC Firmware Standard Library'. --- It is subject to the license terms in the LICENSE.txt file found in the --- top-level directory of this distribution and at: --- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. --- No part of 'SLAC Firmware Standard Library', including this file, --- may be copied, modified, propagated, or distributed except according to --- the terms contained in the LICENSE.txt file. -------------------------------------------------------------------------------- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.std_logic_arith.all; - - -library surf; -use surf.StdRtlPkg.all; -use surf.AxiPkg.all; -use surf.AxiStreamPkg.all; -use surf.AxiLitePkg.all; -use surf.SsiPkg.all; -use surf.AxiRssiPkg.all; -use surf.RssiPkg.all; - -entity AxiRssiCoreTb is -end AxiRssiCoreTb; - -architecture testbed of AxiRssiCoreTb is - - constant CLK_PERIOD_C : time := 10 ns; -- 1 us makes it easy to count clock cycles in sim GUI - constant TPD_G : time := CLK_PERIOD_C/4; - - -- RSSI Timeouts - constant CLK_FREQUENCY_C : real := 100.0E+6; -- In units of Hz - constant TIMEOUT_UNIT_C : real := 1.0E-6; -- In units of seconds - constant ACK_TOUT_C : positive := 25; -- unit depends on TIMEOUT_UNIT_G - constant RETRANS_TOUT_C : positive := 50; -- unit depends on TIMEOUT_UNIT_G (Recommended >= MAX_NUM_OUTS_SEG_G*Data segment transmission time) - constant NULL_TOUT_C : positive := 200; -- unit depends on TIMEOUT_UNIT_G (Recommended >= 4*RETRANS_TOUT_G) - -- Counters - constant MAX_RETRANS_CNT_C : positive := 3; - constant MAX_CUM_ACK_CNT_C : positive := 2; - - constant JUMBO_C : boolean := true; - constant AXI_CONFIG_C : AxiConfigType := ( - ADDR_WIDTH_C => ite(JUMBO_C, 16, 13), -- (true=64kB buffer),(false=8kB buffer) - DATA_BYTES_C => 8, -- 8 bytes = 64-bits - ID_BITS_C => 2, - LEN_BITS_C => ite(JUMBO_C, 8, 7)); -- (true=2kB bursting),(false=1kB bursting) - - type RegType is record - packetLength : slv(31 downto 0); - trig : sl; - txBusy : sl; - errorDet : sl; - end record RegType; - - constant REG_INIT_C : RegType := ( - packetLength => toSlv(0, 32), - trig => '0', - txBusy => '0', - errorDet => '0'); - - signal r : RegType := REG_INIT_C; - signal rin : RegType; - - signal clk : sl := '0'; - signal rst : sl := '0'; - - signal txMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - signal txSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_FORCE_C; - - signal ibSrvMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - signal ibSrvSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_FORCE_C; - signal obSrvMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - signal obSrvSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_FORCE_C; - - signal ibCltMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - signal ibCltSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_FORCE_C; - signal obCltMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - signal obCltSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_FORCE_C; - - signal axiWriteMasters : AxiWriteMasterArray(3 downto 0); - signal axiWriteSlaves : AxiWriteSlaveArray(3 downto 0); - signal axiReadMasters : AxiReadMasterArray(3 downto 0); - signal axiReadSlaves : AxiReadSlaveArray(3 downto 0); - - signal rxMaster : AxiStreamMasterType := AXI_STREAM_MASTER_INIT_C; - signal rxSlave : AxiStreamSlaveType := AXI_STREAM_SLAVE_FORCE_C; - - signal linkUp : sl; - signal updatedResults : sl; - signal errorDet : sl; - signal rxBusy : sl; - signal txBusy : sl; - -begin - - --------------------------- - -- Generate clock and reset - --------------------------- - U_ClkRst : entity surf.ClkRst - generic map ( - CLK_PERIOD_G => CLK_PERIOD_C, - RST_START_DELAY_G => 0 ns, - RST_HOLD_TIME_G => 1 us) - port map ( - clkP => clk, - rst => rst); - - ---------- - -- PRBS TX - ---------- - U_SsiPrbsTx : entity surf.SsiPrbsTx - generic map ( - TPD_G => TPD_G, - AXI_EN_G => '0', - MASTER_AXI_STREAM_CONFIG_G => RSSI_AXIS_CONFIG_C) - port map ( - -- Master Port (mAxisClk) - mAxisClk => clk, - mAxisRst => rst, - mAxisMaster => txMaster, - mAxisSlave => txSlave, - -- Trigger Signal (locClk domain) - locClk => clk, - locRst => rst, - packetLength => r.packetLength, - -- packetLength => toSlv(800,32), - trig => r.trig, - busy => txBusy); - - -------------- - -- RSSI Server - -------------- - U_RssiServer : entity surf.AxiRssiCoreWrapper - generic map ( - TPD_G => TPD_G, - JUMBO_G => JUMBO_C, - SERVER_G => true, -- Server - AXI_CONFIG_G => AXI_CONFIG_C, - -- AXIS Configurations - APP_AXIS_CONFIG_G => (0 => RSSI_AXIS_CONFIG_C), - TSP_AXIS_CONFIG_G => RSSI_AXIS_CONFIG_C, - -- RSSI Timeouts - CLK_FREQUENCY_G => CLK_FREQUENCY_C, - TIMEOUT_UNIT_G => TIMEOUT_UNIT_C, - ACK_TOUT_G => ACK_TOUT_C, - RETRANS_TOUT_G => RETRANS_TOUT_C, - NULL_TOUT_G => NULL_TOUT_C, - -- Counters - MAX_RETRANS_CNT_G => MAX_RETRANS_CNT_C, - MAX_CUM_ACK_CNT_G => MAX_CUM_ACK_CNT_C) - port map ( - clk => clk, - rst => rst, - openRq => '1', - -- AXI TX Segment Buffer Interface - txAxiOffset => (others => '0'), - txAxiWriteMaster => axiWriteMasters(0), - txAxiWriteSlave => axiWriteSlaves(0), - txAxiReadMaster => axiReadMasters(0), - txAxiReadSlave => axiReadSlaves(0), - -- AXI RX Segment Buffer Interface - rxAxiOffset => (others => '0'), - rxAxiWriteMaster => axiWriteMasters(1), - rxAxiWriteSlave => axiWriteSlaves(1), - rxAxiReadMaster => axiReadMasters(1), - rxAxiReadSlave => axiReadSlaves(1), - -- Application Layer Interface - sAppAxisMasters(0) => txMaster, - sAppAxisSlaves(0) => txSlave, - mAppAxisSlaves(0) => AXI_STREAM_SLAVE_FORCE_C, - -- Transport Layer Interface - sTspAxisMaster => ibSrvMaster, - sTspAxisSlave => ibSrvSlave, - mTspAxisMaster => obSrvMaster, - mTspAxisSlave => obSrvSlave); - - -------------- - -- RSSI Client - -------------- - U_RssiClient : entity surf.AxiRssiCoreWrapper - generic map ( - TPD_G => TPD_G, - JUMBO_G => JUMBO_C, - SERVER_G => false, -- Client - AXI_CONFIG_G => AXI_CONFIG_C, - -- AXIS Configurations - APP_AXIS_CONFIG_G => (0 => RSSI_AXIS_CONFIG_C), - TSP_AXIS_CONFIG_G => RSSI_AXIS_CONFIG_C, - -- RSSI Timeouts - CLK_FREQUENCY_G => CLK_FREQUENCY_C, - TIMEOUT_UNIT_G => TIMEOUT_UNIT_C, - ACK_TOUT_G => ACK_TOUT_C, - RETRANS_TOUT_G => RETRANS_TOUT_C, - NULL_TOUT_G => NULL_TOUT_C, - -- Counters - MAX_RETRANS_CNT_G => MAX_RETRANS_CNT_C, - MAX_CUM_ACK_CNT_G => MAX_CUM_ACK_CNT_C) - port map ( - clk => clk, - rst => rst, - openRq => '1', - linkUp => linkUp, - -- AXI TX Segment Buffer Interface - txAxiOffset => (others => '0'), - txAxiWriteMaster => axiWriteMasters(2), - txAxiWriteSlave => axiWriteSlaves(2), - txAxiReadMaster => axiReadMasters(2), - txAxiReadSlave => axiReadSlaves(2), - -- AXI RX Segment Buffer Interface - rxAxiOffset => (others => '0'), - rxAxiWriteMaster => axiWriteMasters(3), - rxAxiWriteSlave => axiWriteSlaves(3), - rxAxiReadMaster => axiReadMasters(3), - rxAxiReadSlave => axiReadSlaves(3), - -- Application Layer Interface - sAppAxisMasters(0) => AXI_STREAM_MASTER_INIT_C, - mAppAxisMasters(0) => rxMaster, - mAppAxisSlaves(0) => rxSlave, - -- Transport Layer Interface - sTspAxisMaster => ibCltMaster, - sTspAxisSlave => ibCltSlave, - mTspAxisMaster => obCltMaster, - mTspAxisSlave => obCltSlave); - - ------------- - -- AXI Memory - ------------- - GEN_VEC : for i in 3 downto 0 generate - U_MEM : entity surf.AxiRam - generic map ( - TPD_G => TPD_G, - SYNTH_MODE_G => "xpm", - AXI_CONFIG_G => AXI_CONFIG_C) - port map ( - -- Clock and Reset - axiClk => clk, - axiRst => rst, - -- Slave Write Interface - sAxiWriteMaster => axiWriteMasters(i), - sAxiWriteSlave => axiWriteSlaves(i), - -- Slave Read Interface - sAxiReadMaster => axiReadMasters(i), - sAxiReadSlave => axiReadSlaves(i)); - end generate GEN_VEC; - - ---------- - -- PRBS RX - ---------- - U_SsiPrbsRx : entity surf.SsiPrbsRx - generic map ( - TPD_G => TPD_G, - SLAVE_AXI_STREAM_CONFIG_G => RSSI_AXIS_CONFIG_C) - port map ( - -- Slave Port (sAxisClk) - sAxisClk => clk, - sAxisRst => rst, - sAxisMaster => rxMaster, - sAxisSlave => rxSlave, - -- Error Detection Signals (sAxisClk domain) - updatedResults => updatedResults, - errorDet => errorDet, - busy => rxBusy); - - comb : process (errorDet, ibCltSlave, ibSrvSlave, linkUp, obCltMaster, - obSrvMaster, r, rst, txBusy) is - variable v : RegType; - begin - -- Latch the current value - v := r; - - -- Keep delay copies - v.errorDet := errorDet; - v.txBusy := txBusy; - v.trig := not(r.txBusy) and linkUp; - - -- Check for the packet completion - if (txBusy = '1') and (r.txBusy = '0') then - -- Sweeping the packet size size - v.packetLength := r.packetLength + 1; - end if; - - -- Reset - if (rst = '1') then - v := REG_INIT_C; - end if; - - --------------------------------- - -- Simulation Error Self-checking - --------------------------------- - if r.errorDet = '1' then - assert false - report "Simulation Failed!" severity failure; - end if; - - if (r.packetLength < 8192) then - -- if (r.packetLength < 128) then - ibSrvMaster <= obCltMaster; - obCltSlave <= ibSrvSlave; - ibCltMaster <= obSrvMaster; - obSrvSlave <= ibCltSlave; - else -- Emulation a cable being disconnected - ibSrvMaster <= AXI_STREAM_MASTER_INIT_C; - obCltSlave <= AXI_STREAM_SLAVE_FORCE_C; - ibCltMaster <= AXI_STREAM_MASTER_INIT_C; - obSrvSlave <= AXI_STREAM_SLAVE_FORCE_C; - end if; - - -- Register the variable for next clock cycle - rin <= v; - - end process comb; - - seq : process (clk) is - begin - if (rising_edge(clk)) then - r <= rin after TPD_G; - end if; - end process seq; - -end testbed;