关于FPGA同时使用时钟的上升沿和下降沿的问题
FPGA中的有关资料中提到不要同时使用时钟的上升沿和下降沿,这个说法曾让很多人迷惑过,今天就我的看法发表出来和大家探讨下:
附件已经删除,不便之处请原谅
同楼上,不懂。
不同的寄存器用不同的时钟沿触发有什么问题呢?
观点同2楼
不同的reg信号用不同的时钟沿,再将这些信号连到同一个wire信号,可行不?
FPGA中的有关资料中提到不要同时使用时钟的上升沿和下降沿,这个说法曾让很多人迷惑过,今天就我的看法发表出来和大家探讨下:
第一种写法:在一个always 语句里面直接对上升沿和下降沿进行赋值
always @(posedge clk or negedge clk)
第二种写法:在不同的alwys语句里面在时钟的上升沿和下降沿对同一个寄存器进行赋值
always @(posedge clk ) begin .......reg1<=....end //对寄存器1赋值
always @(negedge clk) begin .......reg1<=....end // 对寄存器1赋值
第三种写法:在不同的alwys语句里面在时钟的上升沿和下降沿对不同寄存器进行赋值
always @(posedge clk ) begin .......reg1<=....end //对寄存器1赋值
always @(negedge clk) begin .........reg2<=....end // 对寄存器1赋值
很明显,第1和第一种写法是不可行的,在verilog的语法里面有说明,编译也明显通不过,
现在对第三种进行讨论,第三种是在时钟的上升沿和下降沿分别对不同的寄存器进行赋值处理,
上升沿和下降沿都使用,就相当于是电平触发,电平触发比时钟沿触发更容易受到干扰,在高速时
容易受干扰,也不够好。
解决方法
方法1.先通过PLL锁相环产生两个频率相同相位差为180度的clk1,clk2,然后在每个clk的上升沿输出
always@(posedge clk1)
begin
...
end
always@(posedge clk2)
begin
...
end
方法2:通过PLL对clk进行倍频,得到clk2,那么clk2的上升沿也就是clk的下降沿
always@(posedge clk)
begin
...
end
always@(posedge clk2)//相当于clk的下降沿
begin
...
end
方法3:如果对clk的下降沿操作只是用于后面的使能之用,可以把clk分频得到clk_new;
例如:
always @(posedge clk)
begin
clk_new<=!clk_new;//把clk_new当作是新时钟用,信号都是在clk_new的上升和下降沿触发
end
always @(posedge clk_new)//clk_new的上升沿
begin
....
end
always @(posedge clk)///clk_new的下降沿,由于clk信号是clk_new的二倍频,
begin
....
end
方法4:在低速信号处理的时候可以把clk取反得到一个新的时候clk_n
always @(posedge clk)
begin
end
always @(posedge clk_n)//取反后clk_n的上升沿也就是clk的上升沿
begin
end
你说的这些解决方法只是在说明怎么产生clk,而在实际设计中如果想同时用时钟的上升和下降沿,关键问题不在于时钟怎么产生,而是寄存器怎么用。
当然CLK产生也是必须的。
第一种方法应该说是一种最佳的方法,PLL产生的时钟质量最好,而且能够直接上全局时钟网络。
第二种方法:clk2既然是倍频出来的,那么clk2的上升沿既是clk的上升沿也是clk的下降沿。
这种方法产生时钟最大的问题就是对时序的要求提高了一倍,因为时钟频率变味了两倍。
第三种方法:首先这种分频方法是不推荐的,最好用PLL实现而不是用LE资源实现(当然低频的设计这样做没有问题,但如果对频率要求不高,又何必采用上升和下降沿同时采呢,直接升高频率不就能提高系统的处理速度了吗!);其次posedge clk并不是negedge clk_new。
第四种方法:这样产生的时钟也是没有问题的,但是未必用于低速设计,clk和clk_n可以用全局时钟资源中的INV来产生,之后通过bufg直接上全局时钟,时钟质量没有问题的,不会比第一种方法差的。
除了时钟的产生之外,关键的是寄存器怎么处理,同时用上升沿和下降沿并不是同一个寄存器同时存在上升沿和下降沿触发,这样的寄存器是不存在的。假设有一连串的寄存器,同时用上升沿和下降沿,可以选择寄存器1 3 5 7 。用上升沿,2 4 6 8 。用下降沿,这样做在不提高频率的情况下,系统的处理速度恰好是只用一个触发沿的两倍。
如果有跟LZ理解上的偏差,请指出,谢谢。
大家都出来探讨下,讨论下....有什么意见和见解的请都发表下。楼上说的都很不错,
有点 复杂
看到这种经典问题 总是很兴奋,木办法,经验太少了
上升沿、下降沿分别对不同信号赋值为什么就是电平敏感了?
你分析的很有道理,但是对于小编所提出的,用CLK的上升沿和下降沿 触发不同的寄存器存在什么问题,似乎并没有给出解释,而是直接给出了解决的办法?
小编忽略了一个很重要的问题
为什么要上升沿下降沿同时都动作?那还不是因为时钟很高,不想用更高的时钟来工作,结果小编直接说来个PLL2倍频的时钟,这样做失去了上升下降同时工作的意义
而且也不存在说上升下降都动作就代表电平敏感,这个理解完全错误
实现的方法,通常是由两组寄存器,一组上升沿动作,一组下降沿动作
怎么看不到啊?
好文章!
QDR的读写操作,不就是在时钟的上升沿和下降沿吗?
好文章 mark 一下
这样的讨论很好
学习了,谢谢~
感觉是把问题想复杂了吧,使用PLL,生成一个相位为180的时钟不就好?或者assign clk=~clkn;生成一个相位相反的时钟。
经常在系统中,使用相位时钟,来消除数据建立的竞争冒险.
这个会报错的
Execept special register, most of FPGA registers didn't support double edge sample. When you used two edges of same clock, it may lead to touch timing performance.
第二种方法好像不能直接达到效果,这时候两个寄存器应该变成同时触发了;高速时第四个方法感觉可行,没试过。另外想问问,这个命题的意义是什么?
QDR需要用MMCM或PLL产生一个180°相移的K K#,本质上还是用两个时钟
怎么没看到主要内容呢
我感觉是木有意义的,因为这种问题,最后都会归结到FPGA的结构还有综合软件的算法上。是随着工具变动的
同问,这样第三种方法为什么不行
小编,那关于第二种写法的解决办法是?
又学习了新知识
非常经典的讨论。
