Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20703 Discussions

PLL frequency doubling but shouldn't

Joossss
Novice
934 Views

Hey!

I'm using a PLL on Cyclone 10 LP to create a clock with the same frequency, but shifting the phase. The PLL works fine in simulation when I create a clock and feed it straight into the PLL. However, I need to have it working with a differential clock. So, I'm simulating a differential clock and feeding it through the differential input buffer (ALTIOBUF). Now for some reason the PLL doubles the clock's frequency. Image shown below. Is this an error with Modelsim, or how could I solve this issue?

I'd presume this issue arises due to the signal being undefined when they cross?

Joossss_0-1615384577901.png

Thanks in advance!

 

0 Kudos
1 Solution
Ash_R_Intel
Employee
841 Views

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.


View solution in original post

4 Replies
Ash_R_Intel
Employee
853 Views

Hi,

Can you please attach the piece of code showing connections from differential input pins to the PLL output?


Regards


Joossss
Novice
848 Views

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;
0 Kudos
Ash_R_Intel
Employee
842 Views

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.


Joossss
Novice
827 Views

Hey!

Thanks this works indeed, I only tried to use this process, because I tried to solve the same issue with it, by introducing delays into one of the lines, because before this I used 

lvds_clk_p <= not lvds_clk_p after 3.3 ns;
lvds_clk_n <= not lvds_clk_p; -- 150 MHz

and this also didn't work. 

Anyway, thanks for solving the issue.

0 Kudos
Reply