4f6d3fe0dc830578f40081dfc2a5e5ca.png

1.运算符及表达式

01cf6f403496366d278ca1f8a0c7e6a1.png

在Verilog HDL语言中运算符所带的操作数是不同的,按其所带

操作数的个数运算符可分为三种:

a)单目运算符(unary operator):可以带一个操作数,操作数放在运算符的右边。

b)二目运算符(binary operator):可以带二个操作数,操作数放在运算符的两边。

c)三目运算符(ternary operator):可以带三个操作,这三个操作数用三目运算符分隔开。

例:

 clock = ~clock;// ~是一个单目取反运算符, clock是操作数。
 c = a | b; // 是一个二目按位或运算符, a 和 b是操作数。
 r = s ? t : u; // ?: 是一个三目条件运算符, s,t,u是操作数。

1)算数运算

a22312ba2b55af6427ddaef929c4079a.png

将负数赋值给reg或其它无符号变量使用2的补码算术。如果操作数的某一位是x或z,则结果为x。在整数除法中,余数舍弃。模运算中使用第一个操作数的符号。注意integer和reg类型在算术运算时的差别。integer是有符号数,而reg是无符号数。

2)位运算

39bdf24544eae45424c44810b2c42896.png

0b237792b25ca291af4f7d94390a57e3.png

3506e1983088bf0e390093a0e050261e.png

23515fa1c1815129486c4684f6ce5fbf.png

222d2b9f5d4b292b3af687254e05ffe0.png

按位运算的例子:

643772735f51fdf01b86be3d250446ef.png

注:当两个操作数位数不同时,需要用0来扩展。

a72799c1193ed8424a1990076f2766c0.png

3)逻辑运算符

逻辑与 : &&;逻辑或: ||;逻辑非: !。逻辑运算符中“&&”和“||”的优先级别低于关系运算符,“!”高于算术运算符。

4)等式运算符

等于:== ;不等于:!=;全等:===;不全等:!==

在等式运算符中“==”和“!=”又被称为逻辑等式运算符,其结果可能是1、0或x。如果左边和右边为确定值并且相等,则结果为1;如果左边和右边为确定值并且不相等,则结果为0;如果左边和右边有值不能确定的位,但值确定的位相等,则结果为x。

在等式运算符中的“===”和“!==”又被称为绝对等式运算符,其结果只能为0或1。如果左边和右边的值相同(包括x、z),则结果为1。如果左边和右边的值不相同,则结果为0。但是不可综合

5)关系运算符

大于:>;不大于:<=;小于:<;不小于:>=

关系运算符的结果为1位1、0 、x;如果声明的关系是假的(false),则返回值是0;如果声明的关系是真的(true),则返回值是1;如果某个操作数的值不定,则关系是模糊的,返回值是不定值x;所有的关系运算符具有相同的优先级别;关系运算符的优先级别低于算术运算符的优先级别。

6)移位运算符

左移位: <<;右移位: >>;使用方法: a >> n 或 a << n;a代表要进行移位的操作数,n代表要移几位。这两种移位运算都用0来填补移出的空位。

移位操作符对其左边的操作数进行指定位数的向左或向右移位操作;移位位数是无符号数;若第二个操作数是x或z,则结果为x; 在赋值语句中,若右边的结果位宽大于左边,则把最高位截去;若小于左边,则用零进行扩展。

7)拼接运算符

位拼接运算符{}.用这个运算符可以把两个或多个信号的某些位拼接起来进行运算操作。

wire [3:0] a,b;
wire[15:0] c;
assign c={a,b};//assign c={a,b[3:0],4'b0000}

8)缩位运算符

缩位运算符包括&(与缩位)、~&(与非缩位)、|(或缩位)、~|(或非缩位)、^~或~^(同或缩位)5种。位运算和缩位运算虽然运算符相同,但是运算过程不同。位运算的操作数有两个,操作数是几位,运算结果也是几位。而缩位运算只有一个操作数,运算时对一个操作数由左向右进行运算,运算结果为1位。

x=4'b1001
&x =1'b0
~&x=1'b1
| x =1'b1
~|x =1'b0
~ ^ x=1'b1

