当RTL
块包含对同一寄存器的多个赋值时,我无法理解Kansas Lava的行为。这是版本号1:
foo :: (Clock c) => Signal clk Bool
foo = runRTL $ do
r <- newReg True
r := low
return $ var r
这表现得像我预期的那样:
*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .
生成的VHDL
是:
architecture str of assignments is
signal sig_2_o0 : std_logic;
begin
sig_2_o0 <= '0';
OUTPUT <= sig_2_o0;
end architecture str;
但是,我希望其他版本也可以使用:
foo = runRTL $ do
r <- newReg True
r := low
r := high
return $ var r
但事实并非如此,第二项任务未被考虑在内:
*Main> takeS 10 foo :: Seq Bool
low | low | low | low | low | low | low | low | low | low | ? .
我感到困惑的原因是因为reg
和var
是根据一个完整的时钟周期定义的,所以我不可能做到不可能合成诸如基于{的分支之类的东西{1}}然后为其重新分配新值。那么为什么第二种形式不起作用呢?
这不仅仅是一个模拟问题:第二个版本生成的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;
但是我不确定在VHDL中它会/应该是什么意思。
答案 0 :(得分: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显然存在问题。