📄 usb_new_clkrec_rtl.vhdl
字号:
--------------------------------------------------------------------------------
---- File >>> usb_new_clkrec_rtl.vhdl
---- Iden >>> 951017-16:10:26
----
---- Project: USB Development
---- Customer: Philips_ITCL
----
---- Module: architecture RTL of entity CLKREC
---- Written by: Jan Decaluwe (e-mail: jand@easics.be)
---- Easics nv
---- Kapeldreef 60
---- B-3001 Leuven
---- Belgium
---- Tel +32-16-270.400
---- Fax +32-16-270.319
---- e-mail: vhdl@easics.be
----
---- Creation Date: Tue, 17 Oct 1995
----
---- Purpose:
----
---- Revision history:
----
--------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library work;
use work.PCK_GENERAL.all;
use work.PCK_USB.all;
-- DESCRIPTION_BEGIN
-- The clock recovery generates a clock based on the transactions
-- on the Usb Bus (Dplus and Dmin). The recovered clock has a
-- rising edge in the middle of the bit on the Usb Bus.
-- DESCRIPTION_END
architecture RTL of CLKREC is
signal UsbLineBits: two_bits;
signal SyncCREN: booleans(2 downto 0);
signal SyncD, SyncP, SyncN: two_bits;
signal SyncSuspend: booleans(1 downto 0);
signal DelayLineD, DelayLineP, DelayLineN: six_bits;
signal DelayLineSample: six_bits;
signal Count: integer range 0 to 5;
signal RefCount: integer range 0 to 3;
signal Reduce, Extend, Rephase: boolean;
signal NegEdgeTime, EvalTime, PosEdgeTime, ExtendedPosEdgeTime: boolean;
begin
RECOVERY_PROCESS: process (Clk48MHz, Reset48MHz_N)
begin
if (Reset48MHz_N = ACTIVE_LOW) then
SyncCREN <= (others => FALSE);
SyncD <= (others => LOW);
SyncP <= (others => LOW);
SyncN <= (others => LOW);
SyncSuspend <= (others => FALSE);
DelayLineD <= (others => HIGH);
DelayLineP <= (others => HIGH);
DelayLineN <= (others => LOW);
DelayLineSample <= (others => HIGH);
Count <= 0;
RefCount <= 0;
Reduce <= FALSE;
Extend <= FALSE;
RePhase <= FALSE;
NegEdgeTime <= FALSE;
EvalTime <= FALSE;
PosEdgeTime <= FALSE;
ExtendedPosEdgeTime <= FALSE;
Clk12MHz_O <= LOW;
Clk12MHzRef_O <= LOW;
UsbLineBits <= (LOW, LOW);
elsif Clk48MHz'event and (Clk48MHz = '1') then
EvalTime <= FALSE;
-- DOC_BEGIN: Synchronizers and Delay Lines
-- Warning: this implementation is biased towards high speed
-- function clock recovery
-- A number of signals influencing the clock recovery come from
-- the recovered clock domain. This causes problems with a synchronous
-- reset strategy as in USBALB. To solve this generally, we will force
-- these signals asynchronously to 0 during reset
-- This is not a conceptual problem as these signals are treated
-- in this module as asynchronous signals anyway: in other words,
-- they are synchronized to the 48MHz clock before being used
-- Synchronizer for Clock Recovery Enable from SIE module
SyncCREN <= (SyncCREN(1), SyncCREN(0),
(SIE_CREnable and (PU_Reset_N = INACTIVE_HIGH)));
-- Synchronizers for differential and single ended inputs
SyncD <= (SyncD(0) , (HB_USBDifBit and PU_Reset_N));
SyncP <= (SyncP(0) , (HB_USBLineBits(1) and PU_Reset_N));
SyncN <= (SyncN(0) , (HB_USBLineBits(0) and PU_Reset_N));
-- Synchronizer for Suspend from the Timers module
SyncSuspend <= (SyncSuspend(0),
(TM_Suspend and (PU_Reset_N = INACTIVE_HIGH)));
-- Delay Line for the differential and single ended inputs
DelayLineD <= DelayLineD(DelayLineD'high-1 downto 0) & SyncD(1);
DelayLineP <= DelayLineP(DelayLineP'high-1 downto 0) & SyncP(1);
DelayLineN <= DelayLineN(DelayLineN'high-1 downto 0) & SyncN(1);
-- DOC_END
-- DOC_BEGIN: No Rephase during SE0
-- Avoid rephase during SE0, during SE0 the RCV input is not well
-- defined and can toggle causing rephase. This is not a problem,
-- but is unwanted. It is solved by filling the DelayLineD that is
-- used for rephase with the last value before SE0 was detected.
-- This is done as long as SE0 is detected. SE0 is detected by
-- looking at three values in the delay line of the single ended
-- receivers.
if (SyncP(1) = LOW) and (SyncN(1) = LOW) and
(DelayLineP(0) = LOW) and (DelayLineN(0) = LOW) and
(DelayLineP(1) = LOW) and (DelayLineN(1) = LOW) then
DelayLineD <= (others => DelayLineD(DelayLineD'high-1));
end if;
-- DOC_END
-- DOC_BEGIN: Generating the Recovered Clock
-- The recovered clock is generated using a counter Count. The
-- phase of this clock can be adjusted. When there is no
-- activity on the Usb Bus, the recovered clock is free running
-- on 12 MHz. When there is activity, the clock has to be
-- rephased so that the rising edge is in the middle of the
-- bit on the Usb Bus. Changing the phase is done by changing
-- the way the counter Count is reset to 0. The counter can
-- be reset to 0 at different times defined by the signals Reduce,
-- Extend and Rephase.
NegEdgeTime <= ((Count = 1) and Reduce) or
((Count = 2) and (not (Reduce or Extend or Rephase))) or
((Count = 3) and Extend) or
((Count = 4) and Rephase);
-- Reset the counter and take a sample of the delay line.
-- Evaluation of this sample is used for rephasing (EvalTime).
-- Recovered clock becomes LOW.
if NegEdgeTime then
Clk12MHz_O <= LOW;
Count <= 0;
Reduce <= FALSE;
Extend <= FALSE;
Rephase <= FALSE;
DelayLineSample <= DelayLineD;
EvalTime <= TRUE;
else
Count <= Count + 1;
end if;
-- The following code generates the HIGH period of the recovered
-- clock. If there is a rephase, defined by Rephase, the clock
-- stays high for one extra 48 MHz period. If this was not done,
-- the clock would only stay HIGH for one 48 MHz period. This
-- means an increase in frequency which is not allowed.
PosEdgeTime <= (Count = 0);
ExtendedPosEdgeTime <= (Count = 1);
if PosEdgeTime and not Rephase then
Clk12MHz_O <= HIGH;
end if;
if ExtendedPosEdgeTime and Rephase then
Clk12MHz_O <= HIGH;
end if;
-- DOC_END
-- DOC_BEGIN: Evaluation Delay Line Sample
-- Reset delay line sample (on 'J') while not SyncCREN(1)
-- The goal is to prevent packets that are sent out to
-- influence the clock recovery
if not SyncCREN(1) then
DelayLineSample <= (others => HIGH);
end if;
-- The delay line sample is evaluated to decide what kind of
-- rephasing is needed.
-- Qualify eval time with SyncCREN(2) (consistent with reset above)
if EvalTime and SyncCREN(2) then
if ( DelayLineSample(0) /= DelayLineSample(1) ) then
Extend <= TRUE;
elsif ( DelayLineSample(2) /= DelayLineSample(3) ) then
Reduce <= TRUE;
elsif ( DelayLineSample(3) /= DelayLineSample(4) ) then
-- Out-of-phase error condition
Rephase <= TRUE;
end if;
end if;
-- DOC_END
-- DOC_BEGIN: Generate Dplus and Dmin for SIE
-- Generation of clean DP and DM from incoming DP, DM and RCV
-- in Suspend, take bus signals from single-ended receivers
-- because differential receiver may be turned of
if (SyncSuspend(1)) then
UsbLineBits <= (DelayLineP(5), DelayLineN(5));
elsif (two_bits'(DelayLineP(5), DelayLineN(5)) = two_bits'("00")) then
UsbLineBits <= (LOW, LOW);
else
UsbLineBits <= (DelayLineD(5), not DelayLineD(5));
end if;
-- DOC_END
-- DOC_BEGIN: Reference Clock
-- Free running 12 MHz reference clock.
RefCount <= (RefCount + 1) mod 4;
Clk12MHzRef_O <= conv_active_high(RefCount >= 2);
-- DOC_END
end if;
end process RECOVERY_PROCESS;
-- recovered output data
CR_UsbLineBits <= UsbLineBits;
-- recovered output data for debug purposes
CR_DebugRecDataP <= UsbLineBits(1);
CR_DebugRecDataN <= UsbLineBits(0);
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -