element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
555 Timers
  • Technologies
  • More
555 Timers
Blog 555 Phase-Locked Loop (PLL)
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join 555 Timers to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: jc2048
  • Date Created: 29 Jun 2022 10:16 AM Date Created
  • Views 8998 views
  • Likes 13 likes
  • Comments 22 comments
  • phase-locked loop
  • pll
  • constant current
  • analogue design
  • jc2048
  • 555
  • voltage controlled oscillator
Related
Recommended

555 Phase-Locked Loop (PLL)

jc2048
jc2048
29 Jun 2022
555 Phase-Locked Loop (PLL)

In the previous blog I took a simple 555 oscillator and adapted it so that it was voltage controlled (a VCO). In this blog I'm going to carry on and use that VCO as a component part of a phase-locked loop (PLL).

This is the overall circuit now. The VCO (V->I stage and 555 oscillator) are joined with a phase comparator (in the FPGA) and a filter (capacitor integrator) in a control loop.

image

My starting point for the phase comparator was this circuit that I found in an Application Brief in an old Xilinx databook[3].

image

If I'm understanding it correctly, it has some nice properties: it gives a true phase lock, with both signals locked with zero phase difference; it doesn't lock to harmonics; and the capture range is the same as the tracking range. The major disadvantage seems to be that, as it's working from edges, it will be thrown by very noisy signals, so it might be problematic with amplified low-level signals, though it shouldn't have any problems with my digital signals.

It looks a little confusing, but it's essentially four S/R flip-flops and a global reset from the 4-input NAND gate. I've drawn round the flip-flops here

image

The inputs are the two waveforms being compared. The outputs are two enable signals for a pair of tristate buffer outputs from the FPGA. One output pin (up) will either drive a high level (3.3V) or high impedance, the other (down) will drive either a low level (0V) or high impedance. For the filter, I had a resistor from each to a capacitor to give a simple RC filter. The Xilinx application brief indicates an integrator built with an op-amp, but my crude integrator will do for the moment. I used two resistors for  safety, in case I got the logic wrong and drove both outputs at the same time, but what I've done is equivalent to joining the two outputs and having a single resistor.

To implement it in the FPGA, I've designed a phase comparator component. The gates that make up the component are themselves components that I've described with simple combinatorial statements using logic operators. The phase comparator component consists of instances of those basic components, with signal wiring to join them up to make the circuit. So it's as basic as it gets with HDL, whilst still being (notionally) portable. [I did consider using the primitive gate components that are available, rather than define my own, but I wasn't very sure how portable that would be.]

Here's the phase comparator VHDL

---------------------------------------------------------------
--- Filename: Phase-Comparator.vhd                          ---
--- Target device: LFXP2-5E-6TN144                          ---
---                                                         ---
--- Phase comparator                                        ---
---                                                         ---
--- Formed of four SR flip-flops, though that won't be very ---
--- evident looking at the signal connections  of the       --- 
--- component below unless you draw the circuit.            ---
--- This implementation is at a low level - wiring          ---
--- up the component 'logic gates' that I've created.       ---
--- I'm hoping that should be safe for initial testing      ---
--- of the circuit.                                         ---
---                                                         ---
--- Might try coding it as an asynchronous state machine    ---
--- later and see whether the synthesis can get to          ---
--- something that works from a higher level description.   ---
---                                                         ---
--- Jon Clift 27th June 2022                                ---
---                                                         ---
---------------------------------------------------------------
--- Rev    Date         Comments                            ---
--- 1.0    27-Jun-22                                        ---
---------------------------------------------------------------
---
--- phase comparator component
---
--- Two input signals, vco and ref, that will be compared
--- Two outputs that are enables for the tristate buffers
--- that will cause the filter capacitor to be either pumped up or down,
--- if there is a phase error, or left alone if it's on track
---
--- this is built with simple subcomponent logic gates

library IEEE;
use IEEE.std_logic_1164.all;

entity phase_comparator_component is  
  port (  
    vco_in:    in  std_logic;    --- vco signal  
    ref_in:    in  std_logic;    --- reference signal  
    en_up:     out std_logic;    --- enable up  
    en_down:   out std_logic     --- enable down
    );  
end phase_comparator_component;  
  
architecture phase_comparator_component_arch of phase_comparator_component is

signal s1, s2, s3, s4: std_logic;   --- S/R 'set' signals
signal r1, r2, r3, r4: std_logic;   --- S/R 'reset' signals
signal re: std_logic;               --- overall 'reset' signal


--- declare components that are going to be used

component nand_2
  port (  
    in_a:    in  std_logic;
    in_b:    in  std_logic;
    out_o:     out std_logic
     );  
end component;

