VHDL中的“非时钟”采样和锁存

时间:2011-11-01 19:12:19

标签: vhdl

3 个答案:

答案 0 :(得分:5)

  

所以,我的第一次尝试通常是最简单的 - 在我的VHDL文件中加入这样的东西:

  wdata_reg <= wdata_in when (en_n = '0');  
是的,这是一个经典的闩锁。当en_n为零时,它是一条线,当它是一个时,wdata_reg将保持它的值,因为没有任何东西在驱动它。

  

然后,我猜我刚刚描述的内容(非时钟/异步'采样'寄存器) - 根据定义,是一个锁存器?所以,我不确定我是否想要那里。

锁存仅在跨越时钟域时非常有用,以避免出现故障。一般来说,你不需要它们。

时钟进程内的版本会生成一个寄存器,因为它是时钟控制的(惊喜!)。您现在有两个信号,一个时钟和一个启用。就VHDL而言,差异在于一个分配连续发生(锁存器),一个仅在时钟边沿(寄存器)发生

  

所以,我想,我的问题可以提出为:每当我需要“采样”到寄存器中时,我是否应该始终在状态机(或时钟电路)中进行 - 或者是否有替代方案?

它需要处于计时过程中。寄存器需要一个时钟。

  

例如,我可以尝试欺骗“不完整...... if语句”,如下所示:

wd_read_o <= d_io when (wrd_n = '0') else wd_read_o;

这与以前完全相同。 else子句是在先前版本中推断的。重要的一点是,当wrd_n为零时,d_io上的任何转换都将发生在wd_read_o上,这不是寄存器的行为。这是一个闩锁。

  

我很感激如何思考这个问题的一些指导 - 所以每次我需要注册时我都不会遇到这种困境:)干杯!

寄存器有时钟,因此必须在时钟进程中。简单。 (原谅重复)


推断没有意义的锁存器的另一种常见方法是,如果您有一个具有路径的异步进程,则不会更新信号。

p_async : process (wibble, wobble)
begin
  if (wibble = '1' and wobble = '0') then
      next_reg_b <= data_in;
  end if;
end process;

如果if语句不成立,next_reg_b将不会更新,并且必须保持其值。这会产生一个锁存器,因为它需要存储一个值,但不需要锁存器(甚至寄存器),只需要一点逻辑。解决方案是添加默认分配。

p_async : process (wibble, wobble, reg_b)
begin
  next_reg_b <= reg_b;
  if (wibble = '1' and wobble = '0') then
      next_reg_b <= data_in;
  end if;
end process;

无论next_reg_bwibble的状态如何,始终会wobble分配给{{1}}。没有闩锁。

答案 1 :(得分:3)

首先,我将首先阅读锁存器的概述:Why should I care about latches?

您可以使用边沿触发的触发器构建您描述的电路,如下所示。这将在input处于活动状态时传递enable,或者在input处于非活动状态时传递enable的最后一个值。

last_input_set <= input WHEN enable='1' ELSE
                  last_input_reg;
output <= last_input_set;

if rising_edge(clk) then
    last_input_reg <= last_input_set;
end if;

答案 2 :(得分:1)

你(几乎)总是希望寄存器不是锁存器。这意味着您需要一个时钟进程。您可以使用已经为状态机“踢”的一个,或者有时在单独的过程中更可读。

这可能是传统的

process(clk)
begin
  if rising_edge(clk) then
    if en = '1' then
      latched <= raw;
     end if;
  end if;
end process;

或更整洁(如果你正在做的那样):

latched <= raw when rising_edge(clk) and en = '1';