使用Kansas Lava对RTL块中的同一寄存器进行多次分配

Cac*_*tus 38 haskell lava vhdl

当一个RTL块包含对同一个寄存器的多个赋值时,我无法理解Kansas Lava的行为.这是版本号1:

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

这表现得像我预期的那样:

*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .
Run Code Online (Sandbox Code Playgroud)

生成的VHDL是:

architecture str of assignments is
  signal sig_2_o0 : std_logic;
begin
  sig_2_o0 <= '0';
  OUTPUT <= sig_2_o0;
end architecture str;
Run Code Online (Sandbox Code Playgroud)

但是,我希望其他版本也可以使用:

foo = runRTL $ do
    r <- newReg True

    r := low
    r := high
    return $ var r
Run Code Online (Sandbox Code Playgroud)

但事实并非如此,第二项任务未被考虑在内:

*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .
Run Code Online (Sandbox Code Playgroud)

我之所以感到困惑的原因是因为regvar是根据一个完整的时钟周期定义的,所以我不可能做不可能合成诸如基于分支的事情r,然后重新分配一个新的值.那么为什么第二种形式不起作用呢?

这不仅仅是模拟问题:VHDL为第二个版本生成的内容清楚地表明第二个赋值在生成时被抛弃:

architecture str of assignments2 is
  signal sig_2_o0 : std_logic;
begin
  sig_2_o0 <= '0';
  OUTPUT <= sig_2_o0;
end architecture str;
Run Code Online (Sandbox Code Playgroud)

所以基本上,我希望输出更像

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;
Run Code Online (Sandbox Code Playgroud)

但我不确定在VHDL中它会/应该是什么意思.

tra*_*ley 3

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

  sig_2_o0 <= '0';
  sig_2_o0 <= '1';
Run Code Online (Sandbox Code Playgroud)

这可以翻译为:

at next event assign '0' to sig_2_o0.
at next event assign '1' to sig_2_o0.
Run Code Online (Sandbox Code Playgroud)

这与使用阻塞分配不同:

  sig_2_o0 := '0';
  sig_2_o0 := '1';
Run Code Online (Sandbox Code Playgroud)

这将翻译为:

assign '0' to sig_2_o0.
assign '1' to sig_2_o0.
Run Code Online (Sandbox Code Playgroud)

阻塞分配

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

非阻塞分配

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