⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 altclklock.txt

📁 倍频锁频
💻 TXT
字号:

----------------------------------------------------------------------------
-- altclklock
----------------------------------------------------------------------------
--
-- Restrictions: 
--   1. NORMAL operation mode only 
--   2. Zero delay outputs
--
library ieee;
use ieee.std_logic_1164.all;

entity altclklock is
    generic
      ( inclock_period          : natural := 10000;
        inclock_settings        : string := "UNUSED";
        valid_lock_cycles       : natural := 5;
        invalid_lock_cycles     : natural := 5;
        valid_lock_multiplier   : natural := 1;
        invalid_lock_multiplier : natural := 1;
        operation_mode          : string := "NORMAL";
        clock0_boost            : natural := 1;
        clock0_divide           : natural := 1;
        clock1_boost            : natural := 1;
        clock1_divide           : natural := 1;
        clock2_boost            : natural := 1;
        clock2_divide           : natural := 1;
        clock_ext_boost         : natural := 1;
        clock_ext_divide        : natural := 1;
        clock0_settings         : string := "UNUSED";
        clock1_settings         : string := "UNUSED";
        clock2_settings         : string := "UNUSED";
        clock_ext_settings      : string := "UNUSED";
        outclock_phase_shift    : natural := 0;
        clock0_time_delay       : string := "0";
        clock1_time_delay       : string := "0";
        clock2_time_delay       : string := "0";
        clock_ext_time_delay    : string := "0";
        intended_device_family  : string := "APEX20KE" );
    port
      ( inclock   : in std_logic;
        inclocken : in std_logic := '1';
        fbin      : in std_logic := '1';
        clock0    : out std_logic;
        clock1    : out std_logic;
        clock2    : out std_logic;
        clock_ext : out std_logic;
        locked    : out std_logic );

    function time_delay ( s : string ) return TIME is
	variable len : integer := s'length;
	variable outclock_phase_shift_adj : integer := 0;
	variable sign : integer := 1;
	variable digit : integer;
	begin
        for i in 1 to len loop
			case s(i) is
				when '-' =>
                                        if i = 1 then
					    sign := -1;
                                        else
 				       	    ASSERT FALSE
					    REPORT "Illegal Character "&  s(i) & "in string parameter! "
					    SEVERITY ERROR;
                                        end if;
				when '0' =>
					digit := 0;
				when '1' =>
					digit := 1;
				when '2' =>
					digit := 2;
				when '3' =>
					digit := 3;
				when '4' =>
					digit := 4;
				when '5' =>
					digit := 5;
				when '6' =>
					digit := 6;
				when '7' =>
					digit := 7;
				when '8' =>
					digit := 8;
				when '9' =>
					digit := 9;
				when others =>
					ASSERT FALSE
					REPORT "Illegal Character "&  s(i) & "in string parameter! "
					SEVERITY ERROR;
			end case;
			outclock_phase_shift_adj := outclock_phase_shift_adj * 10 + digit;
	end loop;
        outclock_phase_shift_adj := outclock_phase_shift + sign*outclock_phase_shift_adj;
        while (outclock_phase_shift_adj < 0) loop
            outclock_phase_shift_adj := outclock_phase_shift_adj + inclock_period;
        end loop;
        while (outclock_phase_shift_adj >= inclock_period) loop
            outclock_phase_shift_adj := outclock_phase_shift_adj - inclock_period;
        end loop;
	return  outclock_phase_shift_adj * 1 ps;
    end;
end altclklock;

architecture behavior of altclklock is

signal pll0_half_period : TIME;
signal pll1_half_period : TIME;
signal pll2_half_period : TIME;
signal pll_ext_half_period : TIME;
signal new_clock0 : std_logic;
signal new_clock1 : std_logic;
signal new_clock2 : std_logic;
signal new_clock_ext : std_logic;
signal start_new_clock0 : std_logic;
signal start_new_clock1 : std_logic;
signal start_new_clock2 : std_logic;
signal start_new_clock_ext : std_logic;
signal phase_delay0 : TIME;
signal phase_delay1 : TIME;
signal phase_delay2 : TIME;
signal phase_delay_ext : TIME;
signal locked_int : std_logic := '0';
signal highcycle, lowcycle: time := 0 ps;
signal check_lock : std_logic := '0';

