Verilog :无法理解生成的模拟(延迟、阻塞/非阻塞)



我正在学习Verilog语言(我已经使用了VHDL),我不理解以下代码的模拟:

module exam2011;
integer a,b,c,d;
always
begin
c = #1 a; 
#2 b=a;
d = a;
end
initial
begin
     a = 0; b = 0; c = 0; d = 0;
     #1 a=1;
     #2 a=2;
     #2 a=3;
     #2 a=4;
     #2 a=5;
end
initial $monitor($time, “a=%d, b=%d, c=%d, d=%d”,a,b,c,d);
endmodule

结果:

#                    0a=          0, b=          0, c=          0, d=          0
#                    1a=          1, b=          0, c=          x, d=          0
#                    3a=          2, b=          1, c=          x, d=          1
#                    4a=          2, b=          1, c=          1, d=          1
#                    5a=          3, b=          1, c=          1, d=          1
#                    6a=          3, b=          3, c=          1, d=          3
#                    7a=          4, b=          3, c=          3, d=          3
#                    9a=          5, b=          5, c=          3, d=          5
#                   10a=          5, b=          5, c=          5, d=          5

首先,我不知道我的想法是否正确:当我们同时改变"a"的值和"b"one_answers"d"的值(它们是"a")时,这些改变是如何执行的?另外,我真的不明白如何解释分配"="之后的延迟命令#。

谢谢你的帮助。

输出始终取决于模拟器。'always'和'initial'语句并行执行。尽管它在我们看来是并行的,但它是由模拟器在相同的时间戳中按顺序执行的。

当前时间戳中的所有事件完成后,模拟器将增加时间戳。在你的代码中,看起来'always'语句是在'initial'语句之前执行的。让我试着解释清楚一点。

c = #1 a;

这个语句等价于

temp = a; //sample the value of 'a'
#1;       // Wait for 1 unit of time
c = temp; //assign the sampled value to 'c'

由于'always'语句第一次进入模拟器队列,它将'a'的值采样为'x',并在第0次将其存储在临时变量中。然后,它进入'initial'语句,并将'a','b','c'和'd'赋值为0。在#1时间单元之后,在'always'语句中将'a'的采样值'x'赋值给'c'。

#2 b = a;

这个语句等价于

#2 //Wait for 2 time unit
b = a //sample the value of 'a' and assign to b

在3个时间单位之后,由于'always'块位于模拟器队列的顶部,'a'的值仍然是'1',它被分配给'c'。在这个'initial'语句被执行之后,'2'的值被赋给'a'。其余的输出以相同的方式表现。

如前所述,Output取决于模拟器。我认为对于时间戳#9,"initial"块首先进入模拟器队列。所以它把a更新为5。在同一时间戳中,'always'块在'initial'块之后执行。所以'c'和'd'被赋予了'a'的更新值'5'。

由于时间戳仍然是#9,因此对'a'的值'5'进行采样并存储在临时变量中。这后来被分配给时间戳#10的"c"。希望这能说得通。

所以这不是一个好的编码方式。这将导致模棱两可的结果。为了说明这个模棱两可的结果,我可以举一个例子。考虑以下代码。

always@(posedge clk)
begin
cnt = cnt+1;
end
always@(posedge clk)
begin
A = cnt;
end

如果初始值为40,下一个时钟周期A的值是多少?看,现在输出依赖于模拟器。它取决于哪个'always'块首先进入模拟器队列。如果第一个'always'块首先执行,则'A'的值为'41',否则为'40'。这可以通过使用非阻塞语句"<="来消除。

always@(posedge clk)
begin
cnt <= cnt+1;
end
always@(posedge clk)
begin
A <= cnt;
end

现在'A'将是40不管模拟器。希望这对你有所帮助。

最新更新