2017-10-29 55 views
1

我知道,对于2个总是具有相同触发器的块,它们的评估顺序是完全不可预知的。在Verilog中总是在块中触发块的评估顺序?

然而,假设我有:

always @(a) begin : blockX 
c = 0; 
d = a + 2; 
if(c != 1) e = 2; 
end 

always @(a) begin : blockY 
e = 3; 
end 

always @(d) begin : blockZ 
c = 1; 
e = 1; 
end 

假设块X评估第一。在blockX中更改d是否会立即跳转到blockZ?如果不是,blockZ是否就blockY进行了评估?

我的程序员的本能认为堆栈中的事件序列,其中评估blockX就像是一个函数调用blockZ,我立即跳到代码中,然后完成评估blockX。但是,因为我们称之为活动事件队列,所以这是一个队列,这表明blockZ被排队在活动事件队列的后面,我100%保证它会被最后评估(除非有其他的总是触发块)。

还有中间可能性,它既不是第一个也不是最后一个,但也是以随机和不可预测的顺序进行评估。

那么在这个例子中,根据编译器在运行时的感觉如何,e,所有可能的最终值是1,2或3吗?

此外,虽然我明白,当然,这代表了糟糕的风格,我在哪里可以找到这种behvaior规范?

+1

是否总是@(a):blockX begin'有效的语法?我认为它必须是'始终@(a)begin:blockX'(在verilog 2001中,无论如何) – Eric

+0

正如你所说的,这是一种糟糕的风格 - 第一个块应该在其敏感列表中包含“c” '*' - 然后问题就变得没有意义了。 – Eric

+0

我认为这个问题更多的是充分理解系统行为的精神,而不是制作实际的代码。 就像介绍性的编程类一样,要求学生用指向指针的(更有用的)指针跟踪代码并评估某些表达式的结果。这有点多用了,但这个练习足够迂回,清楚地表明意图是严格教学的。 另外,@Eric,感谢语法catch! – Dragonsheep

回答

1

总是块不是函数调用。看到我刚刚给了一个类似的问题recent answer。这些块是并发进程。 LRM只保证begin/end区块内的报表的排序。在同时执行begin/end块之间没有定义的顺序(请参阅第4.7节“1800-2012 LRM中的非确定性”)因此,模拟器可以以任何方式自由地交织语句,只要它能够在单个块内完成顺序即可。

所以你是正确的,e可能有最终值1,2或3取决于模拟器如何决定实现和优化你的代码。