After gaining a theoretical understanding of the carrier
recovery sub-system of a digital receiver, you will simulate
the sub-system in MATLAB and implement it on the DSP. The
sub-system described is specifically tailored to a
non-modulated carrier. A complete implementation will require
modifications to the design presented.
The phase-locked loop (PLL) is a
critical component in coherent communications receivers that
is responsible for locking on to the carrier of a received
modulated signal. Ideally, the transmitted carrier frequency
is known exactly and we need only to know its phase to
demodulate correctly. However, due to imperfections at the
transmitter, the actual carrier frequency may be slightly
different from the expected frequency. For example, in the
QPSK transmitter of Digital
Transmitter: Introduction to Quadrature Phase-Shift
Keying, if the digital carrier frequency is
π2
2
and the D/A is operating at 44.1 kHz, then the
expected analog carrier frequency is
f
c
=π22π44.1=11.25kHz
f
c
2
2
44.1
11.25
kHz
. If there is a slight change to the D/A sample rate
(say
f
c
=44.05kHz
f
c
44.05
kHz
), then there will be a corresponding change in the
actual analog carrier frequency
(
f
c
=11.0125kHz
f
c
11.0125
kHz
).
This difference between the expected and actual carrier
frequencies can be modeled as a time-varying phase. Provided
that the frequency mismatch is small relative to the carrier
frequency, the feedback control of an appropriately calibrated
PLL can track this time-varying phase, thereby locking on to
both the correct frequency and the correct phase.
In a complete coherent receiver implementation, carrier
recovery is required since the receiver typically does not
know the exact phase and frequency of the transmitted
carrier. In an analog system this recovery is often
implemented with a voltage-controlled
oscillator (VCO) that allows for precise
adjustment of the carrier frequency based on the output of a
phase-detecting circuit.
In our digital application, this adjustment is performed
with a numerically-controlled oscillator
(NCO) (see Figure 1). A simple
scheme for implementing an NCO is based on the following
re-expression of the carrier sinusoid:
sin
ω
c
n+
θ
c
=sinθn
ω
c
n
θ
c
θ
n
(1)
where
θn=
ω
c
n+
θ
c
θ
n
ω
c
n
θ
c
(
ω
c
ω
c
and
θ
c
θ
c
represent the carrier frequency and phase,
respectively). Convince yourself that this time-varying
phase term can be expressed as
θn=∑m=0n
ω
c
+
θ
c
θ
n
m
0
n
ω
c
θ
c
and then recursively as
θn=θn-1+
ω
c
θ
n
θ
n
1
ω
c
(2)
The NCO can keep track of the phase,
θn
θ
n
, and force a phase offset in the demodulating
carrier by incorporating an extra term in this recursive
update:
θn=θn-1+
ω
c
+
d
pd
n
θ
n
θ
n
1
ω
c
d
pd
n
(3)
where
d
pd
n
d
pd
n
is the amount of desired phase offset at time
n
n. (What would
d
pd
n
d
pd
n
look like to generate a frequency offset?)
The goal of the PLL is to maintain a demodulating sine and
cosine that match the incoming carrier. Suppose
ω
c
ω
c
is the believed digital carrier frequency. We can
then represent the actual received carrier frequency as the
expected carrier frequency with some offset,
ω
c
˜
=
ω
c
+
θ
˜
n
ω
c
˜
ω
c
θ
˜
n
. The NCO generates the demodulating sine and
cosine with the expected digital frequency
ω
c
ω
c
and offsets this frequency with the output of the
loop filter. The NCO frequency can then be modeled as
ω
c
^
=
ω
c
+
θ
^
n
ω
c
^
ω
c
θ
^
n
. Using the appropriate trigonometric identities
, the in-phase and quadrature signals can
be expressed as
z
0
n=1/2cos
θ
˜
n-
θ
^
n+cos2
ω
c
+
θ
˜
n+
θ
^
n
z
0
n
12
θ
˜
n
θ
^
n
2
ω
c
θ
˜
n
θ
^
n
(4)
z
Q
n=1/2sin
θ
˜
n-
θ
^
n+sin2
ω
c
+
θ
˜
n+
θ
^
n
z
Q
n
12
θ
˜
n
θ
^
n
2
ω
c
θ
˜
n
θ
^
n
(5)
After applying a low-pass filter to remove the double
frequency terms, we have
y
1
n=1/2cos
θ
˜
n-
θ
^
n
y
1
n
12
θ
˜
n
θ
^
n
(6)
y
Q
n=1/2sin
θ
˜
n-
θ
^
n
y
Q
n
12
θ
˜
n
θ
^
n
(7)
Note that the quadrature signal,
z
Q
n
z
Q
n
, is zero when the received carrier and internally
generated waves are exactly matched in frequency and phase.
When the phases are only slightly mismatched we can use the
relation
∀θ,small:sinθ≈θ
θ
small
θ
θ
(8)
and let the current value of the quadrature
channel approximate the phase difference:
z
Q
n≈
θ
˜
n-
θ
^
n
z
Q
n
θ
˜
n
θ
^
n
. With the exception of the sign error, this
difference is essentially how much we need to offset our NCO
frequency. To make sure that the sign of the phase
estimate is right, in this example the phase detector is
simply negative one times the value of the quadrature
signal. In a more advanced receiver, information from both
the in-phase and quadrature branches is used to generate an
estimate of the phase error.
The estimated phase mismatch estimate is fed to the NCO via
a loop filter, often a simple low-pass filter. For this
exercise you can use a one-tap IIR filter,
yn=βxn+αyn-1
y
n
β
x
n
α
y
n
1
(9)
To ensure unity gain at DC, we select
β=1-α
β
1
α
It is suggested that you start by choosing
α=0.6
α
0.6
and
K=0.15
K
0.15
for the loop gain. Once you have a working
system, investigate the effects of modifying these values.
Simulate the PLL system shown in Figure 1
using MATLAB. As with the DLL simulation, you will have to
simulate the PLL on a sample-by-sample basis.
Use Equation 3 to implement your NCO in MATLAB.
However, to ensure that the phase term does not grow to
infinity, you should use addition modulo
2π
2
in the phase update relation. This can be done by
setting
θn=θn-2π
θ
n
θ
n
2
whenever
θn>2π
θ
n
2
.
Figure 2 illustrates how the proposed PLL will
behave when given a modulated BPSK waveform. In this case the
transmitted carrier frequency was set to
ω
c
˜
=π2+π1024
ω
c
˜
2
1024
to simulate a frequency offset.
Note that an amplitude transition in the BPSK waveform is
equivalent to a phase shift of the carrier by
π2
2
. Immediately after this phase change occurs, the
PLL begins to adjust the phase to force the quadrature
component to zero (and the in-phase component to
1/2
12). Why would this phase detector not work in a real
BPSK environment? How could it be changed to work?
As you begin to implement your PLL on the DSP, it is highly
recommended that you implement and test your NCO block first
before completing the rest of your phase-locked loop.
Your NCO must be able to produce a sinusoid with
continuously variable frequency. Computing values of
sinθn
θ
n
on the fly would require a prohibitive amount of computation
and program complexity; a look-up table is a better
alternative.
Suppose a sine table stores
N
N samples from one cycle of the waveform:
∀k,k=0…N-1:sin2πkN
k
k
0
…
N
1
2
k
N
. Sine waves with discrete frequencies
ω=2πNp
ω
2
N
p
are easily obtained by outputting every
p
th
p
th
value in the table (and using circular
addressing). The continuously variable frequency of your
NCO will require non-integer
increments, however. This raises two issues: First, what
sort of interpolation should be used to get the in-between
sine samples, and second, how to maintain a non-integer
pointer into the sine table.
You may simplify the interpolation problem by using
"lower-neighbor" interpolation, i.e., by using the integer
part of your pointer. Note that the full-precision,
non-integer pointer must be maintained in memory so that the
fractional part is allowed to accumulate and carry over into
the integer part; otherwise, your phase will not be accurate
over long periods. For a long enough sine table, this
approximation will adjust the NCO frequency with sufficient
precision.
Maintaining a non-integer pointer is more difficult. In
earlier exercises, you have used the auxiliary registers
(ARx) to manage pointers with integer
increments. The auxiliary registers are not suited for the
non-integer pointers needed in this exercise, however, so
another method is required. One possibility is to perform
addition in the accumulator with a modified decimal point.
For example, with
N=256
N
256
, you need eight bits to represent the integer
portion of your pointer. Interpret the low 16 bits of the
accumulator to have a decimal point seven bits up from the
bottom; this leaves nine bits to store the integer part
above the decimal point. To increment the pointer by one
step, add a 15-bit value to the low part of the accumulator,
then zero the top bit to ensure that the value in the
accumulator is greater than or equal to zero and less than
256. To use the integer part of this
pointer, shift the accumulator contents seven bits to the
right, add the starting address of the sine table, and store
the low part into an ARx register. The
auxiliary register now points to the correct sample in the
sine table.
As an example, for a nominal carrier frequency
ω=π8
ω
8
and sine table length
N=256
N
256
,
the nominal step size is an integer
p=π8N12π=16
p
8
N
1
2
16
. Interpret the 16-bit pointer as having nine bits
for the integer part, followed by a decimal point and seven
bits for the fractional part. The corresponding literal
(integer) value added to the accumulator would be
16×27=2048
16
2
7
2048
.
You may want to refer to Proakis and Blahut. These references may help
you think about the following questions:
-
How does the noise affect the described carrier
recovery method?
-
What should the phase-detector look like for a BPSK
modulated carrier? (Hint: You would need to consider
both the in-phase and quadrature channels.)
-
How does α affect the bandwidth of the loop
filter?
-
How do the loop gain and the bandwidth of the
loop filter affect the PLL's ability to lock on to a
carrier frequency mismatch?