begin

    lock: process(inclock, inclocken, check_lock)    
    variable valid_inclock_edge_count       : integer := 0;
    variable invalid_inclock_edge_count     : integer := 0;
    variable inclock_started          : boolean := false;
    variable check_lock_time          : TIME;
    variable clk_per_tolerance : time;
    begin
    
        --clk_per_tolerance := 0.05 * 1 ps * inclock_period; 
        clk_per_tolerance := 1 ps; 
        if locked_int = '0' and inclocken = '1' then
            if inclock'event then
                locked <= '0';
            end if;
            check_lock_time := real(real(inclock_period)/2.0) * 1 ps;

            pll0_half_period <= real(real(real(clock0_divide)* real(inclock_period))/(2.0*real(clock0_boost))) * 1 ps;
            pll1_half_period <= real(real(real(clock1_divide)* real(inclock_period))/(2.0*real(clock1_boost))) * 1 ps;
            pll2_half_period <= real(real(real(clock2_divide)* real(inclock_period))/(2.0*real(clock2_boost))) * 1 ps;
            pll_ext_half_period <= real(real(real(clock_ext_divide)* real(inclock_period))/(2.0*real(clock_ext_boost))) * 1 ps;
      
            phase_delay0 <= time_delay(clock0_time_delay);
            phase_delay1 <= time_delay(clock1_time_delay);
            phase_delay2 <=  time_delay(clock2_time_delay);
            phase_delay_ext <= time_delay(clock_ext_time_delay);
    
            if ((inclock = '0') and ((clock0_boost/clock0_divide) mod 2 = 0) and (clock0_boost>clock0_divide)) then
                start_new_clock0 <= NOT inclock;
            else
                start_new_clock0 <= inclock;
            end if;
            if ((inclock = '0') and ((clock1_boost/clock1_divide) mod 2 = 0) and (clock1_boost>clock1_divide)) then
                start_new_clock1 <= NOT inclock;
            else
                start_new_clock1 <= inclock;
            end if;
            if intended_device_family = "MERCURY" then
                if ((inclock = '0') and ((clock2_boost/clock2_divide) mod 2 = 0) and (clock2_boost>clock2_divide)) then
                    start_new_clock2 <= NOT inclock;
                else
                    start_new_clock2 <= inclock;
                end if;
                if ((inclock = '0') and ((clock_ext_boost/clock_ext_divide) mod 2 = 0) and (clock_ext_boost>clock_ext_divide)) then
                    start_new_clock_ext <= NOT inclock;
                else
                    start_new_clock_ext <= inclock;
                end if;
            end if;
        end if;
          
        if inclocken = '0' then
            valid_inclock_edge_count := 0;
            invalid_inclock_edge_count := 0;
            locked_int <= '0';
            locked <= '0';
            inclock_started := false;
        elsif inclock'event then -- any inclock edge
            if locked_int = '1' then
                check_lock <= NOT check_lock after check_lock_time;
            end if;
            if inclock_started = false then
                if inclock = '1' then
                    highcycle <= NOW;
                    inclock_started := true;
                    valid_inclock_edge_count := 1;
                    invalid_inclock_edge_count := 0;
                elsif inclock = '0' then
                    lowcycle <= NOW;
                    inclock_started := true;
                    valid_inclock_edge_count := 0;
                    invalid_inclock_edge_count := 0;
                end if;
            elsif inclock = '1' then
                if (((NOW - lowcycle)*2 < ((1 ps * inclock_period) - clk_per_tolerance)) or ((NOW - lowcycle)*2 > ((1 ps * inclock_period) + clk_per_tolerance))) then
                    invalid_inclock_edge_count := invalid_inclock_edge_count + 1;
                    valid_inclock_edge_count := 1;
                    ASSERT FALSE
                    REPORT "Duty cycle violation"
                    SEVERITY ERROR; 
                else
                    valid_inclock_edge_count := valid_inclock_edge_count + 1;
                    invalid_inclock_edge_count := 0;
                end if;
                highcycle <= NOW;
            elsif inclock = '0' then
                if (((NOW - highcycle)*2 < ((1 ps * inclock_period) - clk_per_tolerance)) or ((NOW - highcycle)*2 > ((1 ps * inclock_period) + clk_per_tolerance))) then
                    invalid_inclock_edge_count := invalid_inclock_edge_count + 1;
                    valid_inclock_edge_count := 1;
                    ASSERT FALSE
                    REPORT "Duty cycle violation"
                    SEVERITY ERROR; 
                else
                    valid_inclock_edge_count := valid_inclock_edge_count + 1;
                    invalid_inclock_edge_count := 0;
                end if;
                lowcycle <= NOW;
            end if;
            if (valid_inclock_edge_count >= valid_lock_cycles) and (NOW > 0 ps) then
                locked_int <= '1';
                locked <= '1';
                valid_inclock_edge_count := 0;
            else
                if (invalid_inclock_edge_count >= invalid_lock_cycles) and 
                    (invalid_inclock_edge_count > 0) and (NOW > 0 ps) then
                    locked_int <= '0';
                    locked <= '0';
                    invalid_inclock_edge_count := 0;
                end if;
            end if;
        else
            if check_lock'event and (locked_int = '1') then
                invalid_inclock_edge_count := invalid_inclock_edge_count + 1;
                if (invalid_inclock_edge_count >= invalid_lock_cycles) and 
                    (invalid_inclock_edge_count > 0) and (NOW > 0 ps) then
                    locked_int <= '0';
                    locked <= '0';
                    ASSERT FALSE
                    REPORT "altclklock out of lock."
                    SEVERITY WARNING; 
                else
                    check_lock <= NOT check_lock after check_lock_time;
                end if;
            end if;
        end if; -- inclocken
    end process;

    gen_clock0: process(new_clock0,locked_int)
    variable first_cycle: boolean := true;
    begin
        if locked_int = '1' then
            if first_cycle = true then
                clock0 <= start_new_clock0;
                if (clock0_divide /= 1) and (valid_lock_cycles mod 2 = 0) then
                    -- Lock on -ve edge of inclock
                    new_clock0 <= not start_new_clock0 after (phase_delay0 + inclock_period/2* 1 ps);
                else
                    new_clock0 <= not start_new_clock0 after phase_delay0 + pll0_half_period;
                end if;
            else
                clock0 <= new_clock0; 
                new_clock0 <= not new_clock0 after pll0_half_period;
            end if;
            first_cycle := false;
        else
            first_cycle := true;
            new_clock0 <= start_new_clock0;
        end if;
    end process;

    gen_clock1: process(new_clock1,locked_int)
    variable first_cycle: boolean := true;
    begin
        if locked_int = '1' then
            if first_cycle = true then
                clock1 <= start_new_clock1;
                if (clock1_divide /= 1) and (valid_lock_cycles mod 2 = 0) then
                    -- Lock on -ve edge of inclock
                    new_clock1 <= not start_new_clock1 after (phase_delay1 + inclock_period/2* 1 ps);
                else
                    new_clock1 <= not start_new_clock1 after phase_delay1 + pll1_half_period;
                end if;
            else
                clock1 <= new_clock1; 
                new_clock1 <= not new_clock1 after pll1_half_period;
            end if;
            first_cycle := false;
        else
            first_cycle := true;
            new_clock1 <= start_new_clock1;
        end if;
    end process;

    gen_clock2: process(new_clock2,locked_int)
    variable first_cycle: boolean := true;
    begin
        if intended_device_family = "MERCURY" then
            if locked_int = '1' then
                if first_cycle = true then
                    clock2 <= start_new_clock2;
                    if (clock2_divide /= 1) and (valid_lock_cycles mod 2 = 0) then
                        -- Lock on -ve edge of inclock
                        new_clock2 <= not start_new_clock2 after (phase_delay2 + inclock_period/2* 1 ps);
                    else
                        new_clock2 <= not start_new_clock2 after phase_delay2 + pll2_half_period;
                    end if;
                else
                    clock2 <= new_clock2; 
                    new_clock2 <= not new_clock2 after pll2_half_period;
                end if;
                first_cycle := false;
            else
                first_cycle := true;
                new_clock2 <= start_new_clock2;
            end if;
        end if;
    end process;

    gen_clock_ext: process(new_clock_ext,locked_int)
    variable first_cycle: boolean := true;
    begin
        if intended_device_family = "MERCURY" then
            if locked_int = '1' then
                if first_cycle = true then
                    clock_ext <= start_new_clock_ext;
                    if (clock_ext_divide /= 1) and (valid_lock_cycles mod 2 = 0) then
                        -- Lock on -ve edge of inclock
                        new_clock_ext <= not start_new_clock_ext after (phase_delay_ext + inclock_period/2* 1 ps);
                    else
                        new_clock_ext <= not start_new_clock_ext after phase_delay_ext + pll_ext_half_period;
                    end if;
                else
                    clock_ext <= new_clock_ext; 
                    new_clock_ext <= not new_clock_ext after pll_ext_half_period;
                end if;
                first_cycle := false;
            else
                first_cycle := true;
                new_clock_ext <= start_new_clock_ext;
            end if;
        end if;
    end process;

end behavior;

⌨️ 快捷键说明

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