📜  Verilog行为建模和计时

📅  最后修改于: 2021-01-11 14:36:13             🧑  作者: Mango

行为建模和时间安排

在Verilog中,行为模型包含过程语句,该过程语句控制模拟并操纵数据类型的变量。

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

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

初始语句执行一次,而always语句则重复执行。

在模拟时间零,寄存器变量ab分别初始化为二进制1和0。

初始语句已完成,并且在该模拟运行期间不再执行。此初始语句包含一个语句的开始-结束块。在该开始端型,首先被初始化,随后用b。

module behave; 
reg [1:0]a,b; 

initial 
begin 
   a = 'b1; 
   b = 'b0; 
end 

always 
begin 
   #50 a = ~a; 
end 

always 
begin 
   #100 b = ~b; 
end 
End module 

程序分配

过程分配用于更新整数,reg,时间内存变量。过程分配和连续分配之间存在显着差异,例如:

1.每当输入操作数更改值时,连续赋值就会驱动净变量,求值并进行更新。

程序分配在围绕它们的程序流程构造的控制下更新寄存器变量的值。

2.过程分配的右侧可以是任何求值的表达式。但是,右侧的零件选择必须具有恒定的索引。左侧表示从右侧接收分配的变量。过程分配的左侧可以采用以下形式之一:

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

作业延迟

在延迟分配中,在执行语句之前经过了Δt个时间单位,并进行了左侧分配。由于存在内部分配延迟,因此会立即评估右侧,但是在将结果放入左侧分配之前会有Δt延迟。

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

句法

分配具有以下语法,例如:

Procedural Assignmentvariable = expression
Delayed assignment#Δt variable = expression;
Intra-assignment delayvariable = #Δt expression;

阻止分配

必须先执行阻塞过程分配语句,然后才能在顺序块中执行紧随其后的语句。

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

句法

以下语法适用于阻塞过程分配,例如:

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

非阻塞(RTL)分配

非阻塞过程分配用于调度分配而不会阻塞过程流。

每当我们想要在同一时间步内进行多个寄存器分配而无需考虑顺序或彼此依赖时,都可以使用非阻塞过程语句。

句法

以下语法适用于非阻塞过程分配:

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

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

步骤1:模拟器评估右侧,并在过程定时控件指定的时间安排新值的分配。

步骤2:在时间步骤的末尾,当给定的延迟已到期或发生了适当的事件时,模拟器通过将值分配给左侧来执行分配。

条件

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

句法

语法如下:

 
::= if (  )  
||= if (  )  
   else  
 

::=  
||= ; 

  • 评估。如果为true(已知值非零),则执行第一条语句。如果为假(零值或值为x或z),则不执行第一条语句。
  • 如果存在else语句且为false,则执行else语句。
  • 由于如果测试表达式的数值为零,则可以使用特定的快捷方式。

案例陈述

case语句是唯一的多向决策语句,用于测试一个表达式是否与其他几个表达式匹配,并相应地进行分支。

case语句对于描述例如微处理器指令的解码很有用。

句法

case语句具有以下语法:

 
::= case (  ) + endcase 
||= casez (  ) + endcase 
||= casex (  ) + endcase 
 
::=  <,>* :  
||= default :  
||= default  
  • 案例表达式将按照给出的确切顺序进行评估和比较。
  • 在线性搜索期间,如果一个案例项目表达式与括号中的表达式匹配,则将执行与该案例项目关联的语句。
  • 如果所有比较都失败,并且给出了默认项目,则执行默认项目语句。
  • 如果未提供默认语句,并且所有比较均失败,则不会执行任何case item语句。

case语句与多路if-else-if构造在两个基本方面不同,例如:

1. if-else-if构造中的条件表达式比case语句中的一个表达式与其他多个表达式相比更通用。

2.当表达式中有x和z值时,case语句提供确定的结果。

循环语句

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

1.永远持续执行一条语句。

2.重复执行一条语句固定次数。

3.在执行语句直到表达式变为假之前,如果表达式开始为假,则根本不执行该语句。

4.对于控件,通过三个步骤执行其关联语句:

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

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

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

句法

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

 
::= forever  
||=forever 
begin 
   + 
end  


 
::= repeat (  )  
||=repeat (  ) 
begin
   + 
end  


 
::= while (  )  
||=while (  ) 
begin 
   + 
end  


 
::= for (  ;  ;  ) 
 
||=for (  ;  ;  ) 
begin 
   + 
end

延迟控制

Verilog通过以下方式处理延迟控制,例如:

1.延迟控制

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

 
::=   
 
::= #  
||= #  
||= # (  )

以下示例将分配的执行延迟了10倍。

#10 rega = regb;

通过表达式的值指定的仿真时间来执行分配延迟。

2.事件控制

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

 
::=   

 
::= @  
||= @ (  ) 

 
::=  
||= posedge  
||= negedge  
||=  > 

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

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

Verilog语法还用于根据更改的方向来检测更改,该更改的方向是朝向值1(冒口)或朝向值0(负)。

对于未知表达式值,posege和negedge的行为是:

  • 在从1到未知以及从未知到0的转换中检测到一个忽略。
  • 在从0到未知以及从未知到1的过渡中检测到姿势。

程序

在以下四个模块之一中指定了Verilog中的所有过程。

  • 初始块
  • 一律封锁
  • 任务
  • 功能

初始块

在模拟开始时会启用initialalways语句。初始块仅执行一次,并且语句结束后其活动终止。

句法

以下语法适用于初始语句:

 
::= initial 

以下示例说明了使用初始语句初始化变量以及模拟开始的过程。

Initial 
Begin 
   Areg = 0; // initialize a register 
   For (index = 0; index < size; index = index + 1) 
   Memory [index] = 0; //initialize a memory 
   Word 
End

初始模块的另一种用法是对波形描述的规范,该描述执行一次即可为模拟电路的中心部分提供激励。

Initial 
Begin 
   Inputs = 'b000000; 
   // initialize at time zero 
   #10 inputs = 'b011001; // first pattern 
   #10 inputs = 'b011011; // second pattern 
   #10 inputs = 'b011000; // third pattern 
   #10 inputs = 'b001000; // last pattern 
End 

永远封锁

Always块重复执行。仅当模拟终止时,其活动才会终止。对模块中定义的初始块和始终块的数量没有限制。

句法

在整个模拟运行中,always语句会不断重复。 always语句的语法如下所示

 
::= always  

always语句仅在与某种形式的时序控制结合使用时才有用,因为它具有循环性质。

任务与功能

任务和功能是在其他过程中一个或多个位置启用的过程。