与堪萨斯熔岩RTL块相同的寄存器的多个分配
当RTL
块包含多个赋值给同一个寄存器时,我无法理解堪萨斯熔岩的行为。 这是版本号1:
foo :: (Clock c) => Signal clk Bool foo = runRTL $ do r <- newReg True r := low return $ var r
这performance得如我所料:
*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
这样基于r
分支来合成它,然后重新分配一个新的值。 那么为什么这个第二种forms没有工作?
这不仅仅是一个模拟问题:为第二个版本生成的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中会有什么意思。
问题是你正在使用多个非阻塞语句来分配信号。
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纳秒后”,那么你会注意到第一次分配,然后是第二次分配。 在硬件上,延迟被忽略,所以不会因为延迟而增加。 实际上,由于这个原因,强烈build议在RTL中插入意图合成的延迟。 硬件与模拟相匹配是非常理想的,并且增加延迟会引起不匹配。
非阻塞分配
但是,当您使用非阻塞分配模拟器有两个分配计划下一次事件。 将信号设置为“1”,同时将其设置为“0”。 那么信号将采用哪个预定分配? 没有办法知道。 由于分配不正确,这可能是任何值。 当遇到这样的多个非阻塞任务时,地球上的每一个棉绒检查器和综合工具都应该抛出一个错误。 有可能模拟它,但RTL显然存在问题。