Verilog学习笔记(1):Verilog基础知识
第一章 Verilog基础知识
文章目录
-
1,Verilog语法要素
-
- 1.1 空白符
- 1. 2 注释符
- 1.3 标识符
- 1.4 关键字
- 1.5 转义标识符
- 1.6 数值
-
2, 数据类型分类
- 2.1, 物理属性数据类型
- 2.2, 连接型与reg型的数据类型声明
- 2.3, 存储器相关的数据类型
- 2.4, 抽象数据类型的定义
-
3, 运算符和表达式
-
3.1 算术运算符
- 3.2 比较(关系)运算符
- 3.3 等值比较(相等关系)操作
- 3.4 逻辑操作
- 3.5 位操作(按位)
- 3.6 缩减(归约)运算法则
- 3.7 位移运算法则
- 3.8 判断(条件)运算法则
- 3.9 连接与复制法则
-
4,模块的基本概念
-
- 4.1 模块的基本概念
- 4.2 端口
-
来源:蔡觉平老师的Verilog课程
-
1,Verilog语法要素
1.1 空白符
在编译及综合过程中,在处理空白符时,请注意以下几种空白符号:空格(\b)、制表符(\t)以及换行(\n)与回车(\r)。这些空白符号通常会被系统自动过滤或忽略。
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 注释符
例如://标注此行为单行注释。
wire [1:0] ip; //定义一个线网类型
reg[5-1:0] op; //定义一个寄存器类型
/*
result数据宽为2
op数据宽为5
*/
1.3 标识符
在Verilog语言中使用标识符(identifier)来命名诸如信号名、模块名以及参数名等元素。它由字母、数字以及$和_组成。需要注意的是标识符的第一个字符必须是字母或下划线,并且区分大小写。reserved keywords in Verilog are reserved for defining the language's structural syntax. Verilog中的所有关键字均为小写。例如:
//合法标识符 //非法标识符
count 30count //标识符不允许以数字开头
COUNT//与count不同 out* //标识符中不允许包含字符*
CC G5 a+b-c //标识符中不允许包含字符+和一
B25 78 n@238 //标识符中不允许包含字符@
SIX
1.4 关键字
关键点是Verilog语言中的内置专有名词,并非任意字母都可以作为关键词使用。这些专有名词具有固定大小和作用域,并规定了合法的操作符和语法规则。需要注意的是这些专有名词都是以小写字母书写的
| 关键字 | 含义 |
|---|---|
| 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,9.等均为无效形式。
(2)在科学记数法中,数值书写需遵循特定规则:例如,将数值写作"3e+2"即相当于将该数值放大了一百倍;又如,"5e-4"则代表该数值缩小了一千分之一。
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 signed[3:0] rega;
rega=-2 //rega的值为1110(14),是2的补码.
2.2 连线型和reg型数据类型的声明
- 连线型数据类型的声明:
< net_declaration><drive_strength>
[list_of_variables];
`net_declaration`:包括wire、trim、tri0、tri1、wand、triand、trior、wor中的任意一种。
`drive_strength`:表示连线变量的驱动强度。
`range`:用来指定数据类型为标量或矢量。若该项默认,表示数据类型为1位的标量,超过一位则为矢量类型。
`delay`:指定仿真延迟时间。
`list_of_variables`:变量名称,一次可定义多个名称,之间用逗号分开。
- 寄存器型数据类型的声明:
reg
<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
<name_of_register>;
其中: - range1和range2均为可选参数,默认值均为1。
表示存储器中寄存器的位宽(格式:[msb:lsb])。 表示寄存器的数量(格式:[msb:lsb]),即共有msb至lsb加l个寄存器。 - <name_of_register>用于定义多个寄存器名称(如name1,name2,...),每个名称之间用逗号分隔。
- 存储器变量的一般声明格式包括: reg
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 type),以及实数类型(real type),还包括参数类型(parameter type)。
- 整数类型的定义为 integer <list_of_register_variables>;
integer index; //简单的32位有符号整数
integer i[31:0]; //定义了整型数组,有32个元素
时间型数据与整型数据具有相似性,在结构上也相仿,在功能上具有相同的特性,在性能上有相同的限制条件等特征;它们都属于64位无符号整数类型的数据类型;时间型数据主要用于存储和计算模拟的时间值;该类型的数据常与系统函数中的time指令配合使用;例如:
时间型数据的定义格式为:time <list_of_register_variables>; 该格式表示的时间域变量通常被用来表示模拟的时间值域变量;其中涉及的各种寄存器变量均属于64位无符号整数值类型;例如:
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
c

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
c

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 移位操作符
在运算过程中,在左侧或右侧的操作数会分别向左或向右移动一定的位置,在这一过程中其位移的数目等于右侧操作数所表示的数值,在完成移动之后随后,在移除多余部分时会填充足够的零以确保数据的有效性

3.8 条件运算符
该条件语句采用以下结构:
< 条件表达式>?< 表达式1 >:< 表达式2>
其中该条件语句的计算结果包含三种情况:
- 当计算结果为真(值为"1")时执行第一个操作;
- 当计算结果为假(值为"0")时执行第二个操作。


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

4,模块的基本概念
4.1 模块的基本概念
- 在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信号名称,...)模块Name(.接口A (输入信号A), .接口B (输入信号B)...);
采用该表示方法的一个优点是可以利用端口名与被引用模块之间的端口对应关系,并不需要严格按照端口顺序进行对应匹配,从而提升了程序的可读性和移植性
