📄 usb_new_sie_rtl.vhdl
字号:
------------------------------------------------------------------------
-- 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 + -