一.概述
博主由于做的项目中出现很多关于复位的问题,所以最近看了好多复位的资料,也做了仿真,做了一些总结,现在把这些东西分享出来。
二.关于复位
其实之前的博客中写过同步复位,异步释放的文章,在其中也阐述了同步复位和异步复位的概念。这里就不再过多阐述。
1.复位模块中有关信号没有全部复位
对于一种不规范的问题,如果在一个always块中不想对所有信号复位,那么就有两种写法,例如图一中不规范的写法,为了方便看,我们把规范的写法也贴了出来,如图二。
这会导致什么问题呢?我们将不规范的规范的进行对比,首先看下RTL原理图:
可以看到不规范的写法会用到前两个寄存器的CE端(时钟使能端),而且用到了2个MUX(2选1),这在综合的时候其实就是对前两个触发器的CLR端接地,即不复位,然后让复位用一个LUT取反接到CE,也就是用一个LUT代替两个2选1MUX的功能。不规范的写法会导致资源增加。
我们再来看看对应的仿真图:
两种写法对应的仿真是有区别的。
Note:
Xilinx建议一个always块中如果有复位,就必须把所有变量复位。
2.关于直接赋值和复位给初始值的区别
定义reg时直接赋值和复位时赋值是有区别的。
在讲这个以前,我们先谈配置阶段,就说一下什么是FPGA的配置(以7系列FPGA为例),可以参考UG470。
配置是指将特定应用的数据加载到器件内部存储器中的过程,即down或者烧录bit的过程。
整个配置流程:
step1:上电
step2:清除配置存储器。
step3:采样配置模式管脚,M2 M1 M0
step4-7:下载bit流(CRC校验,失败则终止配置)
step8:开始启动序列(状态机有8步)
(1)定义reg时赋初值
定义reg时赋初值即初始化INIT属性。在FPGA配置或重配置时的step4-7会将初始值赋值给有关寄存器。
(2)复位给初始值
在FPGA配置结束,(这是博主项目中的做法)由step8其中产生的DONE信号作为复位芯片的输入,从而产生一个200ms的复位信号(具体时间和复位芯片型号有关),该复位信号引脚再引入FPGA,完成异步复位的操作,这就是用户模式的复位,会将有关寄存器赋值为RTL代码中复位时的值。
值得一提的是,如果没有初始化 INIT 属性并且没有复位操作,那么默认INIT 属性为 0(但其实我发现在项目中如果不初始化 INIT 属性,那么有可能ila查看到的寄存器不为0,有的位为1)。这个值可以在综合的网表属性里面改动。如果既初始化 INIT 属性并且也有复位操作,这个时候寄存器的值是什么就看处于FPGA的配置阶段还是用户阶段了。
3.有关复位的一些建议
(1)我们知道BRAM和DSP内部都有一些可用的寄存器资源,比如BRAM的输出寄存器,DSP的流水线寄存器,但这些寄存器只具备同步复位或者置位的功能,举个BRAM的例子,如果你在定制IP核界面没有选输出寄存器选项,而你自己又定义了输出寄存器,这个时候vivado会把你定义的寄存器用BRAM中的输出寄存器来实现,但是如果你定义的寄存器用的是异步复位,那么此推断将不成立。会用Slice中的触发器资源实现,降低了器件资源的利用率。
(2)对于BRAM,LUTRAM,SRL(移位寄存器)的输入端口,不建议用异步复位去驱动,这样可能会导致块中的数据损坏。
Note:
这里就给出大家很容易忽略的建议,其他的太常见了就不写了,也很容易查到,比如建议使用局部复位,同步复位,不建议异步复位以及各种复位的优缺点等等。