2016.9.2
目标:
1.理解操作符、注释、空白符、数字、字符串、和标识符放入词法约定
2.定义逻辑值集合和数据类型
3.学习使用用于显示和监视信息、暂停和结束仿真的系统任务
4.学习用于宏定义、文件包含的基本编译指令
1词法约定
1.1空白符
由空格()、制表符( )和换行符组成
1.2注释
单行注释(\)
多行注释(/**/)
1.3操作符
单目、双目、三目
a= ~ b;//单目 a=b && c;//双目 a=b ? c : d//三目
1.4数字声明
指明位数声明和不指明位数声明
指明位数声明格式:<size>'<base format><number>
<size>数字的为宽度
<base format>
'd或'D
'h或'H
'b或'B
'o或'O
不指明位数的数字
没指定基数,则默认为十进制数,
没指定位宽,则默认与仿真器和计算机有关(最小为32位)
X和Z值
X代表不确定值
Z代表高阻值
16进制中,X和Z代表4位;
8进制中,X和Z代表3位;
2进制中,X和Z代表1位。
负数
在表示位宽的数字前面增加一个减号来表示它是一个负数。
而将减号放在基数和数字之间是非法的
2.数据类型
2.1值的类型
四值逻辑和八种信号对实际硬件进行建模
四值电平逻辑
值的级别 |
硬件电路的条件 |
0 |
逻辑0,条件为假 |
1 |
逻辑1,条件为真 |
x |
逻辑值不确定 |
y |
高阻,浮动状态 |
强度等级
强度等级 | 类型 | 程度 |
supply | 驱动 |
最强 最弱 |
strong | 驱动 | |
pull | 驱动 | |
large | 存储 | |
weak | 驱动 | |
medium | 存储 | |
small | 存储 | |
highz | 高阻 |
不同强度的信号驱动同一线网,则竞争结果为高强度信号的值;同等强度的信号驱动同一线网,则结果为不确定值
2.2线网
线网表示硬件单元之间的连接。
一般用wire进行声明
线网的默认值为z(trireg类型的线网例外,其默认值为x)
线网值由驱动源确定,如果没有,则线网的值为z
2.3寄存器
寄存器用来表示存储器件,它保持原有数值,直到被改写。
关键字为reg,默认值为x。
reg reset;//声明能保持数值的变量reset initial //这个结构以后讨论 begin reset = 1'b1;//把reset初始化为1,使数字电路复位 #100 reset = 1'b0;//经过100个时间单位后,reset置逻辑0 end
也可以声明为带符号(signed)类型的变量,这样的寄存器就可以用于带符号的算术运算
reg signed [63:0] m; //64位带符号的值 integer i ; //32位带符号的值
2.4向量
线网和寄存器类型的数据均可以声明为向量(位宽大于1)。若没指定,则默认为标量(1位)
wire a;/ /标量线网变量,默认 wire [7:0] bus //8位的总线 wire[31:0] busA,busB,busC;//3条32位宽的总线 reg clock;//标量寄存器,默认 reg [0:40] virtual_addr;//向量寄存器,41位宽的虚拟地址(最高有效位是它的第0位)
方括号中左边的数总是代表向量的最高有效位。
向量域选择
我们可以在向量中指定它的某一位或若干相邻位,但要注意高位依然要写在左侧
可变的向量域选择
可以通过for循环来动态地选取向量的各个域。
专用操作符
[<starting_bit>+:width]:从起始位开始递增,位宽为width。
[<starting_bit>-:width]:从起始位开始递减,位宽为width。
起始位可以是变量,但位宽必须是常量。
reg[255:0] data1; // reg[0:255] data2;// reg[7:0] byte; // byte = data1[31-:8]; //从31位算起,宽度为8位,相当于data2[31:24] byte = data1[24+:8];//从24位算起,宽度为8位,相当于data2[31:24] byte = data2[31-:8]; //从31位算起,宽度为8位,相当于data2[24:31] byte = data2[24+:8];//从24位算起,宽度为8位,相当于data2[24:31] //起始位可以是变量,但宽度必须是常数。因此可以通过可变域选择 //用循环语句选取一个很长的向量的所有位 for(j=0;j<=31;j=j+1) byte = data1[(j*8)+:8];//次序为[7:0],[15:8]...[255:248] //用于初始化向量的一个域 data1[(byteNum*8)+:8] =8'b0;//如果byteNum = 1,共有8位被清零,[15:8]
2.5整数、实数和时间寄存器数据类型
除reg类型之外,verilog还支持integer,real,和time寄存器数据类型。
整数(integer)
通用的寄存器数据类型,用于对数量进行操作。
声明一个整数类型的变量来完成计数等功能显然比reg更为方便。
位宽为宿主机的字的位数,最小应为32位。
reg类型的寄存器变量为无符号数,而整数类型的变量则为有符号数。
实数(real)
实常量和实数寄存器数据类型,可以使用十进制或科学计数法。实数声明不能带有范围,默认值为0;
如果将一个实数赋给一个整数,那么实数将会被取整为最接近的整数
时间寄存器(time)
时间变量通过time来声明,宽度与具体实现有关,最小为64位。
通过调用系统函数$time可以得到当前的仿真时间。
2.6数组
允许声明reg,integer,time,real,realtime及其向量类型的数组,对数组维数没有限制。
形如<数组名>[<下标>],对于多维数组需要说明其每一维的索引
赋值
integer count[0:7];//8个计数变量组成数组 reg bool[31:0];//32个1位的布尔寄存器变量组成数组 time chk_point[1:100];//100个时间检查变量组成数组 reg [0:4] port_id[0:7];//8个端口标识变量组成数组,端口位宽为5 integer matrix[4:0][0:255];//二维的整数型数组 reg [63:0] array_4d [15:0] [7:0] [7:0] [255:0];//四维64位寄存器型数 组 wire [7:0] w_array2 [5:0];//声明8位向量数组 wire w_array1 [7:0] [5:0];//声明1位线型变量的二维数组 //赋值 count[5]=0;//count中第五个整数型单元(32位)复位 chk_point[100] = 0;//第100个时间型单元(64位)复位 port_id[3] = 0;//第3个寄存器型单元(5位)复位 marix[1][0] = 33339;//第1行第0列的整数型单元(32位)置为33339 array_4d[0][0][0][0][15:0] = 0;//把四维数组中索引号为[0][0][0][0]的寄存器型单元的0~15位都置于0
2.7存储器
对寄存器,RAM和ROM建模。使用寄存器的一维数组来表示存储器,数组每个元素称为一个元素或一个字(Word),由一个数组索引来指定,每一个字的位宽为1位或多维。
2.8参数
使用parameter在模块内定义常数。参数代表常数,不能像变量那样赋值,但是每一个模块实例的参数值可以在编译阶段被重载。通过参数重载使得用户可以对模块实例进行定制。
局部参数使用关键字localparam来定义,其作用等同于参数,区别在于它的值不能改变,不能通过参数重载语句(defparam)或通过有序参数列表或命名参数赋值来直接修改。
2.9字符串
字符串保存在reg类型的变量中,每一个字符占用8位(一个字节)。左补左截。
特殊字符
转义字符 | 显示的字符 |
换行 | |
tab(制表空格) | |
%% | % |
\ | |
" | " |
ooo | 1到3个八进制数字字符 |
3系统任务和编译指令
3.1系统任务
为某些常用操作提供了标准的系统任务(系统函数),包括屏幕显示、线网值动态监视、暂停和结束仿真。
所有系统任务都具有$<keyword>的形式
显示信息($display)
用于显示变量、字符串或表达式的主要系统任务
用法:$display(p1,p2,p3,...,pn);
p1,p2,p3,...,pn是双引号括起来的字符串、变量或者表达式,会自动在字符串结尾插入一个换行符。
字符串格式说明
格式 | 显示 |
%d或%D |
用十进制显示变量 |
%b或%B |
用二进制显示变量 |
%s或%S |
显示字符串 |
%h或%H |
用十六进制显示变量 |
%c或%C |
显示ASCII字符 |
%m或%M |
显示层次名 |
%v或%V |
显示强度 |
%o或%O |
用八进制显示变量 |
%t或%T |
显示当前时间 |
%e或%E |
用科学记数法格式显示实数 |
%f或%F |
用十进制浮点数格式显示实数 |
%g或%G | 用科学记数法或十进制格式显示实数,显示较短的格式 |
监视信息
通过系统函数$monitor,提供了对信号值变化进行动态监视的手段。
用法:$monitor(p1,p2,p3,...,pn);
p1,p2,p3,...,pn可以是变量、信号名或双引号括起来的字符串。其对参数列表中的变量值或信号值进行不间断监视。因此在任意仿真时刻只有一个监视列表有效,也就是只有最后一次的调用有效
两个用于控制监视的系统任务:$monitoron和$monitoroff
用法:$monitoron;(允许监视任务的执行)
$monitoroff;(暂停监视)
在$monitor中使用系统函数$time来取得系统仿真时间。
暂停和结束仿真
用法:$stop;
$finish;
3.2编译指令
使用方法'<keyword>;
'define
用于定义文本宏
'include
可以在编译期间将一个Verilog源文件包含在另一个源文件中,作用类似于C语言中的#include结构。