FPGA复位设计与DFF资源浅析
摘要:很多FPGA工程师习惯于对FPGA设计进行上电复位,总担心如果不复位,触发器就处于未知状态,导致系统跑飞。事实上,每个触发器都有明确的初始值,这个初始值与是否复位无关。即,一旦系统上电,即使没有复位信号,对于FDSE和FDPE,其初始值为1,对于FDRE和FDCE,其初始值为0,Block RAM和DSP48内部触发器初始值为0。本文对于四种DFF触发器与复位设计进行一些浅要的探讨。
Xilinx器件中的四种DFF
我们先看一下xilinx器件中的4中不同的DFF:
异步复位(FDCE):CLR clear DFF 异步清0
异步置位(FDPE):PRE preset positive DFF 异步置1
同步复位(FDRE):R reset DFF 同步清0
同步置位(FDSE):S set DFF 同步置1
Verilog Code如下:
module clk_rst(
input wire clk_sys,
input wire rst_sys,
input wire din,
output reg dout1,
output reg dout2,
output reg dout3,
output reg dout4,
output reg dout5
);
//FDCE
always@(posedge clk_sys or posedge rst_sys)
begin
if (rst_sys == 1'b1)
dout1 <= 1'b0;
else
dout1 <= din;
end
//FDRE
always@(posedge clk_sys)
begin
if (rst_sys == 1'b1)
dout2 <= 1'b0;
else
dout2 <= din;
end
//FDPE
always@(posedge clk_sys or posedge rst_sys)
begin
if (rst_sys == 1'b1)
dout3 <= 1'b1;
else
dout3 <= din;
end
//FDSE
always@(posedge clk_sys)
begin
if (rst_sys == 1'b1)
dout4 <= 1'b1;
else
dout4 <= din;
end
(*keep = "ture"*) reg rst_sys_1d;
(*keep = "ture"*) reg rst_sys_2d;
wire rst_sys_bufg;
always@(posedge clk_sys or posedge rst_sys)
begin
if (rst_sys == 1'b1) begin
rst_sys_1d <= 1'b0;
rst_sys_2d <= 1'b0;
end
else begin
rst_sys_1d <= rst_sys;
rst_sys_2d <= rst_sys_1d;
end
end
always@(posedge clk_sys or posedge rst_sys_2d)
begin
if (rst_sys_2d == 1'b1)
dout5 <= 1'b0;
else
dout5 <= din;
end
/*
wire [5:0] dout_16;
c_shift_ram_0 your_instance_name (
.A(depth), // input wire [5 : 0] A
.D({15{1'b1}}), // input wire [15 : 0] D
.CLK(clk_sys), // input wire CLK
.CE(dout3[0]), // input wire CE
.Q(dout_16) // output wire [15 : 0] Q
);
*/
endmodule
如图所示,D是数据输入端口,CE是使能端口,CLK是时钟输入,SR是Set/Reset的意思,可用作置位或者复位,置位和复位又分同步和异步,因此D触发器有如下四种应用类型:
如何进行复位设计
什么情形下用复位信号,why?
很多工程师习惯于对FPGA设计进行上电复位,总担心如果不复位,触发器就处于未知状态,导致系统跑飞。事实上,每个触发器都有明确的初始值,这个初始值与是否复位无关。即,一旦系统上电,即使没有复位,对于FDSE和FDPE,其初始值为1,对于FDRE和FDCE,其初始值为0,Block RAM和DSP48内部触发器初始值为0。
结论1:如果只是上电复位,那么这种复位是不需要的
结论2:控制路径需要复位(如状态机),数据路径不需要复位(如打拍寄存器)
对于控制路径,例如状态机,这种复位通常是必需的,保障状态机。相比之下,数据路径的复位通常是不需要的,数据持续随时钟沿刷新。
结论3:功能仿真时,为获得触发器初始值,可在定义该触发器时直接声明,无需复位
从功能仿真的角度看,如果没有初始值,触发器输出会显示“X”,从而导致仿真无法继续。解决方法是在定义触发器时,给出初始值,且这种方式是可综合的。
Reg [3:0] a = 4’h0;
So同步复位还是异步复位?
如果必须使用复位,Xilinx建议使用同步复位。Xilinx FPGA中的触发器既支持同步复位,也支持异步复位(FDRE和FDCE),常被误认为异步复位并不会带来不良后果。事实上,相比于同步复位,全局异步复位会增加时序分析的复杂度。另外,Block RAM和DSP48自带的触发器只支持同步复位,基于LUT的SRL(移位寄存器, SRL16E,SRLC32E)不支持复位
同步复位的优点:
抗干扰性高,可以剔除复位信号中周期短于时钟周期的毛刺;电路稳定性强。
同步复位的缺点:
- 如果逻辑器件的目标库内的DFF都只有异步复位端口,使用同步复位时,综合器会在寄存器数据输入端插入组合逻辑,占用更多的逻辑资源;
- 同步复位依赖于时钟,如果电路中的时钟信号出现问题,无法完成复位。
- 对复位信号的脉冲宽度有要求,必须大于指定的时钟周期,由于线路上的延迟,可能需要多个时钟周期的复位脉冲宽度,且很难保证复位信号到达各个寄存器的时序。
异步复位的优点:
无需额外的逻辑资源,实现简单;复位信号不依赖于时钟。
异步复位缺点:
复位信号容易受到外界的干扰,如毛刺等影响;
复位信号释放的随机性,可能导致时序违规,倘若复位释放时恰恰在时钟有效沿附近,就很容易使电路处于亚稳态。
异步复位,同步释放
异步复位:就是复位信号可以直接不受时钟信号影响,在任意时刻只要是低电平就能复位,即复位信号不需要和时钟同步。
同步释放:同步解复位信号,跟随时钟打两到三拍,即刚好跟时钟同沿,实现同步释放。
异步复位,同步释放的优点
避免复位信号释放的时候造成亚稳态问题
只要复位信号一有效,电路就处于复位状态,与时钟沿无关,
有效捕捉复位,即使是短脉冲复位也不会丢失
有明确的复位撤销行为,复位的撤离是同步信号,因此有良好的的撤离时序和足够的恢复时间
用两级触发器打两拍的方法解决亚稳态的问题
全局复位还是局部复位
全局复位信号意味着该复位的扇出会很大,这会造成两个典型的不利结果。设想一下,从一个点出发要到达芯片其他位置的成千上万甚至几十万个地方,会占用很多布线资源,给布线带来压力,同时,也不利于时序收敛。这也就是为什么对于全局复位,要将其采用复位树的方式优化为局部复位。对于SSI器件更是如此,要确保每个SLR有自己的复位信号,避免一个复位信号全片飞。
复位结论:不必要的复位信号可移除,必要的复位信号建议使用同步复位,非要使用异步复位的信号,可以选择异步复位同步释放,全局复位信号优化为局部复位信号
复位设计在FPGA中非常关键,对复位设计经验有限,欢迎大家一起探讨,一起成长