热度 3
2015-11-15 12:35
576 次阅读|
0 个评论
从开始学FPGA一直想写博客,记录自己的FPGA学习过程,二是对学的知识进行巩固,后来才发现并不是那么容易的事情,学过一段时间有一定领悟之后敢去写,表达自己的一些想法,既然开始了,以后有时间有想法就写,最后借用bingo的一句话“永远相信自己,既然选择了FPGA,便不顾风雨兼程,Just Try!!!” 今天看到bingo的好书《FPGA设计技巧与案例开发详解》,第九章优化设计FPGA全局时钟管理模块,有一部分是讲得复位电路的设计,之前在特权同学的书上也看到过,今天又看到了bingo写到了,想来这一部分还是很重要的,就写下我的理解与心得跟网友分享一下子,我们经常在设计FPGA电路时,复位部分一般采用异步复位,很久之前我也是没有考虑为什么?因为在我们刚开始接触FPGA时,不管是板子上带的资料还是网上的代码还是看大神前辈们留下的代码都是写的异步复位的,(大神写的肯定是有大神的道理的,我们来分析一下哈) 即代码结构如下 always @ (posedge sclk,negesge rst_n) if (!rst_n) ... else ... 这样设计的复位信号对外部时钟信号没有要求,也就是说复位信号和时钟信号是完全没有联系的,当复位信号来时,就立马进行复位,但这样的设计有一个缺点就是当时钟信号的上升沿和复位信号的时间很紧,或者是说在复位信号释放时恰巧时钟的上升沿也到来了,这样if的条件和else 的条件都同时满足了,输出的信号也就不能够唯一确定了,这样就导致输出的数据不稳定,也就是我们所说的亚稳态。 但是我们看到的大部分代码都是这样设计的原因是大部分逻辑器件的library中是异步复位端口的触发器,这样的设计也简单明了,而且异步复位的信号识别方便(不受到时钟的限制),这样我们一个电路所有的复位就都可以使用FPGA的全局复位端口,也就是我们顶层设计的端口中的rst_n。 还有一种复位电路就是复位信号和时钟信号有联系的,复位信号只有在时钟信号的上升沿或者下降沿才会有效。代码结构如下: always @ (posedge slck) if (!rst_n) ... else ... 我们分析这段代码时可以看到只有当时钟的上升沿来到时,复位才会被执行,(前提也得是复位信号还存在),前面也提到过,大部分的逻辑器件的目标库内的触发器只有异步复位的端口,这样我们的同步设计的在被综合器综合之后就会产生组合逻辑电路,这也就会增加资源,一个复杂点的设计可不是只有几个复位,而且复位信号的保持时间在安全的情况下必须至少有一个时钟周期,才能完成复位。 听过华成英老师的模电课的同学,都知道华老师的一句口头禅,“做电子设计,有一利必有一弊”哈哈!那我们该用哪种结构的电路呢?我个人觉得需要看不同的需要,一般用异步复位电路,出现亚稳态的话我们也就只有乖乖再想办法了。 异步复位的同步化设计的出现秒秒钟解决问题 我们在前面讲到的同步复位,会产生逻辑电路,那我们可以把前面的逻辑电路用时序电路替代而且实现一样的功能,这样就不占用逻辑资源了吗?这就是异步复位的同步化,先展示一下bingo的代码,根据我的个人习惯有些许修改,结构如下: module system_ctrl ( input wire sclk, input wire rst_n, input wire in, output wire out ); reg rst_n_r; reg out_r always @ (posedge sclk) if (!rst_n) rst_n_r = 1'b0; else rst_n_r = rst_n; //不处于复位时,该信号一直为高 always @ (posedge sclk,negedge rst_n_r)//复位时,即产生negedge if (!rst_n_r) out_r = 1'b0; else out_r = in; assign out = out_r; endmodule 所谓异步复位的同步化就是把复位信号打拍延迟作为异步复位电路的复位信号,这样就保证了不会出现复位信号和时钟信号的冲突而竞争产生的亚稳态。我记得特权同学的书上不是这么设计的,后来看书确认了下确实不一样,(深入浅出玩转FPGA那本书的设计思路是用D触发器的透明性,从本质上产生一个给异步复位电路提供复位的信号(本质就是信号从1-0-1的变化))但思想是一致的,就是基于系统复位信号然后打拍延迟作为异步复位电路的复位信号,这样就降低了出现亚稳态的概率。 最后把我们FPGA的前辈大师特权同学的代码贴在下面,大家领悟一下,代码结构如下: input sclk; input rst_n; output rst_nr2; reg rst_nr1,rst_nr2; always @ (posedge sclk,negedge rst_n) if (!rst_n) rst_nr1 = 1'b0; else rst_nr1 = 1'b1; always @ (posedge sclk,negedge rst_n) if (!rst_n) rst_nr2 = 1'b0; else rst_nr2 = rst_nr1; 然后把输出的rst_nr2信号作为异步复位电路的复位信号。