基于Cyclone IV的动态PLL重配置设计
0赞基于Cyclone IV的动态PLL重配置设计
——CrazyBingo
——2012-08-28
在实际项目应用中,由于系统的复杂,在某些需求中,需要实现动态时钟输入,或者输出,以实现不同的时序电路,完成特定的功能。
对于多时钟的输入,当波动超过了一定范围,与之对应的PLL将无法重新锁定时钟,其输出时钟频率将变为不确定的值;同时过去FPGA内部PLL上电完成配置,只能输出固定频率的时钟,无法在上电后在此配置改变(而使用多个PLL也只能局限于几个频率,况且浪费资源)。这些限制,让我们在多时钟设计中不免觉得无能为力。
尽管Stratix II早就有了动态PLL,能在上电后动态配置输入时钟、输出时钟、相位等,但是其价格的高昂,使得动态PLL没有受到广泛的应用。直到Cyclone III/IV面世以来,在成本敏感的领域实现高性价比的动态时钟配置,完成不可能的设计,成为了一种可能。
1. PLL的原理与可重配置PLL
锁相环(PLL,Phase Lock Loop)主要作用就是把内部/外部时钟的相位和频率同步于输入参考时钟。PLL一般由模拟电路所实现,其结构如下图所示。
1.1. PLL可充配组件
PLL 使用几个分频计数器和不同的 VCO 相位抽头来执行频率合成及相移。在 Cyclone IV 器件的 PLL 中,您可以实时重配置计数器设置及相移 PLL 输出时钟。此外,您也可以修改电荷泵和环路滤波器组件,这会对 PLL 带宽产生动态影响。 您可以使用这些PLL 组件,在几微妙内来实时更新输出时钟频率、PLL 带宽和相移,而无需重配置整个 FPGA。
以下PLL可重配置组件:
当然,还有PLL还允许动态相移配置,不过这个配置模块与PLL冲配置模块不在一块儿,因此此处没有罗列出,这也不是本文主要的研究目标。Cyclone III/IV的可充沛组件参数,如下所示:
1.2. 可重配PLL
如上图所示,PLL的重配置,是通过一条扫描链完成的。所谓扫描链,其实是一系列的寄存器,通过寄存器的更新,来完成PLL的重配置。因此,PLL的重配置,要严格遵循一定的时序,即不能违背扫描链的架构,否则必然导致重配置失败,甚至失锁。
有关扫描链时序的分析,如下官方手册的截屏:
在Quartus LPM中定制PLL,并且使能PLL动态特性,允许用户可以通过相关接口对PLL进行重配置,如下如所示:
用户可以通过一个Mif文件,来初始化输出时钟,相移等参数(事实证明这个mif不存在也不会影响,因为后端用户设定了参数)。最后生成了如下模块:
其中包含了PLL的复位,输入时钟,输出时钟,以及动态配置的信号线。通过configuradta信号,让PLL动态配置。
1.3. PLL重配模块
纵然PLL的重配置时序不是那么复杂,但是Altera怕我们出意外,为了设计上的简单,减少开发周期,Altera提供了PLL重配置模块。用户只要更新本模块的寄存器(Mif)文件,通过configuradta,本模块会自动完成对可重配PLL的配置。
如上图所示,红圈圈部分,即ALTPLL_RECONFIG的用户接口。用户可以通过更新ALTPLL_RECONFIG内部的Mif文件,通过其对可重配PLL的自动配置功能,完成PLL的动态配置。
具体电路如下所示。通过write_fraom_rom信号,通过选择电路。直接让ALTPLL_RECONFIG自动读取选择的外部ROM的数据,完成对ALTPLL_RECONFIG内部Mif文件的更新。在此之后,通过使能信号,在此自动完成PLL的重配置。
2. PLL重配置的实现
2.1. 相关参数的研究
在可重配PLL的定制过程中,可以生成以定制参数的Mif文件,如上图所示。经过反复的研究,观察了10M~80M,步进为5M的时钟输出的Mif文件,发现了如下规律。其中0-~36为默认,其他有一定的规律,如下图所示:
序号 |
地址 |
位数 |
参数 |
1 |
36 |
1 |
M counter: Bypass,0表示打开,1表示旁路 |
2 |
37-44 |
8 |
M counter: High Count,缩放因子 |
3 |
45 |
1 |
M counter: Odd Division,1表示奇数分频 |
4 |
46-53 |
8 |
M counter: Low Count,乘法因子 |
5 |
54 |
1 |
clk0 counter: Bypass,0表示打开,1表示旁路 |
6 |
55-62 |
8 |
clk0 counter: High Count,高脉冲计数 |
7 |
63 |
1 |
clk0 counter: Odd Division,1表示奇数分频 |
8 |
64-71 |
8 |
clk0 counter: Low Count,低脉冲计数 |
反复的研究Altera 《Implementing PLL Reconfiguration in Cyclone III Devices》手册,详细的分析了ALTPLL_RECONFIG的更新时序,最终研究表明,有三种PLL重配置的方法:
(1)不用ALTPLL_RECONFIG,直接编写时序,更新相关参数(难度较大,无用功太大,不考虑了)
(2)使用ALTPLL_RECONFIG,通过更新Mif文件,完成重配置(还行,Altera推介这样干)
(3)直接在ALTPLL_RECONFIG中需要改变的参数,然后通过ALTPLL_RECONFIG,全自动更新PLL(前期需要一定的研究,要写一些时序,不过一旦成功,一劳永逸)
2.2. Mif文件更新方案
如上图,只要完成了ALTERA_RECONFIG的更新,对PLL的动态配置相当的简单,具体电路见altera官方手册截屏:
Altera貌似推介这种方法,因为不容易出错,不过缺点是,每一个Mif文件,都在在配置PLL的时候,通过修改参数生成,而且需要多少个CLK输出,就需要定制多少个ROM。当然,在完成任务的前提下,我们已经成功了。
2.3. Param更新方案
对于有完美强迫症的我,通过Mif更新的方法,实在是无法忍受。我们明明能做的更好一点,为什么不在努力一把,再花点功夫,研究的深入一些,直接对需要修改的参数进行更新。
在本节第一部分中的参数研究,得出了需要改变的参数,如下表所示:
N |
CLK |
LFC |
LFR |
VPS |
CPU |
NX |
MH |
ML |
odd |
CH |
CL |
odd |
0 |
10 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
30 |
30 |
0 |
|
1 |
15 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
20 |
20 |
0 |
|
2 |
20 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
15 |
15 |
0 |
|
3 |
25 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
12 |
12 |
0 |
|
4 |
30 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
10 |
10 |
0 |
|
5 |
35 |
0 |
27 |
0 |
1 |
4 |
3 |
1 |
5 |
5 |
0 |
|
6 |
40 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
8 |
7 |
1 |
|
7 |
45 |
0 |
27 |
0 |
1 |
5 |
4 |
1 |
5 |
5 |
0 |
|
8 |
50 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
6 |
6 |
0 |
|
9 |
55 |
0 |
27 |
0 |
1 |
6 |
5 |
1 |
5 |
5 |
0 |
|
10 |
60 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
5 |
5 |
0 |
|
11 |
65 |
0 |
27 |
0 |
1 |
7 |
6 |
1 |
5 |
5 |
0 |
|
12 |
70 |
0 |
27 |
0 |
1 |
4 |
3 |
1 |
3 |
2 |
1 |
|
13 |
75 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
4 |
4 |
0 |
|
14 |
80 |
0 |
27 |
0 |
1 |
4 |
4 |
0 |
3 |
2 |
1 |
|
15 |
85 |
0 |
27 |
0 |
1 |
9 |
8 |
1 |
5 |
5 |
0 |
|
16 |
90 |
0 |
27 |
0 |
1 |
5 |
4 |
1 |
3 |
2 |
1 |
|
17 |
95. |
0 |
27 |
0 |
1 |
10 |
9 |
1 |
5 |
5 |
0 |
|
18 |
100 |
0 |
27 |
0 |
1 |
5 |
5 |
0 |
3 |
2 |
1 |
|
19 |
105 |
0 |
27 |
0 |
1 |
11 |
10 |
1 |
5 |
5 |
0 |
|
20 |
110 |
0 |
27 |
0 |
1 |
6 |
5 |
1 |
3 |
2 |
1 |
|
21 |
115 |
0 |
27 |
0 |
1 |
12 |
11 |
0 |
5 |
5 |
0 |
|
22 |
120 |
0 |
27 |
0 |
1 |
6 |
6 |
0 |
3 |
2 |
1 |
因此,只要通过一定的时序,将这些参数更新,便可。而且这些参数不是任意的,而是密切跟输出输出频率相关联的,因此,甚至可以用过其他控制逻辑,发送需要输出CLK的参数,来完成动态PLL的配置。
配置的LPM如上如所示,唯一的区别就是舍弃了ROM读取的接口,因为这已经是多余的了。通过上图中的时序,对counter_type的counter_param进行更新,因此,对照着时序图自行设计状态机,对模式寄存器的参数进行更新。具体对应频率的参数如下所示:
经过21个状态,按照一定的时序,更新CLK的倍频与分频的参数,状态机如下:
最后,10M到35M的PLL动态配置,Modelsim时序图如下所示:
3. PLL动态配置的结论与意义
最后,整体设计如上RTL所示,当然目前实现的只是5M-80M,步进为5M的不同时钟的选择,而不是任意时钟的输出。目前实现的万能显示控制器,在5M-80M间运行正常,性能稳定,多亏了动态PLL的功劳。顶层主要包括了如下几个模块:
序号 |
模块 |
功能 |
1 |
pll_reconfig_top |
PLL重配置顶层模块 |
2 |
pll_parameter |
不同频率的参数选择模块 |
3 |
user_reconfig_ctrl |
PLL需要改变的参数更新模块 |
4 |
pll_reconfig |
ALTERA PLL更新模块 |
5 |
ref_pll |
可重配的PLL模块 |
对于任意的输出,由于某些频率下,当分频参数大了,还需要改变电容泵,环路滤波电容电阻等参数,(比如27M的时候,就需要),此处暂时没有再深入,因为对本设计失去了意义。
要问意义何在?毋庸置疑!
(1)在数字信号处理领域,输入CLK改变得时候……
(2)输出时钟需要动态改变,比如ULC的时候……
(3)……
自从有了动态PLL,很多苍白无力的事情,变得更精彩了……