Lab 5: Digital Phase Locked Loop (PLL) : Matlab Part: Objective
Lab 5: Digital Phase Locked Loop (PLL) : Matlab Part: Objective
Lab 5: Digital Phase Locked Loop (PLL) : Matlab Part: Objective
Objective
In this assignment, you will
Design a simple digital PLL with a single-pole loop filter
Simulate the response of the PLL in MATLAB
Pre-Lab
Please read the background and answer the questions at the bottom under "PreLab Exercise" below. We will ask to see your answers at the beginning of the lab
and may ask you to explain any of your answers.
Background
Synchronization plays a major role in many signal processing applications. For
example, in a communications system, the receiver must synchronize its local
oscillator and matched filter sample points correctly with respect to the
transmitted signal in order to properly decode the information stream. In the
Simulink labs, I gave you a pre-designed block that implemented the PLL, but in
this lab, you will learn some details about the internal operation of the PLL and
code and simulate it in MATLAB.
Basic PLL Operation
The diagram below shows the block diagram of the basic PLL to be implemented
in this assignment:
The low pass filter (LPF) removes the doubled frequency component, giving the
control voltage signal
The second approximation is true when the phase difference is small, or the loop
is "tracking". The VCO performs the operation
The VCO therefore integrates the control voltage to compute what the phase of
its output sinusoid should be. The term k is referred to as the loop gain. In the
tracking mode, you can think of the whole loop as being a linear system, where
the input and output phase are related by the transfer function
where G(s) is the response of the loop filter. Note that the factor of 0.5 has been
lumped into the loop gain k. Often, a simple first order loop filter is employed
with the response
and this leads to a second order response for the linear PLL, and depending on
the coefficients tau1 and tau2, the response is classified as overdamped, critically
damped, or underdamped. A strongly overdamped system requires a long time to
adapt to phase changes. An underdamped system has the characteristic of fast
response, but a tendency to overshoot the target, leading to oscillations. The loop
filter parameters can be derived from the desired overall loop response as
where D is the damping factor and w0 is the corner frequency. You can think of
the corner frequency w0 as controlling how fast the loop adapts to phase
changes, and usually this frequency should be much lower (<0.1) than the
frequency of the sinusoid or clock being tracked. The damping factor D is often
chosen to be approximately 1, meaning critical damping. For some applications,
it may be desired to have a slower response, and so D is made greater than 1.
Lookup Tables
For the PLL, we are going to need to access to sinusoidal functions, and in
writing mathematical code in the past, you may be accustomed to doing things
like
#include "math.h"
process()
{
int n;
float input, output;
for (n=0; n<N_PERIOD; n++)
{
output = input*cos(2.0*pi*freq*n/sample_rate);
/* More processing here */
}
The problem with this kind of code on the DSP is that you want your code to be
as efficient as possible in order for the algorithm to run in real-time. Also, DSP
algorithms often use the same patterns (like the sine wave in this example) over
and over. Calling trig functions like cos() computes the result using a
Now, we can just call the init() function once when our program initializes (like
in a block init function). When we process signals in process(), we just use the
lookup table, which can be much faster than recomputing all of those samples.
Discretization of the PLL
To map the continuous-time loop filter response H(s) to discrete time, we use
the bilinear transformation or
where T is the sample period and z is the discrete frequency from the Z
transform. Making the appropriate substitutions, we derive the coefficients for
our filter as
In our analysis, we have used discrete frequency, which means that T=1.
The discretization of the VCO requires a little explanation. As explained above,
we will use a lookup table rather than computing sin() and cos() directly. Also,
for our discrete PLL, we will use a phaseaccumulator method, where instead of
having an incrementing time variable t and a separate phase phi, we have a
single real number, known as the accumulator, that keeps track of the current
phase. At each time step, the contents of the accumulator tell us the current
position in the sin() lookup table, where the lookup table holds just one
sinusoidal cycle.
Note that in the lookup table example above, we only computed (and used)
samples of sin() spaced by the sample period. This will not be the case for the
PLL, since we will often need the "in between" samples, and the phase can
change continuously to track the input. You can experiment with the size of the
sine table, but I recommend that you use a large number of samples (say 1024) to
be safe.
Although we can have our accumulator represent phase directly with period
2*pi, computations are more convenient if we just make the period 1.0. (Note: on
fixed point architectures, you often make the period equal an integer multiple of
the length of your sine table, so that everything can be done with integer
arithmetic.)
Thus, on each time step, we do the following operation on our accumulator:
The first term is just the deterministic phase increase of our sinusoidal signal due
to the onward advance of time. The second term is the additional phase shift due
to the control signal present on the VCO. Note that we assume everything is
At each time step, the output of the VCO can then be computed in C as
s = sin_table[(int)((float)SIN_TABLE_SIZE*accum)];
Procedure
Loop Filter Design
Compute the filter coefficients for your first oder loop filter assuming the
following specifications:
Parameter
f
D
k
w0
Description
Nominal ref. frequency
Damping factor
Loop gain
Loop corner frequency
Value
0.1
1.0
2.0
2*pi/100
These were chosen so that the response time of the loop is about 100 samples (10
sinusoidal cycles). For a sample rate of 8000 Hz, the center frequency is 800 Hz.
Note that you should use 1.0 for k in computations due to the factor of 0.5 that
was absorbed into k in the analysis.
Simple MATLAB Implementation
Test the response of your loop filter in MATLAB and compare its response with
the ideal frequency response. Refer back to the FIR filter lab for information on
how to test a filter and plot its response.
Implement the complete PLL in MATLAB using an accumulator. Test its
operation with a number of different input signals. The input signals should be
sinusoids with frequencies that are within 10% of the nominal reference
frequency.
To get you started, you can use the signal ref_in contained in the data
files ref_800hz.mat and ref_stepf.mat. The first file gives you a constant 800 Hz
sinusoid, which you should try first. In the second file, the signal steps through 4
different frequencies (see the variable freq_in for which frequency is active at
which time). For each step to a new frequency, the PLL should undergo a
transition and then eventually track.
To give you an idea of what "tracking" means graphically, the figure below
shows the result of my PLL implementation at a point when tracking is achieved.
You can see that the input and output frequency are identical, and that a constant
90 degree phase shift is maintained between the two. Plotting the two waveforms
before or after this point, you will see the same relationship. If you see one
waveform "slipping" relative to the other over time, your loop is not working!
In the development above, we assumed that the amplitude of the input signals
was 1, which simplified the analysis. Also, the signals you generated to test your
MATLAB implementation were also probably unit amplitude. If the amplitude of
the input reference is not unity, this effectively changes the loop-gain of your
filter, and may make the loop unable to track.
To solve this problem, you should change your PLL so that each block of
samples is scaled to have approximately unit amplitude. Consider the
pseudocode below:
amp = 0;
for sample_idx = 1:number_samples,
amp = amp + abs(sample[sample_idx]);
sample_scale = sample[sample_idx]/amp_est;
... Do processing here on sample_scale ...
end
amp_est = amp/number_samples/(2/pi);
Pre-Lab Exercise
You should have the following things prepared when you come to the first PLL
lab:
Questions
Please provide short answers (say 1-3 sentences) for the following questions. In
the pre-lab quiz we will ask to see your answers and may ask you to explain
what they mean.
Check-Off
Demonstrate to the TA that your PLL implementations work correctly. Your PLL
should be able to handle changes in frequency of about plus or minus 10% of the
nominal reference frequency.
Lab Write Up
Include the following items in your final write-up:
1. Answers to the questions asked in the pre-lab.
2. A paper design of your PLL, showing the important parameters that are
needed for implementation
3. A printout of your final MATLAB implementation of the PLL
4. A plot showing the simulated performance of the final PLL,
demonstrating that the PLL can adapt to abrupt changes in
frequency/phase