📄 usb_new_uc_handler_rtl.vhdl
字号:
end if;
Setup(CmdArgument) := FALSE;
Overwritten(CmdArgument) := FALSE;
end if;
end if;
-- end InitializeEndpoint
if EndpointInfo(ConfigNr)(CmdArgument).EndpointType /= CONTROL then
Disable(CmdArgument) :=
conv_active_high(DataFromUC.Data(C_DISABLED));
end if;
if (EndpointInfo(ConfigNr)(CmdArgument).EndpointType =
BULK_OR_INTERRUPT and
EndpointInfo(ConfigNr)(CmdArgument).USBDirection = DIR_IN) then
RateFeedback(CmdArgument) :=
conv_active_high(DataFromUC.Data(C_INTMODE));
else
RateFeedback(CmdArgument) := FALSE;
end if;
when others =>
DataToUC.Ready <= TRUE;
end case;
-- External controller reads data
elsif (DataFromUC.Read and Selected_int) then
NeedClock <= TRUE;
DataToUC.Ready <= FALSE;
case Command is
when SELECT_EP | SET_BUFFER_FE =>
null;
-- The Select Endpoint/Clear interrupt Command is the same as
-- the Select Endpoint command, but clears the interrupt and
-- setup and overwritten bits.
when SET_EP_STATUS =>
EndpointNr := CmdArgument;
DataToSie.Interrupts(EndpointNr) <= FALSE;
if ((EndpointInfo(ConfigNr)(EndpointNr).EndpointType = CONTROL) and
(EndpointInfo(ConfigNr)(EndpointNr).USBDirection = DIR_OUT ))then
Setup(EndpointNr) := FALSE;
Overwritten(EndpointNr) := FALSE;
end if;
-- The command Read data reads an Endpoint Data Buffer.
-- Each read pulse the contents of the buffer is returned
-- and the pointer is incremented to the next position in the
-- buffer.
when others =>
DataToUC.Ready <= TRUE;
end case;
else
DataToUC.Ready <= TRUE;
end if;
-- DOC_END
-- DOC_BEGIN
-- On bus reset, reset the complete Device Address Table
-- disable all functions and their endpoints
-- but enable function 0.
if RG_SetSE0Int and (DH_CONNECT or not SUPPORT_SOFTCONNECT) then
PreventInt_N_I <= '0';
PreventInt_Count := 0;
Device_In_UC := 0;
DevAddrTable <= (others => (others => '0'));
EndpointEnables <= (others => '0');
DataPID := (others => 0);
for i in 0 to (N_ENDPOINTS-1) loop
if EndpointInfo(ConfigNr)(i).EndpointType /= ISOCHRONOUS then
UCToggle(i) := 0;
USBToggle(i) := 0;
end if;
end loop;
Stall := (others => FALSE);
Setup := (others => FALSE);
Overwritten := (others => FALSE);
Disable := (others => FALSE);
RateFeedback := (others => FALSE);
Full:= (others => (others => FALSE));
-- disable all endpoints and set all function addresses to zero.
for i in 0 to N_DEVICES -1 loop
if (ADDRESS_HANDLER(i) = ID) then
if ENABLE_RESET_ON(GetConfiguration(ConfigArray)) = i then
DevAddrTable(Device_In_UC)(7) <= '1';
end if;
Device_In_UC := Device_In_UC + 1;
end if;
end loop;
end if;
-- DOC_END
-- DOC_BEGIN: Delayed Set Address
-- The addresses given by the Write Configuration Array command are
-- first stored in a temporary register. The SieHandler indicates
-- when the address can be stored in the Device Address Table. (After
-- a successfull IN token for endpoint 0)
-- This is after the status stage of the control transfer. (Host
-- sends Set Address command, using a SETUP token. Status stage
-- is an IN token).
if (DataToHandlers.EndofTransfer and DataToHandlers.success) then
for i in 0 to N_HANDLER_DEVICES(ID)-1 loop
if (DataToHandlers.Endpoint =
DEFAULT_IN_EP(GetConfiguration(ConfigArray))(i)
and Loaded(i)) then
DevAddrTable(i)(6 downto 0) <=
DevAddrTable_tmp(i);
Loaded(i) := FALSE;
elsif (DataToHandlers.Endpoint =
DEFAULT_OUT_EP(GetConfiguration(ConfigArray))(i)) then
Loaded(i) := FALSE;
end if;
end loop;
end if;
-- DOC_END
-- DOC_BEGIN: Interface with the SIE-side of the design
-- This part consists of :
-- * logic that handles the control signals and
-- the passing/reading of the data to/from the GIF
-- This code only comes in effect when the SIEInterface has selected the
-- UCHandler.
if Selected_by_SIE then
-- A new packet is arriving and can/must be accepted
if (DataToHandlers.RxDataValid and
(not IsFull(DataToHandlers.Endpoint, USBToggle, Full, ConfigNr) or
DataToHandlers.SetupPacket or
EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType =
ISOCHRONOUS )) then
uc_to_pi.Rx_Data <= DataToHandlers.RxData;
uc_to_pi.Endpoint <= DataToHandlers.Endpoint;
uc_to_pi.SetupPacket <= DataToHandlers.SetupPacket;
sie_write <= '1';
-- if the buffer is still full while receiving a packet, set
-- the overwrite bit (this can only happen in the case of a
-- setup packet, since this has to be accepted.)
if IsFull(DataToHandlers.Endpoint, USBToggle, Full, ConfigNr) then
if EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType =
CONTROL and EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).USBDirection = DIR_OUT then
Overwritten(DataToHandlers.Endpoint) := TRUE;
end if;
end if;
else
sie_write <= '0';
end if;
-- Generate an interrupt on a NAKed transfer if this
-- feature is on.
if Selected_by_SIE and InterruptOnNAK(ConfigArray) and
DataToHandlers.EndOfTransfer and DataToHandlers.NAKed then
DataToSIE.Interrupts(DataToHandlers.Endpoint) <= TRUE;
if (EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType
= CONTROL) then
Naked(DataToHandlers.Endpoint) := TRUE;
end if;
end if;
if (EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType
= BULK_OR_INTERRUPT and EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).USBDirection = DIR_IN) then
RFB := RateFeedback(DataToHandlers.Endpoint);
else
RFB := FALSE;
end if;
-- When an IN command is handled succesfully, clear the
-- buffer and generate an interrupt
if (EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).USBDirection
= DIR_IN) then
Accepted <= IsFull(DataToHandlers.Endpoint, USBToggle, Full, ConfigNr);
if EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType =
ISOCHRONOUS then
Accepted <= TRUE;
end if;
if (DataToHandlers.EndOfTransfer and
(DataToHandlers.Success or (EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).EndpointType = BULK_OR_INTERRUPT and RFB)) and
(IsFull(DataToHandlers.Endpoint, USBToggle, Full, ConfigNr) or
EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).Endpointtype = ISOCHRONOUS)) then
-- USBClearBuffer/USBToggleBuffer
if EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).N_Buffers > 1 then
Full(DataToHandlers.Endpoint)
(USBToggle(DataToHandlers.Endpoint)) := FALSE;
USBToggle(DataToHandlers.Endpoint) :=
1-USBToggle(DataToHandlers.Endpoint);
else
Full(DataToHandlers.Endpoint)(0) := FALSE;
end if;
-- Toggle PID and set interrupt
if EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).EndpointType /= ISOCHRONOUS then
DataPID(DataToHandlers.Endpoint) :=
1-DataPID(DataToHandlers.Endpoint);
DataToSIE.Interrupts(DataToHandlers.Endpoint) <= TRUE;
end if;
-- Clear Nak-bit
if (EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType
= CONTROL) then
Naked(DataToHandlers.Endpoint) := FALSE;
end if;
end if;
-- When an OUT or SETUP command is handled succesfully,
-- the endpoints statusbits are updated...
elsif ((EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).USBDirection
= DIR_OUT) and
(DataToHandlers.EndOfTransfer) and
(DataToHandlers.Success and Accepted)) then
if (EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).EndpointType
= CONTROL) then
Naked(DataToHandlers.Endpoint) := FALSE;
end if;
-- Declare buffer full / Toggle buffer for non ISO
if EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).N_Buffers
> 1 then
Full(DataToHandlers.Endpoint)
(USBToggle(DataToHandlers.Endpoint)) := TRUE;
if EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).EndpointType /= ISOCHRONOUS then
USBToggle(DataToHandlers.Endpoint) :=
1-USBToggle(DataToHandlers.Endpoint);
end if;
else
Full(DataToHandlers.Endpoint)(0) := TRUE;
end if;
-- Toggle PID and set Interrupt
if EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).EndpointType /= ISOCHRONOUS then
DataPID(DataToHandlers.Endpoint) :=
1-DataPID(DataToHandlers.Endpoint);
DataToSIE.Interrupts(DataToHandlers.Endpoint) <= TRUE;
end if;
-- Initialize on SetupPacket
if (EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).EndpointType = CONTROL) then
Setup(DataToHandlers.Endpoint) := DataToHandlers.SetupPacket;
if DataToHandlers.SetupPacket then
CorrespEP := EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).CorrespondingEP;
Setup(DataToHandlers.Endpoint) := TRUE;
Stall(DataToHandlers.Endpoint) := FALSE;
DataPID(DataToHandlers.Endpoint) := 1;
PreventInt_N_I <= '0';
PreventInt_count := 0;
Full(CorrespEP)(0) := FALSE;
Stall(CorrespEP) := FALSE;
DataPID(CorrespEP) := 1;
end if;
end if;
end if;
start_in_transfer <= '0';
if (DataToHandlers.StartOfTransfer) then
SendEmptyPacket := FALSE;
-- Start of IN-transfer: if buffer full: transfer data
-- For ISO-endpoints, if buffer empty, send empty packet
if (EndpointInfo(ConfigNr)(DataToHandlers.Endpoint).USBDirection
= DIR_IN) then
if (EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).EndpointType = ISOCHRONOUS and
not IsFull(DataToHandlers.Endpoint, USBToggle, Full, ConfigNr)) then
SendEmptyPacket := TRUE;
elsif IsFull(DataToHandlers.Endpoint, USBToggle, Full, ConfigNr) then
uc_to_pi.endpoint <= DataToHandlers.Endpoint;
start_in_transfer <= '1';
sie_read_i <= '1';
end if;
--Start of OUT transfer
else
-- Allways accept ISO and Setup-packets
if DataToHandlers.SetupPacket or
EndpointInfo(ConfigNr)
(DataToHandlers.Endpoint).EndpointType = ISOCHRONOUS then
Accepted <= TRUE;
-- Accept other packets when buffer empty
else
Accepted <= not IsFull(DataToHandlers.Endpoint, USBToggle,
Full, ConfigNr);
end if;
end if;
end if;
if sie_read_i = '1' and N_Data_EP = "0000" then
sie_read_i <= '0';
end if;
-- if the SIEInterface received his data and the transfer is not
-- over yet, read the next byte from the RAM
if ((DataToHandlers.N_Data < N_Data_EP) and
(not DataToHandlers.EndOfTransfer) and
(not SendEmptyPacket)) then
if (DataToHandlers.TXDataFetched) then
uc_to_pi.Endpoint <= DataToHandlers.Endpoint;
sie_read_i <= '1';
else
sie_read_i <= '0';
end if;
-- if (Pi_To_Uc.Data_Ready) then
-- DataToSIE.TxData <= Pi_To_UC.Rx_Data;
-- end if;
DataToSIE.TxDataValid <= TRUE;
else
DataToSIE.TxDataValid <= FALSE;
end if;
end if;
-- DOC_END;
-- DOC_BEGIN: HUB wants a downstream port to be reset
Device_In_UC := 0;
for i in 0 to N_DEVICES -1 loop
if (ADDRESS_HANDLER(i) = ID) then
if HC_ResetDevice(Device_In_UC) then
DevAddrTable(Device_In_UC) <= (others => '0');
DevAddrTable(Device_In_UC)(7) <= '1';
EndpointEnables(Device_In_UC) <= '0';
end if;
Device_In_UC := Device_In_UC + 1;
end if;
end loop;
-- DOC_END;
--Prevent interrupt on IN-endpoints on arrival of Setuppacket, Busreset or
--Reset. PreventInt should stay low for three cycles.
--if PreventInt_N_I = '0' then
-- if PreventInt_Count = 2 then
-- PreventInt_Count := 0;
-- PreventInt_N_I <= '1';
-- else
-- PreventInt_Count := PreventInt_Count + 1;
-- end if;
--end if;
Selected <= Selected_int;
end if;
end process MAIN;
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -