我刚开始创建一个FPGA系统来驱动I2C总线(尽管我认为这个问题适用于任何FPGA系统),使用各种不同的模块,这些模块都使用同步复位。
该模块使用时钟分频器模块进行时钟锁定,该分频器模块获取系统时钟,并将较低的频率输出到系统的其余部分。
我遇到的问题是,当复位信号变低时,分频器会重置,因此其他模块依赖于停止的时钟-因此其他模块不会注册重置。
一个明显的解决方案是异步重置,然而,在Xilinx中,它似乎不喜欢它们,并发出警告说这与Spartan-6FPGA不兼容(特别是当异步代码后的代码是同步的,这是因为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;发布于 2015-12-03 14:25:51
不要生成具有用户逻辑的内部时钟,但是如果确实需要多个时钟,则使用特定于设备的PLL/DCM。然后,在导出时钟上运行的所有用户逻辑都应该保持复位状态,直到时钟稳定为止,然后根据设计的要求,可以释放对用户逻辑的重置。可以使用同步复位或异步复位。
但在这种情况下,可能会生成时钟启用信号,并在每次需要更新信号时断言该启用信号为单个周期,以便生成所需的任何协议,例如具有适当定时的I2C协议。
使用较少的时钟,再加上同步时钟启用信号,可以简化静态时序分析(STA)的设置,同时也避免了重置同步和时钟域交叉(CDC)的问题。
发布于 2015-12-04 14:59:46
在这样的系统中,一种处理重置的健壮方法如下:
使用Xilinx FPGA中的DCM/PLL/MMCM处理输入系统时钟并生成所需的所有输出时钟频率,同时考虑到真正的低频,您应该在时钟管理器的规范范围内使用一个时钟,并生成一个与之结合使用的时钟启用信号。这可以在启动时从主机系统重置,或者如果在任何时候输入时钟被移除,然后重新应用。
反转来自时钟管理器的锁定信号,以便在复位时或在锁定到输入端的过程中产生活动的高复位。这应该通过SRL16或SRL32来延迟。这个SRL应该与PLL的输出一起时钟,当它被放在一个BUFG的全局时钟路由上之后。在SRL之后使用额外的触发器来改进计时。然后,该信号可用作对所需设备中的逻辑的其余部分的主动高同步复位。
如果在时钟上出现计时错误,因为它是高扇形网络,那么也可以通过BUFG来访问快速的全球时钟网络来提高定时。
发布于 2015-12-06 23:50:39
@斯图尔特·维维安
(这应该作为评论发布,但我没有足够的声誉点来这么做,对此我很抱歉)
考虑使用计数器而不是移位寄存器来延迟重置,因为如果在加载比特流之后没有清除LUT内容(一些FPGA家族具有这种行为),重置信号可能会反弹,导致不可预测的结果。
https://stackoverflow.com/questions/34067276
复制相似问题