我几乎总是在VHDL中遇到这个问题,这可能与我的思维方式有关。因此,我希望有人可以指出正确的思考方式。
无论如何,我比平时更多地开始需要一个变量(或更确切地说,是一个“寄存器”),如果使能信号为低电平,它将基本上复制输入信号的值-如果使能信号,则将其保持为“最后”值信号高。 (现在,我已经写了这篇文章,我隐含地看到,此处的采样将发生在使能信号的上升沿(从低到高的过渡)上;因为只要使能处于低电平有效,那么对于任何小增量,输入传播到寄存器,因此“覆盖”“上一个”增量时间中设置的值)。
因此,我的第一次尝试通常是最简单的方法-将这样的内容放入我的VHDL文件:
wdata_reg <= wdata_in when (en_n = '0');
...这表示电路为非时钟/异步电路-在获得仿真结果的同时,ISE WebPack的
xst
合成器也得到了预期的效果,例如,带有以下内容的barfs:再说一遍,我想我刚刚描述的(非时钟/异步“采样”寄存器)-从定义上来说是一个锁存器?因此,我不确定是否要在那儿。
另一方面(如果我没记错的话),我曾经也试图在状态机中编写这样的代码(因此,计时):
...
IF en_n = '0' THEN
wdata_reg <= wdata_in;
END IF;
...
...,而且我相信,编译器对此没有提示(并且按预期工作)。
因此,我想,我的问题可能是:只要我需要“采样”到寄存器中,我是否应该总是在状态机(或时钟电路)中进行操作-还是有替代方法?例如,我可以尝试欺骗“incomplete ... if语句”,如下所示:
wd_read_o <= d_io when (wrd_n = '0') else wd_read_o;
...(换句话说:...否则将自己分配给自己)-但是编译器会透漏我的盲目性,无论如何都会吐出ole
WARNING:Xst:737
:)对于如何考虑这一问题,我将不胜感激-因此,每次我需要注册时,我都不会遇到这个难题:)干杯!
最佳答案
wdata_reg <= wdata_in when (en_n = '0');
是的,这是一个经典的闩锁。当en_n为零时,它是一条线;当它为1时,wdata_reg将保持其值,因为没有任何驱动力。
锁存器仅在跨时钟域时才真正有用,以避免出现毛刺。通常,您不想要它们。
计时进程中的版本将产生一个寄存器,因为它是计时的(惊奇!)。现在,您涉及到两个信号,一个时钟和一个启用信号。就VHDL而言,不同之处在于,一种分配是连续发生的(锁存器),而另一种分配只在时钟沿(寄存器)发生
它需要处于一个定时的过程中。寄存器需要一个时钟。
wd_read_o <= d_io when (wrd_n = '0') else wd_read_o;
这和以前完全一样。 else子句是在先前版本中推断的。重要的一点是,当wrd_n为零时,d_io上的任何转换都将发生在wd_read_o上,这不是寄存器的行为。这是一个闩锁。
寄存器具有时钟,因此必须处于时钟控制状态。简单的。
(原谅重复)
推导无意义锁存器的另一种常见方法是,如果您有一个异步过程,该异步过程的路径是is,它不会更新信号。
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
分配给它。无闩锁。