fpga论坛|fpga设计论坛

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 31|回复: 0

【Verilog语法简介】

[复制链接]
dameihuaxia 发表于 昨天 10:33 | 显示全部楼层 |阅读模式
1.Verilog简介
Verilog语言是一种用于建模电子系统的硬件描述语言,这种硬件描述语言最多的用于进行数字电路系统的寄存器传输级建模和验证工作,同时一些例如生物电路等数模混合电路的建模和验证电路。Verilog语言的语法规则与C语言有很多相似之处。Verilog语言的标准化内容在IEEE 1364标准中规定。

2. Verilog语法讲解
Verilog硬件描述语言有变量和常量,下面分别对变量和常量进行介绍。

2.1 Verilog变量数据类型
2.1.1 线网型数据(Nets)
线网型数据代表着不同电路结构体之间的直接物理连接。这种类型的变量不存储数据,变量的值跟随驱动信号的变化而进行瞬时变化。这种数据类型用关键字wire来定义。
下面表格是wire类型变量的值,下一节要介绍的reg类型值也类似。
在这里插入图片描述

2.1.2 寄存器型数据(Reg)
寄存器类型变量经常用在时序电路中。这种类型的变量可以存储数据的值。触发信号到来时,变量的值跟随驱动信号变化。触发信号没有到来时,变量值不变化。寄存器类型数据使用关键字reg来定义。

2.1.3 其他数据类型:(integer、real、time)
integer、real、time这三种变量其实也是寄存器类型的变量。
integer变量一般是一个32bit的整形数据。
real 变量是一个IEEE标准的64bit浮点型数据。
time是一个64位的无符号整形变量。代表了仿真运行时间.可以利用系统函数$time查看time类型的变量.

2.1.4 向量型数据结构
2.1.1和2.1.2两节中提到的wire类型和reg类型都是1 bit数据。Verilog中存在向量类型(Vector),向量变量类型代表了一个包含了多bit数据的一个数据类型。
下面这段代码定义了一个线网型wire类型数据的向量signal,signal变量包含了32bit数据。[31:0]代表了32bit数据的最高位角标位31,最低为角标为0。

wire [31:0] signal
下面这段代码定义了一个线网型reg类型数据的向量signal,signal变量包含了32bit数据。[31:0]代表了32bit数据的最高位角标位31,最低为角标为0。

reg [31:0] signal
2.1.5 存储器类型数据
寄存器变量组成的数组就是存储器类型数据。定义语句如下所示:

reg [15:0] memo [7:0];
上面的语句定义类一个存储器memo,有8个存储单元,每个存储单元有16位。

2.1.6 Verilog常量表示
Verilog中的常量主要有整数型和参数型常量
对于整型常量最完整的描述为<位宽><数制><数值>。位宽和数制可以根据需要或者指定或者省略。对于整型数据的数制类型主要有二进制(b或B表示)、八进制(o或O表示)、十六进制(h或H表示)。可以以如下形式表示:

//指明数据位宽,二进制数据
4'b1011
//指明数据位宽、十六进制表示
4'hFF
//负数表示,符号标注在最前面
-4'b1001
参数型的常量是使用关键字parameter来申明,被称为参数型变量。parameter类型常量赋值语句的右边都必须是一个常数表达式。参数类型定义的示例:

parameter msb =7;
2.2 Verilog操作符
Verilog运算符可以分为10个大类。

2.2.1 算数运算符
+                                //加法
-                                //减法
*                                //乘法
/                                //整除
%                                //取余
**                                //幂运算
Hint:
在进行算数运算操作时,只要有一个操作数为x和z,则运算结果为x。

2.2.2 赋值运算符
详细见2.4节

2.2.3 关系运算符
关系运算符用于判断两个操作数的大小。操作数之间的关系为真时返回为1,当为假时返回值为0。

>                                        //大于
>=                                        //大于或者等于
<                                        //小于
<=                                        //小于或者等于
Hint:
关系运算符的优先级低于算数运算符。在进行关系运算操作时,只要有一个操作数为x和z,则运算结果为x。

2.2.4 等式运算符
等式运算符用于判断两个操作数的是否x。操作数之间的关系为真时返回为1,当为假时返回值为0。

==                                        //相等
!=                                        //不相等
===                                        //全等
!==                                        //不全等
运算符==,!=进行比较时,值x和’z’具有物理意义,操作数中包含了x和z,则逻辑相等比较结果为x。
运算符===,!==,可以比较含有x和z的操作数,比较时,不考虑x和z的物理含义,严格按照字符值进行比较,结果非零即一。
下面这个例子可以用来说明问题。

a=4'b10x0
b=4'b10x0
//a和b是两个位宽为4的二进制表示的整型量,最低位起第二位为不定值(x)
(a==b)返回的结果是x
(a===b)返回结果是1
2.2.5 逻辑运算符
&&                                逻辑与
||                                逻辑或
!                                逻辑非
2.2.6 条件运算符
条件操作符根据条件表达式的值从两个表达式中选择其一,语法格式为:
(条件表达式)?表达式1:表达式2

表示若条件表达式为真,则返回表达式1的值,若条件表达式为假,则返回表达式2的值。

wire y;
assign y=(sel==1)?a:b;
2.2.7 位运算符
位运算符共有7种:

&                                                //与
|                                                //或
~                                                //非
^                                                //异或
^~                                                //同或
~&                                                //与非
~|                                                //或非
位操作是对变量的每一位进行操作。如果两个操作数的长度不相等,将会对较短的数高位补零,然后进行对应位操作,输出结果的长度与位宽较长的操作数长度保持一致。

2.2.8 移位运算符
移位运算符用于将操作符左侧的操作数向左或者向右移位,移位的次数与运算符的右侧的位数决定。

