什么时候使用 "assign" 关键字以及什么时候使用“<=”运算符?
When exactly to use "assign" keyword and when to use "<=" operators?
我正在学习 verilog,我已经阅读了一些教程,但对此我有点困惑:
何时以及为何使用 "assign" 关键字以及何时以及为何使用“<=”运算符。在什么情况下?我很清楚“<=”和“=”之间的区别,非阻塞和阻塞,但除此之外,一些文献开始使用 "assign" 而其他文献甚至不使用此关键字。
示例:
分配 var_z = x|~y
var_z <= a + b
谢谢。
assign
用于 driving wire/net 类型声明。由于电线根据驱动它们的值更改值 ,每当 RHS 上的操作数发生变化时,该值就会被 评估 并分配给 LHS(从而模拟电线)。
只要right-hand侧值发生变化,连续赋值就会将值驱动到网络中,因此连续赋值始终处于活动状态并且只要 right-hand 侧操作数发生变化,就会发生赋值。
连续赋值提供了一个组合逻辑模型比更高的抽象层次 =58=]Gate-Level 逻辑.
always
是一个程序块,用于建模 寄存器 和组合逻辑。 always
块包含 敏感度列表 ,即 事件列表 ,必须评估块内的逻辑。
always(@ posedge clk)
在每个 上升沿 触发块内的逻辑。从而对一种 flop 行为进行建模。
always @ (*)
对 所有 RHS 语句敏感。如果 always 块的 RHS 中的 任何内容 发生变化,则会评估并分配该特定表达式。这类似于 assign
语句,但这种类型的块用于驱动 reg
数据类型。
// var_z needs to be driven continuously
// Evaluated when any of x or y changes
assign var_z = x|~y
有关详细信息,请参阅 assign statement and Continuous assignments。
开始 阻塞和 non-blocking 语句:
A blocking statement must be executed before the execution of the statements that follow it in a sequential block.
Non blocking statements allow you to schedule assignments without blocking the procedural flow.
阻塞和 non-blocking 分配可以通过以下示例更好地理解:
x = #10 5; // x = 5 at time 10ns
y = #5 6; // y = 6 at time 15ns
x <= #10 5; // y = 6 at time 10ns
y <= #5 6; // y = 6 at time 5ns
这里,在阻塞赋值中,y
在x
赋值后求值。在使用 non-blocking 赋值时,、x
和 y
被评估并推入 模拟器 内部队列并分配分别在 10ns
和 5ns
。
阻塞赋值立即生效。非阻塞分配发生在处理当前“时间增量”的结束时。
所以,直觉上,我们可以说,由于组合块需要连续驱动,使用块语句 必须完成。同时,为了对 顺序硬件 进行建模, 持有或保留 一个值,non-blocking 赋值 必须使用。
// model a flop var_z
var_z <= a+b;
管道建模可以通过 non-blocking 分配有效地完成。考虑一个移位寄存器示例:
// Improper hardware, q3 is directly assigned the value of d
always @(posedge clk) begin
q1 = d;
q2 = q1;
q3 = q2; end
// Proper hardware, q3=q2, q2=q1 and q1=d
always @(posedge clk) begin
q1 <= d;
q2 <= q1;
q3 <= q2; end
以上示例在使用非阻塞分配时对适当的硬件进行建模。有关详细信息,请参阅 CummingsSNUG2000SJ_NBA paper, this link。
我正在学习 verilog,我已经阅读了一些教程,但对此我有点困惑:
何时以及为何使用 "assign" 关键字以及何时以及为何使用“<=”运算符。在什么情况下?我很清楚“<=”和“=”之间的区别,非阻塞和阻塞,但除此之外,一些文献开始使用 "assign" 而其他文献甚至不使用此关键字。
示例:
分配 var_z = x|~y
var_z <= a + b
谢谢。
assign
用于 driving wire/net 类型声明。由于电线根据驱动它们的值更改值 ,每当 RHS 上的操作数发生变化时,该值就会被 评估 并分配给 LHS(从而模拟电线)。
只要right-hand侧值发生变化,连续赋值就会将值驱动到网络中,因此连续赋值始终处于活动状态并且只要 right-hand 侧操作数发生变化,就会发生赋值。
连续赋值提供了一个组合逻辑模型比更高的抽象层次 =58=]Gate-Level 逻辑.
always
是一个程序块,用于建模 寄存器 和组合逻辑。 always
块包含 敏感度列表 ,即 事件列表 ,必须评估块内的逻辑。
always(@ posedge clk)
在每个 上升沿 触发块内的逻辑。从而对一种 flop 行为进行建模。
always @ (*)
对 所有 RHS 语句敏感。如果 always 块的 RHS 中的 任何内容 发生变化,则会评估并分配该特定表达式。这类似于 assign
语句,但这种类型的块用于驱动 reg
数据类型。
// var_z needs to be driven continuously
// Evaluated when any of x or y changes
assign var_z = x|~y
有关详细信息,请参阅 assign statement and Continuous assignments。
开始 阻塞和 non-blocking 语句:
A blocking statement must be executed before the execution of the statements that follow it in a sequential block.
Non blocking statements allow you to schedule assignments without blocking the procedural flow.
阻塞和 non-blocking 分配可以通过以下示例更好地理解:
x = #10 5; // x = 5 at time 10ns
y = #5 6; // y = 6 at time 15ns
x <= #10 5; // y = 6 at time 10ns
y <= #5 6; // y = 6 at time 5ns
这里,在阻塞赋值中,y
在x
赋值后求值。在使用 non-blocking 赋值时,、x
和 y
被评估并推入 模拟器 内部队列并分配分别在 10ns
和 5ns
。
阻塞赋值立即生效。非阻塞分配发生在处理当前“时间增量”的结束时。
所以,直觉上,我们可以说,由于组合块需要连续驱动,使用块语句 必须完成。同时,为了对 顺序硬件 进行建模, 持有或保留 一个值,non-blocking 赋值 必须使用。
// model a flop var_z
var_z <= a+b;
管道建模可以通过 non-blocking 分配有效地完成。考虑一个移位寄存器示例:
// Improper hardware, q3 is directly assigned the value of d
always @(posedge clk) begin
q1 = d;
q2 = q1;
q3 = q2; end
// Proper hardware, q3=q2, q2=q1 and q1=d
always @(posedge clk) begin
q1 <= d;
q2 <= q1;
q3 <= q2; end
以上示例在使用非阻塞分配时对适当的硬件进行建模。有关详细信息,请参阅 CummingsSNUG2000SJ_NBA paper, this link。