FPGA系统中的同步复位与异步复位

时间:2015-12-03 13:27:15

标签: asynchronous vhdl reset clock xilinx

我很擅长创建一个FPGA系统来驱动I2C总线(尽管我认为这个问题适用于任何FPGA系统)使用各种不同的模块,并且都使用同步复位。

使用时钟分频器模块为模块提供时钟,该模块接收系统时钟并向系统的其余部分输出较低的频率。

我遇到的问题是,当复位信号变低时,时钟分频器复位,因此其他模块依赖的时钟停止 - 因此其他模块不会注册复位

一个明显的解决方案是进行异步复位,但是,在Xilinx ISE中,它似乎并不喜欢它们并发出警告,说这与Spartan-6 FPGA不兼容(特别是当代码之后异步代码是IS同步的,这是因为I2C总线使用总线时钟将位放到总线上。

另一个解决方案是时钟分频器根本无法复位,因此时钟永远不会停止,所有模块都会正确复位。然而,这意味着时钟分频器寄存器不能被初始化/重新初始化为已知状态 - 我已经被告知这将是一个大问题,虽然我知道你可以在模拟中使用 := '0'/'1'; 运算符,但一旦在实际FPGA(?)上编程,这就不起作用。

同步重置的惯例是什么?时钟发生器通常不会重置吗?或者他们只在复位信号的瞬间边缘复位?或者我的建议都不是真正的解决方案!

我已经提供了时序图和我的代码来说明我的意思,并展示我一直在使用的代码。

非常感谢!

大卫

enter image description here

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
ENTITY CLK_DIVIDER IS
    GENERIC(INPUT_FREQ : INTEGER;
            OUT1_FREQ  : INTEGER;
            OUT2_FREQ  : INTEGER
    );
    PORT(SYSCLK  : IN  STD_LOGIC;
         RESET_N : IN  STD_LOGIC;
         OUT1    : OUT STD_LOGIC;
         OUT2    : OUT STD_LOGIC);
END CLK_DIVIDER;
architecture Behavioral of Clk_Divider is
    constant divider1 : integer   := INPUT_FREQ / OUT1_FREQ / 2;
    constant divider2 : integer   := INPUT_FREQ / OUT2_FREQ / 2;
    signal counter1   : integer   := 0;
    signal counter2   : integer   := 0;
    signal output1    : std_logic := '0';
    signal output2    : std_logic := '0';
begin
    output1_proc : process(SYSCLK)
    begin
        if rising_edge(SYSCLK) then
            if RESET_N = '0' then
                counter1 <= 0;
                output1  <= '1';
            else
                if counter1 >= divider1 - 1 then
                    output1  <= not output1;
                    counter1 <= 0;
                else
                    counter1 <= counter1 + 1;
                end if;
            end if;
        end if;
    end process;
    output2_proc : process(SYSCLK)
    begin
        if rising_edge(SYSCLK) then
            if RESET_N = '0' then
                counter2 <= 0;
                output2  <= '1';
            else
                if counter2 >= divider2 - 1 then
                    output2  <= not output2;
                    counter2 <= 0;
                else
                    counter2 <= counter2 + 1;
                end if;
            end if;
        end if;
    end process;
    OUT1 <= output1;
    OUT2 <= output2;
end Behavioral;

3 个答案:

答案 0 :(得分:4)

不要使用用户逻辑生成内部时钟,但如果确实需要多个时钟,则使用特定于器件的PLL / DCM。然后,在导出时钟上运行的所有用户逻辑应保持复位,直到时钟稳定为止,然后可以根据设计要求释放用户逻辑的复位。可以使用同步复位或异步复位。

但是在这种情况下,可能代之以产生时钟使能信号,并且每次需要更新信号时将该使能信号断言一个周期,以便产生所需的任何协议,例如,具有适当时序的I2C协议。

使用更少的时钟,结合同步时钟使能信号,可以更轻松地设置Static Timing Analysis (STA),还可以避免重置同步问题Clock Domain Crossing (CDC)

答案 1 :(得分:2)

在这样的系统中处理重置的有效方法如下:

使用Xilinx FPGA中的DCM / PLL / MMCM处理输入系统时钟并生成所需的所有输出时钟频率,请记住,对于非常低的频率,您应该使用时钟管理器规格内的时钟和生成时钟使能信号以与其一起使用。这可以在启动时从主机系统重置,或者在任何时候删除输入时钟然后重新应用。

从时钟管理器反转LOCKED信号,以便在复位或锁定输入时产生高电平有效复位。这应该通过SRL16或SRL32传递以延迟它。在使用BUFG将其置于全局时钟路由之后,应该使用PLL的输出为该SRL提供时钟。在SRL之后使用额外的触发器以改善定时。然后,该信号可用作有源高同步复位,以便在需要它的器件中的其余逻辑。

如果时钟使能信号出现时序错误,因为它是高扇出网络,也可以通过BUFG来访问快速全局时钟网络以改善时序。

答案 2 :(得分:0)

@Stuart Vivian

(这应该作为评论发布,但我没有足够的声誉点这样做,对不起)

考虑使用计数器而不是移位寄存器来延迟复位,因为如果在加载比特流后未清除LUT内容(某些FPGA系列具有此行为),则复位信号可能会反弹,从而导致不可预测的结果。