📄 apex20ke_mf.vhd
字号:
locked: out std_logic);
end altclklock;
architecture behavior of altclklock is
signal pll0_period : TIME ;
signal pll1_period : TIME ;
signal new_clock0 : std_logic ;
signal new_clock1 : std_logic ;
signal start_new_clock0 : std_logic;
signal start_new_clock1 : std_logic;
signal phase_delay0 : TIME;
signal phase_delay1 : TIME;
signal locked_int : std_logic := '0';
signal highcycle, lowcycle: time := 0 ps;
signal cycleviolation : std_logic := '0';
begin
lock: process(inclock, inclocken)
variable inclock_edge_count: integer := 0;
variable outclock_start_edge : std_logic ;
begin
if locked_int = '0' then
pll0_period <= real(real(real(clock0_divide)/real(clock0_boost))* real(inclock_period )) * 1 ps;
pll1_period <= real(real(real(clock1_divide)/real(clock1_boost))* real(inclock_period )) * 1 ps;
if outclock_phase_shift = 0 then
outclock_start_edge := '1';
phase_delay0 <= (0.5 ) * pll0_period;
phase_delay1 <= (0.5 ) * pll1_period;
else
phase_delay0 <= outclock_phase_shift * 1 ps;
phase_delay1 <= outclock_phase_shift * 1 ps;
end if;
start_new_clock0 <= outclock_start_edge;
start_new_clock1 <= outclock_start_edge;
end if;
if inclocken = '0' or cycleviolation = '1' then
inclock_edge_count := 0;
locked_int <= '0';
locked <= '0';
elsif inclock'event then -- any inclock edge
if inclock = '1' then
if (((NOW - lowcycle) /= (1 ps * inclock_period/2))and (NOW > (1 ps * inclock_period/2))) then
cycleviolation <= '1';
assert false
report "Duty cycle violation"
severity error;
end if;
highcycle <= NOW;
end if;
if inclock = '0' then
if ((NOW - highcycle) /= (1 ps * inclock_period/2)) then
cycleviolation <= '1';
assert false
report "Duty cycle violation"
severity error;
end if;
lowcycle <= NOW;
end if;
inclock_edge_count := inclock_edge_count + 1;
if inclock_edge_count = valid_lock_cycles then
cycleviolation <= '0';
locked_int <= '1';
locked <= '1';
end if;
end if;
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;
new_clock0 <= not start_new_clock0 after phase_delay0;
else
clock0 <= new_clock0;
new_clock0 <= not new_clock0 after pll0_period/2;
end if;
first_cycle := false;
else
first_cycle := true;
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;
new_clock1 <= not start_new_clock1 after phase_delay1;
else
clock1 <= new_clock1;
new_clock1 <= not new_clock1 after pll1_period/2;
end if;
first_cycle := false;
else
first_cycle := true;
end if;
end process;
end behavior;
-- lvds receiver megafunction
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity altlvds_rx is
generic(
number_of_channels: natural;
deserialization_factor: natural;
registered_output: string := "ON";
inclock_period: natural;
clock_setting: string := "UNUSED");
port (
rx_in: in std_logic_vector(number_of_channels-1 downto 0);
rx_inclock: in std_logic;
rx_deskew: in std_logic := '0';
rx_out: out std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
rx_outclock : out std_logic;
rx_locked : out std_logic);
end altlvds_rx;
architecture behavior of altlvds_rx is
type channel_cnt is array (number_of_channels-1 downto 0) of integer;
signal data_int2, data_int3, data_regs: std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
signal rx_clkout_int : std_logic;
signal rx_locked_int : std_logic;
signal deskew_done: std_logic_vector(number_of_channels-1 downto 0) := (others => '1');
signal en: std_logic := '1';
signal first_load : std_logic := '0';
component altclklock
generic (
inclock_period : natural;
inclock_settings : string := "UNUSED";
valid_lock_cycles : natural := 3;
invalid_lock_cycles : natural := 3;
operation_mode : string := "NORMAL";
clock0_boost : natural := 1;
clock0_divide : natural := 1;
clock1_boost : natural := 1;
clock1_divide : natural := 1;
clock0_settings : string := "UNUSED";
clock1_settings : string := "UNUSED";
outclock_phase_shift : natural := 0);
port (inclock : in std_logic;
inclocken : in std_logic;
fbin : in std_logic := '0';
clock0 : out std_logic;
clock1: out std_logic;
locked: out std_logic);
end component;
begin
rx_out <= data_regs when registered_output = "ON" else data_int2;
rx_outclock <= rx_clkout_int;
rx_locked <= rx_locked_int;
U0: altclklock generic map (inclock_period => inclock_period,
clock0_boost => deserialization_factor)
port map (inclock => rx_inclock, inclocken => en,
clock0 => rx_clkout_int, locked => rx_locked_int);
-- At start up deskew is done due to inability to detect unconnected rx_deskew
-- pin.
deskew: process(rx_deskew)
begin
if rx_deskew = '1' then
deskew_done <= (others => '0');
end if;
end process;
load_data: process(rx_clkout_int, rx_inclock)
variable rxin_cnt : integer := 0;
variable edge_count: integer := 0;
variable count: channel_cnt := (others => 0);
variable sample: integer;
variable start_data : integer := 0;
variable pattern, data_int: std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
begin
if rx_inclock'event and rx_inclock = '1' then
rxin_cnt := 0;
if (deserialization_factor = 8) then
if (rx_deskew = '1') then
for i in 0 to number_of_channels-1 loop
if (pattern(((deserialization_factor*(i+1))-1) downto deserialization_factor*(i)) = "00001111") then
count(i) := count(i) + 1;
else
count(i) := 0;
end if;
if count(i) = 3 then
deskew_done(i) <= '1';
end if;
end loop;
end if;
elsif (deserialization_factor= 7) then
if (rx_deskew = '1') then
for i in 0 to number_of_channels-1 loop
if (pattern(((deserialization_factor*(i+1))-1) downto deserialization_factor*(i)) = "0000111") then
count(i) := count(i) + 1;
else
count(i) := 0;
end if;
if count(i) = 3 then
deskew_done(i) <= '1';
end if;
end loop;
end if;
elsif (deserialization_factor= 4) then
if (rx_deskew = '1') then
for i in 0 to number_of_channels-1 loop
if (pattern(((deserialization_factor*(i+1))-1) downto deserialization_factor*(i)) = "0011") then
count(i) := count(i) + 1;
else
count(i) := 0;
end if;
if count(i) = 3 then
deskew_done(i) <= '1';
end if;
end loop;
end if;
else
deskew_done <= (others => '1');
end if;
elsif rx_clkout_int'event and rx_clkout_int = '0' then
rxin_cnt := rxin_cnt + 1;
if rxin_cnt = 3 then
data_int2 <= data_int;
start_data := 1;
end if;
if start_data = 1 then
sample := edge_count rem deserialization_factor;
edge_count := edge_count + 1;
for i in 0 to number_of_channels -1 loop
if deskew_done(i) = '1' then
data_int((i*deserialization_factor)+sample) := rx_in(i);
else
pattern((i*deserialization_factor)+sample) := rx_in(i);
data_int((i*deserialization_factor)+sample) := 'X';
end if;
end loop;
end if;
end if;
end process;
parallel_reg: process(rx_inclock)
begin
if rx_inclock = '1' then
if deserialization_factor = 8 or deserialization_factor = 7 then
data_regs <= data_int2;
else
data_regs <= data_int3;
end if;
elsif rx_inclock = '0' then
if deserialization_factor <= 4 then
data_int3 <= data_int2;
end if;
end if;
end process parallel_reg;
end behavior;
-- lvds transmitter megafunction
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity altlvds_tx is
generic(
number_of_channels: natural;
deserialization_factor: natural;
registered_input: string := "ON";
multi_clock: string := "OFF";
inclock_period: natural;
clock_setting: string := "UNUSED");
port (
tx_in: in std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
tx_inclock: in std_logic;
sync_inclock: in std_logic := '0';
tx_out: out std_logic_vector(number_of_channels-1 downto 0);
tx_outclock : out std_logic;
tx_locked : out std_logic);
end altlvds_tx;
architecture behavior of altlvds_tx is
signal data_int, data_reg, tx_in_rgd: std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
signal clock_in: std_logic;
signal clock_out: std_logic;
signal tx_locked_int: std_logic;
signal en: std_logic := '1';
component altclklock
generic (
inclock_period : natural;
inclock_settings : string := "UNUSED";
valid_lock_cycles : natural := 3;
invalid_lock_cycles : natural := 3;
operation_mode : string := "NORMAL";
clock0_boost : natural := 1;
clock0_divide : natural := 1;
clock1_boost : natural := 1;
clock1_divide : natural := 1;
clock0_settings : string := "UNUSED";
clock1_settings : string := "UNUSED";
outclock_phase_shift : natural := 0);
port (inclock : in std_logic;
inclocken : in std_logic;
fbin : in std_logic := '0';
clock0 : out std_logic;
clock1: out std_logic;
locked: out std_logic);
end component;
begin
data_int <= data_reg when registered_input = "ON" else tx_in;
clock_in <= sync_inclock when multi_clock = "ON" else tx_inclock;
tx_outclock <= clock_out;
tx_locked <= tx_locked_int;
U0: altclklock generic map (inclock_period => inclock_period,
clock0_boost => deserialization_factor)
port map (inclock => tx_inclock, inclocken => en,
clock0 => clock_out, locked => tx_locked_int);
serialize: process(clock_out, clock_in)
variable edge_count: integer;
variable load_data : std_logic := '0';
variable count: integer := 0;
variable sample: integer;
variable tx_in2: std_logic_vector(deserialization_factor*number_of_channels -1 downto 0);
begin
if clock_in'event and clock_in = '1' then
edge_count := 0;
end if;
if clock_out'event and clock_out = '1' then
edge_count := edge_count + 1;
if edge_count = 3 then
tx_in2 := data_int; -- register the incoming data on the third edge
count := 0;
load_data := '1'; -- third_rising edge
end if;
if load_data = '1' then
for i in 0 to number_of_channels-1 loop
tx_out(i) <= tx_in2(i*deserialization_factor + count);
end loop;
count := count + 1;
end if;
end if;
end process;
sync: process(clock_in)
begin
if clock_in = '0' then
if deserialization_factor = 8 or deserialization_factor = 7 then
data_reg <= tx_in_rgd;
end if;
elsif clock_in = '1' then
if deserialization_factor <= 4 then
data_reg <= tx_in;
end if;
end if;
end process sync;
end behavior;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -