Verilog Always 块

17 Mar 2025 | 5 分钟阅读

在 Verilog 中,always 块是过程块之一。 always 块中的语句按顺序执行。

与仅在模拟开始时执行一次的 initial 块不同,always 块始终执行。 always 块应具有敏感列表或与之关联的延迟

敏感列表告诉 always 块何时执行代码块。

语法

Verilog always 块具有以下语法

示例

保留字 always 之后的符号 @ 表示该块将在符号 @ 之后的括号中的条件at触发。

在上面的示例中,我们描述了一个具有输入 x 和 y 的 2:1 多路复用器。 sel 是选择输入,m 是多路复用器输出。

在任何组合逻辑中,输出都会在输入更改时发生更改。 当此理论应用于 always 块时,无论输入或输出变量何时更改,都需要执行 always 块内的代码。

注意:它可以驱动 reg 和 integer 数据类型,但不能驱动 wire 数据类型。

Verilog 中有两种类型的敏感列表,例如

  1. 电平敏感(用于组合电路)。
  2. 边沿敏感(用于触发器)。

下面的代码是相同的 2:1 多路复用器,但输出 m 现在是一个触发器输出。

注意:always 块在某些特定事件时执行。 敏感度列表定义了该事件。

敏感度列表

敏感度列表是一个表达式,它定义了何时执行 always 块,并且在 @ 运算符的括号 ( ) 中指定。 此列表可以包含一个或一组信号,这些信号值的更改将执行 always 块。

在下面显示的代码中,只要信号 x 或 y 的值发生变化,就会执行 always 块内的所有语句。

需要敏感度列表

always 块在整个模拟过程中不断重复。 敏感度列表带来了一定的时序感,即,每当敏感度列表中的任何信号发生变化时,就会触发 always 块。

如果 always 块中没有时序控制语句,则模拟将因零延迟无限循环而挂起。

例如,always 块尝试反转信号 clk 的值。 该语句在每 0 个时间单位后执行。 因此,由于语句中缺少延迟,它会永远执行。

如果敏感度列表为空,则应该有其他形式的时间延迟。 模拟时间由 always 结构中的延迟语句提前。

现在,时钟反转在每 10 个时间单位后完成。 这就是为什么真正的 Verilog 设计代码总是需要敏感度列表。

注意:显式延迟无法综合为逻辑门。

always 块的用途

always 块可用于实现组合或时序元素。 当提供时钟和复位时,像触发器这样的时序元素会变得有效。

同样,当其输入值之一发生变化时,组合块会变得有效。 所有这些硬件块都在并发地独立于彼此工作。 它们之间的连接决定了数据的流向。

always 块被制成一个连续的过程,当敏感度列表中的信号变为活动状态时,该过程会被触发并执行某些操作。

在以下示例中,always 块中的所有语句都在信号 clk 的每个正边缘执行

时序元件设计

下面的代码定义了一个名为 tff 的模块,该模块接受数据输入、时钟和低电平有效的复位。 在这里,always 块在 clk 的正边缘或 rstn 的负边缘触发。

1. 时钟的正边缘

以下事件发生在时钟的正边缘,并为时钟的所有正边缘重复。

第 1 步:首先,if 语句检查低电平有效复位 rstn 的值。

  • 如果 rstn 为零,则输出 q 应重置为默认值 0。
  • 如果 rstn 为 1,则表示未应用复位,应遵循默认行为。

第 2 步:如果上一步为假,则

  • 检查 d 的值,如果发现 d 为 1,则反转 q 的值。
  • 如果 d 为 0,则保持 q 的值。

2. 复位的负边缘

以下事件发生在 rstn 的负边缘。

第 1 步:首先,if 语句检查低电平有效复位 rstn 的值。 在信号的负边缘,其值为 0。

  • 如果 rstn 的值为 0,则表示应用了复位,输出应重置为默认值 0。
  • 如果 rstn 的值为 1,则不予考虑,因为当前事件是 rstn 的负边缘。

组合元件设计

always 块还可用于组合块的设计。

例如,下面的数字电路表示三个不同的逻辑门,它们在信号 o 处提供特定的输出。

Verilog Always Block

下面显示的代码是一个具有四个输入端口和一个名为 o 的单个输出端口的模块。 只要敏感度列表中的任何信号值发生变化,就会触发 always 块。

输出信号在模块端口列表中声明为 reg 类型,因为它在过程块中使用。 所有在过程块中使用的信号都应声明为 reg 类型。

每当 RHS 上的组合表达式变为真时,信号 o 变为 1。 同样,当 RHS 为假时,o 变为 0。


下一个主题Verilog Initial 块