📄 pll.vhd
字号:
-- inputs : vcoClk, iResetL -- outputs: pllActive process (vcoClk, iResetL) begin -- process if iResetL = '0' then -- asynchronous reset (active low) intPllActive1 <= '0'; intPllActive2 <= '0'; pllActive <= '0'; elsif vcoClk'event and vcoClk = '1' then -- rising clock edge intPllActive1 <= '1'; intPllActive2 <= intPllActive1; pllActive <= intPllActive2; end if; end process; -- purpose: latch and triple bank pllActive to generate clkResetL -- type : sequential -- inputs : vcoClk, iResetL, iPllLock -- outputs: iClkResetL process (vcoClk, iResetL) begin -- process if iResetL = '0' then -- asynchronous reset (active low) intClkResetL1 <= '0'; intClkResetL2 <= '0'; iClkResetL <= '0'; elsif vcoClk'event and vcoClk = '1' then -- rising clock edge intClkResetL1 <= iPllLock or intClkResetL1; intClkResetL2 <= intClkResetL1; iClkResetL <= intClkResetL2; end if; end process; -- purpose: generate IPDReset -- type : sequential -- inputs : refClk, iResetL -- outputs: IPDReset process (refClk, iResetL) begin -- process if iResetL = '0' then -- asynchronous reset (active low) intIPDReset <= '0'; IPDReset <= '0'; elsif refClk'event and refClk = '1' then -- rising clock edge intIPDReset <= '1'; IPDReset <= intIPDReset; end if; end process; iResetL <= porL and sleepL; pllLock <= iResetL and iPllLock; sysResetL <= iResetL and iSysResetL; clkResetL <= iResetL and iClkResetL;-- synopsys translate_onend beh;--///////////////////////////////////////////////////////////////////////////--///////////////////////////////////////////////////////////////////////////--/--/ entity & architecture : pllCore--/ Author : ParthusCeva Inc.--/_______________________________________________________________________--/ --/ Copyright (c) ParthusCeva Inc.--/ --/ This code is confidential and proprietary product of ParthusCeva. Any--/ unauthorized use, reproduction or transfer of this code is strictly--/ prohibited.--/_______________________________________________________________________--/ --/ Description: This entity & architecture contains a VHDL behavioural --/ (non-synthesizable) model of the PLL core.--/_______________________________________________________________________--/ --/--///////////////////////////////////////////////////////////////////////////--///////////////////////////////////////////////////////////////////////////library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_signed.all;entity pllCore4215 is port ( divClkin : in std_logic; porL : in std_logic; sleepL : in std_logic; VCODelayed : in std_logic; FBD : in std_logic_vector(7 downto 0); fbClk : out std_logic; lockDetAsync : out std_logic; vcoClk : buffer std_logic; filterVoltageBus: out real);end pllCore4215;architecture beh of pllCore4215 is-- synopsys translate_offfunction time2Real (constant T : time) return real is begin -- time2Real return 1.0e-12 * real (T / ps); end time2Real;function real2TimeShort (constant R : real) return time is begin -- real2TimeShort return integer(R * 1.0e12) * ps; end real2TimeShort;function real2TimeLong (constant R : real) return time is begin -- real2TimeLong return integer(R * 1.0e9) * ns; end real2TimeLong;--signal SETTLINGTIME :real := 2.370000e-04;signal SETTLINGTIME : real := 2.300000e-05;signal DIVCLKNOM : real := 4.500000e+06;signal VCOCLKNOM : real := 2.880000e+08;signal DIVCLKTOL : real := 0.300000;signal VCOCLKTOL : real := 0.250000;signal KVCOTYP : real := 966.571429;-- Parameters to the design (Generics may be better)signal CLKTOL : real := 10.0e-12;signal Vt : real := 0.5;-- End of parameterssignal divClkPeriodChanged : std_logic := '0';signal divClkPeriodGlobal : real := 0.0;signal FBDChanged : std_logic := '0';signal resetDone : std_logic := '0';signal divClkReset : std_logic := '0';signal intDivClkReset1 : std_logic := '0';signal intDivClkReset2 : std_logic := '0';signal divClkRe2Global : real := 0.0;signal divClkRe2 : real := 0.0;signal vcoClkHalfPeriod : real := 0.0;signal tdbuf : real := 0.0;signal noDivClk : std_logic := '0';signal invalidDivClk : std_logic := '0';signal invalidVcoClk : std_logic := '0';signal settlingTimeComplete : std_logic := '0';signal startTimeSet : std_logic := '0';signal invert : std_logic := '0';signal vcoValid : std_logic := '0';signal intVcoValid1 : std_logic := '0';signal intVcoValid2 : std_logic := '0';signal invalidInput : std_logic;signal done : std_logic := '0';signal starttime : real := 0.0;signal currtime : real := 0.0;signal reqtime : real := 0.0;signal delta : real := 0.0;signal filterVoltage : real;signal divClk : std_logic;signal FBDPrev : std_logic_vector(7 downto 0) := CONV_STD_LOGIC_VECTOR(59, 8);signal resetDoneDelayed : std_logic;signal i : integer;signal iFbClk : std_logic;signal countFBD : std_logic_vector(8 downto 0);signal iResetL : std_logic;begin -- beh----------------------------------------------------------------------------- iResetL <= porL and sleepL; divClk <= divClkin; -- FBD <= CONV_STD_LOGIC_VECTOR(59, 8); -- purpose: Convert real number filterVoltage to output port filterVoltageBus -- type : combinational -- inputs : filterVoltage -- outputs: filterVoltageBus process (filterVoltage) begin -- process filterVoltageBus <= filterVoltage; end process; ----------------------------------------------------------------------------- -- purpose: Wait until there have been several divClk cycles after reset before monitoring for invalid input -- type : sequential -- inputs : divClk, iResetL -- outputs: divClkReset process (divClk, iResetL) begin -- process if iResetL = '0' then -- asynchronous reset (active low) intDivClkReset1 <= '0'; intDivClkReset2 <= '0'; divClkReset <= '0'; elsif divClk'event and divClk = '1' then -- rising clock edge intDivClkReset1 <= '1'; intDivClkReset2 <= intDivClkReset1; divClkReset <= intDivClkReset2; end if; end process; ----------------------------------------------------------------------------- -- purpose: Wait until there have been several vcoClk cycles to issue a valid signal -- type : sequential -- inputs : vcoClk, iResetL -- outputs: vcoLaid process (vcoClk, iResetL) begin -- process if iResetL = '0' then -- asynchronous reset (active low) intVcoValid1 <= '0'; intVcoValid2 <= '0'; vcoValid <= '0'; elsif vcoClk'event and vcoClk = '1' then -- rising clock edge intVcoValid1 <= '1'; intVcoValid2 <= intVcoValid1; vcoValid <= intVcoValid2; end if; end process; ----------------------------------------------------------------------------- -- purpose: Calculate the input clock period, monitor changes in it and make sure that its within range process (divClkin) variable divClkRe1, divClkRe2, divClkPeriod, divClkPeriodPrev : real := 0.0; begin -- process if divClkin'event and divClkin = '1' then divClkRe1 := divClkRe2; divClkRe2 := time2Real(now); divClkPeriodPrev := divClkPeriod; divClkPeriod := divClkRe2 - divClkRe1; divClkPeriodGlobal <= divClkPeriod; if (((divClkPeriod - divClkPeriodPrev) > CLKTOL) or ((divClkPeriodPrev - divClkPeriod) > CLKTOL)) then divClkPeriodChanged <= '1'; else divClkPeriodChanged <= '0'; end if; if divClkReset = '1' then if (((1.0/divClkPeriod) < (DIVCLKNOM - (DIVCLKNOM * DIVCLKTOL))) or ((1.0/divClkPeriod) > (DIVCLKNOM + (DIVCLKNOM * DIVCLKTOL)))) then invalidDivClk <= '1'; else invalidDivClk <= '0'; end if; else invalidDivClk <= '0'; end if; end if; end process; ----------------------------------------------------------------------------- -- because if there are no divClk edges then invalidDivClk cannot become active as it posedge divClk triggered process (divClkin) begin -- process divClkRe2Global <= time2Real(now); end process; process begin -- process wait for real2TimeShort(1.0/(2.0 * DIVCLKNOM)); if ((time2Real(now) - divClkRe2Global) > (2.0 / (DIVCLKNOM - ( DIVCLKNOM * DIVCLKTOL)))) then noDivClk <= '1'; else noDivClk <= '0'; end if; end process; ----------------------------------------------------------------------------- -- Monitor for changes in the feedback divider number process (divClk) begin -- process if divClk'event and divClk = '1' then if FBDPrev /= FBD then FBDChanged <= '1'; else FBDChanged <= '0'; end if; FBDPrev <= FBD; end if; end process; ----------------------------------------------------------------------------- -- Calculate the vco clock period, monitor changes in it and make sure that its within range process begin -- process wait until divClkin'event and divClkin = '1'; vcoClkHalfPeriod <= divClkPeriodGlobal / (real((CONV_INTEGER(UNSIGNED(FBD)) + 1)) * 2.0); if (vcoValid = '1') then if (((1.0 / ((divClkPeriodGlobal / (real((CONV_INTEGER(UNSIGNED(FBD)) + 1)) * 2.0)) * 2.0)) < (VCOCLKNOM - ( VCOCLKNOM * VCOCLKTOL))) or ((1.0 / ((divClkPeriodGlobal / (real((CONV_INTEGER(UNSIGNED(FBD)) + 1)) * 2.0)) * 2.0)) > (VCOCLKNOM + ( VCOCLKNOM * VCOCLKTOL)))) then invalidVcoClk <= '1'; else invalidVcoClk <= '0'; end if; else invalidVcoClk <= '0'; end if; end process; ----------------------------------------------------------------------------- -- Measure buffer delay process variable vcoClkRe, VCODelayedRe : real := 0.0; begin -- process wait until vcoClk'event and vcoClk = '1'; if vcoValid = '0' then tdbuf <= 0.0; done <= '0'; elsif done = '1' then tdbuf <= tdbuf; else vcoClkRe := time2Real(now); wait until VCODelayed'event and VCODelayed = '1'; VCODelayedRe := time2Real(now); if ((VCODelayedRe - vcoClkRe) > (vcoClkHalfPeriod * 2.0)) then tdbuf <= VCODelayedRe - vcoClkRe - (vcoClkHalfPeriod * 2.0); invert <= '0'; elsif ((VCODelayedRe - vcoClkRe) > vcoClkHalfPeriod) then tdbuf <= (vcoClkHalfPeriod * 2.0) - (VCODelayedRe-vcoClkRe); invert <= '0'; else tdbuf <= VCODelayedRe - vcoClkRe; tdbuf <= (divClkPeriodGlobal / 2.0) - tdbuf; invert <= '1'; end if; done <= '1'; end if; end process; ----------------------------------------------------------------------------- -- Check that always get an initial porL and also after going to an invalid input or vco clock frequency and back -- 15/01/02 - added FBDChanged,divClkPeriodChanged to invalidInputto force a porl after changing divider ratio's invalidInput <= (invalidDivClk or invalidVcoClk or noDivClk or FBDChanged or divClkPeriodChanged) when divClkReset = '1' else '0'; process begin -- process wait until porL'event or (invalidInput'event and invalidInput = '1'); if invalidInput = '1' then resetDone <= '0'; elsif porL = '1' and invalidInput = '0' then resetDone <= '1'; elsif porL = '0' then resetDone <= '0'; else resetDone <= resetDone; end if; end process; ----------------------------------------------------------------------------- -- resetDoneDelayed <= resetDone after real2TimeShort(6.0 * vcoClkHalfPeriod); ----------------------------------------------------------------------------- -- Generate lock detect signal process variable lockStartTime : real := 0.0; begin -- process wait until (divClk'event and divClk = '1') or sleepL'event or invalidInput'event or resetDone'event or FBDChanged'event or divClkPeriodChanged'event; if (not (resetDone = '1' and sleepL = '1')) or invalidInput = '1' or FBDChanged = '1' or divClkPeriodChanged = '1' then lockDetAsync <= '0'; settlingTimeComplete <= '0'; startTimeSet <= '0'; else if startTimeSet = '0' then lockStartTime := time2Real(now); startTimeSet <= '1'; end if; if ((time2Real(now) - lockStartTime) > SETTLINGTIME) then settlingTimeComplete <= '1'; lockDetAsync <= '1'; end if; end if; end process; ----------------------------------------------------------------------------- -- Generate Vco Clock process begin -- process if sleepL = '0' then wait for 1 ns; vcoClk <= '0'; elsif divClkReset = '0' or resetDoneDelayed = '0' then wait for 1 ns; vcoClk <= 'U'; else wait until divClk'event and divClk = '1'; i <= 0; for x in 0 to CONV_INTEGER(UNSIGNED(FBD)) loop vcoClk <= '1'; wait for real2TimeShort(vcoClkHalfPeriod); vcoClk <= '0'; if (x < CONV_INTEGER(UNSIGNED(FBD))) then wait for real2TimeShort(vcoClkHalfPeriod); end if; i <= i + 1; end loop; -- x end if; end process; ----------------------------------------------------------------------------- -- Generate Feedback Clock process begin -- process wait until (VCODelayed'event and VCODelayed = '1') or sleepL'event or resetDone'event; if divClkReset = '0' or resetDone = '0' then iFbClk <= 'U'; countFBD <= "000000000"; elsif sleepL = '0' then iFbClk <= '0'; countFBD <= "000000000"; else if countFBD = FBD + 1 then iFbClk <= '1'; countFBD <= "000000000"; else iFbClk <= '0'; countFBD <= countFBD + 1; end if; end if; end process; ----------------------------------------------------------------------------- fbClk <= VCODelayed when FBD = "00000000" else iFbClk; ----------------------------------------------------------------------------- -- Generate Filter Voltage process (vcoClk) begin -- process if resetDone = '0' or sleepL = '0' then filterVoltage <= 0.0; else filterVoltage <= (1.0 / (KVCOTYP * vcoClkHalfPeriod * 2.0e-3)) + Vt; end if; end process;-- synopsys translate_onend beh;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -