当前位置: 代码迷 >> 综合 >> Verilog HDL的语言--运算符,变量
  详细解决方案

Verilog HDL的语言--运算符,变量

热度:123   发布时间:2023-11-08 21:15:19.0

A、常 量

(1)数 字

**整数,**整型常量即整常数有以下4种进制表示形式:
1)二进制(b或B);
2)十进制(d或D);
3)十六进制(h或H);
4)八进制(o或O)。

数字表达式分为三种:

1)<位宽><进制><数字>,这是最完整的形式。

2)<进制><数字>,数字的位宽采用默认位宽(不同的机器系统不同,至少32位)。

3)<数字>,采用默认进制(十进制)。

示例:(位宽指的是时间所占位数,而不是指十六进制有几位。如示例二,每一位十六进制数字需要4位二进制数字表示,所以2位十六进制的位宽为8)

8’b10101100 //位宽为8的二进制数字10101100

8’ha2 //位宽为8的十六进制数字a2

**x值和z值:**在数字电路中,x代表不定值,z代表高阻值。一个x可以定义十六进制的4位,八进制的3位。z的表示方式同x相同,另外z亦可以用“?”来表示。(case块中用得较多)

4’b10x0 //位宽为4的二进制数从低位数起第二位为不定值

4’b101z //位宽为4的二进制数从低位数起第一位为高阻值

12’dz //位宽为12的10进制数,其值为高阻值(形式一)

12’d? //位宽为12的10进制数,其值为高阻值(形式二)

8’h4x //位宽为8的十六进制数,其低4位为不定值

**负数:**在位宽前面加一个减号,减号必须在数字定义表达式的最前面。

-8’d5 //代表5的补数(采用8位二进制表示)
**下划线:**用于区别开数字的表达式以提高程序的可读性。不能用在位宽和进制的地方,只能用在数字之间(数字前也不可以)。

16’b1010_1011_1111_1010 //合法形式

常量未加标志时,默认为32位的十进制数,字母用八位的ASCII值表示。

“AB”=16’b01000001_01000010 //字符串AB,为十六进制数16’h4142

(1)wire型,默认为高阻值z。

网络数据类型包括 wire型 和 tri型 数据。

wire用于表示单个门驱动或者连续赋值语句驱动的网络数据类型;

tri型则用来表示多驱动器驱动的网络型数据。

如果没有定义wire和tri的逻辑强度,在多驱动元的情况下逻辑值会发生冲突,从而产生不确定值。
(2)reg型,默认为不定值x。

寄存器是存储单元的抽象,寄存器数据类型的关键字是reg。常用来表示always模块内的指定信号,代表触发器。在always模块内被赋值的每一个信号都必须定义成reg型。格式与wire型类似:

reg [n-1,0] 数据名1,数据名2,…数据名i;

reg [n,1] 数据名1,数据名2,…数据名i;

reg数据可以赋正值,也可以赋负值。但是当一个reg数据是一个表达式的操作式时,它的值被当做无符号值,即正值。如:4位的reg被赋值为-1,在表达式中为+15.

reg型只是表示被定义的信号将被用在always模块中,并不是说reg型数据就一定是存储器或触发器的输出。
在这里插入图片描述
注意: 被赋值的信号

(3)memory型(特殊的reg)

在Verilog中通过对reg数据建立数组来对存储器进行建模,用来买哦书RAM ROM和reg文件。verilog中没有多维数组存在,memory型数据是通过扩展reg型数据的地址范围实现的。存储器的地址索引必须是常数表达式(n-1,m-1等必须是常量,符号常量也可以)。如:

reg [n-1,0] 存储器名[m-1,0];

reg [n-1,0] 存储器名[m,1];

在这里[n-1,0]定义了存储器中每一个存储单元的大小,即n位寄存器。存储器名后面的[m-1,0],表示定义的存储器中有多少个这样的寄存器。

reg [7,0] mem[255,0]; //256个8位寄存器的存储器mem

reg [n-1,0] rega; //一个n位的寄存器

reg mema[n-1,0] //n个1位的寄存器形成的存储器

rega = 0; //合法,对n位的寄存器赋值位0

mema = 0; //非法,不能对完整的存储器直接赋值

mema[3] = 0; //合法,将mema中第三个存储单元赋值为0

Verilog HDL的语言的运算符的范围很广,按照其功能大概可以分为以下几类:

(1)算术运算符 +,-,*,/,%
优先顺序

!~/   % *-
<<    >>
<    <=  >   >=  
==    !==   ===          !===
&
^  ^~
|
&&
||
?:

(2)赋值运算符 =,<=
(3)关系运算符> ,<,>=,<=
(4)逻辑运算符 &&, ||, !
(5)条件运算符 ?:
(6)位运算符 ~, | , ^ ,& ,^~
(7)移位运算符 << ,>>
(8)拼接运算符 {}
(9)其他。

