【发布时间】:2013-05-31 19:23:22
【问题描述】:
我有一个利用同步复位的 fpga 设计(由于其他地方讨论的原因,我更喜欢同步复位而不是异步)。我在设计中有四个不同的时钟域,我使用一个按钮来生成我的复位信号,这当然与所有东西完全异步(保存我的手指)。我在四个时钟域中的每一个中对按钮信号进行去抖动处理,以从单个源为四个域生成同步复位。我的去抖模块基本上计算了复位按钮被断言的 N 个时钟周期。如果在置位复位的情况下经过了 N 个以上的周期,那么我会生成我的复位信号(此模块的代码粘贴在下面)。
第一个问题——有没有比这种方法更好的生成重置的方法?
第二个(更有趣的问题):当我查看时序报告(使用 xilinx 工具)时,我发现限制信号始终都与复位相关。例如,限制路径是从复位发生器(去抖动器)到某个状态机的状态寄存器。复位信号非常高扇出(它们触及各自时钟域中的所有内容)。虽然我的速度受到重置的限制,但我有点惊讶。我发现我的速度仅限于 8.5 nS,其中约 50% 是路由,其中约 50% 是逻辑。关于如何更好地做到这一点的任何建议?您如何处理 fpga 设计中的同步复位生成?
这是重置生成的代码。请注意,信号复位信号类似于去抖输出(例如,当我实例化模块时,debounced 输出是该特定时钟域的复位)。
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
【问题讨论】:
-
我原来的去抖动器好像没有注册输出(原来的版本被注释掉了)。通过注册输出,我(不出所料)能够提高性能,使复位信号不再是限制路径。也就是说,重置策略的一般问题仍然存在。谢谢!
-
您的 fpga 真的需要重置吗? FPGA 可以使用初始状态进行编程,因此如果您只需要一个干净的起点,您可以使用
initial,然后为您自己节省重置网络的面积/时序费用。 -
感谢@Tim 的评论。是的,我确实需要重置。谢谢。