最近有人告诉我,解决 VHDL 合成期间所有(大多数)意外锁存器问题的解决方案是将任何有问题的信号记录在案。
这似乎有点好得令人难以置信,但我对 VHDL 的经验并不多,所以可能还有其他一些我没有考虑的东西。
我应该把我所有的信号都记录下来吗?
不,您不应该将所有信号都记录在案。这将很快变得非常混乱,并且您不会通过使用记录获得任何收益。
记录可以帮助您避免闩锁的一种方法是,如果您在时钟进程中注册整个记录,那么您实际上是在注册记录的所有组件。这需要一行代码,而不是可能的数十行。如果您有许多元素都需要被同等对待,则记录可以为您节省“愚蠢的错误”,并可能使您免于创建闩锁。
正如其他人所说,记录没有任何具体的综合解释。它只是为了编码方便而组合在一起的一组信号。
我看不出这有什么帮助——一条记录(甚至只是记录的一部分)可以像信号一样容易地成为锁存器。如果信号通过某个组合过程保持其状态(即,未在通过该过程的所有路径上分配值),则生成锁存器。这同样适用于记录的组成部分。
记录可用于对相关信号进行分组以提高可读性,但在综合方面,记录几乎等同于一堆单独的信号。
我个人建议避免闩锁:避免组合过程。使所有进程有时钟,并在架构级别执行组合逻辑。
记录只是对其他类型进行分组的另一种方式,类似于使用数组对 a 进行分组std_logic
,std_logic_vector
因此记录没有什么神奇之处可以更好地避免设计中的闩锁。
如果您在设计中遇到意外的闩锁,我猜您认为这是“闩锁问题”,那是因为您的编码风格指定了闩锁,并且您应该更改编码风格,正如@zennehoy 所建议的那样。
一种方法是为您使用的不同结构定义一些代码模板,然后坚持使用这些已知且有效的模板。
具有异步复位的触发器 (FF) 的模板可以是:
process (clk_i, rst_i) is
begin
-- Clock
if rising_edge(clk_i) then
... Control structures with Qs assign by function for Ds
... Synchronous reset is just another branch
end if;
-- Reset (asynchronous) if required
if rst_i = '1' then
... Qs assign with constant reset value for so or all Qs
end if;
end process;
尽可能使用并发信号分配,并且可以通过使用并发函数调用来完成更复杂的表达式,其中函数在进程外部使用,例如:
z_o <= fun(a_i, b_i);
如果一个过程用于创建组合逻辑,那么 VHDL 中锁存器的常见缺陷和原因是忘记敏感列表中的信号。但是,VHDL-2008 对此有一个解决方案,因为您可以将(all)
其用作灵敏度列表,从而将过程中使用的所有信号都隐式包含在灵敏度列表中。因此,如果您使用 VHDL-2008,那么您的组合过程模板可以是:
process (all) is
begin
z_o <= a_i and b_i;
end process;
这些模板应该是典型可综合设计所需的全部,这些模板将使您的设计保持自由。