官方源码,LVDS中判断数据是否对齐时钟上升沿的方法解析
/*----时钟上升沿与滞后半个周期检测----*/
generate
for (i = 0 ; i <= S-2 ; i = i+1) begin : loop0
assign msxoria[i+1] = ((~s_ovflw & ((mdataouta[i] & ~mdataouta[i+1] & ~sdataouta[i]) | (~mdataouta[i] & mdataouta[i+1] & sdataouta[i]))) |
( s_ovflw & ((mdataouta[i] & ~mdataouta[i+1] & ~sdataouta[i+1]) | (~mdataouta[i] & mdataouta[i+1] & sdataouta[i+1])))) ; // early bits
assign msxorda[i+1] = ((~s_ovflw & ((mdataouta[i] & ~mdataouta[i+1] & sdataouta[i]) | (~mdataouta[i] & mdataouta[i+1] & ~sdataouta[i])))) |
( s_ovflw & ((mdataouta[i] & ~mdataouta[i+1] & sdataouta[i+1]) | (~mdataouta[i] & mdataouta[i+1] & ~sdataouta[i+1]))) ; // late bits
end
endgenerate
//判断分为两种情况
//情况1就是没有溢出:~s_ovflw
//情况2就是溢出:s_ovflw
//msxoria代表信号到达太早,需要将信号延时一下
assign msxoria[0] = ((~s_ovflw & ((mdataoutb & ~mdataouta[0] & ~sdataoutb) | (~mdataoutb & mdataouta[0] & sdataoutb))) | // first early bit
( s_ovflw & ((mdataoutb & ~mdataouta[0] & ~sdataouta[0]) | (~mdataoutb & mdataouta[0] & sdataouta[0])))) ;
//msxorda代表信号到达太晚,需要将信号减小延时
assign msxorda[0] = ((~s_ovflw & ((mdataoutb & ~mdataouta[0] & sdataoutb) | (~mdataoutb & mdataouta[0] & ~sdataoutb)))) | // first late bit
( s_ovflw & ((mdataoutb & ~mdataouta[0] & sdataouta[0]) | (~mdataoutb & mdataouta[0] & ~sdataouta[0]))) ;
数据延时模块实现数据延时的理论思路是什么样的?
注意:以下只是理论,区别与具体实现。具体实现会有差别
先采一个值,延时半个周期再次采一个数值
- 采样的值相同,则增大数据的延时
- 采样的值不同,则减小数据的延时
如果前一个采样值相同,改变延时后采样值不同了,那么就确定在中心附近了。
如果前一个采样值不相同,改变延时后采样值相同了,那么也能确定在中心附近了。
注意:以下只是理论,区别与具体实现。具体实现会有差别
先采一个值,延时半个周期再次采一个数值(记住下面的两句口诀)
- 采样的值相同,则增大数据的延时
- 采样的值不同,则减小数据的延时
如果前一个采样值相同,改变延时后采样值不同了,那么就确定在中心附近了。
如果前一个采样值不相同,改变延时后采样值相同了,那么也能确定在中心附近了。
数据延时模块实现数据延时的具体实现思路是什么样的?
FPGA内部实际只能单沿操作,理想的情况下需要双边沿检测,不好始实现。
故:首先对P端的延时调整快半个周期或者慢半个周期,
(这里我们认为P端与~N端信号是一模一样的)
那么P端与~N端之间就会有半个周期差,在时钟上升沿同时采样P端和~N端信号,效果上就是对一个信号隔半个周期采样一次了。
重点:为了让前后周期的数据不一样,便于检测是是都是采样同一周期还是非同一周期的数据,因此源码上面用的是边沿检测的方法。只对前后数据产生跳变的数据进行判断。
- 如果~N 端 是超前P端 的那么,我们重点关注P端边沿前的数据与~N端采样数据的关系
- 如果~N 端 是滞后P端 的那么,我们重点关注P端边沿后的数据与~N端采样数据的关系
然后用前面记的两个公式来判断数据应该增大延时还是减小延时。(刚开始的时候对数据都有初始延时)