第一章 Verilog基础知识


1,Verilog语法要素

1.1 空白符

包括 空格符(\b)、制表符(\t) 、换行符和换页符。在编译和综合时,空白符会被忽略。
例如:

wire [1:0]  results ;assign results = (a == 1'b0) ? 2'b01 : (b==1'b0) ? 2'b10 : 2'b11 ;
//相当于
wire [1:0]  results ;
assign  results = (a == 1'b0) ? 2'b01 :
            (b==1'b0) ? 2'b10 :
                2'b11 ;

1. 2 注释符

(1)单行注释:以” // “开始,Verilog HDL忽略从此处到行尾的内容。
(2)多行注释:多行注释以“/*“开始,到“*/‘结束,Verilog HDL忽略其中的注释内容。
例如:

wire [1:0]  ip; //定义一个线网类型
reg[5-1:0]  op; //定义一个寄存器类型
/*
result数据宽为2
op数据宽为5
*/

1.3 标识符

在Verilog中标识符(Identifier)被用来命名信号名、模块名、参数名等,它可以是任意一组字母、数字、“$”符号和 '_' (下划线)符号的组合。应该注意的是标识符的字母区分大小写,并且第一个字符必须是字母或者下划线。
(2)关键字是 Verilog 中预留的用于定义语言结构的特殊标识符。Verilog 中关键字全部为小写。
例如:

//合法标识符				//非法标识符
count					30count	//标识符不允许以数字开头
COUNT//与count不同		out*	//标识符中不允许包含字符*
CC G5					a+b-c	//标识符中不允许包含字符+和一
B25 78					n@238	//标识符中不允许包含字符@
SIX

1.4 关键字

关键字是 Verilog 语言内部的专用词,是事先定义好的确认符,用来组织语言结构,这些关键字用户不能随便使用。需注意的是,所有关键字都是小写的
例如,ALWAYS不是关键字,它只是标识符,与always(关键字)是不同的。

关键字 含义
module 模块开始
input 输入端口定义
output 输出端口定义
inout 双向端口定义
parameter 参数定义
wire 线网信号定义
reg 寄存器信号定义
always 产生reg信号语句的关键字
assign 产生wire信号语句的关键字
begin 语句的开始标志
end 语句的结束标志
posedge/negedge 时序电路的标志
case case语句开始标志
default case语句默认分支标志
endcase case语句结束标志
if 判断语句开始标志
else 判断语句标志
for 循环语句标志
endmodule 模块结束标志

表格待补充...

1.5 转义标识符

Verilog规定了转义标识符(Escaped Identifier)。采用转义标识符可以在一条标识符中包含任何可打印字符,转义标识符以”\“(反斜线)符号开头,以空白结尾(空白可以是一个空格、一个制表字符或换行符)。
例如:

\a+b=c 
\7400
\~Q
\{******}
转义字符 显示字符
\n 换行
\t 制表符
%% %
\ |
\ooo 1到3个8进制数字字符

1.6 数值

  • verilog有四种基本的逻辑数值状态
状态 含义
0 低电平、逻辑0或“假”
1 高电平、逻辑1或“真”
x或X 不确定或未知的逻辑状态
z或Z 高阻态
  • 整数及其表示
      +/-<Size>'<base format><number>
数制 基数符号 合法表示符
二进制 b或B 0、1、x、X、z、Z、?、_
八进制 o或O 0~7、 x、 X、z、Z、?、_
十进制 d或D 0 ~ 9、_
十六进制 h或H 0 ~ 9、 a ~ f、A ~ F、x、X、 z、Z、? 、_

例如:

//正确表示:
8'b10001101 //位宽为8位的二进制数10001101
8'ha6 //位宽为8位的十六进制数a6
4'd6 //4位十进制数6
4'blx_01	//4位二进制数1x01

//错误表示:
4'd-4 //数值不能为负,有负号应放最左边
3'  b001 //'和基数b之间不允许出现空格
(4+4)'b11 //位宽不能是表达式形式
  • 实数及其表示
    (1)十进制表示法,采用十进制格式,小数点两边必须都有数字,否则为非法的表示形式。例如:9.0,6.59,0.31415等等都是正确的,而3.就是错误扯的表达方式,因为小数点两侧都必须要有数字。
    (2)科学计数法。例如:3141.5e2的值为31415.0、3.6E-2的值为0.036。
    例如:
2.7 //十进制计数法
5.2e8 //科学计数法
3.5E-6 //科学计数法可用e或E表示,其结果相同
5_4582.2158_5896 //使用下划线提高可读性
6. //非法表示
.3e5 //非法表示

2,数据类型

  • 物理数据类型·连线型、寄存器型和存储器型数据类型;
    信号强度表示数字电路中不同强度的驱动源,用来解决不同驱动强度存在下的赋值冲突:
标记符 名称 类型 强弱程度
supply 电源级驱动 驱动 最强
strong 强驱动 驱动
pull 上拉级驱动 驱动
large 大容性 存储
weak 弱驱动 驱动
medium 中性驱动 存储
small 小容性 存储
highz 高容性 高阻 最弱

注:由上到下逐渐减弱。

2.1 物理数据类型

  • 连线型
连线型数据类型 功能说明
wire,tri 标准连线(缺省时为该类型)
wor,trior 多重驱动时,具有线或特性的连线型
wand,trand 多重驱动时,具有线与特性的连线型
trireg 具有电荷保持特性的连线型数据(特例)
tri1 上拉电阻
tri() 下拉电阻
supply1 电源线,用于对电源建模,为高电平1
supply() 电源线,用于对“地”建模,为低电平0
  • wire和tri
    在这里插入图片描述
  • wor和trior
    在这里插入图片描述
  • 寄存器型
    reg型是数据储存单元的抽象类型,其对应的硬件电路元件具有状态保持作用,能够存储数据,如触发器、锁存器等。
    reg型变量常用于行为级描述,由过程赋值语句对其进行赋值。
    reg型变量简单例子:
reg a;	//定义一个一位的名为a的reg变量 
reg [3:0] b;	//定义一个4位的名为b的reg型变量
reg[8:1]c,d,e; //定义了=个名称分别为c、d、e的8位的reg型变量

reg型变量一般为无符号数,若将一个负数赋给reg型变量,则自动转换成其二进制补码形式。例如:

reg signed[3:0] rega;
rega=-2	//rega的值为1110(14),是2的补码.

2.2 连线型和reg型数据类型的声明

  • 连线型数据类型的声明:

<net_declaration><drive_strength><range><delay>[list_of_variables];

 `net_declaration`:包括wire、trim、tri0、tri1、wand、triand、trior、wor中的任意一种。
 
 `drive_strength`:表示连线变量的驱动强度。
 
 `range`:用来指定数据类型为标量或矢量。若该项默认,表示数据类型为1位的标量,超过一位则为矢量类型。
 
 `delay`:指定仿真延迟时间。
 
 `list_of_variables`:变量名称,一次可定义多个名称,之间用逗号分开。
  • 寄存器型数据类型的声明:

reg<range><list_of_register_variables>;

`range`:为可选项,它指定了reg型变量的位宽,缺省时为1位。

`<list_of_register_variables>`:为变量名称列表,一次可以定义多个名称,之间用逗号分开。

例如:物理类型数据声明:

 reg rega  //定义一个1位的寄存器型变量   
 reg [7:0] regb; //定义一个8位的寄存器型变量   
 tri [7:0] tribus; //定义一个8位的三态总线   
 tri0 [15:0] busa; //定义一个16位的连线型,处于三态时为上拉电阻   
 tril [31:0] busb; //定义一个32位的连线型,处于三态时为下拉电阻   
 reg scalared[l1:4] b; //定义一个4位的标量型寄存器矢量   
 wire(pull1 ,strong0)c=a+b; //定义一个1和0的驱动强度不同的1位连线型变量c
 trireg(large) storeline;	//定义一个具有大强度的电荷存储功能的存储线

2.3 存储器型

  • 存储器型变量可以描述RAM型、ROM型存储器以及reg文件。
  • 存储器变量的一般声明格式为: reg<range1><name_of_register>;
    range1和range2都是可选项,缺省都为1。
    <range1>:表示存储器当中寄存器的位宽,格式为[msb:lsb]
    <range2>:表示寄存器的个数,格式为[msb:lsb],即有msb-lsb+l个。
    <name_or_register>为变量名称列表,一次可以定义多个名称,之间用逗号分开。
  reg[7:0] meml [255:0];//定义了一个有256个8位寄存器的存储器meml 
  						//地址范围是0到255    
  						
  reg [15:0] mem2[127:0],regl,reg2; //定义了一个具有128个16位寄存器的存储器mem2
  									//和两个16位的寄存器regl和reg2
  reg[n-1:0]  a; //表示一个n位的寄存器a
  reg mem1[n-1:0]; //表示一个由n个1位寄存器构成的存储器mem1

2.4 抽象数据类型

  • 抽象数据类型主要包括整型(integer)、时间型(time) 、实型(real)及参数型(parameter) 。
  • 整型:integer<list_of_register_variables>;
    例如:
 integer index; //简单的32位有符号整数
 integer i[31:0]; //定义了整型数组,有32个元素
  • 时间型
    时间型数据与整型数据相类似,只是它是64位的无符号数。时间型数据主要用于对模拟时间的存储与计算处理,常与系统函数$time—起使用。
    时间型数据的声明格式为:time<list_of_register_variables>;
    例如:
     time a,b; //定义了两个64位的时间型变量
  • 实型:实型数据在机器码表示法中是浮点型数值,可用于对延迟时间的计算。
    实型数据的声明格式:real<list_of_variables>;
    例如:
     real Stime; //定义了一个实数型数据 
  • 参数型(parameter):属于常量,在仿真开始之前就被赋值,在仿真过程中保持不变,以提高程序的可读性和维护性。
    参数类型的定义格式为:
    parameter 参数名1=表达式1,参数名2=表达式2,…,参数名n:表达式n;
    例如:
parameter length = 32 ,weight = 16;
parameter PI = 3.14  , LOAD = 4'b1101;
parameter DELAY = (BYTE + BIT) / 2;

3,运算符和表达式

Verilog运算符 功能 运算符的优先级别
! , ~ 反逻辑、位反相 高优先级
* , / , % 乘、除、取模
+ , – 加、减
<< , >> 左移、右移
< , <= , => , > , >= 小于、小于等于、大于、大于等于
== , != , === , !== 等、不等、全等、非全等
& 按位与
^ , ^~ 按位逻辑异或和同或
| 按位逻辑或
& 逻辑与
|| 逻辑或
?: 条件运算符,唯一的三目运算,等同于if-else 低优先级

注:由上到下优先级由高到低。

3.1 算术操作符

  • 加法(+),减法(-),乘法(*),除法(/),取模(%)。

(1)算术操作结果的位宽
算术表达式结果的长度由最长的操作数决定。在赋值语句下,算术操作结果的长度由操作左端目标长度决定。
例如:

reg[3:O] A,B,C; 
reg[5:O] D;
A=B+C; //4位
D=B+C; //6位

(2)有符号数和无符号数的使用
例如:

module oper; 
reg [3:0] a;
reg [2:0] b;
initial 
	begin
		a=4'b1111; //15
		b=3'b011; //3
		$display("%b",a*b); //乘法,结果为:4'b1101,高位被舍去
		$display("%b",a/b); //除法,结果为:4'b0101
		$display("%b",a+b); //加法,结果为:4'b0010
		$display("%b",a-b);	//减法,结果为:4'b1100
		$display("%b",a%b); //取模,结果为:4'b0000
	end
endmodule

3.2 关系操作符

  • 大于(>),小于(<),大于等于(>=),小于等于(<=)
    例如:
module oper; 
reg[3:0]a,b,c,d;
initial 
	begin 
		a=3; b=6; c=1; d=4'hx; 
		$display(a<b); //1
		$display(a>b); //0
		$display(a<=b); //0
		$display(d<=a); // 未知数x
	end
endmodule

3.3 相等关系操作符

  • 等于(==),不等于(!=),全等(===),非全等(!==)。
  • 比较结果有三种,即真,假和不定值。
    如下真值表:
    在这里插入图片描述
    在这里插入图片描述
    例如:
    在这里插入图片描述

3.4 逻辑运算符

  • 逻辑与运算符”&&“、逻辑或运算符”||“、逻辑非运算符”!”

在这里插入图片描述
例如:

寄存器变量a,b的初值分别为4'b1110和4'b0000,则:!a=0,!b=l,a&&b=0; allb=1。

a的初值为4'b1100,b的初值为4'b01X0,则!a=0,!b=x, a&&b=x, a||b=x。操作数中存在不定态x,则逻辑运算的
结果也是不定态。

3.5 按位运算符

  • 按位取反”~“、按位与”&“、按位或”|“、按位异或”^“、按位同或”^~”
    在这里插入图片描述
    在这里插入图片描述

3.6 归约运算符(缩位运算符)

  • 与”&“、或”|“、异或”^“、以及相应的非操作”&“、”~|“、”~^“、”^~”
    例如:
    在这里插入图片描述

3.7 移位操作符

  • 左移位运算符“<<“、右移位运算符”>>”.
  • 运算过程是将左边(右边)的操作数向左(右)移,所移动的位数由右边的操作数来决定,然后用0来填补移出的空位。在这里插入图片描述

3.8 条件运算符

  • 表达形式如下:
    <条件表达式>?<表达式1 >:<表达式2>
    条件表达式的计算结果有真“1″、假“0″和未知态x“三种,当条件表达式的结果为真时,执行表达式1,当条件表达式的结果为假时,执行表达式2。
    2选1数据选择器

在这里插入图片描述

3.9 连接和复制运算符

  • 连接运算符”{}“和复制运算符”{{}}”
  • 连接操作符
    {信号1的某几位,信号2的某几位、… 、信号n的某几位}
  • 重复操作符{{}}将一个表达式放入双重花括号中,复制因子放在第一层括号中。
    例如:
    在这里插入图片描述

4,模块的基本概念

4.1 模块的基本概念

  • 模块(module)是Verilog的基本单元,它代表一个基本的功能块,用于描述某个设计的功能或结构以及与其它模块通信的外部端口。
  • 模块结构组成图如下:
    在这里插入图片描述
  • 一个模块主要包括:模块的开始与结束、模块端口定义、模块数据类型说明和模块逻辑功能描述这几个基本部分。
    (1)模块的开始与结束:以关键词module开始,以关键词endmodule结束的一段程序,其中模块开始语句必须要以分号结束。
    (2)端口定义:用来定义端口列表里的变量哪些是输入(input)、输出(output)和双向端口(inout)以及位宽的说明。
    (3)数据类型说明:数据类型在语言上包括wire、reg、memory和parameter等类型,用来说明模块中所用到的内部信号、调用模块等的声明语句和功能定义语句。
    (4)逻辑功能描述:用来产生各种逻辑(主要是组合逻辑和时序逻辑)。主要包括以下部分:initial语句、always语句、其它子模块实例化语句、门实例化语句、用户自定义原语(UDP)实例化语句、连续赋值语句(assign)、函数(function)和任务(task) 。

在这里插入图片描述
在这里插入图片描述

4.2 端口

  • 端口的定义
    模块的端口可以是输入端口(input)、输出端口(output)或双向端口(inout) 。
  • 模块引用时端口的对应方式
    (1)在引用时,严格按照模块定义的端口顺序来连接,不用标明源模块定义时规定的端口名。格式如下:
    模块名(连接端口1信号名,连接端口2信号名,...)
    (2) 在引用时用“.”标明源模块定义时规定的端口名。格式如下:
    模块名(.端口1名(连接信号1名), .端口2名(连接信号2名)...);
  • 这样表示的好处在于可以用端口名与被引用模块的端口对应,不必严格按端口顺序对应,提高了程序的可读性和可移植性。

来源:蔡觉平老师的Verilog课程


版权声明:本文为KIDS333原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/KIDS333/article/details/126928475