⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 verilog_4.htm

📁 Verilog HDL硬件描述语言的教程
💻 HTM
📖 第 1 页 / 共 3 页
字号:
4.1.7 存储器单元<br />
<br />
  存储器单元从存储器中选择一个字。形式如下:<br />
<br />
memory [word_address]<br />
<br />
例如:<br />
reg [1:8] Ack, Dram [0:63];<br />
. . . <br />
Ack = Dram [60]; //存储器的第60个单元。<br />
<br />
  不允许对存储器变量值部分选择或位选择。例如,<br />
<br />
Dram [60] [2] 不允许。<br />
Dram [60] [2:4] 也不允许。<br />
<br />
  在存储器中读取一个位或部分选择一个字的方法如下:将存储器单元赋值给寄存器变量,然后对该寄存器变量采用部分选择或位选择操作。例如,Ack [2] 和Ack [2:4]是合法的表达式。<br />
<br />
4.1.8 函数调用<br />
<br />
  表达式中可使用函数调用。函数调用可以是系统函数调用(以$字符开始)或用户定义的函数调用。例如:<br />
<br />
$time + SumOfEvents (A, B)<br />
/*$time是系统函数,并且SumOfEvents是在别处定义的用户自定义函数。*/<br />
<br />
4.2 操作符<br />
<br />
  Verilog HDL中的操作符可以分为下述类型:<br />
<br />
  1) 算术操作符<br />
  2) 关系操作符<br />
  3) 相等操作符<br />
  4) 逻辑操作符<br />
  5) 按位操作符<br />
  6) 归约操作符<br />
  7) 移位操作符<br />
  8) 条件操作符<br />
  9) 连接和复制操作符<br />
<br />
  下表显示了所有操作符的优先级和名称。操作符从最高优先级(顶行)到最低优先级(底行)排列。同一行中的操作符优先级相同。<br />
  除条件操作符从右向左关联外,其余所有操作符自左向右关联。下面的表达式:<br />
<br />
A + B - C<br />
等价于:<br />
(A + B ) - C //自左向右<br />
而表达式:<br />
A ? B : C ? D : F<br />
等价于:<br />
A ? B : (C ? D : F) //从右向左<br />
圆扩号能够用于改变优先级的顺序,如以下表达式:<br />
(A ? B : C) ? D : F<br />
<br />
4.2.1 算术操作符<br />
<br />
  算术操作符有:<br />
<br />
* +(一元加和二元加)<br />
* -(一元减和二元减)<br />
* *(乘)<br />
* /(除)<br />
* %(取模)<br />
<br />
  整数除法截断任何小数部分。例如:<br />
<br />
7/4 结果为 1<br />
取模操作符求出与第一个操作符符号相同的余数。<br />
7%4 结果为 3<br />
而:<br />
- 7%4 结果为 -3<br />
<br />
  如果算术操作符中的任意操作数是X或Z,那么整个结果为X。例如:<br />
<br />
'b10x1 + 'b01111 结果为不确定数'bxxxxx<br />
<br />
1. 算术操作结果的长度<br />
  算术表达式结果的长度由最长的操作数决定。在赋值语句下,算术操作结果的长度由操作符左端目标长度决定。考虑如下实例:<br />
<br />
reg [0:3] Arc, Bar, Crt;<br />
reg [0:5] Frx;<br />
. . . <br />
Arc = Bar + Crt;<br />
Frx = Bar + Crt;<br />
<br />
  第一个加的结果长度由Bar,Crt和Arc长度决定,长度为4位。第二个加法操作的长度同样由Frx的长度决定(Frx、Bat和Crt中的最长长度),长度为6位。在第一个赋值中,加法操作的溢出部分被丢弃;而在第二个赋值中,任何溢出的位存储在结果位Frx[1]中。<br />
  在较大的表达式中,中间结果的长度如何确定?在Verilog HDL中定义了如下规则:表达式中的所有中间结果应取最大操作数的长度(赋值时,此规则也包括左端目标)。考虑另一个实例:<br />
<br />
wire [4:1] Box, Drt;<br />
wire [1:5] Cfg;<br />
wire [1:6] Peg;<br />
wire [1:8] Adt;<br />
. . .<br />
assign Adt = (Box + Cfg) + (Drt + Peg);<br />
<br />
  表达式左端的操作数最长为6,但是将左端包含在内时,最大长度为8。所以所有的加操作使用8位进行。例如:Box和Cfg相加的结果长度为8位。<br />
<br />
2. 无符号数和有符号数<br />
  执行算术操作和赋值时,注意哪些操作数为无符号数、哪些操作数为有符号数非常重要。无符号数存储在:<br />
* 线网<br />
* 一般寄存器<br />
* 基数格式表示形式的整数<br />
  有符号数存储在:<br />
* 整数寄存器<br />
* 十进制形式的整数<br />
  下面是一些赋值语句的实例:<br />
