缩减运算的具体运算过程是:(1)先将操作数的第1位与第2位进行与、或等运算;(2)将运算结果与第3位进行与、或等运算,依次类推,直至最后1位。 7.运算符优先级
非运算(! ~ ) 》算术运算符(* / % + - ) 》移位运算符(<< >>)》关系运算符(< <= > >=)》等号运算符(== != === !==)》位运算符(& ^ ^~ | )》逻辑运算符(&& || )》条件运算符( ?: ) 8.赋值语句
(1)非阻塞赋值“<=”:
●在语句块中,上面语句所赋的变量值不能立即就为下面的语句所用; ●块结束后才完成赋值操作,块结束前被赋值的变量保持上一次所赋的值;
●在编写可综合的时序逻辑模块时,这是最常用的赋值方法。意即,在always块中经常使用。
(2)阻塞赋值“=”:
●赋值语句执行完后,块才结束;
●b的值在赋值语句执行完后立刻就改变;
●在时序逻辑中使用时(在沿触发的always块中使用时),综合后可能会产生意想不到的结果。 9.块语句
(1)顺序块:begin_end块
●块内的语句是按顺序执行的,即只有上面一条语句执行完后下面的语句才能执行。 ●每条语句的延迟时间是相对于前一条语句的仿真时间而言的。 ●直到最后一条语句执行完,程序流程控制才跳出该语句块。
(2)并行块:fork_ join块
●块内语句是同时执行的,即程序流程控制一进入到该并行块,块内语句则开始同时并行地执行。
●块内每条语句的延迟时间是相对于程序流程控制进入到块内的仿真时间。 ●延迟时间是用来给赋值语句提供执行时序的。
●当按时间时序排序在最后的语句执行完后或一个disable语句执行时,程序流程控制跳出该程序块 (3)块名
这样做的原因有以下几点:1)可以在块内定义局部变量,即只在块内使用的变量;2)可以允许块被其他语句调用,如disable语句;3) 块名提供了一个在任何仿真时刻确认变量值的方法。
(4)起始时间和结束时间
对于顺序块,起始时间就是第一条语句开始被执行的时间,结束时间就是最后一条语句执行完的时间;
对于并行块,起始时间对于块内所有的语句是相同的,即程序流程控制进入该块的时间,其结束时间是按时间排序在最后的语句执行结束的时间。 当一个块嵌入另一个块时,块的起始时间和结束时间是很重要的。跟在块后面的语句在该块的结束时间到了才能开始执行,也就是说,只有该块完全执行完后,后面的语句才可以执行。
十四.条件语句、循环语句、块语句与生成语句
1.条件语句(if_else语句)
1)if(表达式)语句
2)if(表达式)
语句1; else
语句2; (3)if(表达式) 语句1; else if(表达式2) 语句2; else if(表达式3) 语句3; ??
else if(表达式m) 语句m; else 语句n;
注意:条件语句必须在过程块语句中使用。所谓过程块语句是指由initial和always语句引导的执行语句集合。除了这两种块语句引导的begin end块中可以编写条件语句外,模块中的其他地方都不能编写
说明:
1)if语句在if后面都有“表达式”,一般为逻辑表达式或关系表达式。系统对表达式的值进行判断,若为0,x,z,按“假”处理;若为1,按“真”处理,执行指定的语句 2)第2)、3)种形式的if语句,在每个else前面有一个分号,整个语句结束处有一个分 3)允许一定形式的表达式简写方式。如下面的例子:
if(expression) 等同与 if(expression==1) if(!expression) 等同与 if(expression!=1) (5)if语句的嵌套。在if语句中又包含一个或多个if语句称为if语句的嵌套。一般形式如下:
if(epression1)
if(expression2) 语句1;(内嵌if) else 语句2; else
if(expression3) 语句3;(内嵌if) else 语句4; else总是与它上面最近的if配对 2.case语句
一般形式如下:
(1) case (表达式)
分支表达式1: 语句; 分支表达式2: 语句;
默认项(default项): 语句; endcase 说明:
1)case括弧内的表达式称为控制表达式,case分支项中的表达式称为分支表达式。 2)当控制表达式的值与分支表达式的值相等时,执行分支表达式后面的语句。如果所有的分支表达式的值都没有与控制表达式的值相匹配,就执行default后面的语句。 3)一个case语句里只准有一个default项。对于default项:
若分支表达式将所有情况列出,可不写default项;若有未列出的可能值,应写default项。 4)每一个case分项的分支表达式的值必须互不相同,否则就会出现矛盾(对表达式的同一个值,有多种执行方案)。
5)执行完case分项后的语句,则跳出该case语句结构,终止case语句的执行。(注:与C语言不同,Verilog中的case语句不需要写break) 6)在用case语句表达式进行比较的过程中,只有当信号的对应位的值能明确进行比较时,比较才能成功。因此,要注意详细说明case分项的分支表达式的值。
7)case语句的所有表达式值的位宽必须相等,只有这样,控制表达式和分支表达式才能进行对应位的比较。一个经常犯的错误是用’bx,’bz来替代n’bx,n‘bz,这是不对的,因为信号x,z的默认宽度是机器的字节宽度,通常是32位(此处n是case控制表达式的位宽)。 3.case语句与if_else_if语句的区别: (1)if_else_if结构中的条件表达式更为直观。
(2)对于那些分支表达式中存在不定值x和高阻值z的位时,case语句提供了处理这种情况的手段。
(3)if语句具有优先级,可用于描述具有优先级的电路;case语句不具有优先级,只能用于描述无优先级的电路。
要点:
1.在\块内,如果在给定的条件下变量没有赋值,这个变量将保持原值,也就是说会生成一个锁存器。
2.为避免产生不必要的锁存器,应遵循下面两个原则: 1)、如果用到if语句,最好写上else项;2)、如果用case语句,最好写上default项。 4.循环语句 1)forever语句 格式如下:
forever 语句; 或
forever begin
多条语句
end
forever循环语句常用于产生周期性的波形,作为仿真测试信号。它与always语句不同之处在于它不能独立写在程序中,而必须写在initial块中。 2)repeat语句
repeat语句的格式如下:
repeat(表达式) 语句; 或
repeat(表达式) begin
多条语句 end
在repeat语句中,其表达式通常为常量表达式。 3)while语句
while语句的格式如下: while(表达式) 语句
或
while(表达式)
begin
多条语句 end 4)for语句
for语句的一般形式为:
for(循环变量赋初值;循环结束条件;循环变量增值) 执行语句;
十五.结构说明语句
initial语句只执行一次,而always语句则是不断地重复活动着,直到仿真过程结束。 无条件的always语句是不允许的,将造成仿真死锁!如:always clock=~clock;) 1. initial语句 initial语句的格式如下: initial
begin
语句1; 语句2; ?? 语句n;
end
(1)用initial 块对存储器变量赋初始值 initial begin
areg=0; //初始化寄存器areg
for(index=0;index (2)用initial语句来生成激励波形 initial begin inputs=’b000000; //初始时刻为0 #10 inputs=’b011001; #10 inputs=’b011011; #10 inputs=’b011000; #10 inputs=’b001000; end 2. always语句 声明格式如下: always <时序控制> <语句> 要点: always的时间控制可以是边沿触发也可以是电平触发; 可以是单个信号也可以是多个信号,当有多个信号时中间需要用关键字or连接。 要点: 沿触发的always块用于描述时序逻辑,如有限状态机; 电平触发的always块用来描述组合逻辑。 3. task和function说明语句 task和function说明语句的不同点 (1) 函数只能与主模块共用同一个仿真时间单位,而任务可以定义自己 的仿真时间单位。 (2) 函数不能启动任务,而任务能启动其他任务和函数。 (3) 函数至少要有一个输入变量,而任务可以没有或有多个任何类型的 输入变量。 (4) 函数返回一个值,而任务则不返回值。 (5) task和function的调用方法不同 16位字字节互换任务的调用为:switch_bytes(old_word,new_word); 16位字字节互换函数的调用为:new_word=switch_bytes(old_word); 4.task说明语句 (1)任务的定义。定义任务的语法如下: task <任务名>; <端口及数据类型声明语句> <语句1> <语句2> ?? <语句n> endtask (2)任务的调用及变量的传递 启动任务并传递输入,输出变量的声明语句的语法如下: 任务的调用: <任务名> (端口1,端口2,?,端口n); 5.function说明语句 (1)定义函数的语法: function <返回值的类型或范围> (函数名); <端口说明语句> <变量类型说明语句> begin <语句> ?? end endfunction 注意:<返回值的类型或范围>这一项是可选项,如缺省则返回值为一位寄存器类型数据。 (2)从函数返回的值: 函数的定义隐含声明了与函数同名的内部寄存器。 如在函数的声明语句中<返回值的类型或范围>为缺省,则这个寄存器是一位的,否则是与函数定义中<返回值的类型或范围>一致的寄存器。 (3)函数的调用: 函数的调用是通过将函数作为表达式中的操作数来实现的。其调用格式如下: