📄 altclklock.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 + -