我想锁定一个信号,但是当我尝试这样做时,我会延迟一个周期,我该如何避免这种情况?
myLatch: process(wclk, we) -- Can I ommit the we in the sensitivity list?
begin
if wclk'event and wclk = '1' then
lwe <= we;
end if;
end process;
然而,如果我尝试这个并在模拟期间观察波浪,我们会延迟wclk的一个周期。我想要实现的只是在we
的上升沿采样wclk
并保持稳定直到下一个上升沿。然后,我将锁存的信号分配给另一个实体端口映射,该映射在架构中定义。
============================================== < / p>
好吧我发现我必须省略wclk'event
来获取锁存器而不是触发器。这对我来说似乎不太直观。通过简单地缩短我对要锁存的信号进行采样的时间,我从锁存器到触发器。任何人都可以解释为什么这是我的看法是错误的。 (我是vhdl初学者)
答案 0 :(得分:2)
首先,对您粘贴的流程进行一些观察:
myLatch: process(wclk, we)
begin
if wclk'event and wclk = '1' then
lwe <= we;
end if;
end process;
可以从灵敏度列表中省略 信号,因为您已经描述了一个时钟进程。在这样的过程的灵敏度列表中,唯一需要的信号是时钟和异步复位(如果您选择使用一个)(不需要将同步复位添加到灵敏度列表中)。
您应该使用if wclk'event and wclk = '1' then
或if rising_edge(wclk) then
代替使用if falling_edge(wclk) then
,而是有一篇关于here的原因的博客文章。
通过省略wclk'event
,您将进程从定时进程更改为组合进程,如下所示:
myLatch: process(wclk, we)
begin
if wclk = '1' then
lwe <= we;
end if;
end process;
在组合过程中,所有输入都应该出现在敏感度列表中,因此在列表中同时包含wclk
和we
是正确的,因为它们对输出有影响。通常,您会确保在if语句的所有情况下都分配lwe
,以避免推断锁定,但在这种情况下,这似乎是您的意图。
一般应该避免使用锁存器,因此如果您发现自己需要锁存器,您应该暂停并考虑您的方法。 Doulos在锁here和here上有几篇你可能会觉得有用的文章。
你说你想要达到的只是在we
的上升沿采样wclk
并保持稳定直到下一个上升沿。下面的过程将实现这一目标:
store : process(wclk)
begin
if rising_edge(wclk) then
lwe <= we;
end if;
end process;
通过此过程,lwe
将在we
的每个上升沿使用wclk
的值进行更新,并且在单个时钟周期内保持有效。
请告诉我这是否能为您解决问题。
答案 1 :(得分:2)
信不信由你,问题实际上在你的测试平台上。这与VHDL仿真模型的工作原理有关。
VHDL通常用于同步硬件设计 - 这意味着,使用在上升沿采样的触发器并在下降沿设置输出,这样在读取和写入之间不存在竞争条件。但是在VHDL中,这种主/从逻辑实际上并不是使用相反的时钟边缘来模拟的。
考虑一个过程
process (clock) begin
if rising_edge(clock) then
a <= b;
end if;
end process;
在模拟时间步的开始,如果clock
刚刚上升,if
将会执行。然后将执行赋值a <= b
,这不会立即导致分配,但计划时间步结束时的分配。
运行所有进程后,将进行所有计划的分配。这意味着在下一个时间步之前,任何进程都不会“看到”a
的新值。
Time a b Actions
Start of ts 1 '0' '1' a <= '1' is scheduled
End of ts 1 '1' '0' a <= '1' is executed
Start of ts 2 '1' '0' a <= '0' is scheduled
End of ts 2 '0' '1' a <= '0' is executed
因此,当您查看波形查看器时,您会看到a
显然是在时钟的上升沿设置,并且跟随b
延迟一个时钟周期;你没有看到导致这种情况发生的分配的中间调度。
当然,在现实生活中,没有“时间步长结束”,并且当触发器的从属部分触发时,即在负边缘上时,发生信号a
的实际变化。 (对于VHDL而言,使用负边缘可能不那么令人困惑;但是,哦,这就是它的工作方式)。
以下是您的闩锁代码的两个测试平台:
首先,如果您查看波形查看器,您将看到您所描述的内容 - lwe
似乎延迟了1个时钟周期 - 但实际上,延迟发生在非阻塞中设置counter
的赋值 - 所以当上升沿发生时,we
实际上还没有新的值。在第二个,你没有看到这样的延迟; lwe
正好在上升边设置为当时we
的值。
有关Verilog中的相关主题,请参阅Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill 。
答案 2 :(得分:1)
根据您的描述,您拥有的过程就是您想要的,尽管应该从敏感度列表中删除“我们”。如果这不起作用,你认为它应该几乎肯定是你的测试台/模拟的问题。 (参见欧文的回答。)具体来说,你可能太晚了改变'我们'的值,所以触发器会锁定前一个值而不是新值。
我很想知道这个信号的来源是什么,如果它是一个可以随时改变的异步信号,你将不得不添加一些逻辑来防止亚稳态。
要回答关于锁存器的第二个问题,省略wclk'event将导致锁存器是正确的。然而,这个过程不会做你想要的,因为它会在时钟的整个正半周期间将变化传播到'我们'到'lwe'。对你的问题的简短回答是,实现这种类型的行为需要一个锁存器,而原始过程描述的行为需要一个触发器。