答案 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_b
和wibble
的状态如何,始终会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';