<<                                //逻辑左移
>>                                //逻辑右移
<<<                                //算数左移
>>>                                //算数右移
语法格式如下:
<操作数><移位运算符><移位位数>,如data<<2,即data信号逻辑左移两位”.
逻辑移位运算符示例如下:

reg [3:0] a;
a =4'b0010;
a<<2    //左移两位,左边丢弃,右边补零,结果是4‘b1000;类似的a>>2,右移两位,右边丢弃,左边补零,结果为4’b0000;
算数移位运算符,对于左移产生的空位补零。算数右移运算符,对于无符号数,右移产生的空位用0补齐,有符号数用有符号位补齐。

2.2.9 拼接运算符
拼接运算符{}用于两个或者以上的线网型变量或者寄存器类型变量拼接起来,形成一个整体。
拼接运算符的语法结构为:
{信号1或者信号1的某几位,信号2或者信号2的某几位,......,信号n或者信号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必须是常量表达式。
2.2.10 缩位运算符
缩位运算符是对单个操作数上的所有位进行操作,结果返回一位数。

reg [3:0] d;
reg y1,y2;
y1=&d;//缩位与,y1=d[3]&d[2]&d[1]&d[0]
y2=|d;//缩位或,y2=d[3]|d[2]|d[1]|d[0]
2.3 模块(module)定义
2.3.1模块定义
模块定义部分包括模块名和IO端口定义部分,以关键词module开始,以关键词endmodule结束。语法结构如下:
module 模块名(端口1,端口2,端口3,…,端口n);
//端口之间用,。语句结束用;
endmodule
在设计时,建议一个模块用一个文件,并且文件名和模块名相同。

2.3.2 端口定义
Verilog支持input,output,inout 三种端口类型。
input代表输入口;
output代表输出口;
inout代表双向口;

2.4 赋值语句
2.4.1 assign 赋值
利用assgin语句进行的是连续赋值,类似于电路中将端口连接起来,激励信号值变化,结构会跟着变化。这种语句用在always语句块以外。只能用assgin语句给wire型变量赋值。

2.4.2 阻塞赋值
阻塞赋值使用=进行赋值。

2.4.3 非阻塞赋值
非阻塞赋值使用<=进行赋值。
Hint:
阻塞赋值和非阻塞赋值都可以被称作过程赋值。都只能对与寄存器(reg)变量进行赋值。阻塞赋值的含义是在前一条阻塞赋值语句结束前,后一条语句不能执行被阻塞。非阻塞赋值的含义是非阻塞语句同时执行,相互不影响。

2.5 initial/always语句
initial语句是不可综合语句,相关代码不能被综合为硬件电路。一般被用于仿真场景中,在仿真时刻的零时刻开始运行一次。
always语句块是一种周期性的语句块。其中的代码会顺序执行。
最一般化的语句块结构如下所示:

always @(敏感信号列表)
begin
......
end
@后面括号中的表达式是敏感信号列表,用来标志合适always语句块中的代码何时应当执行。如果没有敏感信号列表语句块中的输入信号任何一个发生变化,语句块中的语句开始执行。
存在敏感信号列表的情况下,又可以进一步分为电平敏感和时钟沿敏感。如下面这段代码所示:

always @(a or b)
begin
......
end
a、b中任何一个信号变化,都会执行语句块中语句。

always @ (posdege clk)
begin
......
end
always @ (negedge clk)
begin
......
end
上面两段代码是clk的上升沿或者下降沿到来时,语句块开始执行。
本节中介绍提及了可综合语句和不可综合语句。这是因为Verilog是用于进行硬件建模的。也就是Verilog代码要被编译综合为电路模块,所以有些语句和代码写法是无法被综合为电路的。这些不可综合语句主要是进行系统仿真。对于Verilog代码可否综合这个问题,这个知乎答案做了很好的总结,分享在本文中。Verilog中可综合与不可综合的语句

2.6 条件语句
2.6.1 if语句
if-else语句的语法结构如下:

if (条件表达式1) 块语句1;
        else if (条件表达式2) 块语句2;
        ...
        else if (条件表达式n) 块语句n;
                else 块语句n+1;
2.6.2 case语句
case 语句的语法结构如下:

case(表达式)
列出值1:语句块1;
列出值2:语句块2;
......
列出值n:语句块n;
default: 语句块n+1;
endcase
2.6.3 casez和casex语句
除了case-endcase语句以外,还有类似的casez-endcase和casex-endcase。
casez中列出值和表达式中的z被认为是无关项,判断为"1"。
casex中列出值和表达式中的x和z都被认为是无关项,判断为"1"。
在这里插入图片描述

2.7 循环语句
2.7.1 for语句
Verilog中for语句和C语言中的用法相同。

2.7.1 while语句
Verilog中while语句与C语言中的用法相同。

2.7.3 repeat语句
repeat预计按照循环控制条件表达式指定的次数重复循环执行快预计,循环次数在执行语句前就已经确定。如果循环控制条件为x或z,执行次数为0次。
语法结构为

repeat(循环控制条件表达式) 块语句;
2.8 层次化设计
Verilog设计的逻辑模块可以引用之前设计完成的逻辑模块。这个过程可以被称为模块的实例化。即在另一个模块中,创建另外一个模块的实例,在实例化的过程中指明实例的名称,将上一层模块中的信号与等待实例化的模块的输出输出端口完成映射。其语法结构如下所示:

bottom1 u1(.a(q), .b(p), .c(intsig));
bottom2 u2(.l(intsig), .m(r), .n(out));
端口映射表的结构为:
<模块名><实例名>(端口映射表)
端口映射表的格式为:
.<模块端口名>(信号名)
不同端口d的映射之间用,隔开。
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-11-19 03:15 , Processed in 0.115066 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表