cdc5801.vhd

来自「Vhdl cod for a clock for sp3e」· VHDL 代码 · 共 506 行 · 第 1/2 页

VHD
506
字号
                    half_per := half_per - 60 ps;                    PLL_LOCK <= false;                ELSIF mult_period < clk_period THEN                    half_per := half_per + 59 ps;                    PLL_LOCK <= false;                ELSE                    PLL_LOCK <= true;                END IF;            counter := 0;            ELSE                counter := counter + 1;            END IF;        END IF;        IF rising_edge(PLL_OUT) THEN            PLL_OUT <= '0' AFTER half_per, '1' AFTER 2*half_per;        ELSIF NOW = 0 ns THEN            PLL_OUT <= '0' AFTER half_per, '1' AFTER 2*half_per;        END IF;    END PROCESS PLL;    ----------------------------------------------------------------------------    -- Multiplier Process    ----------------------------------------------------------------------------    -- The "Multiplier" actually divides the PLL_OUT signal    MULT : PROCESS (PLL_OUT, MULT0_nwv, MULT1_nwv)        VARIABLE mult_in  : natural range 0 to 3;        VARIABLE multvec  : std_logic_vector(1 downto 0);        VARIABLE mult_cnt : natural range 0 to 8;    BEGIN        multvec := (MULT0_nwv, MULT1_nwv);        mult_in := to_nat(multvec);        IF rising_edge(PLL_OUT) THEN            CASE mult_in IS                WHEN 0 =>  -- divide by 4                    IF mult_cnt > 0 THEN                        MULT_OUT <= not MULT_OUT;                        mult_cnt := 0;                    ELSE                        mult_cnt := mult_cnt + 1;                    END IF;                WHEN 1 =>  -- divide by 2                    MULT_OUT <= not MULT_OUT;                WHEN 2 =>  -- divide by 16                    IF mult_cnt > 6 THEN                        MULT_OUT <= not MULT_OUT;                        mult_cnt := 0;                    ELSE                        mult_cnt := mult_cnt + 1;                    END IF;                WHEN 3 =>  -- divide by 8                    IF mult_cnt > 2 THEN                        MULT_OUT <= not MULT_OUT;                        mult_cnt := 0;                    ELSE                        mult_cnt := mult_cnt + 1;                    END IF;            END CASE;        ELSIF NOW = 0 ns THEN            MULT_OUT <= not MULT_OUT;        END IF;    END PROCESS MULT;    ----------------------------------------------------------------------------    -- Delay Process    ----------------------------------------------------------------------------    -- The Delay process phase aligns the output to DLYCTRL    DELAY : PROCESS (PLL_OUT, DLYCTRL_ipd, LEADLAG_ipd)        VARIABLE phase_dly    : time := 0 ns;        VARIABLE phase_cnt    : natural := 0;    BEGIN        IF PLL_LOCK THEN            IF rising_edge(DLYCTRL_ipd) THEN                IF phase_cnt < 31 THEN                    IF LEADLAG_ipd = '0' OR LEADLAG_ipd = 'L' THEN                        phase_dly := phase_dly + PHASE_INC;                    ELSE                        IF phase_dly > PHASE_INC THEN                            phase_dly := phase_dly - PHASE_INC;                        ELSE                            phase_dly := C_PERIOD - PHASE_INC; -- wrap                        END IF;                    END IF;                    phase_cnt := phase_cnt +1;                ELSE                    phase_cnt := 0;                END IF;            END IF;        ELSE            phase_dly := 0 ps;        END IF;        DLY_OUT <= TRANSPORT PLL_OUT AFTER phase_dly;    END PROCESS DELAY;    ----------------------------------------------------------------------------    -- Divider Process    ----------------------------------------------------------------------------    -- The Divider process divides the frequency of the phase aligner output,    -- gates the result with STOPB, and drives the outputs.    DIV : PROCESS (DLY_OUT, P1_nwv, P2_nwv, STOPBNeg_nwv, C_int)        VARIABLE div_in      : natural range 0 to 3;        VARIABLE divvec      : std_logic_vector(1 downto 0) := "00";        VARIABLE div_cnt     : natural range 0 to 8;        VARIABLE toggle_cnt  : natural range 0 to 2;        VARIABLE prev_lock   : boolean := false;        VARIABLE prev_c      : time := 0 ns;    BEGIN        divvec := (P1_nwv, P2_nwv);        div_in := to_nat(divvec);        IF P1_nwv'EVENT OR P2_nwv'EVENT OR PLL_LOCK = false THEN            prev_lock := false;        END IF;        IF rising_edge(C_int) THEN            C_PERIOD := NOW - prev_c;            prev_c := NOW;            IF PLL_LOCK /= prev_lock THEN                IF PLL_LOCK THEN                    IF toggle_cnt > 1 THEN                        CASE div_in IS                            WHEN 0 =>  -- special mode                            WHEN 1 =>  -- divide by 3072                                PHASE_INC := C_PERIOD/3072;                            WHEN 2 =>  -- divide by 1536                                PHASE_INC := C_PERIOD/1536;                            WHEN 3 =>  -- divide by 768                                PHASE_INC := C_PERIOD/768;                        END CASE;                        toggle_cnt := 0;                        prev_lock := true;                    ELSE                        toggle_cnt := toggle_cnt +1;                    END IF;                ELSE                    prev_lock := false;                END IF;            END IF;        END IF;        IF rising_edge(DLY_OUT) THEN            CASE div_in IS                WHEN 0 =>  -- special mode                    ASSERT (P0_nwv = '1')                    REPORT "cdc5801 model does not support this mode"                    SEVERITY error;                WHEN 1 =>  -- divide by 8                    IF div_cnt > 2 THEN                        C_zd <= not C_zd;                        div_cnt := 0;                    ELSE                        div_cnt := div_cnt + 1;                    END IF;                WHEN 2 =>  -- divide by 4                    IF div_cnt > 0 THEN                        C_zd <= not C_zd;                        div_cnt := 0;                    ELSE                        div_cnt := div_cnt + 1;                    END IF;                WHEN 3 =>  -- divide by 2                    C_zd <= not C_zd;            END CASE;        ELSIF NOW = 0 ns THEN            C_zd <= DLY_OUT;        END IF;        C_int <= C_zd;    END PROCESS DIV;        ------------------------------------------------------------------------        -- Path Delay Section        ------------------------------------------------------------------------    C_OUT: PROCESS(COut_zd)        VARIABLE C_GlitchData       : VitalGlitchDataType;    BEGIN         VitalPathDelay01 (            OutSignal       => CLKOUT,            OutSignalName   => "CLKOUT",            OutTemp         => COut_zd,            GlitchData      => C_GlitchData,            XOn             => XOn,            MsgOn           => MsgOn,            Paths           => (                0 => (InputChangeTime  => DLY_OUT'LAST_EVENT,                      PathDelay        => VitalZeroDelay01,                      PathCondition    => TRUE),                1 => (InputChangeTime  => STOPBNeg_ipd'LAST_EVENT,                      PathDelay        => tpd_STOPBNeg_CLKOUT,                      PathCondition    => STOPBNeg_nwv = '1'),                2 => (InputChangeTime  => STOPBNeg_ipd'LAST_EVENT,                      PathDelay        => tpd_STOPBNeg_CLKOUTB,                      PathCondition    => STOPBNeg_nwv = '0'),                3 => (InputChangeTime  => PWRDNBNeg_ipd'LAST_EVENT,                      PathDelay        => tpd_PWRDNBNeg_CLKOUT,                      PathCondition    => PWRDNBNeg_nwv = '1'),                4 => (InputChangeTime  => PWRDNBNeg_ipd'LAST_EVENT,                      PathDelay        => tpd_PWRDNBNeg_CLKOUTB,                      PathCondition    => PWRDNBNeg_nwv = '0')            )        );    END PROCESS C_OUT;   CNeg_OUT: PROCESS(CNeg_zd)        VARIABLE CNeg_GlitchData       : VitalGlitchDataType;    BEGIN        VitalPathDelay01 (            OutSignal       => CLKOUTB,            OutSignalName   => "CLKOUTB",            OutTemp         => CNeg_zd,            GlitchData      => CNeg_GlitchData,            XOn             => XOn,            MsgOn           => MsgOn,            Paths           => (                0 => (InputChangeTime  => DLY_OUT'LAST_EVENT,                      PathDelay        => VitalZeroDelay01,                      PathCondition    => TRUE),                1 => (InputChangeTime  => STOPBNeg_ipd'LAST_EVENT,                      PathDelay        => tpd_STOPBNeg_CLKOUT,                      PathCondition    => STOPBNeg_nwv = '1'),                2 => (InputChangeTime  => STOPBNeg_ipd'LAST_EVENT,                      PathDelay        => tpd_STOPBNeg_CLKOUTB,                      PathCondition    => STOPBNeg_nwv = '0'),                3 => (InputChangeTime  => PWRDNBNeg_ipd'LAST_EVENT,                      PathDelay        => tpd_PWRDNBNeg_CLKOUT,                      PathCondition    => PWRDNBNeg_nwv = '1'),                4 => (InputChangeTime  => PWRDNBNeg_ipd'LAST_EVENT,                      PathDelay        => tpd_PWRDNBNeg_CLKOUTB,                      PathCondition    => PWRDNBNeg_nwv = '0')            )        );    END PROCESS CNeg_OUT;END vhdl_behavioral;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?