<br />
reg [0:5] Bar;<br />
integer Tab;<br />
. . .<br />
Bar = -4'd12; //寄存器变量Bar的十进制数为52,向量值为110100。<br />
Tab = -4'd12; //整数Tab的十进制数为-12,位形式为110100。<br />
<br />
-4'd12 / 4 //结果是1073741821。<br />
-12 / 4 //结果是-3<br />
<br />
  因为Bar是普通寄存器类型变量,只存储无符号数。右端表达式的值为'b110100(12的二进制补码)。因此在赋值后,Bar存储十进制值52。在第二个赋值中,右端表达式相同,值为'b110100,但此时被赋值为存储有符号数的整数寄存器。Tab存储十进制值-12(位向量为110100)。注意在两种情况下,位向量存储内容都相同;但是在第一种情况下,向量被解释为无符号数,而在第二种情况下,向量被解释为有符号数。<br />
  下面为具体实例:<br />
<br />
Bar = - 4'd12/4;<br />
Tab = - 4'd12 /4;<br />
<br />
Bar = - 12/4<br />
Tab = - 12/4<br />
<br />
  在第一次赋值中,Bar被赋于十进制值61(位向量为111101)。而在第二个赋值中,Tab被赋于与十进制1073741821(位值为0011...11101)。Bar在第三个赋值中赋于与第一个赋值相同的值。这是因为Bar只存储无符号数。在第四个赋值中,Bar被赋于十进制值-3。<br />
  下面是另一些例子:<br />
<br />
Bar = 4 - 6;<br />
Tab = 4 - 6;<br />
Bar被赋于十进制值62(-2的二进制补码),而Tab被赋于十进制值-2(位向量为111110)。<br />
<br />
  下面为另一个实例:<br />
<br />
Bar = -2 + (-4);<br />
Tab = -2 + (-4);<br />
Bar被赋于十进制值58(位向量为111010),而Tab被赋于十进制值-6(位向量为111010)。<br />
<br />
4.2.2 关系操作符<br />
<br />
  关系操作符有:<br />
<br />
* >(大于)<br />
* <(小于)<br />
* >=(不小于)<br />
* <=(不大于)<br />
<br />
  关系操作符的结果为真(1)或假(0)。如果操作数中有一位为X或Z,那么结果为X。例如:<br />
<br />
23 > 45<br />
结果为假(0),而:<br />
52< 8'hxFF<br />
结果为x。如果操作数长度不同,长度较短的操作数在最重要的位方向(左方)添0补齐。例如:<br />
'b1000 > = 'b01110<br />
等价于:<br />
'b01000 > = 'b01110<br />
结果为假(0)。 <br />
<br />
4.2.3 相等关系操作符<br />
<br />
  相等关系操作符有:<br />
<br />
* = =(逻辑相等)<br />
* !=(逻辑不等)<br />
* = = =(全等)<br />
* != =(非全等)<br />
<br />
  如果比较结果为假,则结果为0;否则结果为1。在全等比较中,值x和z严格按位比较。也就是说,不进行解释,并且结果一定可知。而在逻辑比较中,值x和z具有通常的意义,且结果可以不为x。也就是说,在逻辑比较中,如果两个操作数之一包含x或z,结果为未知的值(x)。<br />
  如下例,假定:<br />
<br />
Data = 'b11x0;<br />
Addr = 'b11x0;<br />
那么:<br />
Data = = Addr<br />
不定,也就是说值为x,但:<br />
Data = = = Addr<br />
为真,也就是说值为1。<br />
<br />
  如果操作数的长度不相等,长度较小的操作数在左侧添0补位,例如:<br />
<br />
2'b10 = = 4'b0010<br />
与下面的表达式相同:<br />
4'b0010 = = 4'b0010<br />
结果为真(1)。<br />
<br />
4.2.4 逻辑操作符<br />
<br />
  逻辑操作符有:<br />
<br />
* && (逻辑与)<br />
* || (逻辑或) <br />
* !(逻辑非)<br />
<br />
  这些操作符在逻辑值0或1上操作。逻辑操作的结构为0或1。例如, 假定: <br />
<br />
Crd = 'b0; //0为假<br />
Dgs = 'b1; //1为真<br />
那么:<br />
Crd && Dgs 结果为0 (假)<br />
Crd || Dgs 结果为1 (真)<br />
! Dgs 结果为0 (假)<br />
对于向量操作, 非0向量作为1处理。例如,假定:<br />
A_Bus = 'b0110;<br />
B_Bus = 'b0100;<br />
那么:<br />
A_Bus || B_Bus 结果为1<br />
A_Bus && B_Bus 结果为 1<br />
并且:<br />
! A_Bus 与! B_Bus的结果相同。<br />
结果为0。<br />
如果任意一个操作数包含x,结果也为x。<br />
!x 结果为x<br />
<br />
4.2.5 按位操作符<br />
<br />
  按位操作符有:<br />
<br />
* ~(一元非)<br />
* &(二元与)<br />
* |(二元或)<br />
* ^(二元异或)<br />
* ~^, ^~(二元异或非)<br />
<br />
  这些操作符在输入操作数的对应位上按位操作,并产生向量结果。下表显示对于不同操作符按步操作的结果。<br />
