一种可编程的全数字锁相环路的实现
2008-08-04
作者:徐 跃 王 奇 何秋阳
摘 要: 介绍了一种基于FPGA可编程技术实现的用于无线通信实验系统的全数字" title="全数字">全数字锁相环路" title="锁相环路">锁相环路。详细叙述了其工作原理、工作性能、电路实现和仿真结果。
关键词: FPGA 全数字锁相环路 VHDL语言
锁相环路已在模拟和数字通信及无线电电子学等各个领域中得到了极为广泛的应用,特别是在数字通信的调制解调和位同步中常常要用到各种各样的锁相环。锁相就是利用输入信号与输出信号之间的相位误差自动调节输出相位使之与输入相位一致,或保持一个很小的相位差。最初的锁相环全部由模拟电路组成,随着大规模、超高速数字集成电路的发展及计算机的普遍应用,出现了全数字锁相环路。所谓全数字锁相环路,就是环路部件全部数字化,采用数字鉴相器" title="鉴相器">鉴相器(DPD)、数字环路滤波器(DLF)、数控振荡器" title="数控振荡器">数控振荡器(DCO)构成锁相环路。在用Altera公司的EPF10K10TC144-3芯片设计一种无线通信实验系统的FSK、DPSK、QAM调制解调器时,利用剩余的10%FPGA资源设计出了一种可编程全数字锁相环路,它成功地为该通信实验系统的调制解调器提供了64kHz、56kHz和16kHz三种精确、稳定的时钟信号。
1 全数字锁相环的电路设计
1.1 DPLL工作原理分析[1]
所设计的全数字锁相环路的结构如图1所示。其中,数字鉴相器由异或门EXOR构成,数字环路滤波器由变模可逆计数器Q构成,数控振荡器由加/减脉冲控制器" title="脉冲控制器">脉冲控制器I/D和模N计数器组成。可逆计数器和加/减脉冲控制器的时钟频率分别是Mf0和2Nf0。这里f0是环路的中心频率,为64kHz。Mf0等于14336kHz,由晶振电路产生,它经模H计数器分频后得到2Nf0的时钟频率。异或门鉴相器用于比较输入信号IN64与数控振荡器输出信号OUT64的相位差,其输出信号ud作为可逆计数器的计数方向控制信号。当ud为低电平时,可逆计数器作“加”计数;反之,可逆计数器作“减”计数。当环路锁定时,IN64和OUT64正交,鉴相器的输出信号ud为50%占空比的方波。在这种情况下,可逆计数器“加”与“减”的周期相同,只要可逆计数器的模值K足够大(K>M/4),其输出端就不会产生进位或借位脉冲。这时,加/减脉冲控制器只对频率为2Nf0的时钟进行二分频,使IN64和OUT64的相位保持正交。在环路未锁定的情况下,若ud为低电平时,可逆计数器进行加计数,并产生进位脉冲作用到加/减脉冲控制器的“加”控制端INC,该控制器便在二分频过程中加入半个时钟周期;反之,若ud为高电平,可逆计数器进行减计数,并产生借位脉冲作用到加/减脉冲控制器的“减”输入端DEC,该控制器便在二分频的过程中减去半个时钟周期,这个过程是连续发生的。加/减脉冲控制器的输出经过模N计数器分频后,得到输出信号OUT64,它的相位不断受到调整控制,最终达到锁定状态。最后只要对OUT64进行4分频就能得到16kHz的输出信号OUT16,对加/减脉冲控制器的输出进行P分频就能得到56kHz的输出信号OUT56。
该全数字锁相环的三个输出信号的频率分别为64kHz、56kHz和16kHz,经过计算可确定锁相环的参数M、N和P。设H=8,因为Mf0=14336kHz=4×4×2×7×64kHz,故M=4×4×2×7=224。因为2Nf0=Mf0/H=4×4×2×7×64kHz/8=2×2×7×64kHz=2×2×8×56kHz,故N=14、P=16。
1.2 DPLL电路实现
1.2.1 数字鉴相器
数字鉴相器由异或门构成,并使用VHDL语言编程来实现。异或鉴相器比较输入信号IN64和输出信号OUT64之间的相位差,输出误差信号ud作为可逆计数器Q的计数方向信号。环路锁定时,ud为一个占空比为50%的方波,此时的绝对相位差为90°,因此异或鉴相器相位差极限为±90°。
1.2.2 数字环路滤波器[2]
数字环路滤波器由变模可逆计数器Q构成。在ud的控制下,当j=0时,Q对时钟Mf0进行“加”计数;当j=1时,Q对时钟Mf0进行“减”计数。可逆计数器的模数K可以通过Ka、Kb、Kc、Kd四个输入端进行预置,当Ka、Kb、Kc、Kd在0001~1110取值时,相应模数的变化范围是23~216。数字环路滤波器用VHDL语言编程实现,其程序如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity count_zj is
port(clk1,j,Kd,Kc,Kb,Ka,en:in std_logic;INC,DEC:out std_logic);
End count_zj;
architecture behave of count_zj is
signal cq,k,mo,k2,mo2,cq1:std_logic_vector(16 downto 0);
signal cao1,cao2,cao11,cao22,cao111,cao222:std_logic;
signal instruction,aa,q1,q2:std_logic_vector(3 downto 0);
begin
instruction<=Kd & Kc & Kb & Ka;
aa<=instruction+1;
with instruction select
mo<='00000000000000111' when '0001',
'00000000000001111' when '0010',
'00000000000011111' when '0011',
'00000000000111111' when '0100',
'00000000001111111' when '0101',
'00000000011111111' when '0110',
'00000000111111111' when '0111',
'00000001111111111' when '1000',
'00000011111111111' when '1001',
'00000111111111111' when '1010',
'00001111111111111' when '1011',
'00011111111111111' when '1100',
'00111111111111111' when '1101',
'01111111111111111' when '1110',
'11111111111111111' when '1111',
'00000000000000111' when others;
with aa select
mo2 < = '00000000000000111' when '0001',
'00000000000001111' when '0010',
'00000000000011111' when '0011',
'00000000000111111' when '0100',
'00000000001111111' when '0101',
'00000000011111111' when '0110',
'00000000111111111' when '0111',
'00000001111111111' when '1000',
'00000011111111111' when '1001',
'00000111111111111' when '1010',
'00001111111111111' when '1011',
'00011111111111111' when '1100',
'00111111111111111' when '1101',
'01111111111111111' when '1110',
'11111111111111111' when '1111',
'00000000000000111' when others;
process(clk1,j,mo,en)
begin
if (clk1'event and clk1='1') then
k<=mo;
k2<=mo+1;
if (en='0') then
cq<='00000000000000000';
cq1<=mo2;
else
if (j='0') then
if (cq=k) then
cao1<='1';
cao2<='0';
cq<=(others=>'0');
else
cao1<='0';
cao2<='0';
cq<=cq+'1';
cq1<=cq1+'1';
end if;
elsif (j='1') then
if (cq1=k2) then
cao1<='0';
cao2<='1';
cq1<=mo2;
else
cao1<='0';
cao2<='0';
cq<=cq-'1';
cq1<=cq1-'1';
end if;
end if;
end if;
end if;
end process;
process(clk1,cao1)
begin
cao111<=cao11 or cao1;
if(clk1'event and clk1='1') then
if (cao111='1')then
cao11<='1';
if (q1='1111') then
cao11<='0';
q1<='0000';
else
q1<=q1+'1';
end if;
end if;
end if;
end process;
process(clk1,cao2)
begin
cao222<=cao22 or cao2;
if(clk1'event and clk1='1') then
if (cao222='1')then
cao22<='1';
if (q2='1111') then
cao22<='0';
q2<='0000';
else
q2<=q2+'1';
end if;
end if;
end if;
end process;
INC<=cao111;
DEC<=cao222;
end behave;
1.2.3 数控振荡器[3]
数控振荡器采用加/减脉冲控制器I/D和模N计数器实现,它的输出是一脉冲序列,周期受数字环路滤波器送来的进位或借位校正信号控制。图2是加/减脉冲控制器硬件电路图,该电路由四片7474芯片和一片JK触发器以及其它一些逻辑门构成。
1.3 DPLL工作性能分析[4]
可逆计数器Q可看作一个模K分频器,其输出频率为:
fQout=(KeΦeMf0)/K (Hz) (1)
式中,Φe为相位差,Ke为其系数。
加/减脉冲控制器I/D的输出频率为:
fI/Dout=Nf0+(KeΦeMf0)/(2K) (Hz) (2)
经模N计数器分频后,锁相环路的输出信号OUT64的频率为:
fOUT64=f0+(KeΦeMf0)/(2KN) (Hz) (3)
由于锁定的极限范围为KeΦe=±1,所以从公式(3)可以得到环路的捕捉带:
Δfmax=(fOUT64)max-f0=Mf0 (2KN) (Hz) (4)
上式表明,M和N确定后,变化可逆计数器Q的模K可以改变环路的捕捉带。
环路处于锁定状态时,环路输出频率fOUT64必定和输入信号的频率fIN64相等,但同时存在一个稳态相位误差。由式(3)可得:
Φe(∞)=2KN(fIN64-f0)/(KeMf0) (5)
值得注意的是,即使环路在锁定状态下,如果K值取得太小,则可逆计数器因频繁的循环计数会产生进位或借位脉冲,从而导致了相位抖动,增加了同步误差。为了减少这种相位抖动,K值必须大于M/4。但K值取得太大会延长环路锁定时间和减小捕捉带,因此选择一个适当的K值相当重要。
2 全数字锁相环仿真验证与分析
2.1 锁定时间
变模可逆计数器的模数K对DPLL的锁定时间起着关键的作用。图3为K=26时DPLL的输出仿真波形。环路达到锁定状态的仿真时间为371.3μs,而K=28时环路达到锁定状态的仿真时间为1.54ms。由此可见,模K越大,环路进入锁定状态的时间越长。
2.2 捕捉带
根据公式(4)可以得到这样的结论:模数K越大,捕捉带就越小。在本设计中,模数K的变化范围是26~216,相应捕捉带的范围是32kHz~85.3kHz。
2.3 同步带
在本设计中,中心频率为64kHz。将输入信号频率偏移该中心频率,恰能使DPLL锁定的频率范围为同步带。经过测试,同步带范围是63.82kHz~64.1kHz。图4显示的是DPLL在同步带上边界时的锁定波形。
2.4 DPLL系统仿真结果
DPLL的系统仿真结果如图5所示。图中所显示的OUT16、OUT56、OUT64输出信号符合设计要求。
DPLL设计的关键技术集中在数字环路滤波器和数控振荡器上。数字环路滤波器可以看成模数K可预置的可逆计数器,这个可逆计数器与其它计数器最大的区别是“加”与“减”的计数值能够相互抵消,因为只有这样才能保证可逆计数器“加”和“减”的周期相同时,其输出端不会产生进位或借位脉冲。另外,模数K的选择非常重要,要综合考虑捕捉时间和同步误差相矛盾的问题。在数控振荡器的设计中,要注意输入的进位和借位脉冲信号周期不能太小,否则就不能对数控振荡器起作用,必须扩大输入的进位和借位脉冲信号的时钟周期。本设计是将其扩大了16倍。
参考文献
1 胡华春, 石 玉.数字锁相环路原理与应用.上海:上海科学技术出版社,1990
2 庞 浩.一种新型的全数字锁相环.中国电机工程学报,2003;23(2)
3 龚建荣,李晓飞.利用FPGA实现数字锁相及频率转换.南京邮电学院学报,1998;18(4)
4 张振华, 张兴周.一种用可编程逻辑器件实现的全数字锁相环路.四川通信技术,2000;30(6)