我有一个利用同步复位的fpga设计(我更喜欢同步复位而不是异步复位,原因在前面讨论过)。我在设计中有四个不同的时钟域,我利用一个按钮来产生我的重置信号,这当然是完全异步的一切(保存我的手指)。我在四个时钟域中的每个域中去抖动按钮信号,以从单个源为四个域生成同步复位。我的去抖动模块基本上计算被断言的复位按钮的N个时钟周期。如果经过了超过N个周期的reset断言,那么我会生成reset信号(下面粘贴了此模块的代码)。
第一个问题--有比这个方法更好的生成重置的方法吗?
第二个(更有趣的问题):当我查看计时报告(使用xilinx工具)时,我发现所有限制信号都是与重置相关的。例如,限制路径是从复位生成器(去振荡器)到某个状态机的状态寄存器。复位信号是非常高的扇形(它们触及各自时钟域中的所有东西)。我有点惊讶的是,我的速度受到重置的限制。我发现我被限制在类似8.5 nS的范围内,其中~50%是路由,~50%是逻辑。关于如何做得更好,有什么建议吗?如何在fpga设计中处理同步复位生成?
这是重置生成的代码。请注意,信号reset信号类似于去抖动输出(例如,当我实例化模块时,debounced输出是该特定时钟域的reset )。
module button_debouncer(/*AUTOARG*/
// Outputs
debounced,
// Inputs
clk, button
);
/* Parameters */
parameter WIDTH = 1;
parameter NUM_CLKS_HIGH = 12000000;
parameter log2_NUM_CLKS = 24;
/* Inputs */
input clk;
input [WIDTH-1:0] button;
/* Outputs */
output [WIDTH-1:0] debounced;
/* Regs and Wires */
reg [WIDTH-1:0] b1, b2;
reg [log2_NUM_CLKS-1:0] counter;
/* Synched to clock domain */
always @(posedge clk) begin
b1 <= button;
b2 <= b1;
end
/* Debounce the button */
always @(posedge clk) begin
if(~b2)
counter <= 0;
else if(counter < {log2_NUM_CLKS{1'b1}})
counter <= counter + 1;
end
/* Assign the output */
//wire [WIDTH-1:0] debounced = counter > NUM_CLKS_HIGH;
reg [WIDTH-1:0] debounced;
always @(posedge clk) begin
debounced <= counter > NUM_CLKS_HIGH;
end
endmodule //button_debouncer发布于 2013-06-04 07:55:45
在使用重置时提高计时分数的一个非常好的方法是设置最大扇出上限。然后,这些工具将缓冲信号,这样就不会有一个lut试图被路由并用于驱动每个寄存器。这可以通过以下方式完成:
(* max_fanout = <arbitrary_value> *)
wire reset; 因此,我们这里有一个由vivado synth工具使用的约束(或者,如果您仍在使用ISE,则使用该工具)。另外,需要注意的是,这只影响net的下一次声明,因此在此之前或之后声明的其他网络(wires、regs、ext)不受影响。
在xilinx的网站上有一个很好的约束用户指南。还有其他几个你可能也想看看的,它们是: IBUF或BUFG。
发布于 2013-08-03 03:45:18
你不需要四个去保释器的实例。在主时钟上放入一个去缓冲器,然后使用三个亚稳态滤波器将其输出同步到其他三个域。
此外,当你分发你的重置时,你应该使用Cliff Cummings所说的“同步重置分发树”。看看他的网站上有没有这方面的论文。
https://stackoverflow.com/questions/16864444
复制相似问题