Xilinx FPGA复位逻辑处理小结
1. 为什么要复位呢?
(1)FPGA上电的时候对设计进行初始化;
(2)使用一个外部管脚来实现全局复位,复位作为一个同步信号将所有存储单元设置为一个已知的状态,这个全局复位管脚与任何其他的输入管脚没有什么差别,经常以异步的方式作用于FPGA。因此,设计人员可以在FPGA内部采用异步或者同步的方式来复位他们的设计。 (always@(posedge clk or posedge rst) )
2. 复位是针对存储单元--触发器,首先有必要了解一下触发器(flip-flops)
Xilinx7系列架构的FPGA每一个slice里面包含8个寄存器,并且所有的这些寄存器都是D触发器,这些触发器共享控制集。控制集包括输入时钟信号(clk),高电平有效使能信号(ce)和高电平有效清零(SR)。SR在触发器里用作同步置位/复位或者异步预复位/清零。
同步复位与异步复位:
当复位信号出现在敏感信号列表中时,触发器将采用异步复位的方式。触发器的SR端口被配置为预置位/清零端口,用FDCE/FDPE触发器来表示。一旦RST= ‘1’条件满足,触发器将立即输出SRVAl属性。
在同步复位的情形,触发器的SR端口被配置为置位/复位端口,用FDSE/FDRE触发器来表示。一旦RST=‘1’条件满足,
触发器将在下一个时钟上升沿时输出SRVAl属性。
INIT 与SRVAL属性
INIT属性用来初始化触发器,INIT属性的值将在配置过程中加载到触发器。
XilinxFPGA 的触发器可以支持同步或者异步复位、置位控制,但是关联的触发器一次只能实现one set / reset / preset /clear中的一个。RTL代码中使用了set / reset / preset /clear 里不止一种时,将导致一些条件下使用触发器的SR端口,而另一些条件下使用fabric logic,则将消耗了更多FPGA资源。一般来说,最好避免使用超过一种set/reset/preset/clearcondition。
3. 除了考虑复位类型,还需要考虑复位信号与时钟是否同步的问题
只要全局复位脉冲信号持续的时间够长,FPGA所有的触发器都将进入复位状态。然而,复位信号的解除必须满足触发器的时序要求,以确保触发器能够正确的从复位状态恢复到正常状态。不满足这些时序要求,将导致触发器进入亚稳态。
并且,为确保子系统(如状态机、计数器)正常工作,所有的触发器必须在相同的时钟沿跳出复位状态。
如果同一状态机的不同的bit在不同的时钟沿跳出复位状态,则状态机将转移的一个非法的状态,这就说明了解除复位信号时与时钟同步必要性。
4. 两种复位机制
同步复位机制:
可以使用一种标准的亚稳态消除电路(两个触发器背靠背相连)来将全局复位同步到特定的时钟域。同步化的复位信号可以使用同步SR端口来初始化所有的存储单元。由于同步器和触发器在同一时钟域里被复位,标准的时钟周期约束包括了它们之间的路径的时间。在FPGA中每一个时钟域需要使用单独的同步器来为对应的时钟域产生同步化的全局复位信号。
Tip 1: When driving the synchronous SR port of flip-flops, every clock domain requires its own localized version of the global reset, synchronized to that domain
异步复位机制:
设计中的存储单元可能需要使用触发器的异步SR port 来异步复位初始化。尽管这些存储单元使用了异步的SR端口,复位信号的解除必须与时钟信号同步。这与触发器的复位恢复时序要求有关,类似于异步SR解除信号边沿对时钟上升沿要满足建立时间的要求。不能满足这些时序要求时将导致触发器进入一个亚稳态,同步的子系统进入异常的状态。
--复位桥电路复位桥电路提供了异步复位声明、同步复位解除的机制。在这个电路中,假定两个触发器的SR port 有一个异步设置的值,SRVAL= 1:
复位桥电路提供了同步的解除异步复位的安全机制。每一个时钟域需要使用复位桥电路来产生它自己的本地化(localized)的全局复位信号。FPGA的每一个时钟域需要一个单独的、同步化的全局复位信号。它可以由单独的复位桥电路来产生。
图中电路假定:复位桥电路和相关的逻辑的时钟源clk_a是稳定的、无错的。在FPGA中,时钟可以来自芯片外的时钟源(最好通过一个clock-capable管脚),或者采用MMCM或者PLL内部产生。任何用于产生时钟信号的MMCM or PLL在复位后需要校准。因此,你可能需要在全局复位路径插入一些额外的逻辑来稳定时钟信号( 因为复位的产生必须在时钟稳定之后,所以一般的做法如下图:把 外部异步输入时钟(比如按键)经过去抖之后产生的异步时钟和MMCM的lock信号相与之后,产生一个全局异步复位时钟 ,然后输入给复位桥的SR pin,实现异步复位同步解复位处理)。
Tip 2: A reset bridgecircuit provides a safe mechanism to deassert an asynchronous resetsynchronously.Every clock domainrequires its own localized version of the global reset with the use of a resetbridge circuit.
Tip 3: Ensure that theclock the MMCM or PLL has generated is stable and locked before deasserting theglobal reset to the FPGA
FPGA内实现异步复位逻辑的典型框图
(一般应用说明:
用外部晶振时钟(可以降几倍频)作为:按键去抖逻辑的时钟源、 失锁信号的同步时钟、MMCM的复位参考时钟(可以不控制)、全局异步复位的时钟源。
1: MMCM 的复位一般不控制,上电就开始工作 : reg mmcm_rst = 1'b1; )
2: 失锁时钟的处理:
always @ ( posedge clk_100m )
begin
userclk_locked_1dly <= userclk_locked;
userclk_locked_2dly <= userclk_locked_1dly;
userclk_locked_3dly <= userclk_locked_2dly;
end
3: 输入信号去抖用FDCE寄存器:
always @( posedge clk_100m or negedge sysrst_n )
4:参考代码:
always @ ( posedge clk_100m ) (这里不需要rst_100m, 因为 rst_100m是由all_reset产生的)
begin
rst_sys_1dly <= rst_sys_tmp || ( ~ userclk_locked_2dly );
rst_sys_2dly <= rst_sys_1dly;
rst_sys_3dly <= rst_sys_2dly;
all_reset <= rst_sys_1dly || rst_sys_2dly || rst_sys_3dly;
end
rst_cdc_sync u0_rst_cdc_sync
(
.reset_in ( all_reset ),
.clk ( clk_100m ),
.reset_out ( rst_100m )
);
//---------------------复位桥:rst_cdc_sync 子模块-----------------------------------//
module rst_cdc_sync
(
input reset_in,
input clk,
output reg reset_out
);
//(* ASYNC_REG = "true" *) reg rst_a;
//(* ASYNC_REG = "true" *) reg rst_b;
//(* ASYNC_REG = "true" *) reg rst_c;
//(* ASYNC_REG = "true" *) reg rst_d;
reg rst_a;
reg rst_b;
reg rst_c;
reg rst_d;
always @ ( posedge clk or posedge reset_in )
begin
if ( reset_in == 1'b1 )
begin
rst_a <= 1'b1;
rst_b <= 1'b1;
rst_c <= 1'b1;
rst_d <= 1'b1;
reset_out <= 1'b1;
end
else
begin
rst_a <= 1'b0;
rst_b <= rst_a;
rst_c <= rst_b;
rst_d <= rst_c;
reset_out <= rst_c;
end
end
endmodule
//--------------------约束文件------------------------//
set_false_path -to [get_pins u_clk_rst_gen/u*_rst_cdc_sync/rst_a_reg/PRE]
set_false_path -to [get_pins u_clk_rst_gen/u*_rst_cdc_sync/rst_b_reg/PRE]
set_false_path -to [get_pins u_clk_rst_gen/u*_rst_cdc_sync/rst_c_reg/PRE]
set_false_path -to [get_pins u_clk_rst_gen/u*_rst_cdc_sync/reset_out_reg/PRE]
5. 为什么复位信号一般都使用高点平有效呢?
Xilinx 寄存器的SR控制端是高电平有效的。如果RTL代码采用了低电平有效的复位模式,综合器将在复位信号驱动寄存器SR控制端之前的插入一个反相器(interver)。你必须使用一个查找表(look up table)来实现反向器,以利用LUT的输入端口。低电平有效的控制信号带来的额外的逻辑可能拉长了执行时间(runtime),将导致更低的FPGA资源利用率,也将影响时序和功耗。
到底我想说点什么呢?尽可能的在HDL代码或者实例化的模块中使用高电平有效的控制信号。如果在设计中,你不能够改变这些控制信号的极性,你需要在代码的顶层文件反转这些控制信号。采用这种方式描述电路的话,这些反向器将被吸收到I/O逻辑中,而不需要使用额外的FPGA逻辑、路径。
Tip 4: Active-high resets enable better device utilization and improveperformance.
6.到底如何用呢?
应用场合:多个时钟域的情况下的复位,针对每一个时钟域都得有对应的复位逻辑。
参见tri_mode_mac 参考例子中的实现方法。
7. 复位桥电路到底怎么实现呢?
`timescale 1ps/1ps
module tri_mode_mac_reset_sync #(
parameter INITIALISE = 2'b11
)
(
input reset_in,
input clk,
input enable,
output reset_out
);
wire reset_stage1;
wire reset_stage2;
(* ASYNC_REG = "TRUE", RLOC = "X0Y0", SHREG_EXTRACT = "NO", INIT = "1" *)
FDPE #(
.INIT (INITIALISE[0])
) reset_sync1 (
.C (clk),
.CE (enable),
.PRE(reset_in),
.D (1'b0),
.Q (reset_stage1)
);
(* ASYNC_REG = "TRUE", RLOC = "X0Y0", SHREG_EXTRACT = "NO", INIT = "1" *)
FDPE #(
.INIT (INITIALISE[1])
) reset_sync2 (
.C (clk),
.CE (enable),
.PRE(reset_in),
.D (reset_stage1),
.Q (reset_stage2)
);
assign reset_out = reset_stage2;
endmodule