假设我在Verilog中有以下代码:
module A (clk,a,c);
input clk;
input a;
output c;
wire clk;
wire a;
reg c;
reg b;
always @(posedge clk)
begin
b = a;
c = b;
end
endmodule
让我们假设这个模块实现了一些Flip Flop,它有两个输入(a和clk)并且有一个输出(c)
我已经读过operator =和operator< =之间的主要区别在于当使用operator =时,命令是按顺序依次执行的(意思是:b得到a和c的值得到了b)的值,当使用运算符< =命令在同一时间执行时(意思是:b得到a的值,c得到b的值)。
现在,我的问题是:
我可以说,如果我们使用operator =然后b得到a的新值,c得到b的旧值(当前一个时钟周期内的值) 如果我们使用运算符< =然后b得到a的新值,c也得到a的新值?
不知何故,这对我来说是有意义的,但在这两种情况下,c的值应该是当前时钟周期中收到的a,这是一个总是阻塞意义
谢谢你, 迈克尔
答案 0 :(得分:0)
Verilog模拟由与事件相关的微步(或delta周期)组成。事件实际上是变量值的任何变化,导致重新评估其他块。因此,增量循环是一个需要模型静止的步骤。
增量循环本身由多个调度桶组成,在循环中一个接一个地执行。在非常简化的视图中,至少有一个阻塞桶和非阻塞桶。所有阻塞分配都在第一个桶中进行评估,所有阻塞分配都在第二个桶中进行评估。
所以,在你的情况下
always @(posedge clk)
begin
b = a;
c = b;
end
b
在第一个广告资源中得到评估,c
也是如此,因此它变为a
的值。因此,a
为1,则b
的值为1,第一个存储区中的值c
也将变为“1”。
你使用非阻塞分配,verilog将在第一个桶中运行,但它只会安排在第二个桶中执行非阻塞分配。所以,在这段代码中
always @(posedge clk)
begin
b <= a;
c <= b;
end
b
将被安排在第二个桶中获得a
int的值,c
将被安排在第二个桶中成为b
的值。但是后者安排分配当前值b
,而不是将在第二个桶中评估的值。
因此,在上述情况下,a
的值为1,b
的值为0,c
将在第二个存储桶中变为 0 。
当然,如果c
导致更多第一桶类型的事件,则verilog将返回第一个存储桶并再次评估所有事件。实际上,在verilog中有超过2个桶,在系统verilog中有更多桶。
使用阻止和非阻塞分配以及为什么它们存在于verilog中有一定的推理。但为简单起见,您应该遵循一个简单的方法:所有输出状态元素,如触发器和锁存器必须使用非阻塞分配进行分配,所有组合逻辑和时钟都应使用阻塞分配。这样可以避免对种族和毛刺效应进行整齐的调试。因此,在您的情况下,假设b
只是翻牌中的中间节点,应使用以下代码:
always @(posedge clk)
begin
b = a;
c <= b;
end
在这种情况下,b
将在第一个桶中立即变为a
的值,但是根据该阻塞分配,将使用非阻塞分配来分配此触发器c
的输出。全行业的方法论,
答案 1 :(得分:0)
当您使用阻塞分配时,块中的引用(读取)与赋值(写入)的顺序会对其实现产生影响。在您的示例中,您对b
进行了写入,然后将其读取。所以b
本质上是一个表示组合逻辑的临时变量。但是如果你在变量写入块之前读取变量,则可以获得上一个循环中的值;触发器的输出。
使用非阻塞分配时,顺序不再重要 - 您始终从上一个循环中获取值。这就是为什么当一个块写入时有多个始终为@(posedge clock)
且其他块读取相同变量时必须使用非阻塞赋值的原因,您总是从上一个循环中获取值。如果您要使用阻塞分配,则在模拟中,读取和写入之间没有保证的顺序。