⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_new_sie_rtl.vhdl

📁 实现USB接口功能的VHDL和verilog完整源代码
💻 VHDL
📖 第 1 页 / 共 3 页
字号:

    
  ------------------------------------------------------------------------
  --                           Sync Detector                            --
  ------------------------------------------------------------------------

    -- DOC_BEGIN: Detection of a sync pattern
    -- The four last incoming bits are compared to the pattern 'KJKK',
    -- which is the end of the sync pattern (KJKJKJKK).
    -- The first few bits are not used because they can be missed as the
    -- clock is not synchronized to the data stream yet.

    SyncDetected := FALSE;
    if ( (not TxUsbEnable) and 
       ( (RxUsbLogValue    = USB_LOG_K) and
	 (RxUsbLogValue_Z1 = USB_LOG_K) and
	 (RxUsbLogValue_Z2 = USB_LOG_J) and
	 (RxUsbLogValue_Z3 = USB_LOG_K))) then
      SyncDetected := TRUE;
    end if;

    -- DOC_END

  ------------------------------------------------------------------------
  --                      End Of Packet Detector                        --
  ------------------------------------------------------------------------


    -- DOC_BEGIN: End of Packet detection
    -- An end of packet consists of at least one SE0, followed by a J.
    -- When an SE0 is received, the SE0Detect flag is set. When after this
    -- a J is received, this is considered as a valid end of packet.
    -- Otherwise an error is generated.
    EndOfPacket := FALSE;
    if (not TxUsbEnable) then  
      if (RxUsbLogValue = USB_LOG_SE0) then
	SE0Detected := TRUE;
      elsif SE0Detected then
	SE0Detected := FALSE;
	if (RxUsbLogValue = USB_LOG_J) then
          if not TimeOutStarted then
	    EndOfPacket := TRUE;
          end if;  
	else
	  SetError(ERROR_TR_EOP);
	end if;
      end if;

      -- reset LowSpeedTransaction one every (FALSE) EOP
      if MAX_DEVICE_SPEED = USB_FULL_SPEED then
	SIE_LowSpeedTransaction <= FALSE;
      end if;
    end if;

    -- DOC_END

  ------------------------------------------------------------------------
  --                     Main FSM                                       --
  ------------------------------------------------------------------------

    Ready := FALSE;
    StartTimeOut := FALSE;
    StopTimeOut := FALSE;
    InitCRC := FALSE;
    EvalCrc := FALSE;
    PidReady := FALSE;
    if MAX_DEVICE_SPEED = USB_FULL_SPEED then
      SIE_SOFByte1 <= FALSE;
      SIE_SOFByte2 <= FALSE;
    end if;
    SIE_RxDataRdy <= FALSE;
    SIE_TxDataAck <= FALSE;
    TxUsbLogValue <= USB_LOG_J;
    TxUsbEnable <= FALSE;
    SIE_StartEndpSearch <= FALSE;
    BitstuffError := FALSE;
    BitValue := '0';

    -- Delayed input, for NRZI decoding
    TxUsbLogValue_Z <= TxUsbLogValue;


    -- DOC_BEGIN: Main State Machine
    -- The Main State Machine handles the USB protocol. It determines the
    -- order of packets, using the procedures to send or receive these
    -- packets.
    -- The possible sequences are:

    -- Receive OUT Token - Receive Data 

    -- Receive OUT Token - Receive Data - Send Handshake

    -- Receive IN Token - Send Data 

    -- Receive IN Token - Send Handshake

    -- Receive IN Token - Send Data - Receive Handshake

    case PMState is


    -- In the PM_WAIT_FOR_REQUEST state, the SIE waits for an IN, OUT
    -- or SETUP token. Other tokens (SOF, PRE) are handled in the 
    -- ReceiveToken procedure.
    -- Depending on the token, the state machine jumps to the
    -- PROCESS_IN or PROCESS_OUT_SETUP state.

      when PM_WAIT_FOR_REQUEST =>
	-- Any transaction should start with a request
	-- in the form of a token. (IN/OUT/SETUP/SOF)
	ReceiveToken;
	if (MAX_DEVICE_SPEED = USB_FULL_SPEED) and PidReady and (PidType = PID_PRE) then
	  -- PRE is not a complete token : it has no EOP
	  SIE_LowSpeedTransaction <= TRUE;
        elsif EndOfPacket then -- Token received, but possibly with an error
	  case PidType is
	    when PID_IN =>
	      PMState := PM_PROCESS_IN;
	    when PID_OUT | PID_SETUP =>
	      TimeOutCnt := DEVICE_TIMEOUT + 7;
	      StartTimeOut := TRUE;
	      PMState := PM_PROCESS_OUT_SETUP;
	    when others =>
	      -- SOF or Not a valid token pid, so wait for the next one
	      -- (SOF is already handled in ReceiveToken)
	      null;
	    end case;
	end if;


      -- The PM_PROCESS_IN state answers IN Tokens. This answer can be
      -- a handshake or a data packet, depending on the availability of
      -- data. If the answer was a data packet, the state machine jumps to
      -- the RECEIVE_HANDSHAKE state or to the WAIT_FOR_REQUEST state,
      -- depending on the endpoint properties. If the answer was a
      -- handshake, the state machine always goes to the WAIT_FOR_REQUEST
      -- state to accept the next token.

      when PM_PROCESS_IN =>
	-- Host requesting input from function, wait until the MM block
	-- has determined access is for this device
	if (MM_EndpSearchReady) then 
	  if (MM_EndpSearchSelected) then
	    -- The device was addressed and the endpoint number is
	    -- valid -> must respond
	    if MM_Accepted or MM_ISO then
	      -- Data are available or the endpoint is isochronous
	      -- -> A data packet should be sent (which can be empty
	      -- in the case of an iso endpoint that has no data)
	      if not PacketSent then
		SendData;
	      end if;
	    else
	      -- No data are available and the endpoint is not iso
	      -- -> send a handshake
	      if not PacketSent then
		SendHandshake;
	      end if;
	    end if;
	    if EndOfPacket then
	      -- wait for handshake if data are sent and not ISO
	      -- otherwise goto IDLE
	      if MM_ISO or (not MM_Accepted) then         
		PMState := PM_WAIT_FOR_REQUEST;
                --  Reset PidType
                PidType := PID_INVALID;
	      else
		PMState := PM_RECEIVE_HANDSHAKE;
		StartTimeOut := TRUE; -- to receive handshake
		TimeOutCnt := DEVICE_TIMEOUT + 7;
	      end if;
	    end if;
	  else
	    PMState := PM_WAIT_FOR_REQUEST;
            --  Reset PidType
            PidType := PID_INVALID;
	  end if;
	end if;


      -- The RECEIVE_HANDSHAKE state is used to receive a handshake  
      -- after sending a data packet. At the end of the handshake, the
      -- state machine jumps to the WAIT_FOR_REQUEST state to accept
      -- the next token. 

      when PM_RECEIVE_HANDSHAKE =>
	ReceiveHandshake;
	if EndOfPacket then
	  PMState := PM_WAIT_FOR_REQUEST;
          --  Reset PidType
          PidType := PID_INVALID;
        end if;

      -- The PROCESS_OUT_SETUP state is used to receive a data packet 
      -- after a SETUP or OUT token. After reception of the data packet
      -- a can jump to the SEND_HANDSHAKE or WAIT_FOR_REQUEST state, 
      -- depending on the endpoint properties.

      when PM_PROCESS_OUT_SETUP =>
	-- Host sending output to function
	ReceiveData;
	if EndOfPacket then
	  if MM_EndpSearchReady then
	    if MM_EndpSearchSelected then
	      if MM_ISO then         
		-- endpoint is iso, so transfer is done
		PMState := PM_WAIT_FOR_REQUEST;
                --  Reset PidType
                PidType := PID_INVALID;
	      else
		-- endpoint is not iso so send a handshake
		PMState := PM_SEND_HANDSHAKE;
	      end if;
	    else
	      PMState := PM_WAIT_FOR_REQUEST;
              --  Reset PidType
              PidType := PID_INVALID;
	    end if;
	  end if;
	end if;


      -- The SEND_HANDSHAKE state is used to send a handshake 
      -- after receiving a data packet. When the handshake is sent,
      -- The state machine goes to the WAIT_FOR_REQUEST state for
      -- accepting the next token.

      when others =>
	if not PacketSent then
	  SendHandshake;
	end if;
	if EndOfPacket then
	  PMState := PM_WAIT_FOR_REQUEST;
          --  Reset PidType
          PidType := PID_INVALID;
	end if;

    end case; -- PMState
    -- DOC_END


    -- DOC_BEGIN: Error Handling and State Machine Reset
    -- At the end of each packet, the packet state machine is reset. In the case
    -- of an error, both packet and protocol state machines are reset. 
    -- Precautions are taken that the state machines can never be reset while
    -- sending (especially for babble error, which is an error that occurs while
    -- sending).

    if EndOfPacket or Error or 
      (SUPPORT_HUB and PMState = PM_RECEIVE_HANDSHAKE and MM_EmbeddedBabbled) then
      RxTxState := SOP;
      PacketSent := FALSE;
      DataWord := SYNC_PATTERN;
      Position := 0;
      if (MAX_DEVICE_SPEED = USB_FULL_SPEED) then
	SIE_RxSOF <= FALSE;
      end if;
    end if;

    if Error or
      (SUPPORT_HUB and PMState = PM_RECEIVE_HANDSHAKE and MM_EmbeddedBabbled) then
      PMState := PM_WAIT_FOR_REQUEST;
      PidType := PID_INVALID;
      if MAX_DEVICE_SPEED = USB_FULL_SPEED then
	SIE_LowSpeedTransaction <= FALSE;
      end if;
    end if;
    -- DOC_END 

    -- DOC_BEGIN: Remote Wake up
    -- If TM_SendResume is asserted, a remote wake up is sent, regardless 
    -- the state of the other state machines (since a remote wake up can only
    -- be sent after 5 ms of idle on the bus, the state should be WAIT_FOR_REQUEST).

    if SUPPORT_RESUME and TM_SendResume then
      TxUsbLogValue <= USB_LOG_K;
      TxUsbEnable   <= TRUE;
    end if;
    -- DOC_END 

  ------------------------------------------------------------------------
  --                     TimeOut Handling                               --
  ------------------------------------------------------------------------

    -- DOC_BEGIN: Time Out Timing
    -- The time out timer is controlled by the StartTimeOut and StopTimeout
    -- flags. When the timer expires before it is stopped, the TimeOut flag
    -- is asserted, which generates an error.

    if TimeOutStarted and (not StopTimeOut) then
      assert (StartTimeOut = FALSE)
	report "Restarting already running timeout"
	severity note;
      --  Make sure that TimeOutCnt can not become negative
      if TimeOutCnt /= 0 then
        TimeOutCnt := TimeOutCnt -1;
      end if;
      if TimeOutCnt = 0 then
	TimeOut := TRUE;
      end if;
    elsif StartTimeOut then
      TimeOutStarted := TRUE;
    elsif StopTimeOut then
      TimeOutStarted := FALSE;
    end if;
    -- DOC_END

  ------------------------------------------------------------------------
  --                     CRC Generation and check                       --
  ------------------------------------------------------------------------

    -- DOC_BEGIN: CRC calculation and check
    -- CRC calculation and checks are controlled by the InitCRC flag which
    -- initializes the CRC to all 1's and the EvalCRC flag which updates
    -- the CRC with the current bit value.
    --
    -- At every byte boundary, the Crc5Ok and Crc16Ok flags, which indicate
    -- that the CRC equals the required residual, are updated.
    -- This update is only done at byte boundaries to avoid updates on dribble
    -- bits.


    if (InitCrc) then
      Crc5  := (others => '1');
      Crc16 := (others => '1');
    elsif (EvalCrc) then
      Crc5  := MultipleCRC5_D1(BitValue, Crc5);
      Crc16 := MultipleCRC16_D1(BitValue, Crc16);
    end if;

    if Position = 0 and (RxTxState /= SOP) then
      Crc5ok  := (Crc5  = CRC5_RESIDUAL);
      Crc16ok := (Crc16 = CRC16_RESIDUAL);
    end if;
    -- DOC_END

    SIE_RxEOP <= EndOfPacket;
    SIE_RxPidRdy <= PidReady;
    RxPid <= PidType;
    RxError <= Error;
    RxErrorType <= ErrorType;

	    

  end if; -- FsClk-Reset_N
end process MAIN;


end RTL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -