2012-09-29 102 views
1

我想锁定一个信号,但是当我尝试这样做时,我得到一个周期的延迟,我该如何避免这种情况?无延迟锁存信号

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; 

但是,如果我尝试这一点,看看海浪模拟LWE期间由WCLK的一个周期延迟。我想要达到的目标是在wclk的上升沿对we进行采样,并保持稳定直到下一个上升沿。然后,我将锁定信号分配给架构中定义的另一个实体端口映射。

==============================================

嗯,我发现我必须省略wclk'event才能获得锁存器而不是触发器。这对我来说似乎相当不直观。通过简单地缩短我采样锁存信号的时间,我从锁存器变成触发器。任何人都可以解释为什么这是和我的看法是错误的。 (我是VHDL的初学者)

回答

2

首先,你在上面粘贴过程中的几点看法:

myLatch: process(wclk, we) 
begin 
    if wclk'event and wclk = '1' then 
    lwe <= we; 
    end if; 
end process; 
  1. 信号我们可以从敏感列表被省略,因为你所描述一个钟表过程。如果您选择使用一个进程(同步重置不需要添加到灵敏度列表中),那么此类进程的灵敏度列表中所需的唯一信号是时钟和异步复位。

  2. 而不是使用if wclk'event and wclk = '1' then你应该使用if rising_edge(wclk) thenif falling_edge(wclk) then的,有一个在原因here一个很好的博客文章。

通过省略wclk'event从时钟控制处理改变的过程中,以一个组合过程中,像这样:

myLatch: process(wclk, we) 
begin 
    if wclk = '1' then 
    lwe <= we; 
    end if; 
end process; 

在一个组合过程中的所有输入应存在于灵敏度列表,以便在列表中有wclkwe是正确的,因为它们对输出有影响。通常情况下,您应确保lwe在您的if语句的所有情况下都被分配以避免推断闩锁,但这似乎是您在这种情况下的打算。

锁存器一般应该避免,所以如果你发现自己需要一个,你应该停下来考虑一下你的方法。 Doulos有几篇有关闩锁herehere的文章,您可能会觉得有用。

您声明所有您想要实现的是在wclk的上升沿对we进行采样,并保持稳定直到下一个上升沿。下面的过程将做到这一点:

store : process(wclk) 
    begin 
    if rising_edge(wclk) then 
     lwe <= we; 
    end if; 
    end process; 

有了这个过程中,lwe将与we后的wclk每个上升沿的值进行更新,并保持有效的一个时钟周期。

让我知道,如果这清除了你的东西。

+0

这对我来说非常有价值,我将不得不调查为什么要避免闩锁部分。但如果不确定的话,我不得不提出一个新的问题。由于我只是为一个寄存器文件写一个子模块,并且不能改变外部模块的时序,所以我看不到任何方式的锁定(Studentassignment,实现一个带有单端口RAM的寄存器文件) – ted

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

1

你有这个过程是你根据你的描述想要的东西,但“我们”应该从灵敏度列表中删除。如果这不起作用,你认为它应该是你的测试台/仿真几乎肯定是一个问题。 (请参阅Owen的答案)具体而言,您可能很晚才更改“我们”的价值,以便触发器锁定之前的值而不是新的值。

我很想知道这个信号的来源是什么,如果它是一个异步信号,可以随时改变,你将不得不添加一些逻辑来防止亚稳态。

要回答关于锁存器的第二个问题,省略wclk'event将导致锁存器是正确的。然而,这个过程不会做你想做的事情,因为它会在整个时钟的正半周期间将'我们'的变化传播到'lwe'。你的问题的简短答案是实现这种行为需要一个锁存器,而原始过程描述的行为需要一个触发器。