-------------------------------------------------------------------------------- -- File Name: ds92lv1212a.vhd -------------------------------------------------------------------------------- -- Copyright (C) 2005 Free Model Foundry; -- -- 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: -- V1.0 A.Anic 05 Nov 24 Initial release -- -------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: IF -- Technology: -- Part: ds92lv1212a -- Description: 16-40 MHz 10-Bit Bus LVDS Random Lock Deserializer with -- Embedded Clock Recovery -------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.vital_primitives.ALL; USE IEEE.vital_timing.ALL; USE IEEE.std_logic_1164.ALL; LIBRARY FMF; USE FMF.gen_utils.ALL; -------------------------------------------------------------------------------- -- ENTITY DECLARATION -------------------------------------------------------------------------------- ENTITY ds92lv1212a IS GENERIC ( -- tipd delays: interconnect path delays tipd_RCLKR : VitalDelayType01 := VitalZeroDelay01; tipd_RI : VitalDelayType01 := VitalZeroDelay01; tipd_RINeg : VitalDelayType01 := VitalZeroDelay01; tipd_PWRDNNeg : VitalDelayType01 := VitalZeroDelay01; tipd_REN : VitalDelayType01 := VitalZeroDelay01; tipd_REFCLK : VitalDelayType01 := VitalZeroDelay01; -- tpd delays tpd_REN_ROUT0 : VitalDelayType01Z := UnitDelay01Z; tpd_PWRDNNeg_ROUT0 : VitalDelayType01Z := UnitDelay01Z; tpd_REFCLK_ROUT0 : VitalDelayType01Z := UnitDelay01Z; tpd_RI_ROUT0 : VitalDelayType01 := UnitDelay01; tpd_PWRDNNeg_LOCKNeg : VitalDelayType01Z := UnitDelay01Z; tpd_REN_RCLK : VitalDelayType01Z := UnitDelay01Z; tpd_PWRDNNeg_RCLK : VitalDelayType01Z := UnitDelay01Z; tpd_REFCLK_RCLK : VitalDelayType01Z := UnitDelay01Z; tpd_RI_RCLK : VitalDelayType01 := UnitDelay01; -- tperiod min (calculated as 1/max freq) tpw_REFCLK_posedge : VitalDelayType := UnitDelay; tpw_REFCLK_negedge : VitalDelayType := UnitDelay; tperiod_REFCLK_posedge : VitalDelayType := UnitDelay; -- tINIT (LOCK time) tdevice_INIT : VitalDelayType := UnitDelay; -- tSYNC (LOCK time) tdevice_SYNC : VitalDelayType := UnitDelay; -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; TimingModel : STRING := DefaultTimingModel ); PORT ( RI : IN std_logic := 'U'; RINeg : IN std_logic := 'U'; REN : IN std_ulogic := 'U'; PWRDNNeg : IN std_ulogic := 'U'; REFCLK : IN std_ulogic := 'U'; RCLKR : IN std_ulogic := 'U'; ROUT0 : OUT std_ulogic := 'Z'; ROUT1 : OUT std_ulogic := 'Z'; ROUT2 : OUT std_ulogic := 'Z'; ROUT3 : OUT std_ulogic := 'Z'; ROUT4 : OUT std_ulogic := 'Z'; ROUT5 : OUT std_ulogic := 'Z'; ROUT6 : OUT std_ulogic := 'Z'; ROUT7 : OUT std_ulogic := 'Z'; ROUT8 : OUT std_ulogic := 'Z'; ROUT9 : OUT std_ulogic := 'Z'; LOCKNeg : OUT std_ulogic := 'Z'; RCLK : OUT std_ulogic := 'Z' ); ATTRIBUTE VITAL_LEVEL0 of ds92lv1212a : ENTITY IS TRUE; END ds92lv1212a; -------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION -------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of ds92lv1212a IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT partID : STRING := "ds92lv1212a"; SIGNAL RI_ipd : std_ulogic := 'U'; SIGNAL RINeg_ipd : std_ulogic := 'U'; SIGNAL REN_ipd : std_ulogic := 'U'; SIGNAL PWRDNNeg_ipd : std_ulogic := 'U'; SIGNAL REFCLK_ipd : std_ulogic := 'U'; SIGNAL RCLKR_ipd : std_ulogic := 'U'; SIGNAL ROUT_zd : std_ulogic_vector(9 downto 0):=(others => 'Z'); SIGNAL RCLK_zd : std_ulogic := 'Z'; SIGNAL LOCKNeg_zd : std_ulogic := 'Z'; SIGNAL BufIn, BufOut : std_logic; BEGIN --------------------------------------------------------------------------- -- Internal Delays --------------------------------------------------------------------------- -- Artificial VITAL primitives to incorporate internal delays INIT :VitalBuf (BufOut, BufIn, (tdevice_INIT, UnitDelay)); SYNC :VitalBuf (BufOut, BufIn, (tdevice_SYNC, UnitDelay)); ---------------------------------------------------------------------------- -- Wire Delays ---------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (RI_ipd, RI, tipd_RI); w_2 : VitalWireDelay (RINeg_ipd, RINeg, tipd_RINeg); w_3 : VitalWireDelay (REN_ipd, REN, tipd_REN); w_4 : VitalWireDelay (PWRDNNeg_ipd, PWRDNNeg, tipd_PWRDNNeg); w_5 : VitalWireDelay (REFCLK_ipd, REFCLK, tipd_REFCLK); w_6 : VitalWireDelay (RCLKR_ipd, RCLKR, tipd_RCLKR); END BLOCK; ---------------------------------------------------------------------------- -- Main Behavior Block ---------------------------------------------------------------------------- Behavior: BLOCK PORT ( RCLKR : IN std_ulogic := 'U'; PWRDNNeg : IN std_ulogic := 'U'; RI : IN std_ulogic := 'U'; RINeg : IN std_ulogic := 'U'; REN : IN std_ulogic := 'U'; REFCLK : IN std_ulogic := 'U'; RCLK : OUT std_ulogic := 'Z'; LOCKNeg : OUT std_ulogic := 'Z'; ROUT : OUT std_ulogic_vector(9 downto 0):=(others => 'Z') ); PORT MAP ( RCLKR => RCLKR_ipd, PWRDNNeg => PWRDNNeg, RI => RI_ipd, RINeg => RINeg_ipd, REN => REN_ipd, REFCLK => REFCLK_ipd, ROUT(0) => ROUT0, ROUT(1) => ROUT1, ROUT(2) => ROUT2, ROUT(3) => ROUT3, ROUT(4) => ROUT4, ROUT(5) => ROUT5, ROUT(6) => ROUT6, ROUT(7) => ROUT7, ROUT(8) => ROUT8, ROUT(9) => ROUT9, RCLK => RCLK, LOCKNeg => LOCKNeg ); ---------------------------------------------------------------------------- -- Functional Section ---------------------------------------------------------------------------- TYPE StateType IS (SYNC, INIT_SYNC, PWR_DWN, DATA_OUT); SHARED VARIABLE State : StateType := PWR_DWN; SHARED VARIABLE EnableRead : BOOLEAN := false; SHARED VARIABLE PERIOD : TIME := 1 ns; SHARED VARIABLE TmpPer : TIME := 2 ns; SHARED VARIABLE time_out : TIME := 1 ns; SHARED VARIABLE SerialCount : INTEGER; SHARED VARIABLE t_REFCLK_ROUT0: VitalDelayType01Z := tpd_REFCLK_ROUT0; SHARED VARIABLE t_REN_ROUT0 : VitalDelayType01Z := tpd_REN_ROUT0; SHARED VARIABLE CntSYNC : INTEGER; SIGNAL RI_dig : std_ulogic := 'U'; SIGNAL FlagREN : std_ulogic := '0'; SIGNAL FromREN : std_ulogic := '0'; SIGNAL FromREFCLK : std_ulogic := '0'; SIGNAL FlagSYNC : std_ulogic := '0'; SIGNAL FlagOUT : std_ulogic := '0'; SIGNAL CLK : std_ulogic := '0'; SIGNAL FlagDATA_OUT : std_ulogic := '0'; SIGNAL FlagRCLK_OUT : std_ulogic := '0'; SIGNAL REN_LATE_fall : std_ulogic := '0'; SIGNAL REN_LATE_ris : std_ulogic := '0'; SIGNAL PWRDN_LATE : std_ulogic := '0'; SIGNAL TIME_in : std_ulogic := '0'; BEGIN DiffRec : PROCESS (RI, RINeg) -- Functionality Results Variables VARIABLE RI_zd : std_ulogic; VARIABLE PrevData : std_logic_vector(0 to 1); -- Glitch Detection Variables VARIABLE RI_GlitchData : VitalGlitchDataType; BEGIN ------------------------------------------------------------------------ -- Functionality Section ------------------------------------------------------------------------ IF RI = 'Z' OR RINeg = 'Z' THEN RI_zd := 'Z'; ELSE VitalStateTable ( StateTable => Diff_rec_tab, DataIn => (RI, RINeg), Result => RI_zd, PreviousDataIn => PrevData ); END IF; ------------------------------------------------------------------------ -- (Dummy) Path Delay Section ------------------------------------------------------------------------ VitalPathDelay ( OutSignal => RI_dig, OutSignalName => "RI_dig", OutTemp => RI_zd, GlitchData => RI_GlitchData, Paths => ( 0 => (InputChangeTime => RI'LAST_EVENT, PathDelay => VitalZeroDelay, PathCondition => FALSE)) ); END PROCESS DiffRec; PLL: PROCESS VARIABLE CntCLK : integer; VARIABLE EnPLL : std_ulogic := '0'; VARIABLE EnTimeOut : boolean := false; BEGIN IF EnPLL = '0' THEN WAIT ON RI_dig, TIME_in; IF rising_edge(RI_dig) AND PWRDNNeg = '1' AND PERIOD < 10 ns THEN EnableRead := true; SerialCount := 0; IF State = DATA_OUT THEN FlagOUT <= '1', '0' after 1 ns; END IF; WAIT FOR PERIOD/2; EnTimeOut := false; CntCLK := 10; CLK <= '1'; EnPLL := '1'; END IF; IF falling_edge (TIME_in) AND EnTimeOut = true AND PWRDNNeg = '1' AND State /= INIT_SYNC AND State /= SYNC THEN State := SYNC; CntSYNC := tdevice_SYNC/62.5 ns; FlagSYNC <= '1', '0' AFTER 1 ns; END IF; ELSE WAIT FOR PERIOD; CLK <= not(CLK); IF CntCLK = 0 THEN EnPLL := '0'; TIME_in <= '1', '0' AFTER time_out; EnTimeOut := true; ELSE CntCLK := CntCLK - 1; END IF; END IF; END PROCESS PLL; DESER: PROCESS (CLK, REFCLK, PWRDNNeg, REN, FlagSYNC, FlagDATA_OUT, FlagRCLK_OUT, PWRDN_LATE, REN_LATE_ris, REN_LATE_fall) -- Pulse Width and Period Check Variables VARIABLE Pviol_REFCLK : X01 := '0'; VARIABLE PD_REFCLK : VitalPeriodDataType := VitalPeriodDataInit; -- Violation variable VARIABLE Violation : X01 := '0'; VARIABLE Rout_tmp : std_ulogic_vector (9 downto 0); VARIABLE RCLK_tmp : std_ulogic; VARIABLE Data_in : std_ulogic_vector (11 downto 0); VARIABLE Previous : time := 0 ns; VARIABLE CntINIT : integer; BEGIN -------------------------------- -- Timing Check Section -------------------------------- IF (TimingChecksON) THEN -- REFCLK pulse ( low&high ) width and period check - Syn VitalPeriodPulseCheck ( TestSignal => REFCLK, TestSignalName => "REFCLK", PulseWidthLow => tpw_REFCLK_posedge, PulseWidthHigh => tpw_REFCLK_negedge, Period => tperiod_REFCLK_posedge, CheckEnabled => TRUE, HeaderMsg => InstancePath & PartID, PeriodData => PD_REFCLK, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_REFCLK); END IF; Violation := Pviol_REFCLK; ASSERT Violation = '0' REPORT InstancePath & partID & " : signal values may be" & " incorrect due to timing violation(s)" SEVERITY Warning; --------------------------------------- --------------------------------------- -- Functional Section --------------------------------------- --------------------------------------- IF rising_edge(PWRDNNeg) THEN State := INIT_SYNC; CntINIT := tdevice_INIT/62.5 ns; EnableRead := false; LOCKNeg_zd <= '1'; Rout_tmp := B"1111100000"; ELSIF falling_edge (PWRDNNeg) THEN PWRDN_LATE <= '1', '0' after TmpPer/2; END IF; IF falling_edge(PWRDN_LATE) THEN State := PWR_DWN; ROUT_zd <= (OTHERS => 'Z'); RCLK_zd <= 'Z'; LOCKNeg_zd <= 'Z'; END IF; IF rising_edge(FlagSYNC) THEN LOCKNeg_zd <= '1'; ROUT_zd <= (OTHERS => 'Z'); RCLK_zd <= 'Z'; Rout_tmp := B"1111100000"; END IF; IF rising_edge (REFCLK) THEN IF State = INIT_SYNC THEN TmpPer := NOW - Previous; PERIOD := TmpPer/12; time_out := PERIOD + 1 ns; Previous := NOW; CntINIT := CntINIT - 1; IF CntINIT = 0 THEN t_REFCLK_ROUT0(trz1):= tpd_REFCLK_ROUT0(trz1)+TmpPer/2; t_REFCLK_ROUT0(trz0):= tpd_REFCLK_ROUT0(trz0)+TmpPer/2; t_REN_ROUT0(tr1z) := tpd_REN_ROUT0(tr1z)+TmpPer/2; t_REN_ROUT0(tr0z) := tpd_REN_ROUT0(tr0z)+TmpPer/2; t_REN_ROUT0(trz1) := tpd_REN_ROUT0(trz1)+TmpPer/2; t_REN_ROUT0(trz0) := tpd_REN_ROUT0(trz0)+TmpPer/2; State := DATA_OUT; LOCKNeg_zd <= '0'; RCLK_tmp := '0'; IF REN = '1' AND FlagREN = '0' AND PWRDNNeg = '1' THEN ROUT_zd <= Rout_tmp; RCLK_zd <= RCLK_tmp; FromREFCLK <= '1', '0' AFTER 1 ns; END IF; END IF; END IF; IF State = SYNC THEN TmpPer := NOW - Previous; PERIOD := TmpPer/12; time_out := 1.5*PERIOD; Previous := NOW; CntSYNC := CntSYNC - 1; IF CntSYNC = 0 THEN State := DATA_OUT; LOCKNeg_zd <= '0'; RCLK_tmp := '0'; IF (REN = '1' AND FlagREN = '0') OR REN_LATE_fall = '1' THEN ROUT_zd <= Rout_tmp; RCLK_zd <= RCLK_tmp; FromREFCLK <= '1', '0' after 1 ns; END IF; END IF; END IF; END IF; IF rising_edge (FlagDATA_OUT) AND State = DATA_OUT THEN IF RCLKR = '1' THEN RCLK_tmp := '0'; ELSIF RCLKR = '0' THEN RCLK_tmp := '1'; END IF; IF (REN = '1' AND FlagREN = '0') OR REN_LATE_fall = '1' THEN ROUT_zd <= Rout_tmp; RCLK_zd <= RCLK_tmp; END IF; END IF; IF rising_edge (FlagRCLK_OUT) AND State = DATA_OUT THEN IF RCLKR = '1' THEN RCLK_tmp := '1'; ELSIF RCLKR = '0' THEN RCLK_tmp := '0'; END IF; IF (REN = '1' AND FlagREN = '0') OR REN_LATE_fall = '1' THEN RCLK_zd <= RCLK_tmp; END IF; END IF; IF CLK'event THEN IF EnableRead THEN Data_in(SerialCount) := RI_dig; SerialCount := SerialCount + 1; IF SerialCount = 11 THEN EnableRead := false; Rout_tmp := Data_in(10 DOWNTO 1); END IF; END IF; END IF; IF falling_edge (REN_LATE_ris) AND State = DATA_OUT THEN ROUT_zd <= Rout_tmp; RCLK_zd <= RCLK_tmp; FromREN <= '1', '0' after 1 ns; END IF; IF falling_edge (REN_LATE_fall) THEN ROUT_zd <= (OTHERS => 'Z'); RCLK_zd <= 'Z'; FromREN <= '1', '0' after 1 ns; END IF; IF rising_edge (REN) THEN REN_LATE_ris <= '1', '0' after t_REN_ROUT0 (trz0); FlagREN <= '1', '0' after t_REN_ROUT0 (trz0); ELSIF falling_edge (REN) THEN REN_LATE_fall <= '1', '0' after TmpPer/2; END IF; END PROCESS; PR_OUT: PROCESS BEGIN WAIT ON FlagOUT; IF rising_edge(FlagOUT) THEN WAIT FOR TmpPer/4; FlagDATA_OUT <= '1','0' after 1 ns; WAIT FOR TmpPer/2; FlagRCLK_OUT <= '1','0' after 1 ns; END IF; END PROCESS; PROCESS (LOCKNeg_zd) VARIABLE LOCKNeg_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z (OutSignal => LOCKNeg, OutSignalName => "LOCKNeg", OutTemp => LOCKNeg_zd, GlitchData => LOCKNeg_GlitchData, Paths => (0 => (InputChangeTime => PWRDNNeg'last_event, PathDelay => tpd_PWRDNNeg_LOCKNeg, PathCondition => PWRDNNeg = '1'), 1 => (InputChangeTime => PWRDN_LATE'last_event, PathDelay => tpd_PWRDNNeg_LOCKNeg, PathCondition => true), 2 => (InputChangeTime => REFCLK'last_event, PathDelay => VitalZeroDelay01Z, PathCondition => FromREFCLK = '1'), 3 => (InputChangeTime => FlagSYNC'last_event, PathDelay => VitalZeroDelay01Z, PathCondition => true))); END PROCESS; PROCESS (RCLK_zd) VARIABLE RCLK_GlitchData : VitalGlitchDataType; BEGIN VitalPathDelay01Z (OutSignal => RCLK, OutSignalName => "RCLK", OutTemp => RCLK_zd, GlitchData => RCLK_GlitchData, Mode => VitalTransport, Paths => (0 => (InputChangeTime => PWRDN_LATE'last_event, PathDelay => tpd_PWRDNNeg_LOCKNeg, PathCondition => true), 1 => (InputChangeTime => FlagDATA_OUT'last_event, PathDelay => VitalExtendToFillDelay(tpd_RI_RCLK), PathCondition => true), 2 => (InputChangeTime => FlagRCLK_OUT'last_event, PathDelay => VitalExtendToFillDelay(tpd_RI_RCLK), PathCondition => true), 3 => (InputChangeTime => REFCLK'last_event, PathDelay => t_REFCLK_ROUT0, PathCondition => FromREFCLK = '1'), 4 => (InputChangeTime => REN_LATE_ris'last_event, PathDelay => VitalZeroDelay01Z, PathCondition => FromREN = '1'), 5 => (InputChangeTime => REN_LATE_fall'last_event, PathDelay => tpd_REN_RCLK, PathCondition => FromREN = '1'), 6 => (InputChangeTime => FlagSYNC'last_event, PathDelay => t_REN_ROUT0, PathCondition => FlagSYNC = '1'))); END PROCESS; QOutPathDelay_Gen: FOR i IN 9 DOWNTO 0 GENERATE PROCESS (ROUT_zd(i)) VARIABLE ROUT_GlitchData : VitalGlitchDataArrayType(9 Downto 0); BEGIN VitalPathDelay01Z (OutSignal => ROUT(i), OutSignalName => "ROUT", OutTemp => ROUT_zd(i), GlitchData => ROUT_GlitchData(i), Paths => (0 => (InputChangeTime => PWRDN_LATE'last_event, PathDelay => tpd_PWRDNNeg_LOCKNeg, PathCondition => true), 1 => (InputChangeTime => FlagDATA_OUT'last_event, PathDelay => VitalExtendToFillDelay(tpd_RI_ROUT0), PathCondition => true), 2 => (InputChangeTime => REFCLK'last_event, PathDelay => t_REFCLK_ROUT0, PathCondition => FromREFCLK = '1'), 3 => (InputChangeTime => REN_LATE_ris'last_event, PathDelay => VitalZeroDelay01Z, PathCondition => FromREN = '1'), 4 => (InputChangeTime => REN_LATE_fall'last_event, PathDelay => tpd_REN_ROUT0, PathCondition => FromREN = '1'), 5 => (InputChangeTime => FlagSYNC'last_event, PathDelay => t_REN_ROUT0, PathCondition => FlagSYNC = '1'))); END PROCESS; END GENERATE QOutPathDelay_Gen; END BLOCK; END vhdl_behavioral;