行为建模与时序

2024年8月29日 | 阅读 8 分钟

在 Verilog 中,行为模型包含过程语句,这些语句控制仿真并操作数据类型的变量。

这些语句包含在过程中。每个过程都有与之关联的活动流。

在行为模型仿真期间,由 alwaysinitial 语句定义的所有流在仿真时间 开始。

initial 语句执行一次,而 always 语句重复执行。

示例

寄存器变量 ab 在仿真时间零时分别被初始化为二进制 1 和 0。

initial 语句执行完毕,在该仿真运行期间不再执行。该 initial 语句包含一个 begin-end 语句块。在这种 begin-end 类型块中,a 首先被初始化,然后是 b

过程赋值

过程赋值用于更新 integer, reg, time,memory 变量。过程赋值与连续赋值之间存在显著差异,例如

1. 连续赋值驱动网络变量,并在输入操作数的值发生变化时进行评估和更新。

过程赋值在周围的过程流结构控制下更新寄存器变量的值。

2. 过程赋值的右侧可以是任何求值为值的表达式。但是,右侧的部分选择必须具有常量索引。左侧指示接收来自右侧赋值的变量。过程赋值的左侧可以采用以下形式之一

  • 寄存器、整数、实数或时间变量:对这些数据类型之一的名称引用进行赋值。
  • 寄存器、整数、实数或时间变量的位选择:对单个位的赋值,其他位保持不变。
  • 寄存器、整数、实数或时间变量的部分选择:对两个或多个连续位的选择,其他位保持不变。对于部分选择形式,只有常量表达式是合法的。
  • 内存元素:单个内存字。对内存元素引用进行位选择和部分选择是非法的。
  • 上述任何元素的连接:可以指定前面四种形式的任何元素的连接,该连接有效地分割右侧表达式的结果,然后按顺序将分区部分分配给连接的各个部分。

赋值延迟

在延迟赋值中,在语句执行之前经过 Δt 时间单位,并进行左侧赋值。使用赋值内延迟,右侧立即评估,但在结果被放入左侧赋值之前有 Δt 的延迟。

如果在 Δt 期间另一个过程更改了右侧信号,则不会影响输出。综合工具不支持延迟。

语法

赋值具有以下语法,例如

阻塞赋值

必须先执行阻塞过程赋值语句,然后才能执行顺序块中后面的语句。

该语句不会阻止并行块中后面语句的执行。

语法

以下是阻塞过程赋值的语法,例如

  • 左值是过程赋值语句有效的数据类型。
  • = 是赋值运算符,而时序控制是可选的赋值内延迟。时序控制延迟可以是延迟控制或事件控制。表达式是模拟器分配给左侧的右侧值。
    连续过程赋值和连续赋值也使用阻塞过程赋值使用的 = 赋值运算符。

非阻塞 (RTL) 赋值

非阻塞过程赋值用于在不阻塞过程流的情况下调度赋值。

当我们想在同一时间步内进行多个寄存器赋值,而不考虑顺序或相互依赖性时,可以使用非阻塞过程语句。

语法

以下是非阻塞过程赋值的语法

  • 左值是过程赋值语句有效的数据类型。
  • <= 是非阻塞赋值运算符,而时序控制是可选的赋值内时序控制。
    时序控制延迟可以是延迟控制或事件控制。表达式是模拟器分配给左侧的右侧值。非阻塞赋值运算符是模拟器用于小于等于关系运算符的相同运算符。
  • 当模拟器在表达式中使用 <= 运算符时,将其解释为关系运算符;当在非阻塞过程赋值结构中使用 <= 运算符时,则将其解释为赋值运算符。

当模拟器遇到非阻塞过程赋值时,模拟器分两步评估并执行非阻塞过程赋值

步骤 1:模拟器评估右侧,并在由过程时序控制指定的时刻调度新值分配。

步骤 2:在时间步结束时,当给定的延迟已过期或发生相应的事件时,模拟器通过将值赋给左侧来执行赋值。

