-------------------------------------------------------------------------------- -- File name: roboclock.vhd -------------------------------------------------------------------------------- -- Copyright (C) 1997 Free Model Foundry http://www.FreeModelFoundry.com/ -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2 as -- published by the Free Software Foundation. -- -- MODIFICATION HISTORY: -- -- version: | author: | mod date: | changes made: -- V2.0 L. Lee 96 SEP 3 Initial release -- V2.1 R. Munden 97 MAR 01 Changed XGenerationOn to XOn, added -- MsgOn, and updated TimingChecks & -- PathDelays -- V2.2 R. Steele 97 MAR 13 Removed configuration -------------------------------------------------------------------------------- -- PART DESCRIPTION : -- -- Library: MISC -- Technology: TTL OR CMOS -- Part: CY7B991 OR CY7B992 -- -- Description: Programmable Skew Clock Buffer -- -------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.std_logic_arith.ALL; USE IEEE.VITAL_timing.all; USE IEEE.VITAL_primitives.all; LIBRARY FMF; USE FMF.gen_utils.all; -------------------------------------------------------------------------------- -- ENTITY DECLARATION -------------------------------------------------------------------------------- ENTITY roboclock IS GENERIC ( -- note: this is a PLL device; so, no tpd generics -- tipd delays: interconnect path delays tipd_FB : VitalDelayType01 := VitalZeroDelay01; tipd_REF : VitalDelayType01 := VitalZeroDelay01; tipd_FS : VitalDelayType01 := VitalZeroDelay01; tipd_TEST : VitalDelayType01 := VitalZeroDelay01; -- tpw values: pulse widths tpw_hi_min_REF : VitalDelayType := UnitDelay; tpw_lo_min_REF : VitalDelayType := UnitDelay; -- tperiod_min: minimum clock period = 1/max freq tperiod_min_REF : VitalDelayType := UnitDelay; -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXOn; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( -- 'Z' denotes internal MID state of peculiar three-state -- input used by this part REF : IN std_logic := 'U'; FB : IN std_logic := 'U'; FS : IN std_logic := 'Z'; TEST : IN std_logic := 'Z'; F10 : IN std_logic := 'Z'; F11 : IN std_logic := 'Z'; F20 : IN std_logic := 'Z'; F21 : IN std_logic := 'Z'; F30 : IN std_logic := 'Z'; F31 : IN std_logic := 'Z'; F40 : IN std_logic := 'Z'; F41 : IN std_logic := 'Z'; Q10 : OUT std_logic := 'U'; Q11 : OUT std_logic := 'U'; Q20 : OUT std_logic := 'U'; Q21 : OUT std_logic := 'U'; Q30 : OUT std_logic := 'U'; Q31 : OUT std_logic := 'U'; Q40 : OUT std_logic := 'U'; Q41 : OUT std_logic := 'U' ); ATTRIBUTE VITAL_level0 OF roboclock : ENTITY IS TRUE; END roboclock; -------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION -------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral OF roboclock IS ATTRIBUTE VITAL_level1 OF vhdl_behavioral : ARCHITECTURE IS FALSE; SIGNAL REF_ipd : std_ulogic := 'X'; SIGNAL FB_ipd : std_ulogic := 'X'; SIGNAL FS_ipd : std_ulogic := 'Z'; SIGNAL TEST_ipd : std_ulogic := 'Z'; -- All lower case signals are internal to the model SIGNAL qa1 : std_ulogic :='0'; SIGNAL qa2 : std_ulogic :='0'; SIGNAL qa3 : std_ulogic :='0'; SIGNAL qa4 : std_ulogic :='0'; SIGNAL a : std_ulogic :='0'; SIGNAL b : std_ulogic :='0'; SIGNAL c : std_ulogic :='0'; SIGNAL d : std_ulogic :='0'; SIGNAL grid : std_ulogic := 'Z'; SIGNAL f_nom : std_ulogic := '0'; SIGNAL f_nom_period : time:= 0 ns; SIGNAL f_nom_period_ini : time:= 0 ns; SIGNAL f_nom_period_up_bond : time:= 0 ns; SIGNAL f_nom_period_low_bond : time:= 0 ns; SIGNAL f_nom_period_fin : time:= 0 ns; SIGNAL tu : time:= 0 ns; SIGNAL ref_period : time:= 0 ns; SIGNAL fb_period : time:= 0 ns; SIGNAL grid_period : time:= 0 ns; SIGNAL ref_count : integer :=0; SIGNAL fb_count : integer :=0; SIGNAL weight_count : integer :=0; SIGNAL M : integer :=0; SIGNAL MP : integer :=0; -- From Table 1. of the Cypress data sheet about this port CONSTANT N_low : integer :=44; CONSTANT N_mid : integer :=26; CONSTANT N_high : integer :=16; BEGIN ---------------------------------------------------------------------------- -- Wire Delays ---------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1: VitalWireDelay (REF_ipd, REF, tipd_REF); w_2: VitalWireDelay (FB_ipd, FB, tipd_FB); w_3: VitalWireDelay (FS_ipd, FS, tipd_FS); w_4: VitalWireDelay (TEST_ipd, TEST, tipd_TEST); END BLOCK; -------------------------------------------------------------------------------- -- Nominal Frequency Process -------------------------------------------------------------------------------- -- This process generates nominal frequency (f_nom) signal. M is the factor of -- reference frequency (REF_ipd) over nominal frequency. -- The period of nominal frequency (f_nom_period) is determined in -- Nominal Frequency Period Mux Process (f_nom_period_mux_process). -- Note that f_nom and REF_ipd are lined up by the wait statement. -- And the last "wait for (f_nom_period/2)" was void to prevent aliasing. -- During test mode (TEST_ipd='Z' or '1'), the PLL is disconnected -- from the output. The device acts like a delay. Output simply is -- a delay signal of reference signal. -------------------------------------------------------------------------------- fnom_process:PROCESS BEGIN WAIT ON REF_ipd; IF (TEST_ipd='0') THEN IF (REF_ipd='1') THEN IF (M=1) THEN f_nom <='1'; wait for (f_nom_period/2); f_nom <= '0'; ELSIF (M=2 or M=4) THEN FOR i in 0 to M-2 LOOP f_nom <='1'; wait for (f_nom_period/2); f_nom <= '0'; wait for (f_nom_period/2); END LOOP; f_nom <='1'; wait for (f_nom_period/2); f_nom <= '0'; ELSE NULL; END IF; END IF; ELSIF (TEST_ipd='Z' or TEST_ipd='1') THEN f_nom <= REF_ipd; ELSE NULL; END IF; END PROCESS; -------------------------------------------------------------------------------- -- Search Mode & Operation Mode Mux Process -------------------------------------------------------------------------------- -- In this process, the output is muxed between the "feedback search" pins and -- the "real" output pins. M=0 indicates "feedback search" mode, M=1,2,or 4 -- indicates "operation" mode. -- mux1,mux2,mux3,mux4 represent the output of the mux. M is the select signal. -- When M is 0, output is connected to a,b,c,d to search feedback pin. -- When M is 1,2, or 4, output is connect to qa1,qa2,qa3,qa4 which are -- generated from f_nom. -- Note that 1Q0 and 1Q1 are identical (same as 2Q0 and 2Q1, 3Q0 and 3Q1, -- 4Q0 and 4Q1). Therefore, use mux1 to generate both 1Q0 and 1Q1. -------------------------------------------------------------------------------- mux_process:PROCESS(M,a,b,c,d,qa1,qa2,qa3,qa4,REF_ipd) VARIABLE PD_REF : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_REF : X01 := '0'; BEGIN ------------------------------------------------------------------------ -- Timing Check Section ------------------------------------------------------------------------ IF (TimingChecksOn) THEN VitalPeriodPulseCheck ( TestSignal => REF, TestSignalName => "REF", Period => tperiod_min_REF, PulseWidthHigh => tpw_hi_min_REF, PulseWidthLow => tpw_lo_min_REF, PeriodData => PD_REF, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_REF, HeaderMsg => InstancePath & "RoboClock", CheckEnabled => TRUE ); END IF; -- Timing Check Section ------------------------------------------------------------------------ -- Functionality Section ------------------------------------------------------------------------ IF (Pviol_REF = 'X') THEN Q10 <= 'X' ; Q11 <= 'X' ; Q20 <= 'X' ; Q21 <= 'X' ; Q30 <= 'X' ; Q31 <= 'X' ; Q40 <= 'X' ; Q41 <= 'X' ; ELSE IF (M=0) THEN -- Search for the output pin connected to the feedback pin Q10 <= a ; Q11 <= a ; Q20 <= b ; Q21 <= b ; Q30 <= c ; Q31 <= c ; Q40 <= d ; Q41 <= d ; ELSE -- Operation mode output Q10 <= qa1 ; Q11 <= qa1 ; Q20 <= qa2 ; Q21 <= qa2 ; Q30 <= qa3 ; Q31 <= qa3 ; Q40 <= qa4 ; Q41 <= qa4 ; END IF; END IF; END PROCESS; -------------------------------------------------------------------------------- -- Initialize Nominal Frequency Period & Time Unit DelayProcess -------------------------------------------------------------------------------- -- This process initializes nominal frequency period (f_nom_period_ini) -- and the time unit delay (tu) -- according to the input of the frequency state (FS_ipd) signal. -- The lower and upper bond of the frequency range were obtianed from -- Cypress databook. -------------------------------------------------------------------------------- f_nom_period_ini_process:PROCESS(FS_ipd,f_nom_period) VARIABLE N : integer:=0; BEGIN -- Initialized nominal frequency period by the select of input of FS pin IF (FS_ipd='0') THEN f_nom_period_ini<=44.44 ns; f_nom_period_up_bond<=66.67 ns; f_nom_period_low_bond<=33.33 ns; N:=N_low; ELSIF (FS_ipd='Z') THEN f_nom_period_ini<=26.66 ns; f_nom_period_up_bond<=40 ns; f_nom_period_low_bond<=20 ns; N:=N_mid; ELSIF (FS_ipd='1') THEN f_nom_period_ini<=16.66 ns; f_nom_period_up_bond<=25 ns; f_nom_period_low_bond<=12.50 ns; N:=N_high; END IF; tu<=(f_nom_period/N); END PROCESS; -------------------------------------------------------------------------------- -- Search Mode Process -------------------------------------------------------------------------------- -- This process is to detect which of the 8 output pin is connected -- to the feedback pin. This process is not repeatable. Because of -- this process, REF_ipd can't be inserted until 10 ns after. -- If feedback is connected to either 1Qx or 2Qx then M=1, if 3Qx then M=4, -- 4Qx then M=2. -------------------------------------------------------------------------------- search_process:PROCESS BEGIN wait for 250 us; -- half PLL lock time a <= '1'; b <= '1'; wait for 250 us; -- half PLL lock time IF (FB_ipd='1') THEN M <=1; ELSE c <= '1'; wait for 2 ns; IF (FB_ipd='1') THEN M <= 4; ELSE d <='1'; wait for 2 ns; IF (FB_ipd='1') THEN M <=2; END IF; END IF; END IF; wait; END PROCESS; -------------------------------------------------------------------------------- -- Ouput Generate Process (Operation Mode output) -------------------------------------------------------------------------------- -- This process delay, divide, or multiply the Nominal Frequency (f_nom) -- according to the input of Fx0 and Fx1. The time unit delay (tu) -- is calcualted at tu process. -- Note that these are the outputs connect to the output pins of the -- model during operation mode. -------------------------------------------------------------------------------- output_generate_process:PROCESS VARIABLE temp3: std_logic:='0'; BEGIN WAIT ON f_nom; IF (F10='0' and F11='0') THEN qa1<=transport f_nom after (f_nom_period- 4 * tu); ELSIF (F10='Z' and F11='0') THEN qa1<=transport f_nom after (f_nom_period-3 * tu); ELSIF (F10='1' and F11='0') THEN qa1<=transport f_nom after (f_nom_period-2 * tu); ELSIF (F10='0' and F11='Z') THEN qa1<=transport f_nom after (f_nom_period-1 * tu); ELSIF (F10='Z' and F11='Z') THEN qa1<=transport f_nom ; ELSIF (F10='1' and F11='Z') THEN qa1<=transport f_nom after (1 * tu); ELSIF (F10='0' and F11='1') THEN qa1<=transport f_nom after (2 * tu); ELSIF (F10='Z' and F11='1') THEN qa1<=transport f_nom after (3 * tu); ELSIF (F10='1' and F11='1') THEN qa1<=transport REF_ipd after (4* tu); END IF; IF (F20='0' and F21='0') THEN qa2<=transport f_nom after (f_nom_period - 4 * tu); ELSIF (F20='Z' and F21='0') THEN qa2<=transport f_nom after (f_nom_period-3 * tu); ELSIF (F20='1' and F21='0') THEN qa2<=transport f_nom after (f_nom_period-2 * tu); ELSIF (F20='0' and F21='Z') THEN qa2<=transport f_nom after (f_nom_period-1 * tu); ELSIF (F20='Z' and F21='Z') THEN qa2<=transport f_nom ; ELSIF (F20='1' and F21='Z') THEN qa2<=transport f_nom after (1 * tu); ELSIF (F20='0' and F21='1') THEN qa2<=transport f_nom after (2 * tu); ELSIF (F20='Z' and F21='1') THEN qa2<=transport f_nom after (3 * tu); ELSIF (F20='1' and F21='1') THEN qa2<=transport f_nom after (4* tu); END IF; IF (F30='0' and F31='0') THEN IF (f_nom='1') THEN qa3<= not qa3; END IF; ELSIF (F30='Z' and F31='0') THEN qa3<=transport f_nom after (f_nom_period-6 * tu); ELSIF (F30='1' and F31='0') THEN qa3<=transport f_nom after (f_nom_period-4 * tu); ELSIF (F30='0' and F31='Z') THEN qa3<=transport f_nom after (f_nom_period-2 * tu); ELSIF (F30='Z' and F31='Z') THEN qa3<=transport f_nom ; ELSIF (F30='1' and F31='Z') THEN qa3<=transport f_nom after (2 * tu); ELSIF (F30='0' and F31='1') THEN qa3<=transport f_nom after (4 * tu); ELSIF (F30='Z' and F31='1') THEN qa3<=transport f_nom after (6 * tu); ELSIF (F30='1' and F31='1') THEN IF (f_nom='1') THEN temp3:= not temp3; IF (temp3='1') THEN qa3<= not qa3; END IF; END IF; END IF; IF (F40='0' and F41='0') THEN IF (f_nom='1') THEN qa4<=not qa4; END IF; ELSIF (F40='Z' and F41='0') THEN qa4<=transport f_nom after (f_nom_period-6 * tu); ELSIF (F40='1' and F41='0') THEN qa4<=transport f_nom after (f_nom_period-4 * tu); ELSIF (F40='0' and F41='Z') THEN qa4<=transport f_nom after (f_nom_period-2 * tu); ELSIF (F40='Z' and F41='Z') THEN qa4<=transport f_nom ; ELSIF (F40='1' and F41='Z') THEN qa4<=transport f_nom after (2 * tu); ELSIF (F40='0' and F41='1') THEN qa4<=transport f_nom after (4 * tu); ELSIF (F40='Z' and F41='1') THEN qa4<=transport f_nom after (6 * tu); ELSIF (F40='1' and F41='1') THEN qa4<=transport not f_nom; END IF; END PROCESS; -------------------------------------------------------------------------------- -- Generate grid siganl -------------------------------------------------------------------------------- -- This process generate grid signal which is used to sample the reference -- and feedback signal. The period of the reference signal (ref_period) -- is calculated then divided by 64 to obtain the grid signal period -- (grid_period). Grid signal is generated after the second reference -- signal. -- Variable loop1 is used to keep track with the numbe of the loop. -- Note that the last "WAIT FOR grid_period" was void to prevent aliasing. -------------------------------------------------------------------------------- ref_grid_process:PROCESS VARIABLE redge1 : time:= 0 ns; VARIABLE redge2 : time:= 0 ns; VARIABLE temp : time; VARIABLE loop1 : integer:=0; BEGIN wait on REF_ipd; IF (TEST_ipd='0') THEN IF (REF_ipd='1') THEN ref_count<=ref_count+1; redge2 :=redge1; redge1 := NOW; ref_period<= (redge1-redge2); grid_period <= (ref_period/64); IF (ref_count>1) then FOR i in 0 to 30 loop grid<='1'; WAIT FOR grid_period; grid<='0'; WAIT FOR grid_period; loop1:=loop1+1; END LOOP; grid<='1'; WAIT FOR grid_period; grid<='0'; loop1:=0; END IF; END IF; END IF; END PROCESS; -------------------------------------------------------------------------------- -- Weight Count Process -------------------------------------------------------------------------------- -- This process samples reference signal and feedback signal with grid signal. -- Weight Count (weight_count) signal is used to adjust the nominal -- period ( to be speed up or slow down). -- The adjusted nominal period is f_nom_period_fin. -- f_nom_period_fin is then to compare with the lower and upper bond -- of the frequency range. If it exceeds the range, it will be clipped. -------------------------------------------------------------------------------- weight_count_process:PROCESS VARIABLE loop2 : integer:=0; VARIABLE loop3 : integer:=0; BEGIN WAIT ON grid; IF (TEST_ipd='0') THEN IF (FB_ipd='1') THEN FOR i in 0 TO 31 LOOP IF( grid='1') THEN IF ( FB_ipd='1' and REF_ipd='0') THEN weight_count<=weight_count-1; ELSIF (REF_ipd='1' and FB_ipd='Z') THEN weight_count<=weight_count+1; ELSE NULL; END IF; loop2:=loop2+1; WAIT FOR grid_period*2; END IF; END LOOP; loop2:=0; f_nom_period_fin<= (f_nom_period+weight_count*grid_period); loop3:=loop3+1; IF (f_nom_period_finf_nom_period_up_bond) THEN f_nom_period_fin<=f_nom_period_up_bond; ELSE NULL; END IF; END IF; END IF; END PROCESS; -------------------------------------------------------------------------------- -- Feedback Process -------------------------------------------------------------------------------- -- This process is to calculated feedback period. -------------------------------------------------------------------------------- fb_process:PROCESS VARIABLE fedge1 : time:= 0 ns; VARIABLE fedge2 : time:= 0 ns; VARIABLE temp : time:= 0 ns; BEGIN wait on FB_ipd; IF (FB_ipd='1') THEN fb_count<=fb_count+1; fedge2 := fedge1; fedge1 := NOW; IF (fb_count>1) then fb_period<= (fedge1-fedge2); END IF; END IF; END PROCESS; -------------------------------------------------------------------------------- -- Nominal Period Mux Process -------------------------------------------------------------------------------- -- This process decides when nominal period gets updated by the adjusted -- nominal period. -------------------------------------------------------------------------------- f_nom_period_mux_process:PROCESS(f_nom_period_ini, f_nom_period_fin,ref_count) BEGIN IF (ref_count<4) THEN f_nom_period<=f_nom_period_ini; ELSE f_nom_period<=f_nom_period_fin; END IF; END PROCESS; END vhdl_behavioral;