element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Members
    Members
    • Benefits of Membership
    • Achievement Levels
    • Members Area
    • Personal Blogs
    • Feedback and Support
    • What's New on element14
  • Learn
    Learn
    • Learning Center
    • eBooks
    • STEM Academy
    • Webinars, Training and Events
    • More
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • More
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • More
  • Products
    Products
    • Arduino
    • Dev Tools
    • Manufacturers
    • Raspberry Pi
    • RoadTests & Reviews
    • Avnet Boards Community
    • More
  • 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
555 Timers
  • Technologies
  • More
555 Timers
Blog 555 Phase-Locked Loop (PLL)
  • Blog
  • Forum
  • Documents
  • Events
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
555 Timers requires membership for participation - click to join
Blog Post Actions
  • Subscribe by email
  • More
  • Cancel
  • Share
  • Subscribe by email
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: jc2048
  • Date Created: 29 Jun 2022 10:16 AM Date Created
  • Views 591 views
  • Likes 12 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.

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

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

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).

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

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
Upload Preview

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


this is stepping up from 5kHz to 10kHz


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.

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.

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.

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

This settles quicker. This is the step up from 5kHz to 10kHz

This the step down down to 5kHz

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

and at 5kHz

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.

Anonymous

Top Comments

  • shabaz
    shabaz 1 month 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…

  • michaelkellett
    michaelkellett 1 month ago in reply to michaelkellett

    The license isn't locked to the board or anything daft like that.

    MK

    • Cancel
    • Vote Up 0 Vote Down
    • Reply
    • More
    • Cancel
  • michaelkellett
    michaelkellett 1 month ago in reply to jc2048

    They don't sell icenses on their own so you have to buy a dev board to get one. The cheapest dev board is the Xyloni at £61 ( none in stock at Digikey,).

    I bought the TF81C-DK at £81.61

    They do chips in TQFP so making your own board is quite feasible - it's next on my agenda.

    You'll need an FTDI 2232H Mini Module for programming your own board. (Farnel have no stock but others do at just under £30 each. (no cheaper on Aliexpress !))

    The same FTDI board will also work with Gowin FPGAs and tools.

    Digikey have stock of parts (today !)

    MK

    • Cancel
    • Vote Up 0 Vote Down
    • Reply
    • More
    • Cancel
  • jc2048
    jc2048 1 month ago in reply to michaelkellett

    That looks good.

    Was that the T8 part? How does the licensing work? Is it actually tied to the dev board in some way, or do you just get a code to use?

    • Cancel
    • Vote Up 0 Vote Down
    • Reply
    • More
    • Cancel
  • jc2048
    jc2048 1 month 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
    • Reply
    • More
    • Cancel
  • michaelkellett
    michaelkellett 1 month ago in reply to michaelkellett

    Interesting !

    I did post here yesterday but E14/Verint seem to have lost my post, in the circumstances not a competely bad thing.

    Yesterday I reported that my implmentation on the Efnix dev board didn't work, today I got it fixed in about 10 minutes !

    Back to the begining.

    I designed the code in AldecHDL using the block diagram editor. This allows you to enter the diagram almost exactly as drawn.

    AldecHDL compiles this block diagram to VHDL (or Verilog if you like) which looks like this:

    library IEEE;
    use IEEE.std_logic_1164.all;

    entity phase_detector is
    port(
    f_ref : in STD_LOGIC;
    f_vco : in STD_LOGIC;
    n_down : out STD_LOGIC;
    n_up : out STD_LOGIC
    );
    end phase_detector;

    architecture phase_detector of phase_detector is

    ---- Signal declarations used on the diagram ----

    signal NET632 : STD_LOGIC;
    signal NET659 : STD_LOGIC;
    signal NET700 : STD_LOGIC;
    signal NET717 : STD_LOGIC;
    signal NET726 : STD_LOGIC;
    signal NET741 : STD_LOGIC;
    signal NET765 : STD_LOGIC;
    signal NET821 : STD_LOGIC;
    signal NET830 : STD_LOGIC;

    begin

    ---- Component instantiations ----

    NET717 <= not(f_ref and NET632);

    NET821 <= not(NET765 and f_vco);

    NET700 <= not(NET821 and NET830 and NET726 and NET717);

    NET632 <= not(NET700 and NET726 and NET717);

    NET765 <= not(NET821 and NET830 and NET700);

    n_down <= NET632;

    n_up <= NET765;

    NET726 <= not(NET659 and NET717);

    NET659 <= not(NET700 and NET726);

    NET741 <= not(NET830 and NET700);

    NET830 <= not(NET821 and NET741);
    end phase_detector;

    There is a problem with the way the NAND gates are represented. On start up the outputs are "undefined", which means that the output is a function of "undefined " and so will remain undefined for always. There is a way round this (actaully several) but I did without the benefit of simulation.

    The Efnix tools are quite nice to use (much, much simpler than X or A). The disk footprint is tiny compared with Vivado at only 1.8Gb. But you don't get a block diagram editor or VHDL simulation. That doesn't bother me because I use Aldec, but that's an expensive paid for tool. You may well be able to use the free simulators packaged with Lattice or ALtera/Intel tools.

    Efnix have a rather unusual way of setting up IO pins, especially IO or tristate pins but it actually works rather well for this application (where the output signals are intnded to enable/disable the output buffers).

    It does mean that you have to explcitly drive the output enable rather than it being inferred from a coding pattern.

    You can see how it works in the top level block diagram:

    I drove one input with a 10kHz square wave and the other with 10kHz frequency modulated at about 10Hz:

    The up and down output pins were biased to 0V and 3.3V with 1k2 resistors.

    I've zoomed in on the transition where the two input frequencies are the same.

    I'm quite happy with this - the Efnix tools and part seem to work OK and I've played with a phase detector I haven't seen before.

    You can still get this FPGA in 144 pin packages for about £5 (although the dev board cost quite a bit more and you need to buy one to get a tool license.)

    MK

    • Cancel
    • Vote Up 0 Vote Down
    • 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 © 2022 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

  • Facebook
  • Twitter
  • linkedin
  • YouTube