📄 usb_new_timers_sf_rtl.vhdl
字号:
---------------------------------------------------------------------------------
---- File >>> usb_new_timers_sf_rtl.vhdl
---- Iden >>> 970604-14:16:12
----
---- Project: USB Development
---- Customer: Philips_ITCL
----
---- Module: architecture RTL of entity TIMERS_SF
---- Written by: Usb User (e-mail: usb@easics.be)
---- Easics nv
---- Kapeldreef 60
---- B-3001 Leuven
---- Belgium
---- Tel +32-16-298.400
---- Fax +32-16-298.319
---- e-mail: vhdl@easics.be
----
---- Creation Date: Wed, 04 Jun 1997
----
---- Purpose:
----
---- Revision history:
----
---------------------------------------------------------------------------------
-- DESCRIPTION_BEGIN
-- The TIMERS_SF module (SF stands for Single Function) generates
-- a 1 kHz clock based on the Start Of Frame packets. The 1 kHz
-- clock (Frame Clock) is used for slow timers (several milliseconds) and for
-- toggling the buffers for isochronous endpoints.
-- The TIMERS_SF module is responsible for timing during resume and
-- suspend. It also controls the clock while the device goes in suspend
-- or starts resuming.
-- DESCRIPTION_END
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
--library LIB_PACKAGES;
--use LIB_PACKAGES.PCK_GENERAL.all;
--use LIB_PACKAGES.PCK_SETUP.all;
--use LIB_PACKAGES.PCK_USB.all;
library work;
use work.PCK_GENERAL.all;
use work.PCK_USB.all;
use work.PCK_SETUP.all;
architecture RTL of TIMERS_SF is
constant SUSPEND_TIME: integer := 3;
constant IDLE_BEFORE_RESUME_TIME: integer := 5;
constant RESUME_TIME: integer := 3;
constant CLOCK_OFF_DELAY: integer := 7;
type T_SR_State is (IDLE, SENDING);
signal Clk1kHz: boolean;
signal Clk1kHzPulse: boolean;
signal DeviceSuspended: boolean;
signal Suspend5ms: boolean;
signal ClockOnTimer: integer range 0 to CLOCK_OFF_DELAY;
signal ClockOn: one_bit;
signal Needclock: boolean;
signal ClockIsOff: boolean;
constant MAX_FRAME_LENGTH:integer := GetFrameLength(MAX_DEVICE_SPEED);
signal FrameTimer: integer range 0 to MAX_FRAME_LENGTH;
signal FrameLength: integer range 0 to MAX_FRAME_LENGTH;
signal HalfWay: integer range 0 to MAX_FRAME_LENGTH/2;
signal ISOToggle: integer range 0 to 1;
signal Clk1kHz_Z: boolean;
begin
-- Device Speed is supposed not to change during normal
-- operation
FrameLength <= GetFrameLength(GetDeviceSpeed(ConfigArray));
HalfWay <= FrameLength /2;
TM_IsoToggle <= ISOToggle;
-----------------------------------------------------------------------
-- FrameTimer --
-----------------------------------------------------------------------
MAIN: process (FsClk, PUReset_N)
variable SOF: boolean;
variable ResumeTimer: integer range 0 to SUSPEND_TIME;
variable SR_State: T_SR_State;
variable ResumePending: boolean;
variable RG_BusActive_S: boolean;
variable SuspendTimer: integer range 0 to IDLE_BEFORE_RESUME_TIME;
variable NeedClock_S: boolean;
variable ClockIsOff_S: boolean;
variable ClockIsOff_SS: boolean;
variable RxSOF_Z: boolean;
variable RemoteWakeup_S: boolean;
variable RemoteWakeup_SS: boolean;
begin
if (PUReset_N = ACTIVE_LOW) then
FrameTimer <= 0;
RxSOF_Z := FALSE;
Clk1kHz <= FALSE;
Clk1kHz_Z <= FALSE;
Clk1kHzPulse <= FALSE;
ResumeTimer := 0;
SR_State := IDLE;
TM_SendResume <= FALSE;
ResumePending := FALSE;
RG_BusActive_S := FALSE;
SuspendTimer := 0;
DeviceSuspended <= FALSE;
Suspend5ms <= FALSE;
TM_RemoteWakeUpEvent <= FALSE;
ClockOnTimer <= 0;
NeedClock_S := TRUE;
ClockIsOff_S := FALSE;
ClockIsOff_SS := FALSE;
TM_ClockRestarted <= FALSE;
if SUPPORT_ISO then
ISOToggle <= 0;
end if;
RemoteWakeup_S := FALSE;
RemoteWakeup_SS := FALSE;
elsif FsClk'event and (FsClk = '1') then
----------------------------------------------------------
-- Bus reset --
----------------------------------------------------------
if RG_SetSE0Int then
ResumeTimer := 0;
TM_SendResume <= FALSE;
ResumePending := FALSE;
SuspendTimer := 0;
DeviceSuspended <= FALSE;
Suspend5ms <= FALSE;
end if;
----------------------------------------------------------
-- 1 kHz Clock and pulse generator --
----------------------------------------------------------
-- DOC_BEGIN: 1kHz Clock Generator
-- The frame timer circuit generates a 50% duty cycle frame
-- clock (1 kHz) and a one cycle pulse on every rising edge
-- of the frame clock. This pulse is used by a number of
-- millisecond timers in this and other modules. The timer
-- is synchronized to the Start of Frame packets in a way
-- the rising edge of the clock occurs in the middle of the
-- SOF packet. If there are no SOF's (this is always the
-- case for low speed devices), the timer is free running.
Clk1kHz <= (FrameTimer < HalfWay);
Clk1kHzPulse <= IsRisingEdge(Clk1kHz, Clk1kHz_Z);
Clk1kHz_Z <= Clk1kHz;
-- set SOF when RxSOF detected
SOF := IsRisingEdge(SIE_RxSOF,RxSOF_Z);
RxSOF_Z := SIE_RxSOF;
if (Clk1kHz and not Clk1kHz_Z) then
if SUPPORT_ISO then
ISOToggle <= 1 - ISOToggle;
end if;
end if;
if SOF or (FrameTimer = FrameLength-1) then
FrameTimer <= 0;
else
FrameTimer <= FrameTimer +1;
end if;
-- DOC_END
-----------------------------------------------------------
-- Resume Timers --
-----------------------------------------------------------
-- DOC_BEGIN: Resume Timing
-- The resume timer controls the generation of a remote
-- wake up. The remote wake-up can be requested by the
-- micro-controller or by making the external input
-- RemoteWakeup active.
--
-- If remote wake-up is requested then this request is
-- queued until the bus has been idle for 5 ms.
-- At that moment, an upstream wake up is generated
-- for 3 ms. If any bus activity occurs before the 5 ms
-- of idle bus, the request is discarded.
TM_SendResume <= FALSE;
if (RG_BusActive_S) then
ResumePending := FALSE;
end if;
case SR_STATE is
when IDLE =>
ResumeTimer := 0;
if MM_Resume or
(RemoteWakeup_SS and RemoteWakeUpEnable(ConfigArray)) then
ResumePending := TRUE;
TM_RemoteWakeUpEvent <= RemoteWakeup_SS and
RemoteWakeUpEnable(ConfigArray);
end if;
if (ResumePending and Suspend5ms) then
SR_State := SENDING;
end if;
when SENDING =>
TM_SendResume <= TRUE;
if Clk1kHzPulse then
if (ResumeTimer = RESUME_TIME) then
SR_State := IDLE;
TM_RemoteWakeUpEvent <= FALSE;
end if;
ResumeTimer := IncSat(ResumeTimer, RESUME_TIME +1);
end if;
end case;
-- DOC_END
-----------------------------------------------------------
-- Suspend Timers --
-----------------------------------------------------------
-- DOC_BEGIN: Awake/Suspend Control
-- The suspend timer controls the suspend/awake behavior.
-- There are 3 states: awake, suspended and an intermediate
-- state. A device is awake if there has been bus activity
-- in the last 3 ms. A device is suspended (the low power
-- state) when it hasn't seen any traffic for at least 5 ms.
-- Between 3 and 5 ms there is an intermediate state during
-- which the device prepares itself to go into the suspended
-- state
if RG_BusActive_S then
SuspendTimer := 0;
DeviceSuspended <= FALSE;
Suspend5ms <= FALSE;
elsif Clk1kHzPulse then
DeviceSuspended <= (SuspendTimer >= SUSPEND_TIME);
Suspend5ms <= (SuspendTimer = IDLE_BEFORE_RESUME_TIME);
SuspendTimer := IncSat(SuspendTimer,IDLE_BEFORE_RESUME_TIME+1);
end if;
-- DOC_END
-----------------------------------------------------------
-- ClockOnTimer --
-----------------------------------------------------------
-- DOC_BEGIN: Clock Control
-- The clock timer controls the minimum time diring which
-- the clock is switched on for devices that switch their
-- clock off when they are suspended. This timer is reset
-- whenever the clock goes on, and the clock can only go
-- off when this timer reaches its maximum.
if NeedClock_S or (ClockIsOff_SS and (not ClockIsOff_S)) then
ClockOnTimer <= 0;
else
ClockOnTimer <= IncSat(ClockOnTimer,CLOCK_OFF_DELAY+1);
end if;
-- DOC_END
NeedClock_S := NeedClock;
TM_ClockRestarted <= (ClockIsOff_SS and (not ClockIsOff_S));
ClockIsOff_SS := ClockIsOff_S;
ClockIsOff_S := ClockIsOff;
RG_BusActive_S := RG_BusActive;
RemoteWakeup_SS := RemoteWakeup_S;
RemoteWakeup_S := RemoteWakeup;
end if;
end process MAIN;
NeedClock <= MM_NeedCLock or PI_NeedCLock or EX_NeedClock or
(not Suspend5ms) or RG_BusActive or (not Suspend_In) or
PUReset_N = ACTIVE_LOW or AlwaysPLLClock(ConfigArray) or
RemoteWakeup;
-- DOC_BEGIN
-- The clock control block controls the switching of the clock.
-- It consists of two asynchronous flip flops. Whenever a clock
-- is needed (NeedClock = TRUE), the first flip flop is set. The
-- output of this flip flop controls the clock. It is reset
-- asynchronously when the clock timer reaches its maximum value,
-- which can only happen if no clock is needed.
-- The second flip flop is used to reset the clock timer. when the
-- output of the first flip flop goes low, it is reset
-- asynchronously. When the clock restarts, the flip flop is
-- reset synchronously, and the output of the flip flop is
-- clocked into a delay line. The rising edge in the delay line
-- causes the clock timer to be reset
CLOCK_ON: process(PUReset_N,FsClk,NeedClock,TestMode)
begin
if (PUReset_N = ACTIVE_LOW) or (NeedClock and TestMode = '0') then
ClockOn <= '1';
elsif FsClk'event and FsClk = '1' then
if ClockOnTimer = CLOCK_OFF_DELAY-1 then
ClockOn <= '0';
end if;
end if;
end process CLOCK_ON;
CLOCK_IS_OFF: process(PUReset_N,FsClk,ClockOn,TestMode)
begin
if (PUReset_N = ACTIVE_LOW) or (ClockOn = '0' and Testmode = '0') then
ClockIsOff <= FALSE;
elsif FsClk'event and FsClk = '1' then
ClockIsOff <= (ClockOn = '0');
end if;
end process CLOCK_IS_OFF;
-- DOC_END
TM_ClockOn <= ClockOn;
USB_Suspended <= conv_active_high(DeviceSuspended);
TM_Suspend <= DeviceSuspended;
TM_Idle5ms <= Suspend5ms;
USB_FrameClock <= conv_active_high(Clk1kHz);
TM_1kHzPulse <= conv_active_high(Clk1kHzPulse);
TM_EOF1 <= FALSE;
TM_EOF2 <= FALSE;
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -