📄 usb_new_sie_rtl.vhdl
字号:
EvalCrc := TRUE;
ReceiveWord;
if SE0Detected then
SetError(ERROR_TR_EOP);
end if;
if Ready and (not Error) then
SIE_RxData <= DataWord;
-- Pass second Frame Number byte
if (MAX_DEVICE_SPEED = USB_FULL_SPEED) and PidType = PID_SOF then
SIE_SOFByte2 <= TRUE;
end if;
RxTxState := EOP;
end if;
-- Endpoint Number is ready when the first 3 bits are received.
-- There is no time enough to wait until the end of the byte before
-- passing it to the MM
if (Position = 3) and (not Error) then -- Endpoint Complete
SIE_RxData <= "0000" & DataWord(2 downto 0) & SaveBit;
SIE_RxDataRdy <= TRUE;
end if;
when others => -- EOP
if EndOfPacket then
RxTxState := SOP;
-- end RxSOF pulse
if (MAX_DEVICE_SPEED = USB_FULL_SPEED) then
SIE_RxSOF <= FALSE;
end if;
if (not CRC5ok) then
SetError(ERROR_TOKEN_CRC);
end if;
else
ReceiveWord;
-- 2 dribble bits allowed, at position 0 and 1
if Position >1 then
SetError(ERROR_TR_EOP);
end if;
end if;
end case;
end ReceiveToken;
-- DOC_END
-- DOC_BEGIN: Procedure for receiving a handshake
-- This procedure takes care of receiving a complete handshake.
-- In the Start of Packet (SOF) state, it waits for the end of a
-- sync pattern. When this is received, the Packet Identifier (PID)
-- state is entered, where the packet PID is received using the
-- ReceiveWord procedure.
-- If the sync pattern is not received within the allowed turn
-- around time, a timeout error is generated.
-- In the EOP state, an end of packet should come in after at most
-- 2 dribble bits.
procedure ReceiveHandshake is
begin
case RxTxState is
when SOP =>
if (TimeOut) then
-- Packet not received before timeout
StopTimeOut := TRUE;
SetError(ERROR_TIMEOUT);
TimeOut := FALSE;
elsif SyncDetected then
StopTimeOut := TRUE;
Error := FALSE; -- clear possible previous error
BitstuffCnt := 0;
RxTxState := PID;
InitCrc := TRUE;
end if;
when PID =>
ReceiveWord;
if SE0Detected then
SetError(ERROR_TR_EOP);
end if;
if Ready then
if (not Error) then
CheckPidPacket(DataWord, PACKET_HANDSHAKE,
PidType, PacketType, Error, ErrorType);
end if;
if (not Error) then
PidReady := TRUE;
RxTxState := EOP;
end if;
end if;
when others => -- EOP
if EndOfPacket then
RxTxState := SOP;
else
ReceiveWord;
if Position >1 then
SetError(ERROR_TR_EOP);
end if;
end if;
end case; -- RxTxState
end ReceiveHandshake;
-- DOC_END
-- DOC_BEGIN: Procedure for receiving a data packet
-- This procedure takes care of receiving a complete data packet.
-- In the Start of Packet (SOF) state, it waits for the end of a
-- sync pattern. When this is received, the Packet Identifier (PID)
-- state is entered, where the packet PID is received using the
-- ReceiveWord procedure.
-- If the sync pattern is not received within the allowed token - data
-- time, a timeout error is generated.
-- After the PID, the DATA state is entered, until an SE0 is received.
-- At that moment, the 16 bit CRC is evaluated, and the EOP state is
-- entered.
procedure ReceiveData is
begin
case RxTxState is
when SOP =>
if (TimeOut) then
-- Data Packet not received before timeout
StopTimeOut := TRUE;
SetError(ERROR_TIMEOUT);
TimeOut := FALSE;
elsif SyncDetected then
StopTimeOut := TRUE;
Error := FALSE; -- clear possible previous error
BitstuffCnt := 0;
RxTxState := PID;
InitCrc := TRUE;
end if;
when PID =>
ReceiveWord;
if Ready then
if (not Error) then
CheckPidPacket(DataWord, PACKET_DATA,
PidType, PacketType, Error, ErrorType);
end if;
if (not Error) then
PidReady := TRUE;
RxTxState := DATA;
end if;
end if;
if SE0Detected then
SetError(ERROR_TR_EOP);
end if;
when DATA =>
EvalCrc := TRUE;
ReceiveWord;
-- Receive data until an EOP is seen
if Ready and (not Error) then
if SE0Detected then
RxTxState := EOP;
else
SIE_RxData <= DataWord;
SIE_RxDataRdy <= TRUE;
end if;
end if;
when others => -- EOP
if (not CRC16ok) then
SetError(ERROR_DATA_CRC);
end if;
if EndOfPacket then
RxTxState := SOP;
elsif not SE0Detected and Position >1 then
SetError(ERROR_TR_EOP);
end if;
end case;
end ReceiveData;
-- DOC_END
-----------------------------------------------------------------------
-- Tx Procedures --
-----------------------------------------------------------------------
-- DOC_BEGIN: Procedure to send a data packet
-- This procedure sends a data packet. After the sync pattern
-- and the PID, data are sent as long as available. When no data
-- are available anymore, the CRC is added, followed by an EOP.
procedure SendData is
begin
case RxTxState is
when SOP =>
DataWord := SYNC_PATTERN;
SendWord;
if Ready then
RxTxState := PID;
InitCrc := TRUE;
end if;
when PID =>
if MM_TxData1Pid then
DataWord := EncodePid(PID_DATA1);
else
DataWord := EncodePid(PID_DATA0);
end if;
SendWord;
if Ready then
-- if data are available, fetch them, otherwise
-- send CRC
if MM_TxDataRdy then
SIE_TxDataAck <= TRUE;
DataWord := MM_TxData;
RxTxState := DATA;
else
RxTxState := CRC1;
end if;
end if;
when DATA =>
EvalCrc := TRUE;
SendWord;
if Ready then
if MM_TxDataRdy then
SIE_TxDataAck <= TRUE;
DataWord := MM_TxData;
else
RxTxState := CRC1;
end if;
end if;
when CRC1 =>
Crc16_tmp := Crc16(15 downto 8);
DataWord := InsertWord(DataWord, not(Crc16_tmp),
Position => 0, RevIns => TRUE);
SendWord;
if Ready then
RxTxState := CRC2;
end if;
when CRC2 =>
DataWord := InsertWord(DataWord, not(Crc16(7 downto 0)),
Position => 0, RevIns => TRUE);
SendWord;
if Ready then
RxTxState := EOP;
end if;
when others => -- EOP
-- Reset the DataWord during EOP to avoid bitstuffing
DataWord := (others => not BITSTUFF_VALUE);
SendEOP;
if Ready then
RxTxState := SOP;
end if;
end case; -- RxTxState
end SendData;
-- DOC_END
-- DOC_BEGIN: Procedure for sending a handshake
-- This procedure sends a handshake packet, consisting of 3 parts:
-- a sync pattern, the PID and an EOP.
procedure SendHandshake is
begin
case RxTxState is
when SOP =>
DataWord := SYNC_PATTERN;
SendWord;
if Ready then
RxTxState := PID;
InitCrc := TRUE;
end if;
when PID =>
if MM_Stalled then
DataWord := EncodePid(PID_STALL);
elsif MM_Accepted then
DataWord := EncodePid(PID_ACK);
else
DataWord := EncodePid(PID_NAK);
end if;
SendWord;
if Ready then
RxTxState := EOP;
end if;
when others => -- EOP
-- Reset the dataword during EOP to avoid bitstuffing
DataWord := (others => not BITSTUFF_VALUE);
SendEOP;
if Ready then
RxTxState := SOP;
end if;
end case; -- SHState
end SendHandshake;
-- DOC_END
begin
if (Reset_N = ACTIVE_LOW) then
PMState := PM_WAIT_FOR_REQUEST;
TxUsbLogValue_Z <= USB_LOG_J;
RxTxState := SOP;
SIE_RxDataRdy <= FALSE;
SIE_RxData <= (others => '0');
ErrorType := ERROR_NO_ERROR;
Error := FALSE;
RxErrorType <= ERROR_NO_ERROR;
RxError <= FALSE;
SIE_RxPidRdy <= FALSE;
RxPid <= PID_INVALID;
SIE_TxDataAck <= FALSE;
if MAX_DEVICE_SPEED = USB_FULL_SPEED then
SIE_LowSpeedTransaction <= FALSE;
SIE_SOFByte1 <= FALSE;
SIE_SOFByte2 <= FALSE;
SIE_RxSOF <= FALSE;
end if;
SIE_StartEndpSearch <= FALSE;
SIE_RxEOP <= FALSE;
PidType := PID_INVALID;
SaveBit := LOW;
TimeOutCnt := 0;
TimeOutStarted := FALSE;
TimeOut := FALSE;
PidReady := FALSE;
Position := 0;
BitstuffCnt := 0;
BitValue := '0';
DataWord := (others => '0');
Crc16 := (others => '0');
Crc5 := (others => '0');
Crc16ok := FALSE;
Crc5ok := FALSE;
TxUsbLogValue <= USB_LOG_J;
TxUsbEnable <= FALSE;
BitstuffError := FALSE;
EndOFPacket := FALSE;
SyncDetected := FALSE;
SE0Detected := FALSE;
PacketSent := FALSE;
RxUsbLogValue <= USB_LOG_J;
RxUsbLogValue_Z1 <= USB_LOG_J;
RxUsbLogValue_Z2 <= USB_LOG_J;
RxUsbLogValue_Z3 <= USB_LOG_J;
elsif (FsClk'event and FsClk='1') then
-- Convert the incoming bits to Logical value
if TxUsbEnable then
-- mask incoming bits during sending
RxUsbLogValue <= USB_LOG_J;
else
RxUsbLogValue <= UsbDif2Log(CR_UsbLineBits, GetDeviceSpeed(ConfigArray));
end if;
RxUsbLogValue_Z1 <= RxUsbLogValue;
RxUsbLogValue_Z2 <= RxUsbLogValue_Z1;
RxUsbLogValue_Z3 <= RxUsbLogValue_Z2;
-- Prevents generation of different registers for variable and signal
Error := RxError;
ErrorType := RxErrorType;
PidType := RxPid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -