XLINUX-FPGA开发-语法篇-Verilog HDL-Verilog HDL基础知识
大家好,我是Xiaojie,桂林电子科技大学计算机在读硕士研究生,这篇内容主要是给大家分享:XLINUX-FPGA开发-语法篇-Verilog HDL-Verilog HDL基础知识,接下来进入正题
文章目录
Verilog HDL语言要素
-
空白符:空白符包括空格符(\b)、制表符(\t)、换行符和换页符。在编译和综合时,空白符被忽略。
-
注释符:
- 单行注释:以"//"开始,Verilog HDL会忽略从此处到行尾的内容
- 多行注释:以"/“开始,到”/"结束,Verilog HDL忽略其中的注释内容
-
标识符:标识符(Identifier)被用来命名信号名、模块名、参数名等,可以是任意一组字母、数字、$符合和_(下划线)符号的组合。应该注意的是标识符的字母要区分大小写,并且第一个字符必须是字母或者下划线。
-
转义标识符(Escaped Idenrifiter):采用转义标识符可以在一条标识符中包含任何可打印的字符,转义标识符以""(反斜线)符号开头,以空白结尾(空白可以是一个空格、一个制表字符或换行符)
-
关键字:Verilog HDL语言内部已经使用的词称为关键字或保留字,他是Verilog HDL语言内部的专用词,是事先定义好的确认符,用来组织语言结构,这些关键字用户不能随便使用,所有关键字都是小写的。
常用的关键字: -
数值
-
逻辑数值状态
-
整数及其表示 +/-’<base_format>
-
实数及其表示
- 十进制表示法,采用十进制格式,小数点两边必须都有数字,否则为非法的表示形式。
- 科学计数法。
-
数据类型
物理数据类型:连线型、寄存器型和存储器型数据类型
信号强度表示数字电路中不同强度的驱动源,用来解决不同驱动强度存在下的赋值冲突:
- 物理数据类型
-
连线型
-
wire和tri
-
wor和trior
-
-
寄存器型:
reg型是数据储存单元的抽象数据类型,其对应的硬件电路元件具有状态保持作用,能够存储数据,如触发器、锁存器等。
reg型变量常量用于行为级描述,由过程赋值语句对其进行赋值
-
- 连线型和reg型数据类型的声明
- 连线型数据类型的声明
<net_declaration><drive_strength>[list_of_variables]- net_declaration包括wire、tri、tri0、tri1、wand、triand、trior、wor中的任意一种
- range:用来指定数据为标量或矢量。若该项默认,表示数据类型为1位的标量,超过1位则为矢量形式
- delay:指定仿真延迟时间
- list_of_variables:变量名称,一次可定义多个名称,之间用逗号分开
- drive_strength:表示连线变量的驱动强度
- 寄存器型数据类型的声明
reg<list_of_register_variables>- range位可选项,指定了reg型变量的位宽,缺省时为1位
- <list_of_register_variables>为变量名称列表,一次可以定义多个名称,之间用逗号分开
- 连线型数据类型的声明
- 存储器型
存储器型变量可以描述RAM型、ROM型存储器以及reg文件
存储器变量的一般声明格式为:reg<name_of_register>
range1和range2都是可选性,缺省都为1
<range1>:表示存储器中寄存器的位宽,格式为[msb:lsb]
<range2>:表示寄存器的个数,格式为[msb:lsb],即有msb-lsb+1个
<name_of_register>:为变量名称列表,一次可以定义多个名称,之间用逗号隔开 - 抽象数据类型
抽象数据类型包括整型(integer)、时间型(time)、实型(real)及参数型(parameter)- 整型:integer<list_of_register_variables>
- 时间型:主要用于对模拟时间的存储与计算处理,常与系统函数$time一起使用,声明格式:time<list_of_register_variables>
- 实型:实型数据在机器码表示法中是浮点型数值,可用于对延迟时间的计算,声明格式:real<list_of_register_variables>
- 参数型:属于常量,在仿真开始之前就被赋值,在仿真过程中保持不变,提高了程序的可读性和维护性,定义格式:parameter 参数名1=表达式1,参数名2=表达式2,……,参数名n=表达式n
运算符
-
算术操作符(加法(+);减法(-);乘法(*);除法(/);取模(%))
- 算术操作结果的位宽
算术表达式结果的长度由最长的操作数决定。在赋值语句下,算术操作结果的长度由操作左端目标长度决定 - 有符号数和无符号数的使用
- 无符号数值一般存储在线网、reg(寄存器)型变量及普通(没有符号标记s)的基数格式表示的整型数中
- 有符号数一般存储在整型变量、十进制形式的整数、有符号的reg(寄存器)型变量及有符号的线网中
- 算术操作结果的位宽
-
关系运算符
关系运算符是双目运算符,是对两个数进行比较的操作,包括大于(>)、小于(<)、大于等于(>=)和小于等于(<=)。在进行关系的比较时,如果成立则结果为1’b1,不成立的结果为0’b0。 -
相等关系操作符
操作符有等于"=="、不等于"!="、全等"==="、非全等"!==",它们比较的结果有三种,真"1"、假"0"和不定值"x"-
"=="运算符的真值表
-
"==="运算符的真值表
-
-
逻辑运算符
逻辑运算符有三种,分别是逻辑与(&&)、逻辑或(||)、逻辑非(!)。逻辑与、逻辑或是双目运算符,逻辑非是单目运算符
若操作数中存在不定状态x,则逻辑运算的结果也是不定态 -
按位操作符
数字逻辑电路中,信号与信号之间的运算称为位运算,5种类型的位运算符:按位取反()、按位与(&)、按位或(|)、按位异或(^)、按位同或(^)-
按位与运算符的真值表
-
按位或运算符的真值表
-
按位异或运算符的真值表
-
-
归约运算符
归约运算符按位进行逻辑运算,属于单目运算符。这类运算符运算的结果是产生1位逻辑值,因此称为缩位运算符。缩位运算符包括&(与)、|(或)、^(异或)以及相应的非操作~&、~|、~^、^~。
归约运算符的运算过程是:设a是一个4位的寄存器型变量,它的4位分别是a[0]、a[1]、a[2]、a[3]。当对a进行缩位运算时,先对a[0]和a[1]进行缩位运算,产生1位的结果,再将这个结果与a[2]进行缩位运算,再接着是a[3],最后产生1位的操作结果 -
移位运算符
移位运算符有两种:左移运算符(<<)、右移运算符(>>)。运算过程是将左边的操作数向左(右)移,所移动的位数由右边的操作数决定,然后用0来填补移出的空位。 -
条件运算符
表达式的形式:<条件表达式>?<表达式1>:<表达式2>
条件表达式的计算结果有真"1"、假"0"和未知态"x"三种,当条件表达式的结果为真时,执行表达式1,当条件表达式的结果为假时,执行表达式2。 -
连接和复制运算符
- 连接运算符是把位于大括号({})中的两个或两个以上信号或数值用逗号隔开的小表达式按位连接在一起,最后用大括号括起来表示一个整体信号,形成一个大的表达式。格式如下:{信号1的某几位,信号2的某即为,……,信号n的某几位}
- 重复运算符({{}})将一个表达式放入双重花括号中,复制因子放在第一层括号中。
模块的基本概念
- 模块的基本概念
-
模块(module)是Verilog HDL语言的基本单元,它代表一个基本的功能块,用于描述某个设计的功能或结果以及与其他模块通信的外部端口
模块结构组成图: -
一个模块主要包括:模块的开始与结束、模块端口定义、模块数据类型说明和模块逻辑功能描述。
- 模块的开始与结束:以module开始,以关键词endmodule结束的一段程序,其中模块开始语句必须要以分号结束
- 端口定义:用来定义端口列表里的变量哪些是输入(input)、输出(output)和双向端口(inout)以及位宽的说明
- 数据类型说明:数据类型在语言上包括wire、reg、memory和parameter等类型,用来说明模块中所用到的内部信号、调用模块等声明语句和功能定义语句
- 逻辑功能描述:用来产生各种逻辑(主要是组合逻辑和时序逻辑)。主要包括:initial语句、always语句、其他子模块实例化语句、门实例化语句、用户自定义原语(UDP)实例化语句、连续赋值语句(assign)、函数(function)和任务(task)。
-
- 端口
- 端口的定义
模块的端口可以是输入端口(input)、输出端口(output)或双向端口(inout)。 - 模块引用时端口的对应方式
- 在引用时,严格按照模块定义的端口顺序来连接,不用表明源模块定义时规定的端口名。格式如下:
模块名(连接端口1信号名,连接端口2信号名,……) - 在引用时用"."标明源模块定义时规定的端口名。格式如下:
模块名(.端口1名(连接信号1名),.端口2名(连接信号2名),……)
- 在引用时,严格按照模块定义的端口顺序来连接,不用表明源模块定义时规定的端口名。格式如下:
- 端口的定义
至此,Verilog HDL中的基础知识就介绍完了,下一章介绍Verilig HDL中的程序设计语句和描述方式
当幸福来敲门
下面的是笔者的微信公众号,欢迎关注,会持续更新c++、python、tensorflow、机器学习、深度学习、计算机视觉、雷达原理、FPGA等系列文章。