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

dav*_*od2 0 asynchronous clock vhdl reset xilinx

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

这些模块使用时钟分频器模块进行计时,该模块获取系统时钟并向系统的其余部分输出较低的频率。

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

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

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

同步复位的约定是什么?时钟发生器一般不复位吗?或者它们仅在复位信号的瞬时边沿复位?或者我的建议都不是真正的解决方案!

我放入了时序图和代码来说明我的意思,并显示我一直在使用的代码。

非常感谢!

大卫

在此输入图像描述

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;
Run Code Online (Sandbox Code Playgroud)

Mor*_*mer 5

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

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

使用更少的时钟,与同步时钟使能信号相结合,可以使静态时序分析 (STA)的设置更加容易,并且还可以避免复位同步和时钟域交叉 (CDC)的问题。

  • 10 MHz 时钟每 100 万个周期置位一次的时钟使能信号可提供 10 Hz 的有效更新率。 (2认同)
  • I2C SCL 时钟只是像控制信号一样生成,并且利用高频基础时钟,仍然可以使用时钟使能的适当更新来生成良好的 50% 占空比 SCL。 (2认同)