七、SDRAM工作时钟相位偏移计算
从上篇文章中我们知道,我们的数据是要经过一定的延时才会到达目标器件的,这个延时也就是相对于源寄存器的时钟发射沿的时间延时,数据在源寄存器时钟的上升沿到来时输出,经过FPGA的走线,PCB走线等,到达目标寄存器的数据端口时会有一定的延时,而这个数据要想被目标器件的目的寄存器锁存,那么,目的寄存器的锁存时钟应该尽量在数据的有效窗口内才能确保数据被捕获成功。所谓数据的有效窗口,就是数据在两次变化之间的中间部分,也是数据最稳定的部分。
所以,要想将数据正确捕获,我们的SDRAM工作时钟必须相对于源时钟有一定的相位偏移,这个相位偏移是我们可以在PLL模块中手动设置的,这个值应该取多少?下面我们就来计算这个值。
这个相移值的计算,需要借助四个参数,即读周期最大滞后、超前时间,写周期最大超前、滞后时间,下面依依来讲
1、读周期滞后时间
所谓读周期滞后时间就是,SDRAM的工作时钟相对于FPGA的工作时钟慢了多少时间。我用一个图来解释
下面我来解释一下这个图,既然是读周期,那么就是在SDRAM的工作时钟下发出数据,在FPGA的工作时钟下捕获数据,由上图可以看出,读周期的滞后时间就是图上的两个参数相减对吧,在理论篇里我讲过,SDRAM在发出一个数据之后,数据会保持一段时间的稳定,这个参数就是Toh,这个参数可以查到。
数据发出后,需要被FPGA的工作时钟捕获,但是捕获的时候需要考虑保持时间不能违规,因此,Th这个参数就是FPGA的寄存器保持时间,这个参数我们需要从时序报告里查,等会我们再说,那么我们可以计算出
读周期最大滞后时间 = Toh - FPGA的保持时间Th
2、读周期超前时间
所谓超前时间,就是SDRAM的工作时钟相对于FPGA的工作时钟快了多少
看到这里,有些人可能就不明白了,SDRAM的时钟比FPGA的时钟相位快了还怎么捕获数据咧?其实,我所说的快慢,只是说时钟的上升沿谁在前而已,我们完全可以这么理解,就是数据是在SDRAM时钟的前一个时钟沿发出的,
上面的原图是错的,即SDRAM发出数据后,要经过Thz的时间数据才会有效,这个时间也是可以查到的,即我们前面理论篇所讲的参数那个参数TOH,注意这个TOH和上面的那个Toh是不一样的。然后是FPGA的建立时间,我们从时序报告里查。那么,可以得到
读周期最大超前时间 = Tclk - (TOH + FPGA的建立时间Tsu)
3、写周期滞后时间
原图也是错误的,既然是写周期,那么就是在FPGA的工作时钟下发数据,在SDRAM的工作时钟下捕获数据,那么源寄存器的工作时钟上升沿到来时,数据发送,要等一段时间后,数据才会有效,这段时间应该是FPGA寄存器的输出延时时间,即图上的Tcomax,这个参数我们需要到时序报告里找,Tss当然就是SDRAM的建立时间了,所以我们可以得到
写周期滞后时间 = Tclk - (Tcomax + SDRAM的建立时间Tsu)
4、 写周期超前时间
这个图可能刚开始理解起来不太好看,我用红笔标出来了,也就是说,这里的Tcomin参数,是当下的时钟沿,到下一个数据有效的时间,而当前的数据,是上一个时钟沿发出的。当然,Toh即SDRAM锁存数据的保持时间了,因此我们得到
写周期最大超前时间 = Tcomin - Toh
5、参数计算
下面我们来找这些参数,将上篇文章中的数据添加约束之后,执行一次全编译,当然这个时候肯定是时序不收敛,不过没关系,时序收不收敛跟我们的PFGA建立保持时间以及数据输出时间是没什么关系的。
我们先来看建立保持时间,由于建立保持时间是读周期的参数,因此,我们查看读周期的路径时序报告,也就是sdram_data路径
我们右键,报告最糟糕路径得到下图
书上说的是,从左上方的数据到达路径中可以得出
数据的建立时间 17.602 - 7.291 - 3.279 =7.032ns
即准建立时间 - 发射沿相对时间 - 时钟网络延时的时间,其实单看这个公式是不好懂的,小墨当时也不明白为什么建立时间是这么算的呢?后来我看了一下右面的图,才渐渐明白过来,其实看右面的图更容易理解一点
看了这个图我们就会明白,当17.602 减去那两项之后,剩下的就是我们设置的最大输入延时时间以及数据进入FPGA的走线延时时间,为什么这段时间是建立时间呢?我们之前不是定义数据不是应该在建立时间内保持稳定吗?但是这段时间内,数据还没到啊。对,没错,好像是这样的,数据没到,为什么没到呢?是因为我们的数据延时太长,以至于我们的捕获时钟在当下的时钟沿捕获不到,因此,这就涉及到了多周期路径约束的知识,我们可以让捕获周期为2 ,也就是说,等到下一锁存沿到来的时候再把数据捕获就好了。
我们再来看一下这两段时间,第一段时间,也就是时钟发射沿相对时间加上时钟网络延时的时间,其实这个时间就是SDRAM发出数据,到数据出现在数据总线上的时间
再回过头去看一下我们分析读周期之后时间的时候,数据出现在数据总线上之后是不是直接被锁存沿锁存了?这样说来就是没有加上数据在PCB走线的延时,因此上图只是一个理想过程,即没有考虑PCB走线的延时,而我们的时序分析工具确实将其考虑在内了,所以,我们的FPGA建立时间,除了包括数据保持稳定的时间外,还应加上这段走线延时的时间,这也就解释了,为什么我们的建立时间是那么算的
这个过程是我自己的理解,不知道是不是准确,觉得有问题的朋友请积极指正,谢谢
同理,我们用同样的方法
算出保持时间为 4.122ns
下面再来看FPGA的输出时间,这个过程就要看时序报告中的输出路径了,按照同样的方法,我们找到输出路径的建立时间的时序报告
我们可以看到,这个很直观,没有像上面那个那么复杂
最大输出延时为6.161ns,
同理,查看输出路径保持时间的时序报告
这个也比较直观,用14.623 减去 10 就好了,为什么要减10呢?再来看这个图
头一个发射沿为0时刻的话,我们需要等一个时钟周期后发射第二个沿,也即这里的数据到达时间14.623,是下一个数据的到达时间,减去10,不就是我们的最小输出时间了么。
所以,我们的最小输出时间为4.623ns
好了,所有的参数都有了,下面计算
读周期最大滞后时间 = Toh - FPGA的保持时间Th = 2.7 - 4.122 = - 1.422ns
读周期最大超前时间 = Tclk - (TOH + FPGA的建立时间Tsu) = 10 - (5.4 +7.032)=-2.432
写周期最大滞后时间 = Tclk - (Tcomax + SDRAM的建立时间Tsu)
= 10 - (6.161 +1.5) = 2.339ns
写周期最大超前时间 = Tcomin - Toh = 4.623 - 0.8 = 3.823ns
这样,我们根据公式,取最小滞后时间为 - 1.422 最小超前时间为 -2.423
取二者平均值得 (-1.422 - 2.423 )/ 2 = - 1.9225
然后,还没有完.... 时序分析这一块就是这么麻烦...
我们现在考虑的,仅仅是考虑的是在SDRAM端口的时钟延时,也就是说还没有考虑SDRAM时钟从PLL输出,经过FPGA内部走线,和外部PCB的延时,我们想一下,是不是有一个这样的关系
就是,PLL的时钟偏移 + 时钟从PLL输出在FPGA内部的延时 + 时钟在外部PCB走线的延时 = SDRAM 端口的时钟延时
而我们要手动添加的,就是PLL的时钟偏移值。再者,上篇文章我们对虚拟时钟SDRAM_CLK进行约束的时候,我们对他就行约束为最大值为3ns对吧, 时钟从PLL输出在FPGA内部的延时就可以按我们所约束的最大值来计算,所以因此,我们计算
PLL的时钟 偏移值 = -1.9225 - 3 - 0.1 = - 5.0225
换算成正值为 10 - 5.0225 = 4.9775
到此为止,我们的相位偏移才计算完毕,我们将它送给PLL
八、多周期约束
对其进行全编译,查看时序报告,发现时序仍然不收敛
查看错误时序报告可以看到,我们没有做多周期约束,至于为什么,上面已经说过了,这里直接来做
我们设置延时周期数为2,即在第二个时钟周期进行数据锁存,因为是输入路径时序违规,所以我们约束的多周期路径就是从我们的虚拟时钟,也就是SDRAM的工作时钟,到我们FPGA的工作时钟clk1
再执行一次全编译,所有的路径达到时序收敛
当然,除了这些,我们还需要一些时序上的优化,以及一些微调,要想达到系统的真正稳定,光做这些还是不够的,小墨也是在学习当中,更深入的探究我只能说对于现在的我来说是力不从心了,有很多经验都是我们后续在不断地摸索中获得的,急也没用,还是安心做好当下,一步一个脚印,学无止境,我们永远不能说自己学会了,只能说熟悉了,慢慢来吧~大家还需加油!
下面是我调好的板级测试图,下面也会附有源代码,不过下到你的板子上不一定跑的起来哦,大家还是自己亲手算算这些参数,等到板子真正跑起来的时候,你才会感受到那种成功的喜悦~