component nand_3
  port (  
    in_a:    in  std_logic;
    in_b:    in  std_logic;
    in_c:    in  std_logic;
    out_o:     out std_logic
     );  
end component;

component nand_4
  port (  
    in_a:    in  std_logic;
    in_b:    in  std_logic;
    in_c:    in  std_logic;
    in_d:    in  std_logic;
    out_o:     out std_logic
     );  
end component;

begin

   --- instantiate actual components used in design
   --- they are 'wired up' within the port map statements

   G1: nand_2 port map (r1,vco_in,s1);
   G2: nand_2 port map (s1,r2,s2);
   G3: nand_2 port map (s2,re,r2);
   G4: nand_2 port map (re,s3,r3);
   G5: nand_2 port map (r3,s4,s3);
   G6: nand_2 port map (ref_in,r4,s4);
   G7: nand_3 port map (s1,s2,re,r1);
   G8: nand_3 port map (s3,s4,re,r4);
   G9: nand_4 port map (s1,s2,s3,s4,re);

   en_down <= r1;
   en_up <= r4;

end phase_comparator_component_arch;

--- following are the gate components
--- it should be fairly obvious what they're doing

--- two input nand gate component

library IEEE;
use IEEE.std_logic_1164.all;

entity nand_2 is  
  port (  
    in_a:    in  std_logic;
    in_b:    in  std_logic;
    out_o:     out std_logic
     );  
end nand_2;  
  
architecture nand_2_arch of nand_2 is
begin
   out_o <= not (in_a and in_b);
end nand_2_arch;

--- three input nand gate component

library IEEE;
use IEEE.std_logic_1164.all;

entity nand_3 is  
  port (  
    in_a:    in  std_logic;
    in_b:    in  std_logic;
    in_c:    in  std_logic;
    out_o:     out std_logic
     );  
end nand_3;  
  
architecture nand_3_arch of nand_3 is
begin
   out_o <= not ((in_a and in_b) and in_c);
end nand_3_arch;

--- four input nand gate component

library IEEE;
use IEEE.std_logic_1164.all;

entity nand_4 is  
  port (  
    in_a:    in  std_logic;
    in_b:    in  std_logic;
    in_c:    in  std_logic;
    in_d:    in  std_logic;
    out_o:     out std_logic
     );  
end nand_4;  
  
architecture nand_4_arch of nand_4 is
begin
   out_o <= not (((in_a and in_b) and in_c) and in_d);
end nand_4_arch;

The flip-flops mean that there is memory there, so, in theory, I could have described it behaviourally as a state machine, but I wasn't convinced that the synthesis could manage a non-clocked state machine. Wiring up simple logic components seemed safer.

The top-level design then incorporates the phase comparator, along with the control of the tristate buffers, and a clocked divider to get a 10kHz reference waveform from the 50MHz oscillator on the FPGA board to compare the vco input with. I can go on and eleborate that if it works, but that's the minimum I need for a first test.

---------------------------------------------------------------
--- Filename: Lattice-555-PLL.vhd                           ---
--- Target device: LFXP2-5E-6TN144                          ---
---                                                         ---
--- Simple PLL with 555 VCO                                 ---
---                                                         ---
---                                                         ---
--- Jon Clift 27th June 2022                                ---
---                                                         ---
---------------------------------------------------------------
--- Rev    Date         Comments                            ---
--- 1.0    27-Jun-21                                        ---
---------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;  
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

--- top level

entity Lattice_555_PLL is  
  port (  
    clk_in:    in  std_logic;   --- input clock (50MHz osc)  
    in_vco:    in  std_logic;   --- vco signal (from 555 VCO) 
    out_ref:   out  std_logic;  --- output ref signal (for test) 
    out_up:    out std_logic;   --- up  
    out_down:  out std_logic    --- down
    );  
end entity Lattice_555_PLL;  
  
architecture Lattice_555_PLL_arch of Lattice_555_PLL is

--- declare signals

signal prescaler1: std_logic_vector(11 downto 0);
signal fifty_micro_en: std_logic;
signal vco_in: std_logic;
signal ref_in: std_logic;
signal en_up: std_logic;
signal en_down: std_logic;

--- declare components

component phase_comparator_component
  port (  
    vco_in:    in  std_logic;
    ref_in:    in  std_logic;  
    en_up:     out std_logic;  
    en_down:   out std_logic
     );  
end component;

