一阶锁相环的FPGA实现(基于quartus+matlab)
\quad
前言:本篇文章参考了杜勇的《锁相环技术原理及FPGA实现》,这本书上是以quartus ii 为工具实现的,由于我之前一直使用的是Xilinx的产品,所以就计划将其移植到Vivado平台上,结果就让人崩溃不已~,没有成功。我想了一下,可能是因为ip核的问题吧。所以我不得不转移到quartus平台上来了。
\quad
Quartus版本:18.0 prime 标准版
\quad
Modelsim版本:Modelsim-altera 10.5b
目录
一.软件使用当中遇到的问题
\quad 由于对Quartus 软件的不熟悉,导致很多问题:
- ip核配置问题
- 仿真问题
\quad 仿真问题是最头疼的了。我搞了三天时间,才算搞定。具体的解决方案如下:在官网上下载与quartus同一版本的Modelsim-altera,同时保证电脑中没有其他的modelsim的版本,这样就可以避免配置文件modelsim.ini的冲突了。
二.一阶锁相环的设计与实现
\quad 下面涉及的理论的知识可以去参考一下《锁相环技术原理及FPGA实现》。接下来着重要说的是FPGA的实现。
2.1 环路设计参数相关
\quad 设计参数:
- 系统频率=采样频率=8KHz
- 鉴相器输出位宽:19bit
- 鉴相滤波器系数位宽:8bit
- 鉴相滤波器输出数据位宽:30bit
- 环路增益K=34Hz
- NCO频率字位宽:30bit
- NCO相位累加字位宽:35bit
- NCO初始频率字:177986918(400Hz)
环路增益
\quad K d K_d Kd为鉴相器增益, K d = 1 2 K m U i U o K_d=\frac{1}{2}K_mU_iU_o Kd=21KmUiUo, K 0 K_0 K0为NCO的控制灵敏度, K 0 = f c l k / 2 B n c o K_0=f_{clk}/2^{B_{nco}} K0=fclk/2Bnco, K l p f K_{lpf} Klpf为 f i r fir fir滤波器的增益。
2.2 一阶环的结构
\quad
如下图所示:
\quad
鉴相器的结构:
2.2.1鉴相滤波器的实现
\quad
乘法器的实现暂不赘述,下面主要讲
f
i
r
fir
fir滤波器的实现。
\quad
f
i
r
fir
fir滤波器在FPGA上通过例化
i
p
ip
ip核来是实现,这其中最重要的是
f
i
r
fir
fir抽头系数的产生。网上的普遍做法是利用
m
a
t
l
a
b
matlab
matlab的
F
D
A
T
O
O
L
FDATOOL
FDATOOL工具,产生系数。我这里直接用了《锁相环技术原理及FPGA实现》里面的程序生成了对应的lpf.txt。具体参数为:采样频率为8Khz,过渡带为[300 600](单位Hz)具体如下:
function h_pm=FilterCompare
%FilterCompare.m程序清单
%用kaiserord计算满中性能要求的最小滤波器阶数;
%用firpm和fir1分别设计最优滤波器,以及窗函数滤波器,并绘制其幅频响应
%输出最优滤波器系数
fs=8000; %采样频率
fc=[300 600]; %过渡带
mag=[1 0]; %窗函数的理想滤波器幅度
dev=[0.04 0.04]; %纹波
[n,wn,beta,ftype]=kaiserord(fc,mag,dev,fs) %获取凯塞窗参数
fpm=[0 fc(1)*2/fs fc(2)*2/fs 1]; %firpm函数的频段向量
magpm=[1 1 0 0]; %firpm函数的幅值向量
format long;
%设计凯塞窗及海明窗滤波器
h_kaiser=fir1(n,wn,ftype,kaiser(n+1,beta));
h_hamm=fir1(n,fc(2)*2/fs);
%设计最优滤波器
h_pm=firpm(n,fpm,magpm);
%求滤波器的幅频响应
m_kaiser=20*log10(abs(fft(h_kaiser,1024)));
m_hamm=20*log10(abs(fft(h_hamm,1024)));
m_pm=20*log10(abs(fft(h_pm,1024)));
%设置幅频响应的横坐标单位为Hz
x_f=[0:(fs/length(m_kaiser)):fs/2];
%只显示正频率部分的幅频响应
m1=m_kaiser(1:length(x_f));
m2=m_hamm(1:length(x_f));
m3=m_pm(1:length(x_f));
%绘制幅频响应曲线
plot(x_f,m1,'-',x_f,m2,'-.',x_f,m3,'--');
xlabel('频率(Hz)');ylabel('幅度(dm_pmB)');
legend('凯塞窗','海明窗','最优滤波器');grid;
\quad 下面着重讲一下fir滤波器的配置,在下面的页面打开FIR II
其他按照默认的设置即可。
\quad
下面是将其在代码中例化:
pd_filter u2(
.clk (clk),
.reset_n (pd_filter_rst_n),
.ast_sink_data (pd_mult_out[18:0]),//pd_mult_out[18:0]
.ast_sink_valid (pd_filter_sink_valid),
.ast_sink_error (pd_filter_sink_error),
.ast_source_data (pd_filter_out)
);
\quad 这里需要注意的是,复位信号的持续时间要超过一个时钟周期,否则 f i r fir fir输出将会异常。
2.2.2 数控振荡器(NCO)的实现
具体配置如图所示:
\quad
例化如下:
//实例化NCO核
nco u3(
.phi_inc_i (START_FREQUENCY),
.clk (clk),
.reset_n (nco_rst_n),
.clken (nco_clken),
.freq_mod_i (pd_filter_out[29:0]),
.fsin_o (nco_sin),
.fcos_o (nco_cos),
.out_valid (nco_out_valid_nc)
);
2.2.3 调用仿真
\quad
首先要说明的是,由于加入ip核后,仿真会报错,所以就将代码中的有关ip核的部分注释,启动modelsim后再取消代码注释,重新编译后开始仿真,这样就可以仿真ip了。
\quad
一阶环主要测试频差改变时,系统的锁定情况,分类如下:
-
NCO输出频率400HZ,频差为0,达到锁定状态
-
NCO输出频率417Hz,频差为17Hz,失锁状态
\quad 经过我多次实验,发现我写的这个一阶锁相环的捕获带宽和《锁相环技术原理及FPGA实现》中的程序相比,小的多。后期在进行二阶锁相环设计时,会将这个问题弄清楚的(感觉上是FIR IP核架构不同)的原因。