CrazyBingo

【红色飓风Nano二代测评】Xilinx DCM IP Core研究及使用方法

1
阅读(4890)

Xilinx DCM IP Core研究及使用方法

         —CrazyBingo

         —20140506

信誓旦旦的,三下五除二,凭借Altera FPGA的丰富经验,一晚上搞定了Xilinx FPGA的基本开发流程,并且搞定了按键、LED灯等的驱动。很哈皮。。。哈皮。。。

 

不过不要高兴得太早,好戏还没开始呢。。。这FPGA只用外部的50MHz晶振时钟,浑身都不自在。强大的时钟网络,怎么可以不用呢???于是乎,开始调用IP Core,拿来主义,搞定PLL即可。。。

但是事实上,真没那么顺利。。。

首先搞不懂什么DCMPLL之类的东西。。。。虽然这不是问题的重点。。。其次,各种警告让我崩溃,摸不着头脑。。。一鼓作气,看Sparatan的用户手册,了解到XC6S1X162CMT


而每个CMT 包括2DCMPLLDCM为数字时钟管理器,而PLL为模拟锁相环。AlteraFPGA只有PLL,因此对这个太熟悉了。。而DCMXilinx的数字时钟管理器,能输出DCM =          CLK0 + CLK90 + CLK180 + CLK270 +CLK2X + CLK2X180 + CLKDV + CLKFX + CLKFX1809中不同的时钟。但是不知怎么的。。。我竟然出问题了。。。不过一开始没搞清楚,很激动的定制了clock_wizard这个ipcore,如下图所示:




由于在Altera FPGA设计中,鄙人已经有了完整的时钟管理架构,因此直接移植sys_ctrl_pll模块,该模块在Quartus II中的RTL图如下所示:


即系统首先经过一段时间的延时(由于刚上电期间,外设、IC等不稳定),在这段时间延时后,开启PLL,等到PLL所想输出信号。当PLL输出锁相完成信号后,此时将外部输入的复位信号同步处理后的结果,通过与运算,输出最终的结果。该理论经过无数次理论与实际的验证,因此果断直接移植啊。。。。

由于一开始没搞清楚状况,莫名其妙的我定制的为DCM,而不是PLL。不过结果与AlteraPLL,完全一样,因此直接例化了,如下所示:

//-----------------------------------
//system pll module
wire pll_rst = 1'b0;
wire locked;
wire     clk_out1;
sys_dcm  u_sys_pll
(
         .CLK_IN1                    (clk),
         .RESET                        (pll_rst),
         .LOCKED                     (locked),
         .CLK_OUT1                (clk_c0)
); 


结果蛋疼的,在编译的时候出现错误,如下所示:


询问+查看sys_dcm的时候,发现模块中,软件自动添加了输入Buffer与输出Buffer,据说是为了提高信号的驱动能力(但实际上我也不是很清楚),如下所示(输出也有一个Buffer):


根据警告,可以直接将clkin1_buf删除,或者在定制Ipcore的时候,的确有一个选项,用以选择输入时钟是否需要Buffer,如下所示。


直接修改sys_dcm模块,或者通过ipcore修改后的结果如下所示。但这修改的只是源端时钟,而非终端。。终端依然有Buffer存在。。。


这样就不会有这个警告了。。同时流水灯跑的欢快。。。不过默认有Buufer,应该也有他的道理吧。。。仔细分析原因,源于我将输入的clkDCM的同时,也给system_delay模块进行延时了。而DCM模块中有一个buffer,因此该时钟信号给模块1的同时,又通过buffer给模块2.。。至于这样为什么不行,摸不着头脑。。。但貌似我这样设计,的确有不合理的地方。。。

于是修改鄙人的sys_pll_ctrl模块,将system_delay模块的时钟换成clk_c0,即DCM输出的时钟,此时万事OK了,不管是否添加Buffer。。。貌似“科学了。。。更仔细的分析sys_dcm模块,部分原语言如下所示:


         正如Spararan DS160手册所说的那样,DCM输出9路时钟,分别为相位、2倍频、2分频、以及小数分频的时钟,手册说的如下:



序号

时钟

描述

1

CLK0

输出0相位差的时钟,并连接反馈时钟CLK_FB

2

CLK90

输出90°相位差的时钟

3

CLK180

输出180°相位差的时钟

4

CLK270

输出270°相位差的时钟

5

CLK2X

输出2倍时钟

6

CLK2X180

输出2倍、180°相位差的时钟

7

CLKFX

输出CLKIN*M/D后的时钟

8

CLKFX180

输出CLKIN*M/D180°相位差的时钟

M[2,32]N∈[1,32]

9

CLKDV

CLK0对齐的小数分频时钟

分母∈[2,16]/1.52.5…15.5,以及2

备注:关于CLKDV的定义,不是看的很懂。。。求指点……

对于一个对代码的移植优化有强迫症的人,即便不用Xilinx原语来操作,也无法承受每次都要重复的定制IPCORE。。。。果断删除了sys_dcm.xcosys_dcm.xise,如下所示:


此时添加sys_dcm文件,如下所示。。。(操作与Altera Quartus II完全一样)


打开sys_dcm,分析相关参数。由于前面已经研究完毕了DCM9条时钟线,极其意义。。这些都变得轻松愉快了。。。这里左图为原始生成的2倍频(100MHz)的DCM原语描述,右图为笔者8倍频生成的400MHz时钟的原语描述,分别如下所示:

(1)       从左图可见,2分频为FALSE,相位移动为NONE,因此乘除因子都不用管。。。。同时时钟从CLK2X输出,可见输出时钟为CLKIN*2,且无相位差。。。

(2)       从右图可见,鄙人添加了clkfx并且CLKFX输出,将CLKFX_MULTIPLY改成8,因此最终频率理论上为400MHz。当然此时由于从clkfx输出,在最后的输出Buffer中需要做修改,如下:


此时,8LED的流水灯,在极其快的速度下,努力的奔跑,亮瞎你的狗眼。。。。。哈哈 。。。搞定。。此时,,可以脱离残酷的IPCORE GUI的崩溃速度了。。。。既然我们还没有直接写原语那么牛逼。。但至少。。我们可以一劳而永逸了。。。。

不过又出现了一个疑问:关于CLKFB,手册说With CLK0 Connect to CLKFB、、、但实际上我修改CLK0 = CLKFB后,即便CLKFB = CLK2X,也没出问题。。。。。求大神解释。。。

 

总结:就目前了解,DCMPLL相比,时钟与相位的生成比较欠缺。。但是方便。。。。2CMT= 2DCM + PLL 的确够用了。。。。