1)基本的算术运算符:加减乘都比较简单这里不再记录。
在进行整数的除法运算时,结果要略去小数部分,只取整数部分;而进行取模运算时(%,亦称作求余运算符)结果的符号位采用模运算符中第一个操作数的符号。

-10%3  结果 -1  11%-3  结果为2

注意:在进行算术运算时,如果某一个操作数有不确定的值x,则整个结果也为不确定值x。

2)位运算符:
按位取反~ 、
按位与 & 、
按位或 | 、
按位异或 ^ 、
按位同或 ^~
在不同长度的数据进行位运算时,系统会自动的将两个数右端对齐,位数少的操作数会在相应的高位补0,一时的两个操作数按位进行操作。

3)逻辑运算符:
逻辑与 &&、逻辑或 ||、逻辑非 !
其中&&和||是双目运算符,其优先级别低于关系运算符,而 !高于算术运算符。
4)关系运算符
< 、 > 、 <= 、 >= 如果关系运算是假的,则返回值是0,如果声明的关系是真的,则返回值是1。 关系运算符的优先级别低于算数运算符。

如:  a<size-1                //这种表达方式与下面的表达方式相同a<(size-1)             //size-1<a               //这种表达方式与下面的表达方式不同size-(1<a)            //

5)等式运算符

== 、!= 、===、!==  符号之间不能有空格。
“==”和“!=”称作逻辑等式运算符,其结果由两个操作数的值决定。由于操作数可能是x或z,其结果可能为x;
“===”和“!==”常用于case表达式的判别,又称作cae等式运算符。其结果只为0和1.如果操作数中存在x和z,那么操作数必须完全相同结果才为1,否则为0.

6)移位运算符

<< 、 >> a>>n其中a代表要进行移位的操作数,n代表要移几位。这两种移位运算都用0来填补移出的空位。
如果操作数已经定义了位宽,则进行移位后操作数改变,但是其位宽不变。

/*不懂之处;(夏宇闻第三版,p41) 
4'b1001<<1=5'b10010;    4'b1001<<2=6'b100100;   (左移会使得位数增加?)          一般会定义位数。所以位数不会增加
答:左移相当于乘2
1<<6=32'b1000000;        4'b1001>>1=4'b0100;       (右移不会改变位数?)
4‘b1001>>4=4'b0000;
答:右移相当于除2
*/

7)位拼接运算符
{信号1的某几位,信号2的某几位,…信号n的某几位} 将某些信号的某些为列出来,中间用逗号分开,最后用大括号括起来表示一个整体的信号。
在位拼接的表达式中不允许存在没有指明位数的信号。

{a,b[3:0],w,3'b101}               //等同于{a,b[3],b[2],b[1],b[0],w,1b'1,1'b0,1'b1}
{4{w}}                                   //等同于{w,w,w,w}
{b,{3{a,b}}}                          //等同于{b,a,b,a,b,a,b}  这里面的3、4必须是常量表达式。

8)缩减运算符
这是单目运算符,也包括与、或、非运算。运算规则与位运算相似,不过是对单个运算符的每一位逐步运算,最后的运算结果是一位的二进制数。
c=&B; //意思同c=((B[0]&B[1]) &B[2] ) & B[3];

附录:myself

always@(posedge clk or negedge rst_n) beginif(~rst_n) beginmode_r <= 8'h00;endelse beginmode_r <= #1 mode;     //  #1 只是在仿真中起作用,综合后不起作用mode_r <=mode;  end
endalways@(posedge clk or negedge rst_n) beginif(!rst_n) begindin_r1 <= 0;
endelse begindin_r1 <= din;end
endassign din_rp = din& ~din_r1;     //上升沿
assign din_fp = ~din & din_r1;      //下降沿always @(posedge clk1) //aa<=data_in; always @(posedge clk2) //bb<=a;   always @(posedge clk2) //cc<=b;    always @(posedge clk2) //dd<=c;    assign data_out=c&&~d;        //一电路会检测同步器输入的上升沿,产生一个与时钟周期等宽、高电平有效的脉冲//用Verilog描述的边沿(上升沿)检测同步器

未完待续。。。。。。。。。。。

 assign  bs= ((d[18] == 1'b1) && (d[17:9] < 9'b110010000)) ? 8'b10010000 :  ((d[18] == 1'b0) && (d[17:9] > 9'b001110000)) ? 8'b01110000 :  d[16:9]; 

如何造帧,场同步信号

位运算符 |

assign din_rp = din& ~din_r1; //上升沿 1&~ 0 =1&1 结果 1
assign din_fp = ~din & din_r1; //下降沿