当一个RTL块包含对同一寄存器的多个赋值时,我很难理解堪萨斯熔岩的行为。下面是版本号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是根据完整的时钟周期定义的,所以我不像是可以做一些不可能综合的事情,比如基于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;所以基本上,我希望输出结果更像是
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;但我不确定这在VHDL中意味着什么。
发布于 2013-07-08 17:44:26
问题是您正在使用多个非阻塞语句来分配信号。
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的脉冲,实际上是零。它相当于只有最后一个赋值,第一个赋值完全省略。需要注意的是,如果您在赋值上设置了延迟,例如“在1 ns之后”,那么在模拟中,您将注意到第一个赋值,然后是第二个赋值。在硬件中,延迟被忽略,因此添加延迟不会有任何变化。事实上,出于这个原因,强烈建议在RTL中插入要合成的延迟。硬件与模拟匹配是非常理想的,而添加延迟可能会引入不匹配。
非阻塞赋值
但是,当您使用非阻塞赋值时,模拟器将为下一个时间事件调度两个赋值。将信号设置为“1”,同时将其设置为“0”。那么信号将接受哪种计划的分配呢?没有办法知道。它可能是任何一个值,因为它被错误地分配了。当遇到像这样的多个非阻塞任务时,地球上的每个lint检查器和合成工具都应该抛出一个错误。也许可以对其进行模拟,但RTL显然存在问题。
https://stackoverflow.com/questions/14002159
复制相似问题