锁定信号无延迟

时间:2012-09-29 11:21:34

标签: vhdl

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

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初学者)

3 个答案:

答案 0 :(得分: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' thenif rising_edge(wclk) then代替使用if falling_edge(wclk) then,而是有一篇关于here的原因的博客文章。

    < / LI>

    通过省略wclk'event,您将进程从定时进程更改为组合进程,如下所示:

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

    在组合过程中,所有输入都应该出现在敏感度列表中,因此在列表中同时包含wclkwe是正确的,因为它们对输出有影响。通常,您会确保在if语句的所有情况下都分配lwe,以避免推断锁定,但在这种情况下,这似乎是您的意图。

    一般应该避免使用锁存器,因此如果您发现自己需要锁存器,您应该暂停并考虑您的方法。 Doulos在锁herehere上有几篇你可能会觉得有用的文章。

    你说你想要达到的只是在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'。对你的问题的简短回答是,实现这种类型的行为需要一个锁存器,而原始过程描述的行为需要一个触发器。