• 数字集成电路设计(二、Verilog HDL基础知识)



    • Verilog来源于C语言,后面会发现它的语法集和C语言几乎完全一样,但是设计方法和C语言完全不一样

    1. 语言要素

    1.1 空白符

    空白符包括空格符(\b)、制表符(\t)、换行符和换页符。空白符使代码看起来结构清晰阅读起来更方便。在编译和综合时,空白符被忽略。
    在这里插入图片描述

    1.2 注释符

    • 和C语言完全一样
      (1)单行注释:单行注释以“//”开始,Verilog HDL 忽略从此处到行尾的内容。
      (2)多行注释:多行注释以“/*”开始,到“*/”结束,Verilog HDL忽略其中的注释内容
      在这里插入图片描述
      在这里插入图片描述
    • 多行注释不允许嵌套,但是单行注释可以嵌套在多行注释中

    1.3 标识符

    • 它可以是任意一组字母、数字、$符号和_(下划线)符号的组合。应该注意的是,标识符的字母区分大小写,并且第一个字符必须是字母或者下划线。
      在这里插入图片描述

    1.3.1 转义标识符

    • Verilog HDL 规定了转义标识符(Escaped Identifier)。采用转义标识符可以在一条标识符中包含任何可打印的字符。转义标识符以“\”(反斜线)符号开头,以空白结尾(空白可以是一个空格、一个制表字符或换行符)。
      在这里插入图片描述

    1.4 关键字

    • Verilog HDL语言内部已经使用的词称为关键字或保留字,它是 Verilog HDL语言内部的专用词,是事先定义好的确认符,用来组织语言结构。
    • 用户不能随便使用这些关键字。需注意的是,所有关键字都是小写的
    • 例如,ALWAYS 不是关键字,它只是标识符,与always(关键字)是不同的
      在这里插入图片描述

    1.5 数值

    • Verilog有四种基本的逻辑数值状态
      在这里插入图片描述

    1.5.1 整数及其表示方式

    在这里插入图片描述

    • 整数的表示形式为如下:
      +/-
      (1)“+/-”是正数和负数标示
      (2)size 指换算过后的二进制数的宽度
      (3)“ ’ ”为基数格式表示的固有字符
      (4)base_format 是其基数符号
      (5)number是可以使用的数字字符集,形式上是相应进制格式下的一串数值

    • 需要注意
      (1)在位宽和字符之间以及进制和数值之间可以有空格,但数字之间不能有空格,下面的情况是允许的
      在这里插入图片描述
      (2)下面的情况是不允许的

    在这里插入图片描述

    1.5.2 实数及其表示方式

    • 在硬件描述语言中,没有实数。想要表示一个带小数点的数字只能用定点(小数点位置固定)或者浮点的表示方法,把小数变成整数
    • 电路设计中,没有传统意义的实数概念。**但是HDL为什么规定这个方式,是用在测试和仿真中间。**不能用在设计。
    • 实数有两种表示方法:
      (1)十进制表示法。采用十进制格式,小数点两边必须都有数字,否则为非法的表示形式。例如:3.0、4.54、0.2 等都是正确的,而5.是错误的。
      (2)科学计数法。例如:564.2e2 的值为 56420.0,8.7E2 的值为870.0(e 不分大小写)3E-3的值为0.003。
      在这里插入图片描述

    1.5.3 字符串及其表示方式

    • 字符串是指用双引号括起来的字符序列,它必须包含在同一行中,不能分行书写。若字符串用作 Verilog HDL表达式或赋值语句中的操作数则字符串被看做8位的ASCII值序列,即一个字符对应8位的ASCII值。例如"hello world"和"Anexample for Verilog HDL"是标准的字符串类型。

    2. 数据类型

    • 这是一个新的概念,因为在HDL中,我们面对的是数字电路,数字电路就会有一个能力的问题(并不是以电压来衡量,是以电流来衡量),所以根据电流驱动能力的强弱,分成了以下等级:
      在这里插入图片描述
    • supply:导线直接连接
    • strong:上拉电阻接到电源
    • pull:上拉电阻比strong的上拉电阻要大
    • large:大容性,有存储的功能
    • weak:电流非常小
    • medium:电流更小一点
    • small:小容性
    • highz:高阻态,直接断开

    2.1 物理数据类型

    2.1.1 连线型

    在这里插入图片描述

    • 最常用的是wire和tri,wire表示的是0,1和不定状态(X)。tri成为三态,包括了0,1,不定状态(X)和高阻状态(Z)
    • wor也是一种连线型的变量,但是它解决的问题是两个线对一个线进行驱动,实际上是在两个线中间增加了一个或门
    • 功能
      (1)wire和tri
      在这里插入图片描述
      (2)wor和trior(带有一定逻辑功能,线或)
      在这里插入图片描述
      (3)wand和triand(带有一定逻辑功能,线或)
      在这里插入图片描述

    2.1.2 寄存器型

    • 在数字电路设计过程中,经常会遇到组合电路和时序电路,组合电路就是连线型的变量和时序电路就是带有寄存器功能的,叫做reg类型
    • reg型数据与 wire型数据的区别在于,reg 型数据保持最后一次的赋值,而wire型数需要有持续的驱动。
    • 一般情况下,reg 型数据的默认初始值为不定值 x,缺省时的位宽1 位。
      在这里插入图片描述
    • reg 型变量一般为无符号数,若将一个负数赋给 reg 型变量,则自动转换成其二进制补码形式
      在这里插入图片描述

    2.2 连线型和寄存器型数据类型的声明

    2.2.1 连线型数据类型的声明

    • 缺省的连线型数据的默认类型为1位(标量)wire类型。
    • Verilog HDL禁止对已经声明过的网络、变量或参数再次声明。
    • 连线型数据类型声明的一般语法格式如下:
      在这里插入图片描述
      (1)net_declaration: 表示网络型数据的类型,可以是 wire、tri、tri0、tr1、wand、triand.trior、wor、trireg 中的任意一种。对于 trireg 类型,其声明还有一个 charge_strength(电荷强度)的可选项
      (2)range:用来指定数据为标量或矢量。若该项默认,表示数据类型为1位的标量,超过1位则为矢量形式。
      (3)delay:指定仿真延迟时间
      (4)list_of_variables: 变量名称,一次可定义多个名称,之间用逗号分开

    2.2.2 寄存器型数据类型的声明

    在这里插入图片描述

    • range为可选项,它指定了 reg 型变量的位宽,缺省时为1位
    • list_of_register_variables:变量名称列表,一次可以定义多个名称,之间用逗号分开
    • 它只表示一个存储,没有驱动强度这样的概念

    2.3 物理数据类型的声明举例

    在这里插入图片描述

    2.4 存储器型

    • 存储器型变量可以描述 RAM 型、ROM 型存储器以及 reg 文件
    • 存储器型变量的一般声明格式:
      在这里插入图片描述
      (1)range1:表示存储器中寄存器的位宽,格式为[msb:lsb]。
      (2)range2:表示寄存器的个数,格式为[msb:lsb],即有 msb-lsb+1个。
      (3)name_of_register:变量名称列表,一次可以定义多个名称,之间用逗号分开

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

    • 一个 n 位的寄存器可以在一条赋值语句里进行赋值,而一个完整的存储器则不行。例如,对于上例可以进行“rega=0;”的赋值操作,而不能进行“meml=0”的赋值操作
    • 如果想对存储器中的存储单元进行读写操作,则必须指定该单元在存储器中的地址

    在这里插入图片描述

    2.5 抽象数据类型

    • 除了物理数据类型外,Verilog HDL 还提供了以下几种抽象数据类型:整型(integer)时间型(time)、实型(real)及参数型(parameter)。它们只是纯数学的抽象描述,不能够与实际的硬件电路相映射。

    3. 运算符

    • 运算符在Verilog起到了很大的作用,它代表着电路,这是一个很重要的内容
      在这里插入图片描述
    • 会牵扯到两个概念:
      (1)优先级是什么(保留了和其他高级语言相类似的运算符优先级)
      (2)功能是什么

    3.1 算术运算符

    • Verilog HDL中常用的算术运算符主要有五种,分别是加法(+)减法(-)乘法(*)除法(和取模(%)。
    • 这五种运算符都属于双目运算符。符号“+”、“-”、“*”、“/”分别表示常用的四则运算。%是取模运算,如“6%3”的值为 0,“7%4”的值为3。
    • 需要注意:
      (1)在赋值语句下,算术操作结果的长度由操作左端的目标长度决定。
      (2)有符号数和无符号数的使用。当信号位宽不同的时候,表征的数是不一样的,希望尽可能采用无符号数作为设计的基础。
      在这里插入图片描述
    • 可以看到Verilog对运算符的处理很特殊,一直在考虑输入位宽和输出位宽(加法器就是两路数进去出来一路数,只和数据位宽有关系),HDL更注重于描述运算符的结构特性
    • !!加法和减法是可以直接进行综合的,也就是说当我们使用这个符号的时候,我们的设计工具就会给我们设计一个加法电路或者减法电路,换句话说,加法电路和减法电路其实是一样的,所谓的减法电路就是加法电路加上一个负数
    • !!乘法在早期是尽可能避免的,因为综合工具支持的不好,但是现在EDA对乘法支持非常好,所以我们可以用这个符号去生成一个乘法电路
    • !!除法和取模目前EDA工具支持的不好,但是如果工艺库里面有除法和取模电路,就可以用符号去做
    • 可以利用MATLAB集成了算法的运算,也就是当我们把数学模型写进去之后,MATLAB可以直接生成我们所需要的Verilog代码,这样就更加提高了对操作算法的支持程度
    • !!算术运算符是整个Verilog运算符中间最复杂的,其他的都和我们的数字电路基本电路是对应的

    3.2 关系运算符

    • 关系运算符也是双目运算符,是对两个操作数的大小进行比较。关系运算符有大于(>)小于(<)、大于等于(>=)和小于等于(<=)几种(还包括了相等运算符中的等于(==)和全等于(===))
    • 关系运算符就是成立输出1,不成立输出0,也就是结果应该是一个1bit的信号
      在这里插入图片描述
    • 第四个在电路中间不会遇到这个问题,因为数字电路对于不定态的管理非常严格(产生不定态的两种情况,一种是信号悬空,一种是两个信号驱动同一个信号,这两种情况对于可靠的数字电路来讲是不会出现的)
    • Verilog规定任何数和不定值的比较都会是一个不定值

    3.3 相等关系运算符

    • 相等关系运算符是对两个操作数进行比较,比较的结果有三种:真(1)、假(0)和不定值(x)。Verilog HDL 语言中有四种相等关系运算符等于(==)、不等于(!=)、全等(===)、非等(!==)
    • 和关系运算符是一样的东西,只不过它比较的是相等
    • Verilog的相等运算符有四种,比较结果有三种“1”,“0”,“X”
      在这里插入图片描述
      (左边表的第一列第一个应该是0)
    • 这四种运算符都是双目运算符,要求有两个操作数。并且,这四种相等运算符的优先级别是相同的
    • “==”和“!”称为逻辑等式运算符,其结果由两个操作数的值决定,由于操作数中某些位可能是不定值x和高阻态值z,所以结果可能为不定值x
    • “===”和“!==”运算符则不同,它是对操作数进行按位比较,两个操作数必须完全一致,其结果才是 1,否则为 0。但是,若两个操作数对应位出现不定值 x 和高阻值 ,则可认为是相同的
    • 大部分用的还是”==“,对“===”的理解是为了避免计算产生了不定态一直传播。而且“===”可以做信号长度的比较,当两个信号值相同长度不同时,“==”会输出1,而“===”会输出0,但是为什么经常用的是“==”,这是因为在电路设计的时候是不允许不同位宽的信号进行比较的。第二个是在可靠的设计中间是不允许不定值和高阻进行比较的

    3.4 逻辑运算符

    • 逻辑运算符有三种,分别是逻辑与运算符(&&)、逻辑或运算符(||)、逻辑非运算符(!)其中逻辑与和逻辑或是双目运算符,逻辑非为单目运算符
    • 逻辑运算符其实也表征的是一个“1”或者“0”的概念,如果是“0”表征的是逻辑非(0电平),如果是非零就是逻辑真(高电平)
      在这里插入图片描述
    • !关系运算符和比较运算符代表数字电路中的数字比较器(数字比较器可以表示不等或者相等)
    • 逻辑运算符非对应的电路如下
      在这里插入图片描述
    • 需注意的是,若操作数中存在不定态 x,则逻辑运算的结果也是不定态,例如:a 的初值为4’b1100,b的初值为4‘b01x0,则!a=0,!b=x,a&&b=x,alb=x

    3.5 按位运算符

    • 按位取反(~),按位与(&),按位或(|),按位异或(^),按位同或(^~)

    在这里插入图片描述

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

    • 归约运算符按位进行逻辑运算,属于单目运算符。由于这一类运算符操作的结果是产生1位逻辑值,因而被形象地称为缩位运算符。
    • 归约运算符包括与(&),或(|),异或(^)以及相应的非操作~&、~|、~^、^~
    • 归约运算符就是为了解决一个信号里面的一串信号中间的运算
      在这里插入图片描述

    3.7 移位操作运算符

    • 移位运算符有两种:左移位运算符(<<)右移位运算符(>>)
    • 运算过程是将边(右边)的操作数向左(右)移,所移动的位数由右边的操作数来决定,然后用0来填补移出的空位
    • 思考:为什么只有两个,而没有C语言当中那么多循环移等操作
      在这里插入图片描述
    • 这个操作符用的不多,为什么等下面来讲

    3.8 条件运算符

    • 条件运算符是 Verilog HDL 里唯一的三目运算符,它根据条件表达式的值来选择执行达式,其表达形式为:
      在这里插入图片描述
    • 条件表达式的计算结果有真(1)、假(0)和不定态(x)三种。当条件表达式的结果为真时执行表达式1,当条件表达式的结果为假时,执行表达式 2
    • 如果条件表达式的结果为不定态 ,则模拟器将按位对表达式1的值与表达式2的值进行比较,位与位的比较按表 2.3-7 的规则产生每个结果位,从而构成条件表达式的结果值
      在这里插入图片描述
    • 条件运算符举例:
      在这里插入图片描述
    • 若该数据选择器的sel端为不定态x,则out 由in1和i2按位运算的结果得出。若in1=4’b0011,in2=4’b0101,则按照上述真值表得出 out=4’b0xx1。

    3.9 连接和复制运算符

    • !!前面说移位运算符是不重要的一个运算符,因为连接和复制运算符能够得到更好的结果
    • Verilog HDL语言中还有两个特殊的运算符:连接运算符({})和复制运算符({{}})
    • 连接运算符是把位于大括号({})中的两个或两个以上信号或数值用逗号(,)分隔的小表达式按位连接在一起,最后用大括号括起来表示一个整体信号,形成一个大的表达式。
    • 重复运算符({{}})将一个表达式放入双重花括号中,复制因子放在第一层括号中。它为复制一个常量或变量提供了一种简便方法
    • 首先明确一点,这个操作没有对应的电路,只是重新定义
      在这里插入图片描述

    4. 模块

    4.1 模块的基本概念

    • 模块(module)是 Verilog HDL语言的基本单元
    • 代表一个最基本的功能模块,语法中代表一段程序,电路中每个模块代表一个电路
      在这里插入图片描述
    • 一个模块主要包括模块的开始与结束、模块端口定义、模块数据类型说明和模块逻辑功能描述几个基本部分
    • 例:上升沿D触发器的Verilog描述:
      在这里插入图片描述
    • 例:上升沿D触发器的硬件:
      在这里插入图片描述

    4.2 端口

    4.2.1 端口的定义

    • 端口是模块与外界或其它模块沟通的信号线。模块的端口可以是输入端口(input)、输出端口(output)或双向端口(inout)。
    • 缺省状态下,端口类型都将默认为 wire 类型

    4.2.2 模块引用时端口的对应方式

    • 在引用模块时其端口可以用如下两种方法连接
      (1)在引用时,严格按照模块定义的端口顺序来连接,不用标明源模块定义时规定的端口名。
      在这里插入图片描述
      (2)在引用时用“”标明源模块定义时规定的端口名。
      在这里插入图片描述
  • 相关阅读:
    python版的羊了个羊,你见过没?
    七牛云 OSS 文件上传demo
    PHICOMM(斐讯)N1盒子 - recovery模式救砖卡登录页LOGO卡1%卡4%卡26%
    排序算法-基数排序法(RadixSort)
    手搓哈希表、列表、队列,只为了用C语言快速求解华容道游戏,我不是大佬,只是一个游戏算法爱好者
    Velocity 不用愁!Velocity 系统的前端工程化之路
    【数据集NO.3】人脸识别数据集汇总
    mybatis代理
    10-Dubbo架构设计与底层原理-集群容错之 Router
    C++ Reference: Standard C++ Library reference: C Library: cwchar: wcscat
  • 原文地址:https://blog.csdn.net/y_u_yu_yu_/article/details/127828175