📄 usb_new_sieinterface_rtl.vhdl
字号:
HandlerNumber <= 0;
USBAddressTable <= (others => (others => '0'));
DeviceEnabled <= (others => FALSE);
StopReceiving <= FALSE;
elsif (FsClk'event and FsClk = '1') then
DataToHandlers.StartOfTransfer <= FALSE;
DataToHandlers.EndOfTransfer <= FALSE;
--DataToHandlers.Success <= FALSE;
DataToHandlers.TxDataFetched <= SIE_TxDataAck;
DataToHandlers.NAKed <= FALSE;
SH_Succes <= FALSE;
-- DOC_BEGIN: Error Handling
-- When there is no error generated in the SIEINTERFACE module, the error
-- code coming from the SIE is copied.
--
if (SIE_RxError) then
if not(DataFromHandlers_In.IntMode and SIE_RxErrorType = ERROR_PACKET_UNEXPECTED) then
SetError(SIE_RxErrorType);
end if;
end if;
-- DOC_END
if N_DEVICES = 1 then
DevNr := 0;
end if;
DataToHandlers.Endpoint <= GetPhysEndpNr(DevNr,
EndpNr,
HandlingINBuffer,
ConfigArray);
HandlerNumber <= GetHandlerNr(DevNr,
EndpNr,
HandlingINBuffer,
ConfigArray);
IsIsoEndpoint := SUPPORT_ISO and IsoEnabled(DevNr,
EndpNr,
HandlingINBuffer,
ConfigArray);
-- DOC_BEGIN: Main State Machine
case SH_State is
-- In this state, the SIEINTERFACE waits to be triggered to do
-- an address lookup when a token comes in.
--
when DEVADDR_SEARCH =>
-- EndpNr := 0;
MM_EndpSearchReady <= TRUE;
TokenReceived := FALSE;
DataSentReceived := FALSE;
HandshakeSentReceived := FALSE;
StopReceiving <= TRUE;
-- DOC_END
-------------------------------------------------------------------
-- Receiving a SOF --
-------------------------------------------------------------------
-- DOC_BEGIN
-- When a Start of Frame (SOF) comes in, the frame number
-- is updated.
if SIE_SOFByte1 then
SOFByte1 := SIE_RxData;
elsif SIE_SOFByte2 and (not SIE_RxError) then
DataToHandlers.FrameNumber <= SIE_RxData(2 downto 0) & SOFByte1;
end if;
-- DOC_END
-------------------------------------------------------------------
-- Receiving an IN/OUT/SETUP Token --
-------------------------------------------------------------------
-- DOC_BEGIN
-- When the SIEINTERFACE is triggered on the arrival of a token,
-- all protocol signals to the SIE are initialized and a device
-- address lookup is done. If the address in the token is the address
-- of an enabled device, the state machine jumps to the
-- WAIT_FOR_ENDPOINT state, where it waits for the endpoint number
-- to come in. Otherwise, it stays in the DEV_ADDR_SEARCH and waits
-- for the next token.
if (SIE_StartEndpSearch) then
MM_EndpSearchReady <= FALSE;
EndpSearchReady := FALSE;
MM_EndpSearchSelected <= FALSE;
MM_Accepted <= FALSE;
MM_Stalled <= FALSE;
MM_EmbeddedBabbled <= FALSE;
DataToHandlers.Success <= FALSE;
DataToHandlers.Error <= FALSE;
-- loop through device address table (content search);
DevAddrEnabled := FALSE;
for i in DataFromHandlers_In.USBAddress'range loop
if DataFromHandlers_In.USBAddress(i)=SIE_RxData(6 downto 0) and
DataFromHandlers_In.DeviceEnabled(i) then
DevNr := i;
DevAddrEnabled := TRUE;
exit;
end if;
end loop;
if N_DEVICES = 1 then
DevNr := 0;
end if;
-- if device enabled, proceed to check endpoint
if DevAddrEnabled then
SH_State := WAIT_FOR_ENDPOINT;
else
SetNoEndpointSelected;
end if;
end if;
-- When the endpoint number arrives, a check is done whether
-- the endpoint exists, is enabled and can handle the current
-- data direction. If there is a match, more endpoint data are
-- retrieved in the WAIT_FOR_ENDOFTOKEN state. Otherwise the SIEINTERFACE
-- waits for the next token.
when WAIT_FOR_ENDPOINT =>
-- wait until endpoint number is available
if SIE_RxDataRdy then
EndpNr := to_integer(SIE_RxData);
HandlingINBuffer := (SIE_RxPid = PID_IN);
-- pid must have right direction and EP must be enabled
if (SIE_RxPid = PID_IN and
not InEndpointEnabled(DevNr, EndpNr, ConfigArray)) or
((SIE_RxPid = PID_OUT or SIE_RxPid = PID_SETUP) and
not OutEndpointEnabled(DevNr, EndpNr, ConfigArray)) or
((SIE_RxPid = PID_SETUP) and
not OutSetupEnabled(DevNr, EndpNr, ConfigArray)) or
(EndpNr /= 0 and not DataFromHandlers_In.DeviceConfigured(DevNr))
then
SetNoEndpointSelected;
SH_State := DEVADDR_SEARCH;
else
SH_State:=WAIT_FOR_ENDOFTOKEN;
end if;
end if;
-- In this state, the SIEINTERFACE waits for the end of the token
-- packet. At that moment, all flags for the SIE are set to
-- generate the right answer.
when WAIT_FOR_ENDOFTOKEN =>
SetupPacket <= (SIE_RxPid = PID_SETUP);
DataPid <= DataFromHandlers_In.DataPID;
N_Data:=0;
if SIE_RxEOP and DataFromHandlers_In.Disabled then
SetNoEndpointSelected;
SH_State := DEVADDR_SEARCH;
elsif SIE_RxEOP then
-- DataToHandlers.StartOfTransfer <= TRUE;
StopReceiving <= FALSE;
SetEndpointSelected;
MM_ISO <= FALSE;
if IsIsoEndpoint then
MM_ISO <= TRUE;
DataPid <= 0; -- always send DATA0
end if;
if SIE_RxPid = PID_SETUP then
-- always accept a setup packet
DataToHandlers.StartOfTransfer <= TRUE;
DataPid <= 0; -- Always DATA0 PID
MM_Stalled <= FALSE;
SH_State := WAIT_FOR_DATA;
elsif SIE_RxPid = PID_OUT then
MM_Stalled <= DataFromHandlers_In.Stalled;
-- Decide how to handle OUT token
if DataFromHandlers_In.Stalled then
-- Endpoint Stalled -> Send STALL
SetError(ERROR_SENT_STALL);
else
-- Otherwise Receive Data
DataToHandlers.StartOfTransfer <= TRUE;
SH_State := WAIT_FOR_DATA;
end if;
else -- PID_IN
MM_Stalled <= DataFromHandlers_In.Stalled;
-- Decide how to handle IN token
if DataFromHandlers_In.Stalled then
-- Endpoint Stalled -> send stall
SetError(ERROR_SENT_STALL);
elsif not DataFromHandlers_In.Accepted and IsIsoEndpoint then
-- Otherwise No data and ISO -> send empty packet
DataToHandlers.StartOfTransfer <= TRUE;
MM_Accepted <= TRUE;
SetError(ERROR_SENT_EMPTYPACK);
elsif not DataFromHandlers_In.Accepted then
-- Otherwise No data -> send nak
SetError(ERROR_SENT_RECEIVED_NAK);
else
-- Otherwise send data
DataToHandlers.StartOfTransfer <= TRUE;
MM_Accepted <= TRUE;
SH_State := SEND_IN_PACKET;
if DataFromHandlers_In.IntMode then
MM_ISO <= TRUE;
end if;
end if;
end if;
end if;
-- In this state, the SIEINTERFACE waits for the data packet to
-- arrive. When the PID comes in, a decision is taken whether
-- the packet must be accepted or ignored, depending on the
-- DATA0/1 sequence.
when WAIT_FOR_DATA =>
if SIE_RxPidRdy then
RxData1Pid := (SIE_RxPid = PID_DATA1);
IgnoreData <= ((DataPid=1) and (not RxData1Pid)) or
((DataPid=0) and RxData1Pid);
if RxData1Pid then
DataPid <= 1;
else
DataPid <= 0;
end if;
if IsIsoEndpoint then
IgnoreData <= FALSE;
end if;
N_Data:=0;
SH_State := RECEIVE_OUT_PACKET;
end if;
-- In the RECEIVE_OUT_PACKET state, the data part of the data packet
-- is received, and all incoming data are stored into the endpoint's
-- buffer. An error is generated on buffer overflow.
-- At the end of the packet, the endpoint's setup information is
-- updated.
when RECEIVE_OUT_PACKET =>
BufferSize := GetBufferSize(DevNr,EndpNr,HandlingINBuffer,ConfigArray);
OverRunSize := BufferSize +2;
if SIE_RxDataRdy and not IgnoreData then
if N_Data < OverRunSize then
N_Data := N_Data +1;
else
SetError(ERROR_OVERRUN);
MM_ISO <= TRUE; -- no ack
end if;
if N_Data >= BufferSize then
StopReceiving <= TRUE;
end if;
elsif DataSentReceived then
MM_Accepted <= DataFromHandlers_In.Accepted or SetupPacket
or IgnoreData;
if not(DataFromHandlers_In.Accepted or DataFromHandlers_In.stalled or
SetupPacket or IgnoreData) then
SetError(ERROR_SENT_RECEIVED_NAK);
elsif IgnoreData then
SetError(ERROR_DATA_IGNORED_WRONG_DATA01);
else
N_Data := N_Data -2;
SetSuccess;
--DataToHandlers.EndOfTransfer <= TRUE;
--EndOfTransfer <= FALSE;
end if;
end if;
-- In this state, the SIEINTERFACE sends a data packet to the host.
-- First the number of data is read from the RAM. After that,
-- that amount of data is read from the endpoint's buffer and
-- is sent to the SIE.
-- At the end, the endpoint's setup information is updated.
when SEND_IN_PACKET =>
if DataFromHandlers_In.Disabled then
DataToHandlers.EndOfTransfer <= TRUE;
DataToHandlers.Success <= FALSE;
SH_State := DEVADDR_SEARCH;
else
if SIE_TxDataAck then
N_Data := N_Data+1;
end if;
if DataSentReceived then
if IsIsoEndpoint or DataFromHandlers_In.IntMode then
SetSuccess;
--DataToHandlers.EndOfTransfer <= TRUE;
end if;
end if;
if SIE_RxPidRdy then
if SIE_RxPid = PID_ACK then
SetSuccessAtEOP;
else
SetError(ERROR_SENT_RECEIVED_NAK);
end if;
end if;
if TM_EOF1 then
SetError(ERROR_BABBLE);
MM_EmbeddedBabbled <= TRUE;
end if;
end if;
end case; -- SH_STATE;
-- DOC_END
-------------------------------------------------------------------
-- Error Handling --
-------------------------------------------------------------------
-- Check for DataSentReceived and TokenReceived after errors
-- are handled, to be sure that no errors are missed.
if SIE_RxEOP and DataSentReceived then
HandshakeSentReceived := TRUE;
end if;
if SIE_RxEOP and TokenReceived then
DataSentReceived := TRUE;
end if;
if SIE_RxEOP then
TokenReceived := TRUE;
end if;
if TokenReceived then
MM_EndpSearchReady <= EndpSearchReady;
end if;
DataToHandlers.N_Data <= N_Data;
if EndOfTransfer and SIE_RxEOP then
DataToHandlers.EndOfTransfer <= TRUE;
EndOfTransfer <= FALSE;
end if;
end if;
end process MAIN;
DataToHandlers.RxData <= SIE_RxData;
DataToHandlers.RxDataValid <= SIE_RxDataRdy and not StopReceiving and not IgnoreData;
DataToHandlers.Interrupts <= DataFromHandlers_In.Interrupts;
DataToHandlers.SetupPacket <= SetupPacket;
DataToHandlers.Handler <= HandlerNumber;
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -