目录
一、不完整的复位
always @(posedege clk) begin
if(rst)
reg1 <= 1'b0;
else begin
reg1 <= din1;
reg2 <= din2;
end
end
该情形下,rst成为了reg2使能端,只有rst==1'b0情况下reg2才有值,使原理图多出一个CE控制端,与设计初衷不符。
二、锁存器
1、锁存器的产生
- 不完备的if语句,if...else...代码块缺少else
- 寄存器赋值无上升沿或者下降沿
2、查找代码中的锁存器
vivado中使用all_latches可以查看代码中的锁存器。
3、锁存器的影响
锁存器会对我们的时序分析会造成困难。这与FPGA的内部结构息息相关,以7系列为例,在每个slice有两列触发器,4个FF/L(flip-flop/latches),4个FF(flip-flops)。如ug474中下图所示。
其中FF/L可以配置成触发器或者锁存器,FF只能是触发器。
如果任意一个FF/L被配置成锁存器,则所有FF都将不可再被配置与使用。整个Slice将有一半的触发器资源将浪费。所以要明确是否代码中的锁存器有必要存在,是否可以去除。
三、循环
循环语句能够精简代码,提高代码效率。
但是综合的结果可能无法达到最优,影响性能。
所以需要使用Vivado更容易识别的语句结构,而不是一味使用或者排斥使用循环语句。
1.在基本的连线问题上建议使用loop,比如bit翻转
2.在一些复杂功能或者设计复杂硬件资源时,并不是wire或interconnect型时,最好不要使用循环。
四、状态机
状态机分为Mealy和Moore型,区别在于
1.Mearly:current state+Input => output
2.Moore:current state => output
通常,Moore状态机更适合FPGA的实现。
状态编码方式:二进制顺序码或者One-Hot
五、控制信号集
由上图的Slice结构中可以看出复位、时钟、使能等信号是公用的,是有同样控制集的触发器才可能在实现中放进一个Slice中,所以设计中控制集多的话,会造成资源的浪费同时对系统性能造成影响。控制集少的话布局也会更加灵活。
如果一个触发器使用使能、置位或者复位信号,其他触发器也要使用同样的使能、置位或者复位信号。
vivado中使用report_control_sets语句可以报告出控制集,方便查看和验证。
六、复位的使用
- 如果不使用初始值,默认情况下初值为0。
- 如果复位的目的仅仅是芯片初始化赋初值,那么代码中可以不用全局复位。
- 如果必须加复位,那么尽量控制复位的扇出。
- 简化复位路径的时序。
- 有无复位都不应该影响系统功能仿真。
- 如果没有复位会给FPGA设计的布局布线带来很大的灵活性。
- 使用入复位等控制信号时,尽量使用高有效。缺省情况触发器的使能或者复位默认是高有效,如果使用低有效,会增加一级逻辑,影响系统功耗和时序。
- 避免全局复位,尽可能使用局部复位。
- 尽量使用同步复位,避免异步复位。
代码实现:
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
syn_rst <= 4'b1111;
else
syn_rst <= {syn_rst[2:0],1'b0};
end
assign o_syn_rst = syn_rst[3];