<br />
  例如,假定,<br />
A = 'b0110;<br />
B = 'b0100;<br />
那么:<br />
A | B 结果为0110<br />
A & B 结果为0100<br />
如果操作数长度不相等, 长度较小的操作数在最左侧添0补位。例如,<br />
'b0110 ^ 'b10000<br />
与如下式的操作相同: <br />
'b00110 ^ 'b10000<br />
结果为'b10110。<br />
<br />
4.2.6 归约操作符<br />
<br />
  归约操作符在单一操作数的所有位上操作,并产生1位结果。归约操作符有:<br />
<br />
* & (归约与)<br />
如果存在位值为0, 那么结果为0;若如果存在位值为x或z,结果为x;否则结果为1。<br />
* ~& (归约与非)<br />
与归约操作符&相反。<br />
* | (归约或)<br />
如果存在位值为1,那么结果为1;如果存在位x或z,结果为x;否则结果为0。<br />
* ~| (归约或非)<br />
与归约操作符|相反。<br />
* ^ (归约异或)<br />
如果存在位值为x或z,那么结果为x;否则如果操作数中有偶数个1, 结果为0;否则结果为1。<br />
* ~^ (归约异或非)<br />
与归约操作符^正好相反。<br />
如下所示。假定,<br />
A = 'b0110;<br />
B = 'b0100;<br />
那么:<br />
|B 结果为1<br />
& B 结果为0<br />
~ A 结果为1<br />
归约异或操作符用于决定向量中是否有位为x。假定,<br />
MyReg = 4'b01x0;<br />
那么:<br />
^MyReg 结果为x<br />
  上述功能使用如下的if语句检测:<br />
<br />
if (^MyReg = = = 1'bx)<br />
$ display ("There is an unknown in the vector MyReg !")<br />
<br />
注意逻辑相等(==)操作符不能用于比较;逻辑相等操作符比较将只会产生结果x。全等操作符期望的结果为值1。<br />
<br />
4.2.7 移位操作符<br />
<br />
  移位操作符有:<br />
<br />
* << (左移)<br />
* >> (右移)<br />
<br />
  移位操作符左侧操作数移动右侧操作数表示的次数,它是一个逻辑移位。空闲位添0补位。如果右侧操作数的值为x或z, 移位操作的结果为x。假定:<br />
<br />
reg [0:7] Qreg;<br />
. . .<br />
Qreg = 4'b0111;<br />
那么:<br />
Qreg >> 2 是 8'b0000_0001<br />
<br />
  Verilog HDL中没有指数操作符。但是,移位操作符可用于支持部分指数操作。例如,如果要计算ZNumBits的值,可以使用移位操作实现,例如:<br />
<br />
32'b1 << NumBits //NumBits必须小于32。<br />
同理,可使用移位操作为2-4解码器建模,如<br />
wire [0:3] DecodeOut = 4'b1 << Address [0:1];<br />
Address[0:1] 可取值0,1,2和3。与之相应,DecodeOut可以取值4'b0001、4'b0010、4'b0100和4'b1000,从而为解码器建模。<br />
<br />
4.2.8 条件操作符<br />
<br />
  条件操作符根据条件表达式的值选择表达式,形式如下:<br />
<br />
cond_expr ? expr1 : expr2<br />
<br />
如果cond_expr 为真(即值为1),选择expr1;如果cond_expr为假(值为0),选择expr2。 如果cond_expr 为x或z,结果将是按以下逻辑expr1和expr2按位操作的值: 0与0得0,1与1得1,其余情况为x。<br />
如下所示:<br />
<br />
wire [0:2] Student = Marks > 18 ? Grade_A : Grade_C;<br />
<br />
计算表达式Marks > 18; 如果真, Grade_A 赋值为Student; 如果Marks < =18, Grade_C 赋值为Student。下面为另一实例:<br />
<br />
always<br />
#5 Ctr = (Ctr != 25) ? (Ctr + 1) : 5;<br />
过程赋值中的表达式表明如果Ctr不等于25, 则加1;否则如果Ctr值为25时, 将Ctr值重新置为5。<br />
<br />
4.2.9 连接和复制操作<br />
<br />
  连接操作是将小表达式合并形成大表达式的操作。形式如下:<br />
<br />
{expr1, expr2, . . .,exprN}<br />
<br />
  实例如下所示:<br />
<br />
wire [7:0] Dbus;<br />
wire [11:0] Abus;<br />
<br />
assign Dbus [7:4] = {Dbus [0], Dbus [1], Dbus[2], Dbus[3]};<br />
//以反转的顺序将低端4位赋给高端4位。<br />
assign Dbus = {Dbus [3:0], Dbus [7:4]};<br />
//高4位与低4位交换。<br />
由于非定长常数的长度未知, 不允许连接非定长常数。例如, 下列式子非法:<br />
{Dbus,5} //不允许连接操作非定长常数。<br />
复制通过指定重复次数来执行操作。形式如下:<br />
{repetition_number {expr1, expr2, ...,exprN}}<br />

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -