38

I'm having trouble understanding Kansas Lava's behaviour when an RTL block contains multiple assignments to the same register. Here's version number 1:

foo :: (Clock c) => Signal clk Bool
foo = runRTL $ do
    r <- newReg True
    r := low    
    return $ var r

This behaves as I expected it:

*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .

The generated VHDL is:

architecture str of assignments is
  signal sig_2_o0 : std_logic;
begin
  sig_2_o0 <= '0';
  OUTPUT <= sig_2_o0;
end architecture str;

However, I hoped this other version would also work:

foo = runRTL $ do
    r <- newReg True

    r := low
    r := high
    return $ var r

But it doesn't, and the second assignment isn't taken into account:

*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .

The reason I'm confused is because reg and var are defined in terms of a full clock cycle, so it's not like I could do impossible-to-synthesize things like branch based on r and then reassign a new value to it. So why doesn't this second form work?

It's not just a simulation issue either: the generated VHDL for the second version clearly shows that the second assignment is thrown away at generation time:

architecture str of assignments2 is
  signal sig_2_o0 : std_logic;
begin
  sig_2_o0 <= '0';
  OUTPUT <= sig_2_o0;
end architecture str;

So basically, I would have expected the output to be more like

architecture str of assignments2 is
  signal sig_2_o0 : std_logic;
begin
  sig_2_o0 <= '0';
  sig_2_o0 <= '1';
  OUTPUT <= sig_2_o0;
end architecture str;

but I'm not sure what that would/should mean in VHDL.

4

1 回答 1

3

问题是您正在使用多个非阻塞语句来分配信号。

  sig_2_o0 <= '0';
  sig_2_o0 <= '1';

这转化为:

at next event assign '0' to sig_2_o0.
at next event assign '1' to sig_2_o0.

这与使用阻塞分配不同:

  sig_2_o0 := '0';
  sig_2_o0 := '1';

这将转化为:

assign '0' to sig_2_o0.
assign '1' to sig_2_o0.

阻止分配

当您使用阻塞分配时,值是明确定义的。首先它将设置为“0”,然后用“1”覆盖它。在此示例中,对于仿真或合成硬件,第一个阻塞分配应该没有影响。您可以将其视为第一次分配和第二次分配之间的延迟为 0。这意味着你有一个宽度为 0 的脉冲,这实际上什么都不是。它相当于只有最后一个赋值,第一个完全省略。需要注意的是,如果您对分配进行延迟,例如“1 ns 之后”,那么您会注意到模拟中的第一个分配,然后是第二个分配。在硬件中,延迟被忽略,因此添加延迟不会有任何变化。事实上,出于这个原因,强烈建议不要在打算合成的 RTL 中插入延迟。

非阻塞赋值

但是,当您使用非阻塞分配时,模拟器会为下一次事件安排两个分配。将信号设置为“1”,同时将其设置为“0”。那么信号将采用哪个预定任务呢?没有办法知道。它可能是任何一个值,因为它被错误地分配了。当遇到像这样的多个非阻塞分配时,地球上的每个 lint 检查器和综合工具都应该抛出错误。可以模拟它,但显然 RTL 存在问题。

于 2013-07-08T09:44:25.957 回答