📄 usb_new_device_handler_rtl.vhdl
字号:
elsif (FsClk'event and FsClk='1') then
DataToSIE.RemoteWakeup <= FALSE;
DataToUc.Ready <= TRUE;
-- DOC_BEGIN: Command Write
-- When a command is received from the external micro controller,
-- the decoder compares the command code with the codes of the commands
-- it can handle. If there is a match, the module selects itself to
-- get access to the microcontroller interface.
if (DataFromUC.Write and DataFromUC.Address = 1) then
DataToUc.Ready <= FALSE;
Selected <= TRUE;
ByteCounter := 0;
if DataFromUC.Data = GET_INTERRUPT_CODE then
Command := GET_INTERRUPT;
elsif DataFromUC.Data = GET_FRAMENUMBER_CODE then
Command := GET_FRAMENUMBER;
elsif DataFromUC.Data = GETSET_MODE_CODE then
Command := GETSET_MODE;
elsif DataFromUC.Data = GET_ERROR_CODE then
Command := GET_ERROR;
elsif DataFromUC.Data = GETSET_DEVICE_STATUS_CODE then
Command := GETSET_DEVICE_STATUS;
elsif DataFromUC.Data = GET_CHIPID_CODE then
Command := GET_CHIPID;
else
Command := INVALID;
Selected <= FALSE;
end if;
-- Depending on the command, the appropriate data are sent
-- to the micro-controller interface for a possible micro-controller
-- data read access.
case Command is
when GET_FRAMENUMBER =>
DataToUC.Data <= GetByteSlice(FrameNumber, ByteCounter);
when GET_INTERRUPT =>
DataToUC.Data <= GetByteSlice(
conv_active_high(DataToHandlers.Interrupts),
ByteCounter);
when GETSET_MODE =>
DataToUC.Data <= GetByteSlice(
conv_active_high(PINConfigArray), ByteCounter);
when GET_CHIPID =>
DataToUC.Data <= GetByteSlice(ChipID, ByteCounter);
when GET_ERROR =>
DataToUC.Data <= "000" & conv_active_high(DataToHandlers.Error) &
EncodeError(DataToHandlers.LastError);
when GETSET_DEVICE_STATUS =>
DataToUC.Data <= GetDeviceStatus(Connect, ConnectChangeInterrupt,
TM_Suspend, SuspendChangeInterrupt,
BusResetInterrupt,
RemoteWakeupEvent);
BusResetInterrupt := FALSE;
SuspendChangeInterrupt := FALSE;
ConnectChangeInterrupt := FALSE;
RemoteWakeupEvent := FALSE;
DataToSIE.Interrupts(0) <= FALSE;
when others =>
DataToUC.Ready <= True;
end case;
-- DOC_END
-- DOC_BEGIN: Data Read Access
-- On every read access, the next byte is fetched and sent to the
-- micro-contoller interface. In the case of a Read Device Status
-- command, the change bits and the interrupt are cleared.
elsif (DataFromUC.Read and Selected) then
ByteCounter := IncMod(ByteCounter, 8);
DataToUc.Ready <= FALSE;
case Command is
when GET_FRAMENUMBER =>
DataToUC.Data <= GetByteSlice(FrameNumber, ByteCounter);
when GET_INTERRUPT =>
DataToUC.Data <= GetByteSlice(
conv_active_high(DataToHandlers.Interrupts),
ByteCounter);
when GETSET_MODE =>
DataToUC.Data <= GetByteSlice(
conv_active_high(PINConfigArray), ByteCounter);
when GET_CHIPID =>
DataToUC.Data <= GetByteSlice(ChipID, ByteCounter);
when GET_ERROR =>
DataToUC.Data <= "000" & conv_active_high(DataToHandlers.Error) &
EncodeError(DataToHandlers.LastError);
when GETSET_DEVICE_STATUS =>
DataToUC.Data <= GetDeviceStatus(Connect, ConnectChangeInterrupt,
TM_Suspend, SuspendChangeInterrupt,
BusResetInterrupt,
RemoteWakeupEvent);
-- BusResetInterrupt := FALSE;
-- SuspendChangeInterrupt := FALSE;
-- ConnectChangeInterrupt := FALSE;
-- RemoteWakeupEvent := FALSE;
-- DataToSIE.Interrupts(0) <= FALSE;
when others =>
null;
end case;
-- DOC_END
-- DOC_BEGIN: Data Write Access
-- For the commands that support data write access, the appropriate
-- registers are updated on every write access.
elsif (DataFromUC.Write and DataFromUC.Address = 0 and Selected) then
DataToUc.Ready <= FALSE;
if Command = GETSET_MODE then
UCConfigArray <= conv_active_high(
SetByteSlice(conv_active_high(UCConfigArray),
DataFromUC.Data, ByteCounter));
end if;
if Command = GETSET_DEVICE_STATUS then
AllowConnect := conv_active_high(DataFromUC.Data(CONNECT_BIT_POS));
if DataFromUC.Data(SUSPEND_BIT_POS) = '0' then
DataToSIE.RemoteWakeUp <= TRUE;
end if;
end if;
-- Increment bytecounter, ready to receive possible next byte
ByteCounter := IncMod(ByteCounter, 8);
else
DataToUC.READY <= TRUE;
end if;
-- DOC_END
--InterruptLevel := or_reduce(DataToHandlers.Interrupts);
-- BULK OUT Interrupt is seperated from DH_Interrupt
--InterruptLevel := or_reduce(DataToHandlers.Interrupts(N_INTR_BITS-1 downto 7))
-- OR or_reduce(DataToHandlers.Interrupts(5 downto 0));
-- All interrupts are seperated from DH_Interrupt
InterruptLevel := or_reduce(DataToHandlers.Interrupts(9 downto 8));
InterruptEdge := FALSE;
for i in Interrupt_Z'range loop
InterruptEdge := InterruptEdge or
(DataToHandlers.Interrupts(i) and not Interrupt_Z(i));
end loop;
Interrupt_Z := DataToHandlers.Interrupts;
if (EdgeInterrupt(ConfigArray_int)) then
DH_Interrupt <= (EdgeTimer > 0);
else
DH_Interrupt <= InterruptLevel;
end if;
DH_Interrupt_Ep0 <= DataToHandlers.Interrupts(0);
DH_Interrupt_Ep1 <= DataToHandlers.Interrupts(1);
DH_Interrupt_Ep2 <= DataToHandlers.Interrupts(2);
DH_Interrupt_Ep3 <= DataToHandlers.Interrupts(3);
DH_Interrupt_Ep4 <= DataToHandlers.Interrupts(4);
DH_Interrupt_Ep5 <= DataToHandlers.Interrupts(5);
DH_Interrupt_Ep6 <= DataToHandlers.Interrupts(6);
DH_Interrupt_Ep7 <= DataToHandlers.Interrupts(7);
DH_Interrupt_Dev <= DataToHandlers.Interrupts(10);
if EdgeTimer > 0 then
EdgeTimer := EdgeTimer -1;
end if;
if InterruptEdge then
EdgeTimer := INTERRUPT_PULSE_LENGTH-1;
end if;
-- DOC_BEGIN: Status Change bits generation
-- On a bus reset, the bus reset change bit is set
-- and an interrupt is generated.
if RG_SetSE0Int and Connect then
BusResetInterrupt := TRUE;
DataToSIE.Interrupts(0) <= TRUE;
end if;
-- On a change in the devices suspend state, the suspend
-- change bit is set and an interrupt is generated.
if TM_Suspend /= TM_Suspend_Z then
SuspendChangeInterrupt := TRUE;
DataToSIE.Interrupts(0) <= TRUE;
TM_Suspend_Z := TM_Suspend;
-- Only check if device goes out of suspend
RemoteWakeupEvent := TM_RemoteWakeupEvent and not TM_Suspend;
end if;
-- When the device is disconnected because Vbus dissapeared,
-- the connect change bit is set and and interrupt is generated.
if (Connect and not VBusDebounced) then
ConnectChangeInterrupt := TRUE;
DataToSIE.Interrupts(0) <= TRUE;
end if;
-- DOC_END
Connect <= VBusDebounced and AllowConnect;
-- DOC_BEGIN: Vbus Debouncing
-- This circuit masks small low spikes on Vbus. This allows
-- to share the Vbus pin with an other input pin, provided
-- that it goes low only for a short time during normal
-- operation.
VBusDebounced <= VBusAvailable or (DebounceTimer > 0);
if VBusAvailable or not SUPPORT_SOFTCONNECT then
DebounceTimer := VBUS_DEBOUNCE_TIME;
elsif (TM_1kHzPulse = '1') then
if (DebounceTimer > 0) then
DebounceTimer := DebounceTimer -1;
end if;
end if;
-- DOC_END
end if;
end process;
-- since all request can be handled in 1 cycle, ready is
-- always true;
-- DataToUc.Ready <= TRUE;
DataToSIE.IntMode <= FALSE;
DataToSIE.NeedClock <= (VBusAvailable /= VBusDebounced);
DH_Connect <= Connect;
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -