Forum Discussion
PLL frequency doubling but shouldn't
- 5 years ago
Hi Joossss,
Thanks for your code!
I was able to reproduce the issue that you mentioned.
In the screen shot that you had shared, the output of the LVDS_CLK_inst (buffer) is not clean. There are some red lines ('X') on the buffer output. Same happened in my code as well (see signal /top_tb/dut/clk_in) . Result was that the PLL output was double the input clock.
Then in the test bench, instead of using the procedure clk_gen, I drove the differential clock inputs using simple process.
SIGNAL clk_in_p : STD_LOGIC := '1';
SIGNAL clk_in_n : STD_LOGIC := '0';
PROCESS
BEGIN
clk_in_p <= not clk_in_p;
clk_in_n <= not clk_in_n;
WAIT FOR 6.6666 ns;
END PROCESS;
With this the buffer output was clean and the PLL generated the output as expected. See the screen shot.
May be due to the 'procedure' there is an delta delay added to the input signals and they are not phase aligned to each other, so the buffer output is not clean.
That impacted the PLL output as well.
Regards.
Hi,
Can you please attach the piece of code showing connections from differential input pins to the PLL output?
Regards
Yeah sure.
The VHDL code:
ntity PLL_TEST is Port (LVDS_Clk_p, LVDS_Clk_n : in std_logic_vector(0 downto 0); clk : in std_logic; step, updown : in std_logic; -- step must be applied for atleast two cycles. cntsel : in std_logic_vector(2 downto 0) -- "000" all counters, "001" M counter?, "010" c0 ... "110" c4 --data : out std_logic_vector(15 downto 0) ); end PLL_TEST; architecture rtl of PLL_TEST is component IOBUF_Differential_1 port( datain : in std_logic_Vector(0 downto 0); datain_b : in std_logic_vector(0 downto 0); dataout : out std_logic_vector(0 downto 0) ); end component IOBUF_Differential_1; component PLL port( areset : in std_logic; inclk0 : in std_logic; phasecounterselect : in std_logic_vector(2 downto 0); phasestep : in std_logic; phaseupdown : in std_logic; scanclk : in std_logic; c0 : out std_logic; locked : out std_logic; phasedone : out std_logic ); end component PLL; signal pll_clk : std_logic; signal pll_lock : std_logic; signal rst : std_logic := '0'; signal pll_phasedone : std_logic; signal LVDS_Clk : std_logic_vector(0 downto 0); begin LVDS_CLK_inst : IOBUF_Differential_1 PORT MAP( datain => LVDS_Clk_P, datain_b => LVDS_Clk_N, dataout => LVDS_Clk ); PLL_CLK_inst : PLL PORT MAP ( areset => rst, inclk0 => lvds_clk(0), phasecounterselect => cntsel, phasestep => step, phaseupdown => updown, scanclk => clk, c0 => pll_clk, locked => pll_lock, phasedone => pll_phasedone ); end rtl;
And just in case the TB code as well:
architecture TB of PLL_TEST_TB is signal clk_50 : std_logic := '1'; signal lvds_clk_p, lvds_clk_n : std_logic_vector(0 downto 0) := "1"; signal step, updown : std_logic := '0'; signal cntsel : std_logic_vector (2 downto 0) := "010"; -- Procedure for clock generation procedure clk_gen(signal clk : out std_logic; constant FREQ : real; constant DELAY : real) is constant PERIOD : time := 1 sec / FREQ; -- Full period constant HIGH_TIME : time := PERIOD / 2; -- High time constant LOW_TIME : time := PERIOD - HIGH_TIME; -- Low time; always >= HIGH_TIME constant DELAYE : time := DELAY * 1 ns; begin -- Check the arguments assert (HIGH_TIME /= 0 fs) report "clk_plain: High time is zero; time resolution to large for frequency" severity FAILURE; -- Generate a clock cycle wait for DELAYE; loop clk <= '1'; wait for HIGH_TIME; clk <= '0'; wait for LOW_TIME; end loop; end procedure; begin -- Clock generation with concurrent procedure call clk_gen(clk_50, 50.0e6, 0.0e0); clk_gen(lvds_clk_p(0), 150.0e6, 0.0e0); clk_gen(lvds_clk_n(0), 150.0e6, 0.0e0); --Instantiante UUT UUT: entity work.PLL_TEST port map( lvds_clk_p => lvds_clk_p, lvds_clk_n => lvds_clk_n, clk => clk_50, step => step, updown => updown, cntsel => cntsel ); Testing : process is begin wait for 30 ns; wait until rising_edge(clk_50); updown <= '1'; wait until rising_edge(clk_50); step <= '1'; wait until rising_edge(clk_50); wait until rising_edge(clk_50); step <= '0'; wait until rising_edge(clk_50); step <= '1'; wait until rising_edge(clk_50); wait until rising_edge(clk_50); step <= '0'; wait until rising_edge(clk_50); step <= '1'; wait until rising_edge(clk_50); wait until rising_edge(clk_50); step <= '0'; wait until rising_edge(clk_50); updown <= '0'; wait for 100 ns; assert false report "Test Complete" severity failure; end process Testing; end architecture TB;