条件

条件语句或 if-else 语句用于决定是否执行语句。

语法

语法如下

  • 计算 。如果为真(非零已知值),则执行第一个语句。如果为假(零值或值为 x 或 z),则不执行第一个语句。
  • 如果存在 else 语句且 为假,则执行 else 语句。
  • 由于 if 表达式的数值被测试是否为零,因此可能存在一些特定的快捷方式。

Case 语句

case 语句是一种独特的 `多路分支` 决策语句,它测试一个表达式是否与其他多个表达式匹配,并据此进行分支。

case 语句对于描述微处理器指令的解码等非常有用。

语法

case 语句具有以下语法

  • case 表达式按给定的顺序进行评估和比较。
  • 在线性搜索过程中,如果其中一个 case 项表达式与括号中的表达式匹配,则执行与该 case 项关联的语句。
  • 如果所有比较都失败,并且给出了 default 项,则执行 default 项语句。
  • 如果未给出 default 语句,并且所有比较都失败,则不执行任何 case 项语句。

case 语句与多路 if-else-if 结构在两个方面有所不同,如下所示

1. if-else-if 结构中的条件表达式比 case 语句中将一个表达式与多个表达式进行比较更为通用。

2. case 语句在表达式中存在 x 和 z 值时提供确切的结果。

循环语句

有四种类型的循环语句。它们用于控制语句执行零次、一次或多次。

1. Forever 语句持续执行一个语句。

2. Repeat 语句执行一个语句固定次数。

3. While 语句一直执行一个语句直到表达式变为假,如果表达式一开始就是假的,则该语句根本不会执行。

4. For 语句通过三个步骤控制其关联语句的执行:

步骤 1:执行一个赋值,通常用于初始化一个控制循环执行次数的变量。

步骤 2:评估一个表达式。如果结果为零,则 for 循环退出。如果非零,则 for 循环执行其关联语句,然后执行步骤 3。

步骤 3:执行一个赋值,通常用于修改循环控制变量的值,然后重复步骤 2。

语法

以下是循环语句的语法规则,例如

延迟控制

Verilog 按以下方式处理延迟控制,例如

1. 延迟控制

可以使用以下语法通过延迟控制来执行过程语句

以下示例将赋值执行延迟 10 个时间单位。

赋值的执行会延迟由表达式值指定的仿真时间量。

2. 事件控制

可以使用以下事件控制语法,通过与网络或寄存器上的值更改同步,或通过已声明事件的发生来同步过程语句的执行

* 是一个解析为一位值的表达式。

网络和寄存器上的值更改可用作触发语句执行的事件。这称为检测隐式事件。

Verilog 语法也用于根据变化的方向检测变化,即朝向值 1 (posedge) 或值 0 (negedge)。

posedge 和 negedge 对于未知表达式值的行为是

  • 从 1 到未知以及从未知到 0 的转换会检测到 negedge。
  • 从 0 到未知以及从未知到 1 的转换会检测到 posedge。

过程

Verilog 中的所有过程都包含在以下四种块之一中。

  1. Initial 块
  2. Always 块
  3. 任务
  4. 函数

Initial 块

initialalways 语句在仿真开始时启用。initial 块只执行一次,并且在语句完成后其活动就消失了。

语法

以下是 initial 语句的语法

示例

以下示例说明了 initial 语句在仿真开始时用于初始化变量。

initial 块的另一种用途是提供波形描述,这些描述执行一次以向正在仿真的电路的中心部分提供激励。

Always 块

always 块会重复执行。只有当仿真终止时,其活动才会消失。模块中定义的 initial 和 always 块的数量没有限制。

语法

always 语句在整个仿真运行期间持续重复。always 语句的语法如下

由于 always 语句的循环性质,仅与某种形式的时序控制结合使用时才有用。

任务和函数

任务和函数是在其他过程中的一个或多个位置被调用的过程。


下一主题Verilog 模块