我几乎总是在VHDL中遇到这个问题,它可能与我的思维方式有关; 所以我希望有人能指出正确的思考方式.
无论如何,我开始需要一个变量(或者更确切地说,一个"寄存器"),如果启用信号说低,它基本上会复制输入信号的值 - 如果使能则保持它的"最后"值信号很高.(现在我写了这个,我看到,隐含地,这里的采样将发生在使能信号的上升沿 - 从低到高的过渡;因为只要使能为低有效,那么对于任何小的增量,输入传播到寄存器,因此"覆盖"从"先前"增量时间设置的值.
所以,我的第一次尝试通常是最简单的 - 在我的VHDL文件中放置这样的东西:
wdata_reg <= wdata_in when (en_n = '0');
Run Code Online (Sandbox Code Playgroud)
...这意味着一个非时钟/异步电路 - 虽然我确实得到了我期望的模拟结果,ISE WebPack的xstsythnesizer,例如barfs:
WARNING:Xst:737 - Found 8-bit latch for signal <wdata_reg>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
然后,我想我刚刚描述的(非时钟/异步'采样'寄存器) - 根据定义,是一个锁存器?所以,我不确定我是否想要那里.
另一方面(如果我没记错的话)我曾经曾尝试在状态机中编写这样的代码(所以,钟表):
...
IF en_n = '0' THEN
wdata_reg <= wdata_in;
END IF;
...
Run Code Online (Sandbox Code Playgroud)
......而且,我相信,编译器并没有抱怨这一点(它按预期工作).
所以,我想,我的问题可以提出为:每当我需要"采样"到寄存器中时,我是否应该始终在状态机(或时钟电路)中进行 - 或者是否有替代方案?例如,我可以尝试欺骗" 不完整的...... if语句 ",如下所示:
wd_read_o <= d_io when (wrd_n = '0') else wd_read_o;
Run Code Online (Sandbox Code Playgroud)
...(换句话说:......否则将自己分配给自己) - 但是编译器通过我的noobery看到了,并且WARNING:Xst:737无论如何吐出了ole :)
我会很感激如何考虑这个问题的一些指导 - 所以每次我需要注册时我都不会陷入这种困境:)干杯!
所以,我的第一次尝试通常是最简单的 - 在我的VHDL文件中放置这样的东西:
wdata_reg <= wdata_in when (en_n = '0');
Run Code Online (Sandbox Code Playgroud)
是的,这是一个经典的锁扣.当en_n为零时,它是一条线,当它是一个时,wdata_reg将保持它的值,因为没有任何东西在驱动它.
然后,我想我刚刚描述的(非时钟/异步'采样'寄存器) - 根据定义,是一个锁存器?所以,我不确定我是否想要那里.
锁存仅在跨越时钟域时非常有用,以避免出现毛刺.一般来说,你不需要它们.
时钟进程内的版本将生成一个寄存器,因为它是时钟(惊喜!).您现在有两个信号,一个时钟和一个启用.就VHDL而言,差异在于一个分配连续发生(锁存器),一个仅在时钟边沿(寄存器)发生
所以,我想,我的问题可以提出为:每当我需要"采样"到寄存器中时,我是否应该始终在状态机(或时钟电路)中进行 - 或者是否有替代方案?
它需要处于计时过程中.寄存器需要一个时钟.
例如,我可以尝试欺骗"不完整的...... if语句",如下所示:
wd_read_o <= d_io when (wrd_n = '0') else wd_read_o;
Run Code Online (Sandbox Code Playgroud)
这与以前完全相同.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;
Run Code Online (Sandbox Code Playgroud)
如果该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;
Run Code Online (Sandbox Code Playgroud)
现在next_reg_b总是分配到,无论状态wibble和wobble.没有闩锁.