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;

但是,如果我尝试这个并在模拟期间查看波浪,我们会延迟一个 wclk 周期。我想要实现的只是在 tpwe的上升沿采样wclk并保持稳定直到下一个上升沿。然后我将锁存的信号分配给架构中定义的另一个实体端口映射。

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

好吧,我发现我必须省略wclk'event以获得闩锁而不是触发器。这对我来说似乎很不直观。通过简单地缩短我对要锁存的信号进行采样的时间,我从锁存器到触发器。谁能解释为什么会这样以及我的看法是错误的。(我是一个 vhdl 初学者)

4

3 回答 3

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) thenor ,这里if falling_edge(wclk) then有一篇很好的博客文章说明了原因。

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

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

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

一般来说,应该避免使用闩锁,因此如果您发现自己需要一个闩锁,您或许应该停下来考虑一下您的方法。Doulos 在这里这里有几篇关于闩锁的文章,您可能会发现它们很有用。

你说你想要实现的只是we在上升沿采样wclk并保持稳定直到下一个上升沿。以下过程将完成此操作:

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

在此过程中,lwewe在每个上升沿更新 的值,wclk并将在单个时钟周期内保持有效。

让我知道这是否可以为您解决问题。

于 2012-09-29T15:00:58.683 回答
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 中的相关主题,请参阅Verilog 综合中的非阻塞分配,Coding Styles That Kill

于 2012-09-29T15:01:30.740 回答
1

根据您的描述,您拥有的过程就是您想要的,尽管“我们”应该从敏感列表中删除。如果这不起作用,你认为它应该几乎肯定是你的测试台/模拟的问题。(请参阅欧文的回答。)具体来说,您可能太迟更改“我们”的值,因此触发器会锁存前一个值而不是新值。

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

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

于 2012-10-01T11:05:12.777 回答