2.编译向导

Verilog HDL和C语言类似,也提供了编译向导的功能。在Verilog HDL中,编译向导以符号“`”(反引号,不同于左单引号,键盘上位于1的左边)开始。这些编译向导的有效作用范围为定义命令之后到文本结束,或者到其它命令替代该命令。Verilog HDL提供了十几条编译向导语句,常用的有以下几种:

`define - 宏定义语句
`include - 文件包含语句
`timescale-时间尺度指令

`ifdef、`else、`endif - 条件编译指令

1)`define - 宏定义语句

`define指令用于文本替换,即用一个有意义的标识符取代程序中反复出现的含义不明显的字符串,好处是提高程序可读性,另外,当需要修改某一变量时,可以只改变`define命令行。其格式为:

`define <宏名> <宏文本>
`define WORDSIZE 16  //行末不加分号
reg[1 : `WORDSIZE] data;//相当于定义reg[1: 16] data;

宏定义和parameyer型变量类似,不同的是宏定义的作用域是从宏定义语句开始到程序结束,而parameter型变量作用域是定义该变量的模块内。

2)`include - 文件包含语句

一个复杂的设计可能包含很多模块,各模块都单独保存为一个文件,当顶层模块调用子模块时,就需要到相应的文件中去找。Verilog HDL语言提供了`include语句用来实现这种“文件包含”操作。其格式如下:

`include “<path/filename>”

`include语句可以出现在程序中的任何位置。被包含文件名可以是相路径名,也可以是绝对路径名。例如:

`include “work/demo.v”
`include “../source/demo.v”

现考虑一个顶层模块top,需调用3个子模块:source1、source2和source3,它们分别存储在sourc1.v、source2.v和source3.v三个文件中。使用文件包含命令完成顶层模块对各个子模块的调用。

`include ''source1.v''
`include ''source2.v''
`include ''source3.v''
module top;
source1 source1();
source2 source2();
source3 source3();
endmodule

3)`timescale-时间尺度指令

`timescale 用于定义模块的仿真时间单位和时间精度,其参量值必须是整数,有效数字为1、10、100。时间单位。`timescale命令必须放在模块的边界前面,它的格式为:

`timescale time_unit/time_precision

4)`ifdef、`else、`endif - 条件编译指令

格式:`ifdef 宏名 程序段1

`else 程序段2

`endif

如果已定义了文本宏,就对程序段1进行编译,程序段2被忽略;否则编译程序段2,程序段被忽略。

例如:下面的模块编译时将编译assign out=`sum+c; 而不编译assign out=a+c;

  `define sum a+b
 module condition_compile(out,a,b,c);
 output[2:0] out; input a,b,c;
 `ifdef sum assign out=`sum+c;
 `else assign out= a+c;
 `endif
 endmodule

5)其他编译指令

`default_nettype该指令用于为隐式线网指定线网类型。也就是将那些没有被说明的连线定义线网类型。

`resetall - 编译重置指令:该编译器指令将所有的编译指令重新设置为缺省值

`unconnected_drive和`nounconnected_drive在模块实例化中,出现在这两个编译器指令间的任何未连接的输入端口或者为正偏电路状态或者为反偏电路状态。

`celldefine 和 `endcelldefine这两个程序指令用于将模块标记为单元模块。它们表示包含模块定义。

3.日常补充

1.在Verlog HDL中,不同数据类型的之间遵循以下驱动规则:

(1) 输入口(input)可以由reg型或net型驱动,但它本身只能驱动net型;

(2) 输出口 (output)可以由reg型或net型驱动,但它本身只能驱动net型;

(3) 输入/输出口(inout)只可以由net型驱动,它本身也只能驱动net型。

2.memory型reg [n-1:0] 存储器名[m-1:0];

50a97d7dfdeeacfa41cbae75226099f5.png

『文末说明』

本文作者:小强子

知乎ID:小强子

微信公众号:小强子

永远年轻,永远热泪盈眶,永远充满希望,一个嗜好太多能力又太小的普通人。

更多推荐