?? cdc5801.vhd
字號:
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 + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -