使用PLL进行led的简单控制时,仿真波形显示不正常
一、问题代码
1、下图是激励文件中对复位信号的初始化,采用异步复位方式
2、下图是在顶层文件中对pll进行例化,areset是创建IP核时生成的用于对pll初始化的信号(后面解释,这个是关键)
3、生成的错误波形
led[3]由系统时钟控制(50M),PLL分出的c0(25M)、c1(75M)、c2(100M)分别控制 led[0]、led[1]、led[2],可以看出这几个时钟控制的led波形显示异常
二、错误原因分析
1、关于areset和deassert
一开始以为是三个时钟在PLL中没有设置好,重进pll发现有一个"areset"选项,分析应该是这个信号出了问题导致pll没有被初始化,产生的时钟没有生效
下面是PLL官方手册中对“areset”的介绍
关键是这两句:
第一句: When you assert the areset signal, all counters in the PLL, including the gated lock counter, are reset to initial values.
翻译过来应该是说当areset信号有效时(为1),PLL中的所有信号都会被初始化。
第二句:When the areset signal is deasserted, the
PLL resynchronizes its input and tries to gain lock.
翻译过来应该是说当areset信号无效时(为0),PLL将重新同步输入信号,并将其锁定。
(关于这个areset和deassert,翻译是“断言”,感觉很奇怪,于是上网搜了帖子,areset解释为“有效”,deassert解释为“无效”,参见>>https://blog.csdn.net/Reborn_Lee/article/details/88736274<<
2、分析
回看第一张图,按常规思路,我一开始将Rst_n置0复位,后拉高为1,由于Rst_n和areset相连,则areset一开始为0,后为1,即一开始PLL信号在重新同步,紧接着一直在被初始化,导致产生的时钟信号起不了作用。
三、解决方案
将顶层文件中的以下代码
pll pll(
.areset(Rst_n),
.inclk0(Clk),
.c0(c0),
.c1(c1),
.c2(c2),
.locked(locked)
);
更改为
pll pll(
.areset(~Rst_n),
.inclk0(Clk),
.c0(c0),
.c1(c1),
.c2(c2),
.locked(locked)
);
使Rst_n拉高时,areset逻辑为0,使PLL将重新产生的时钟信号锁定,以输出正确的分频时钟信号。
下图是正确的波形
四、关于考虑过的另一种改法
将tb文件中的以下代码
initial begin
Rst_n = 0;
#(`clk_period*20 + 1);
Rst_n = 1;
#(`clk_period*2000);
$stop;
end
更改为
initial begin
Rst_n = 1;
#(`clk_period*20 + 1);
Rst_n = 0;
#(`clk_period*2000);
$stop;
end
其他不动
经过仿真分析,所有波形都会出现异常
原因应该是这样做会导致源时钟信号Clk无法正常产生,所以PLL中的所有时钟信号也无法产生。