begin

   --- instantiate a phase comparator

   C1: phase_comparator_component port map (in_vco,ref_in,en_up,en_down);

   --- clocked process to generate 10kHz reference signal
   
   clocked_stuff: process (clk_in)
      begin
         if (clk_in'event and clk_in='1') then

            --- prescaler down to 50us period (divide by 2500 from 50MHz clock)
          
            if (prescaler1(11 downto 0) = "100111000011") then       --- if 2499
               prescaler1(11 downto 0) <= "000000000000";            ---   reset to 0
               fifty_micro_en <= '1';                                ---   and set enable (for one cycle)
            else                                                     --- else
               prescaler1 <= prescaler1 + 1;                         ---   count down
               fifty_micro_en <= '0';                                ---   and keep enable low rest of time
            end if;
         
         --- toggle on the enable to give a 10kHz ref_in
            
            if (fifty_micro_en = '1') then                           --- if enabled, toggle ref_in
               ref_in <= not ref_in;
            end if;
            
         end if;
      end process clocked_stuff;
      
   out_ref <= ref_in;   --- push ref_in to an output pin so it can be scoped

   --- tristate output control
   
   out_up <= '1' when en_up = '0' else 'Z';
   out_down <= '0' when en_down = '0' else 'Z';
   
end Lattice_555_PLL_arch;

My first attempt, using a Max II CPLD and Quartus for the IDE, failed to work properly, though it did appear to be trying to do something. Since the RTL view, after the synthesis, matches the circuit, that might suggest that the problem comes later from the placement and fitting optimisation.

When I tried it with an Lattice XP2, using Diamond for the design, it worked fine (at least, it did when I got my pin numbering right in the constraints).

Here's the voltage on the timing capacitor of the 555 (blue trace), along with the 10kHz reference that it's locked to (yellow trace).

image

And this is all the jitter. That's viewed over 5 seconds.

image

I've adapted my top level design so that the reference frequency swaps between 10kHz and 5kHz at half second intervals. This constitutes a step change in frequency, so the loop can't track it and has to relock on each change. Here's a video of that. It nicely shows how the locking behaves.

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

I've brought a signal out of the FPGA that indicates when that step change happens, so that I can look at what the control voltage does. The yellow trace is the point at which the frequency change happens, the blue trace is the voltage on the filter  capacitor (the probe will load the capacitor, so the voltage is slightly inaccurate - I just want to see visually what it's doing).

This is stepping down from 10kHz to 5kHz


image

this is stepping up from 5kHz to 10kHz


image

Both take a long time to finally settle.

This next trace shows the initial reaction of the phase comparator when the frequency of the reference suddenly increases.
image
Yellow is the reference signal, blue is the 'up' output from the FPGA. Because the up output only drives high and is tristate at other times, the low part of the waveform reflects the current voltage that's on the filter capacitor. In this initial part of the reaction to the change, the frequencies are a long way apart and the up output is pumping the capacitor frantically to get the two aligned again. The waveform is quite complicated because, although the capacitor waveform is analogue and continuous, this one is kind of discrete time (but with two periods mixed up, one of which is varying; good luck with analysing that: way above my pay grade!). The situation is further complicated because the circuit is a phase lock and not simply a frequency lock, so the phase also needs to be nudged into alignment (by momentarily either speeding up or slowing down the VCO).

If I look at it that on a longer timescale, I see this. The capacitor voltage has overshot and so then has to be brought back down by the 'down' output from the FPGA.
image
Here's the down output. This time the output drives to ground with the top of the waveform reflecting the capacitor voltage when the output is tristate.
image
The up operates over shorter periods than the down because the control voltage is closer to gnd than +3.3V and so the current to pump the capacitor (defined by the resistor in the RC circuit)  is less for down than up.

After trying to get the VHDL to work on a iCE40UP-5K part (I failed), I'm now back experimenting with
the filtering. Here's the latest circuit
image
This settles quicker. This is the step up from 5kHz to 10kHz
image
This the step down down to 5kHz
image
The control voltage looks more noisy because the phase comparator can now pull the control voltage
momentarily. The jitter at 10kHz, though, is still about the same
image
and at 5kHz
image
is looking more reasonable.

