如何在综合过程中避免锁存器

电器工程 视频文件
2022-01-05 16:58:12

我想使用 VHDL 设计一个组合逻辑块,但有时综合结果包含一个无意的锁存器。

为了避免合成器推断锁存器,我需要遵循哪些编码准则?

示例:在一小段代码中,我应该使用 if-else 语句吗?

4个回答

为避免闩锁,您需要确保将所有输出分配到代码的所有可能分支。

例如,

if a = '1' then
   b(0) <= '1';
else
   b(1 downto 0) <= "00";
end if;

会生成一个锁存器,因为在第一个条件中,没有指定 b(1) 的值,所以编译器决定你想保留之前的 b(1) 值。一种不会产生闩锁的写法是:

if a = '1' then
   b <= prev_b;
   b(0) <= '1';
else
   b(1 downto 0) <= "00";
end if;

...

if rising_edge (clk)
    prev_b <= b;
end if;

在这里,您明确声明 b 应该保留它的旧值,然后用新值覆盖 b(0)。

另一种方法是给 ba 默认值,如@TomiJ 的回答。

如果您发布您正在锁定的代码,我们可以帮助您找到具体原因。

避免闩锁的四个规则:

  • 不要从您写入的信号中读取。
  • 有一个正确的敏感度列表(您阅读的所有信号都应该在敏感度列表中)
  • 确保在每条路径中分配了写入的所有信号。(例如:在 if-else-statement 的每个分支中)
  • 对于使用变量的进程,请确保在读取每个变量之前将其初始化为默认值(在另一个变量或信号中)。

此外,如果您有多个组合过程,请确保不要创建循环。

几种编码风格可以帮助您遵守这些规则,例如@TomiJ 答案中的风格。正如@Martin Thompson 指出的那样,最好同时避免组合逻辑。而是将所有内容都放在一个时钟进程中。

如果您将流程用于组合逻辑(出于这个原因,我建议不要这样做),那么请确保通过流程的每条路径都为流程驱动的每个信号分配了一些东西。任何输出都不能依赖于进程运行的“最后一次”的任何输出。

否则,您会推断出一个锁存器,因为下一次安排该进程时,它必须保留上次未获得新值的信号的值。

我更喜欢将纯组合逻辑保留为连续分配,并将进程用于时钟逻辑,然后我不会得到锁存器。

正如@fbo 和@Martin Thompson 所指出的,您需要确保流程驱动的每个信号在流程的每个分支中都分配有某个值,并且该值不得依赖于任何输出的先前状态的过程。

确保这一点的最简单方法是在流程开始时为每个输出分配一些默认值,例如(选择 fbo 的示例):

COMBO: process(a)
begin
    b <= (others => '0'); -- Assign default value to b
    if a = '1' then
        b(0) <= '1';
    else
        b(1 downto 0) <= "00";
    end if;
end process COMBO;