Verilog HDL代码使用到的数据对象有以下几种:
线网型数据对象是 Verilgh HDL中常用的数据对象之一,它是作用是电路节点之间的互连,类似于电板上的导线。Verilog HDL支持的线网型有11种之多,如下表1所示:
表1:线网型种类
线网型各种 | 说明 |
---|---|
wire | 普通的连线 |
tri(有三态功能) | 与wire功能类似 |
wand | 具有线与功能的连线 |
triand | 与wand功能类似 |
wor | 具有线或功能的连线 |
trior | 与wor功能类似 |
tri1 | 具有内建上拉功能的连线 |
tri0 | 具有内建下拉功能的连线 |
supply1 | 接到电源的连线,通常为1 |
supply | 接到地的连线,通常为0 |
trireg | 带有存储功能的连线 |
上表中列出的11种线网型中,wire是Verilog HDL默认的线网型,比如在端口声明,当你没有显示给定类型时,它就是默认的wire类型的线网型数据对象;trireg是唯一可以保持原来值的线网型数据对象。
线网型数据对象定义的基本格式如下所示:
net_type[signed][vectored | scalared] list_of_indentifiers
其中
net_type是各种,可以在上表线网型各类中的任意一种。
[signed]是可选项,如果有则标识定义一个或多个有符号的数据对象
[vectored | scalared]是可选项,可以定义多位标量或矢量数据对象
list_of_indentifiers是定义数据对象的列表,可一个或多个
举例如下:
wire cout //定义一个数据对象cout,是1位的wire类型
wand da //定义一个数据对象da,是1位的wand类型
supply1 vcc //定义一个数据对象vcc,是1位的supply1类型
wire[7:0] data //定义一个数据对象data,是8位的wire类型
//定义多位数据对象默认是vectored类型
wire vectored[7:0] bus //显示指明是vectored类型的8位wire
wire scalared[7:0] adr //显示指明是scalared类型的8位wire
wire signed[7:0] data //定义一个有符号的8位wire,它是以2的补码形式出现
Verilog HDL的线网数据对象支持多驱动源操作,即一个线网型对象有两个或两个以上的驱动源对它进行驱动,这时该线网型对象的值不仅跟这些驱动源的值有关,还与该线网型数据对象的种类有关,即使驱动源的值相同,不同线网型各类的数据对象的值也可能不一样。
表2:wire与tri多驱动源的值
wire/tri | 0 | 1 | x | z |
---|---|---|---|---|
0 | 0 | x | x | 0 |
1 | x | 1 | x | 1 |
x | x | x | x | x |
z | 0 | 1 | x | z |
表3:wor与trior多驱动源的值
wor/trior | 0 | 1 | x | z |
---|---|---|---|---|
0 | 0 | 1 | x | 0 |
1 | 1 | 1 | 1 | 1 |
x | x | 1 | x | x |
z | 0 | 1 | x | z |
表4:wand与triand多驱动源的值
wand/triand | 0 | 1 | x | z |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
1 | 0 | 1 | x | 1 |
x | 0 | x | x | x |
z | 0 | 1 | x | z |
表5:tri0与tri1多驱动源的值
tri0/tri1 | 0 | 1 | x | z |
---|---|---|---|---|
0 | 0 | x | x | 0 |
1 | x | 1 | x | 1 |
x | x | x | x | x |
z | 0 | 1 | x | 0/1 |
表6:trireg多驱动源的值
trireg | 0 | 1 | x | z |
---|---|---|---|---|
0 | 0 | x | x | 0 |
1 | x | 1 | x | 1 |
x | x | x | x | x |
z | 0 | 1 | x | 保持最近的值 |
为了便于说明线网型数据对象的使用,提出了两个概念:数据对象的读操作与写操作。所谓写操作就是对数据对象的值有更新或赋值的操作,比如把数据对象放在赋值操作符左边,这时该数据对象就进行了写操作。所谓读操作就是对数据对象的值有读取使用的操作,如把数据对象放在赋值操作符右,这时读取该数据对对象就进行了读操作,举例如下:
data=code; //这里data进行了写操作,code进行了读操作
not I_one(y,a) //这是一个非门的实例化,y进行了写操作,a进行了读操作
了解了数据对象的读操作与写操作,就可以这样说明线网型数据对象的使用。线网型数据对象的读操作在 Verilog HDL代码任何位置都可以使用,例如assign连续赋值语句、initial初始化语句、always进程语句等,而线网型数据对象的写操作只能在assign连续赋值语句中使用。
在定义多位线网型数据对象时,有两个可选的关键字可以使用:vectored与 scalared。它们代表了多位线网型数据对象的不同属性,用vectored进行定义的多位线网型数据对象可以进行某一位或是部分位的选择与使用;用scalared进行定义的多位线网型数据对象不可以进行某一位或是部分位的读写操作,多位线网型数据对象只作为整体进行读写操作。如果没有指定 vectored与 scalared则默认为 vectored,举例如下:
wire vectored[7:0] v_data //定一个vectored属性的多位线网型数据对象v_data
assign a=v_data[0];
assign v_data[1]=1'b1; //可以对v_data的某一位进行读写操作
assign b=v_data[5:3]
assign v_data[7:5]=c //可以对v_data 的部分位进行读写操作,b,c是3位的线网型数据对象
wire scalared[7:0] s_data //定一个scalared属性的多位线网型数据对象s_data
assign a=s_data[0]; //非法,不可以对s_data的某一位进行读写操作
assign s_data[1]=1'b1; //非法,不可以对s_data的某一位进行读写操作
assign b=s_data[5:3] //非法,可以对s_data的部分位进行读写操作,b,c是3位的线网型数据
assign s_data[7:5]=c //非法,可以对s_data的部分位进行读写操作,b,c是3位的线网型数据对象
寄存器(reg)型数据对象是Verilog HDL最常用的数据对象之一。寄存器(reg)型数据对象是对电路中触发线网型数据对象定义的基本格式如下所示:
reg[signed][vectored | scalared] list_of_indentifiers
其中
[signed]是可选性,如果有则表示定义一个或多个有符号的数据对象
[vectored | scalared]是可选项,可以定义多位标量或矢量数据对象
list_of_indentifiers是定义数据对象的列表,可一个或多个
举例如下:
reg cout //定义一个数据对象cout,是1位的reg类型
reg[7:0] data //定义一个数据对象data,是8位的reg类型
//定义多位数据对象默认是vectored类型
reg vectored[7:0] bus //显示指明是vectored类型的8位reg
res scalared[7:0] adr //显示指明是scalared类型的8位reg
res signed[7:0] data //定义一个有符号的8位reg,它是以2的补码形式出现
寄存器(reg)型数据对象的读操作在Verilog HDL代码任何位置都可以使用。而线网型数据对象的写操作只能在initial初始化语句、always进程语句等进程块中,而不能出现在assign连续赋值语句中使用。
在定义多位线网型数据对象时,有两个可选的关键字可以使用:vectored与scalared。它们代表了多位线网型数据对象的不同属性,用vectored进行定义的多位线网型数据对象可以进行某一位或是部分位的选择与使用;用scalared进行定义的多位线网型数据对象不可以进行某一位或是部分位的读写操作,多位线网型数据对象只作为整体进行读写操作。如果没有指定 vectored与 scalared则默认为vectored,举例如下:
wire vectored[7:0] v_data //定一个vectored属性的多位线网型数据对象v_data
initial
begin
a=v_data[0];
v_data[1]=1'b1; //可以对v_data的某一位进行读写操作
b=v_data[5:3]
v_data[7:5]=c //可以对v_data 的部分位进行读写操作,b,c是3位的线网型数据对象
end
initial
begin
scalared[7:0] s_data //定一个scalared属性的多位线网型数据对象s_data
a=s_data[0]; //非法,不可以对s_data的某一位进行读写操作
s_data[1]=1'b1; //非法,不可以对s_data的某一位进行读写操作
b=s_data[5:3] //非法,可以对s_data的部分位进行读写操作,b,c是3位的线网型数据
s_data[7:5]=c //非法,可以对s_data的部分位进行读写操作,b,c是3位的线网型数据对象
end
存储器数据对象其实是寄存器的组合,它的大小由宽度与深度决定。存储器数据对象的定义格式如下所示。
reg[msb1:lsb1] memory[msb2:lsb2]; //定义一个存储器对象
//其中[msb1:lsb1]定义的是存储器对象memory的宽度
//[msb2:lsb2]定义的是存储器对象memory的深度
存储器对象的使用必案子进行,举例如下:
reg[7:0] memory[63:0]; //定义一个宽度为8位,深度为64的存储器对象
memory[0]=8'h12; //合法
memory=12 //非法
整型数据对象存储的值是整数值,它一般作为高级建模使用。整型数据对象定义的基本格式如下所示。
integer idata //定义一个整型数据对象idata
integer iram[7:0] //定义一个整型数据对象数组iram
整型数据对象的位宽是由编译器与机器决定,但不般不会少于32位,整型数据对象可以存储有符号数据,是以2的补码形式存储。整型数据对象也可以进行某一位或部分位的问,整型数据对象的应用如下所示。
integer idata //定义一个整型数据对象idata
integer iram[7:0] //定义一个整型数据对象数组iram
idata=12;
idata=-14;
idata[1]=1'b0;
idata[7:0]8'ha2
时间型数据对象存储的值是时间值,它一般作为高级建模或仿真使用。时间型数据对象定义的基本格式如下所示。
time idata //定义一个时间型数据对象idata
time iram[7:0] //定义一个时间型数据对象数组iram
时间型数据对象的位宽是由编译器与机器决定,但一般不会少于64位。
实型数据对象存储的值可以是浮点数,它一般作为高级建模或仿真使用。实型数据对象定义的基本格式如下所示。
real idata //定义一个实型数据对象idata
idata=1.2;
实型数据对象的默认值为0,对x与z当作0来处理。
参数是用来定义常量的,它可提高Veilog HDL代码的可读性或可维护性, Verilog HDL支持的参数有两种:普通参数与局部参数。普通参数在模块例化时可以重新赋值,局部参数在模块例化时不能进行重新赋值。参数值的更改可以通过 defparam语句来实现,参数举例如下:
parameter HIGH=1; //定义一个参数HIGH,它的值为1,通过实例化可以改变它的值
parameter BUS_WIDTH=16;
defparam BUS_WIDTH=8; //重新修改参数BUS_WIDTH的值为8
localparam real PI=3.14 //定义一个参数PI,它的值为6,通过实例化不能改变它的值
wire[BUS_WIDTH-1:0] data; //相当于wire[7:0] data
字符串是双引号"“内的字符序列,但字符串的值不包括双引号”"本身,Verilog HDL对字符串的存储方式是对每个字符采用8位的ASCⅡ值,所以每个字符就需要8bit的位宽reg型来存储,字符串定义如下:
reg[19*8-1:0] str="I love Verilog HDL!" //因有19个字符,所以需要19*8位来存储
由于字符串不能分多行书写,所以双引号""内也不能有回车或换行符,因此一些特殊字符可以反斜杠加字符\字符表示:
\n //表示换行符
\t //表示制表符Tab
\\ //表示\
\" //表示双引号
\ddd //表示八进制的数,如\104表示8进制的104