If you want to experiment with the VCO circuit, be aware that there's some mode where the voltage to
current stage can 'latch up' and stop working (the voltage at the 555 timing capacitor sits at about 1V
and doesn't move). Once the oscillator is running it's fine, but sometimes it doesn't start. That seems
to be particularly the case when the FPGA board is powered via the USB and the analogue part only has
the power applied later. I haven't investigated it any further.

Next blog: 555 Frequency Synthesizer

If you found this interesting and would like to see more blogs I've written, a list can be found here: /members-area/b/blog/posts/jc2048-blog-index-new-version

References
[1] https://www.st.com/en/clocks-and-timers/ne555.html
[2] https://www.ti.com/lit/ds/symlink/ne555.pdf
[3] Frequency/Phase Comparator for Phase-locked-Loops. Peter Alfke. Page 6-41, The Programmable Gate Array Data Book, Xilinx, 1989.

  • Sign in to reply

Top Comments

  • shabaz
    shabaz over 3 years ago +1
    Hi Jon, Thanks for writing this up, and providing the VHDL. It makes it all a lot clearer, and I doubt there are many other resources showing in this level of practical detail how a PLL can be implemented…
Parents
  • shabaz
    shabaz over 3 years ago

    I'm wondering whether I should try to resurrect the PLL HDL which I was working on, in case I can get it going. It would be awesome to integrate the phase comparator HDL which you've created, since my HDL was missing that (I was planning to use an external one). 

    I too was using Lattice, and was wondering, have you found any way of viewing the top-level graphically with IceCube2? I've searched online, and can't see how to do it. After there are more than a few components in the top level, it gets tricky (to me at least) to mentally picture how they all connect, and I probably sketched a diagram at the time on paper, but I've lost it, so was wondering if there was a way to auto-generate a diagram. 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • jc2048
    jc2048 over 3 years ago in reply to shabaz

    I'm not very familiar with iCEcube2. It's much more basic than Diamond and doesn't appear to have any way to view RTL.

    The synthesis is either LSE (Lattice's own) or Synplify, depending which you choose to use. That's similar to Diamond and I'd think there's a good chance that the synthesis side would behave much the same. But the placement and fitting may be quite different.

    It's got a floor planner, but it doesn't seem to show what's within the block, though you can see the connections between blocks. This is the design compiled in iCEcube2 for a iCE40UP5K device. The block highlighted in yellow is part of the phase comparator but it doesn't really let you see if it's retained the logic. I'm going to try it later, so I'll let you know if it works.

    image

    It does generate post-route simulation files, so if you're familiar with ModelSim you could check it out that way. (I'm trying to learn how to use ModelSim, but I find the whole process very frustrating.) If it functions in the simulator it ought to in real life.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 3 years ago in reply to jc2048

    Found a tool called VHDLVizualizer, although it's just an executable, can't seem to find the source code or any real information on it. 

    I opened the VHDL files with it, they appear in the right side pane, and then clicking on the top-level file displays the diagram.

    Not sure it's any more understandable though! My top-level only has four components so I can figure it out but next time I'll write better notes.

    image

    I used ModelSim about 10 yeas ago when I was first trying to learn it, and it was really good once I got over some of the learning hurdle, but I've forgotten it all.  ModelSim allows the test stimulus to be drawn on-screen.

    There are also some open source simulators. One is GHDL which I've not tried. Another is Alliance, which I have tried ages ago, and I've still got my notes, so I could write it up if needed, although things may have changed. With Alliance, the test stimulus has to be written in a special text file, there's no GUI for it, so it's a bit more involved. ModelSim would be easier to work with, but it's definitely a pain to get over the initial learning bump!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • jc2048
    jc2048 over 3 years ago in reply to shabaz

    Just for interest, the Diamond 'RTL view' of the phase comparator component looks like this. That's as per the circuit, so the synthesis has been nice, left it alone, and not tried to do any clever optimisation.

    image

    This is from the 'technology view' after fitting and routing. This is one of the logic cells in the XP2 (they have multiple LUTs) and constitutes half of the phase comparator component. It's not easy to tell what the fitter has done - overall, there don't seem to be enough LUTs used in the phase comparator for there to be one per logic gate in the original circuit, so it's all a bit odd, but I can see it properly working on the bench, so it must be equivalent. I think the hex numbers might be the LUT contents. If so, with a bit of patience it might be possible to reconstruct the circuit that it's equivalent to.

    image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 3 years ago in reply to jc2048

    That looks a lot better than the IceCube2 software! I don't think I can have such views with it. I'm using iCE40 HX1K, if Diamond supports that, I think I'll move over to it. 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • shabaz
    shabaz over 3 years ago in reply to jc2048

    That looks a lot better than the IceCube2 software! I don't think I can have such views with it. I'm using iCE40 HX1K, if Diamond supports that, I think I'll move over to it. 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • jc2048
    jc2048 over 3 years ago in reply to shabaz

    Unfortunately, it's not on the family list for Diamond.

    image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • jc2048
    jc2048 over 3 years ago in reply to shabaz

    I had a go with my iCE40UP-5K board using iCEcube2, but I can't get it to work properly. That doesn't mean that it wouldn't work with your HX part - the only way to know for sure is to try it - but don't be too surprised if it doesn't work, at least not with the default settings. As well as trying 'gates' described by combinatorial statements, I also tried using LUT4 primatives, but that approach didn't work either. I also experimented with the more obvious settings for the synthesis and placement tools, and some of the pragma-like instructions you can add to the VHDL, though I don't really know what I'm doing with those - they aren't explained well in the documentation, but nothing changed things.

    There seems to be an open-source tool chain for the iCE parts, so that might also be worth a try.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube