微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > FPGA 时序收敛

FPGA 时序收敛

时间:09-24 来源:互联网 点击:

阶梯的前几级进行了’与’运算的梯形采样降低此问题的发生几率。

  data_proc : PROCESS (sys_clk)

  BEGIN

  if rising_edge(sys_clk) then

  reset_1 = reset;

  reset_2 = reset_1 and reset;

  sys_reset = reset_2 and reset_1

  and reset;

  end if;

  if rising_edge(sys_clk) then

  if (sys_reset = ‘1’) then

  data_in = ‘0’;

  else

  data_in = serial_in;

  end if;

  end if;

  END PROCESS data_proc;

  至此,假定您已经慎重实现了所有逻辑的同步化。不过,如果您不小心,则您的逻辑很容易与系统时钟脱节。切勿让您的工具链使用系统时钟所用的本地布线资源。那样做的话您就无法约束自己的逻辑。切记要明确定义所有的重要逻辑。

  以下 VHDL 代码采用赛灵思 BUFG 原语强制 sys_clk 进入驱动低延迟网络 (low-skew net) 的专用高扇出缓冲器

  gclk1: BUFG port map (I => sys_clk,O

  => sys_clk_bufg);

  data_proc : PROCESS (sys_clk_bufg)

  BEGIN

  if rising_edge(sys_clk_bufg) then

  reset_1 = reset;

  reset_2 = reset_1 and reset;

  sys_reset = reset_2 and reset_1

  and reset;

  end if;

  if rising_edge(sys_clk_bufg) then

  if (sys_reset = ‘1’) then

  data_in = ‘0’;

  else

  data_in = serial_in;

  end if;

  end if;

  END PROCESS data_proc;

  某些设计采用单个主时钟的分割版本来处理反序列化数据。以下 VHDL 代码(nibble_proc进程)举例说明了按系统时钟频率的四分之一采集的数据。

  data_proc : PROCESS (sys_clk_bufg)

  BEGIN

  if rising_edge(sys_clk_bufg) then

  reset_1 = reset;

  reset_2 = reset_1 and reset;

  sys_reset = reset_2 and reset_1

  and reset;

  end if;

  if rising_edge(sys_clk_bufg) then

  if (sys_reset = ‘1’) then

  two_bit_counter = "00";

  divide_by_4 = ‘0’;

  nibble_wide_data = "0000";

  else

  two_bit_counter

  = two_bit_counter + 1;

  divide_by_4 = two_bit_counter(0) and

  two_bit_counter(1);

  nibble_wide_data(0)

  = serial_in;

  nibble_wide_data(1)

  = nibble_wide_data(0);

  nibble_wide_data(2)

  = nibble_wide_data(1);

  nibble_wide_data(3)

  = nibble_wide_data(2);

  end if;

  end if;

  END PROCESS data_proc;

  nibble_proc : PROCESS (divide_by_4)

  BEGIN

  if rising_edge(divide_by_4) then

  if (sys_reset = ‘1’) then

  nibble_data_in = "0000";

  else

  nibble_data_in

  = nibble_wide_data;

  end if;

  end if;

  END PROCESS nibble_proc;

  看起来好像一切都已经同步化,但是 nibble_proc 采用乘积项 divide_by_4 对来自时钟域sys_clk_bufg 的 nibble_wide_data 进行采样。由于路由延迟,divde_by_4 与 sys_clk_bufg 之间并无明确的相位关系。将 divide_by_4 转移到 BUFG 也于事无补,因为此进程会产生路由延迟。解决方法是将 nibble_proc 保持在 sys_clk_bufg 域,并且采用 divide_by_4 作为限定符,如下所示。

  nibble_proc : PROCESS (sys_clk_bufg)

  BEGIN

  if rising_edge(sys_clk_bufg) then

  if (sys_reset = ‘1’) then

  nibble_data_in = "0000";

  elsif (divide_by_4 = ‘1’) then

  nibble_data_in

  = nibble_wide_data;

  end if;

  end if;

  END PROCESS nibble_proc

  时序约束的重要性

  如果您希望自己的逻辑正确运行,则必须采用正确的时序约束。如果您已经慎重确保代码全部同步且注册了全部 I/O,则这些步骤可以显著简化时序收敛。在采用上述代码并且假定系统时钟为100MHz 时,则只需四行代码就可以轻松完成时序约束文件,如下所示:

  NET sys_clk_bufg TNM_NET =

  sys_clk_bufg;

  TIMESPEC TS_sys_clk_bufg = PERIOD

  sys_clk_bufg 10 ns HIGH 50%;

  FFSET = IN 6 ns BEFORE sys_clk;

  FFSET = OUT 6 ns AFTER sys_clk;

  请注意:赛灵思 FPGA 中 I/O 注册逻辑的建立与保持时间具有很高的固定性,在一个封装中切勿有太大更改。但是,我们仍然采用它们,主要用作可确保设计符合其系统参数的验证步骤。

  三步简单操作

  仅需遵循以下三步简单操作,设计人员即可轻松实施可靠的代码。

  ? 切勿让综合工具猜测您的预期。采用赛灵思原语对所有 I/O 引脚和关键逻辑进行明确定义。确保定义 I/O 引脚的电气特性;

  ? 确保逻辑 100% 同步,并且让所有逻辑参考主时钟域;

  ? 应用时序约束确保时序收敛。

  只要遵循上述三个步骤,您就能够消除综合与时序导致的差异。扫除这两个主要障碍会让您获得具有 100% 可靠性的代码。


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top