Verilog。寄存器的使用。数值到底什么时候更新?

问题描述 投票:0回答:1

在Verilog中,一个总是块内的变量到底什么时候更新?例如,如果在一个总是块中多次改变reg C:它的值是否总是改变?还是只有在always-block结束时才将值 "物理写入 "reg?

使用一个额外的中间寄存器是否会更好,它只在always-block结束时被实际化?这有什么不同吗?

reg C;

always @(*)
C = 0;
C = A;
C = 1;
C = B;
end

其他例子:如果我有一个总是块的模块,如下图所示,输出的多次赋值会不会出现故障,在得到B的值之前,输出很快就变成了0?如果我使用阻塞(=)或非阻塞(<=)赋值,是否会有区别?

module example1 (output C, input A, input B);

always @(*)
begin
 C = 1’b0;
 if (A==1)
   C = B ;
end
endmodule

用中间寄存器举例,以避免输出发生不必要的变化。

module example1 (output C, input A, input B);

reg intermediateReg;

always @(*)
begin
 intermediateReg = 1’b0;
 if (A==1)
   intermediateReg = B ;
end
   C <= intermediateReg;
endmodule
variables verilog updating
1个回答
0
投票

在你提供的例子中,代码的行为与'c'代码相同。变量被重新分配新的值,最后一个值获胜。在verilog中,这对于阻塞(=)或非阻塞(<=)赋值是正确的,但对于它们的混合赋值则不正确。

就像在'c'中一样,这取决于编译器的优化技术。它可以消除不需要的赋值,所以只有最后一个是相关的。

在你的第一个例子中,'C'的值将在块的最后成为'B'。在第二个例子中,'C'的值要么是 0B根据 A.

.现在,为了简单的解释,挡拆和非挡拆的混合分配会导致最后的'非挡拆'分配获胜。原因是所有的nba都是执行的。之后 块完成。

always @(*) begin
   C <= A;
   C = B;
end

块的 C 将是 A 在模拟周期结束时。

至于使用中间值的问题,没有区别。你根据需要使用它们。仿真编译器或合成器在任何情况下都会优化你的代码。最后一个例子是绝对正常的,只是它根本没有改变任何东西。它的行为和这个一样,在我看来,它更明确,更易读。唯一的问题是,你错误地使用了nba assignments int组合逻辑(我修正了)。

always @(*)
begin
 if (A==1)
   C = B ;
 else
   C = 1'b0;

我想你的帖子里还有一个沉默的问题,中间值会不会引起'C'上的事件,这种情况下的答案是 没有. 在always块完成执行之前(或遇到延迟或开始等待事件之前),不会有事件产生。所以,只有最后一个值是相关的。

在测试平台的代码中,你可以看到这样的情况。

always @* begin
   C = A;
   C = B;
   #5 C = D;
end

在上面的例子中 C 将成为 B. 始终块的执行将在#5个延迟中停止。在这段时间里,其他块将看到值 B. 在#5个滴答中,该值将被改为 D.


0
投票

如果你想知道标准Verilog中的阻塞和非阻塞赋值是做什么的(就像你在仿真中会有的那样),你可以很容易地查找。

如果你说的是硬件,你得到的硬件类型将取决于灵敏度列表中的内容,而不是你使用的赋值类型。赋值类型会影响从你的代码中合成的组合逻辑。假设你没有做任何不可合成的事情,你得到的逻辑应该等同于Verilog标准规定的内容,但不会是你代码的1:1直接映射。

所以,不,增加中间件不一定能帮助解决硬件中的小故障。会有其他的代码和时序规范等来处理这样的东西。

© www.soinside.com 2019 - 2024. All rights reserved.