打工人日报#20250927
打工人日报#20250927
知识点
Verilog HDL 介绍
Verilog HDL(Hardware Description Language,硬件描述语言)是一种用于数字硬件设计的标准语言,在集成电路设计、FPGA 开发等领域应用广泛。以下从多个方面对其进行介绍:
1. 发展历程
- Verilog HDL 由 Gateway Design Automation 公司的 Phil Moorby 在 1983 年开发。最初,它用于该公司的仿真工具中,帮助工程师对数字电路进行建模与仿真。
- 1989 年,Cadence 公司收购 Gateway Design Automation 公司,Verilog HDL 的发展得到推动。
- 1995 年,IEEE 将 Verilog HDL 制定为标准,即 IEEE 1364 - 1995 标准,使其在全球范围内得到广泛认可和应用。之后,该标准不断更新完善,如 IEEE 1364 - 2001、IEEE 1364 - 2005 等版本,增加了新的特性与功能。
2. 语言特点
- 功能强大:可以对数字电路的结构和行为进行描述。既能描述电路的逻辑门级结构,如与门、或门、非门等的连接关系,也能从行为级描述电路的功能,像状态机的状态转移、数据处理算法等。例如,对于一个简单的加法器,可以用逻辑门级描述其由多个全加器单元组成,也能用行为级描述为两个输入数相加得到输出结果。
- 灵活性高:支持多种建模方式,包括数据流建模(通过描述数据在硬件中的流动来建模)、行为建模(基于算法和顺序执行描述硬件行为)和结构建模(通过实例化不同模块来构建硬件结构)。工程师可根据设计需求和场景选择最合适的建模方式,或在同一设计中混合使用多种方式。
- 可综合性好:能够被综合工具转化为实际的硬件电路。这意味着用 Verilog HDL 编写的代码可以经过综合工具处理,生成门级网表,进而用于 ASIC 制造或 FPGA 配置,实现从代码到实际硬件的转化。
- 易于学习:语法与 C 语言有相似之处,对于有 C 语言基础的工程师来说,学习门槛相对较低。同时,其具有丰富的运算符和数据类型,便于理解和使用。
Verilog 的逻辑值
- 1(高电平或逻辑真):表示逻辑上的 “真” 或电路中的高电平状态。常用于表示某个条件满足或信号有效。例如,在比较语句if (a > b)中,如果a确实大于b,则该条件返回逻辑值 1。
- 0(低电平或逻辑假):表示逻辑上的 “假” 或电路中的低电平状态。与 1 相反,用于表示条件不满足或信号无效。
- x(不定值):表示不确定的值。这可能出现在电路初始化阶段,或者当信号的驱动存在冲突时。例如,多个驱动源同时尝试驱动一个线网型信号且它们的输出不一致时,该信号的值可能会变为x。在仿真中,x值的传播可以帮助检测设计中的潜在问题。
- z(高阻态):代表高阻状态,通常用于表示三态逻辑电路中的高阻态输出。当一个电路处于高阻态时,它在电气上相当于开路,不驱动任何电平,对连接的线路没有影响。常用于总线上多个设备共享线路的情况,当某个设备不使用总线时,其输出可以设置为高阻态,以便其他设备使用总线。
Verilog 的标识符
标识符是用于给变量、模块、端口、信号等命名的字符串。在 Verilog 中,标识符具有以下规则:
- 组成字符:由字母(大小写敏感)、数字、下划线(_)和美元符号()组成。例如,modulename、signal1、temp、)组成。例如,module_name、signal1、_temp、)组成。例如,modulename、signal1、temp、count都是有效的标识符。
- 开头字符:必须以字母或下划线开头,不能以数字或美元符号开头。例如,1signal是无效的标识符,而signal1是有效的。
- 保留字:不能使用 Verilog 的保留字作为标识符。保留字是 Verilog 语言中具有特定含义的单词,如module、input、always等。
Verilog 的数字进制格式
Verilog 支持多种数字进制格式来表示常量:
- 二进制(Binary):以b或B开头,后跟 0 和 1 的序列。例如,4’b1010表示一个 4 位的二进制数,值为 10(十进制)。这里的 4 表示该二进制数的位宽,如果省略位宽,则默认位宽为 32 位,如b1010等价于32’b0000_0000_0000_0000_0000_0000_0000_1010。
- 八进制(Octal):以o或O开头,后跟 0 到 7 的数字序列。每一位八进制数字对应三位二进制数字。例如,3’o7表示一个 3 位的八进制数,转换为二进制是3’b111,值为 7(十进制)。
- 十进制(Decimal):最常见的表示方式,直接写数字。例如,10表示十进制数 10。也可以指定位宽,如8’d10表示一个 8 位的十进制数,在内存中以 8 位二进制形式存储(8’b0000_1010)。
- 十六进制(Hexadecimal):以h或H开头,后跟 0 到 9 以及 a 到 f(或 A 到 F)的字符序列。每一位十六进制数字对应四位二进制数字。例如,4’hA表示一个 4 位的十六进制数,转换为二进制是4’b1010,值为 10(十进制)。
Verilog 的数据类型
Verilog 中有多种数据类型,主要分为以下几类:
- 线网类型(Net Types):用于表示连接不同模块或元件的信号线,其值由驱动它的元件决定。
- wire:最常用的线网类型,用于连接组合逻辑电路。例如,wire [7:0] data_bus;定义了一个 8 位宽的 wire 型信号data_bus,可用于传输数据。
- tri:与wire类似,常用于描述具有多个驱动源的总线结构,允许多个驱动源连接到同一根线。当多个驱动源的输出一致时,信号取该值;当驱动源输出冲突时,信号值为x。
- 寄存器类型(Register Types):常用于存储数据,可在always块中赋值。
- reg:最基本的寄存器类型,用于在always块或initial块中保存数据。例如,reg [3:0] counter;定义了一个 4 位宽的reg型变量counter,可用于计数。
- integer:32 位有符号整数类型,常用于循环控制变量或数学计算。例如,integer i;定义了一个整数变量i,可在for循环中使用。
- real:64 位双精度浮点数类型,用于进行高精度的数值计算,但在可综合设计中较少使用,因为大多数硬件不直接支持浮点数运算。
- 数组类型(Array Types):可以定义一维或多维数组。例如,reg [7:0] memory [0:255];定义了一个 256 个元素的数组memory,每个元素是一个 8 位宽的reg型数据,模拟了一个简单的内存结构。
- 用户自定义类型(User - defined Types):
- typedef:允许用户定义新的数据类型。例如,typedef enum {IDLE, READ, WRITE} state_type;定义了一个枚举类型state_type,包含三个状态:IDLE、READ和WRITE。这种类型常用于描述状态机的状态。
Verilog 的运算符
Verilog 提供了丰富的运算符,可分为以下几类:
- 算术运算符(Arithmetic Operators):
- +(加):用于两个操作数相加。例如,result = a + b;将变量a和b相加,并将结果赋给result。
- -(减):用于两个操作数相减。
- *(乘):用于两个操作数相乘。
- /(除):用于两个操作数相除,结果为整数部分。例如,5 / 2的结果为 2。
- %(取模):返回除法运算的余数。例如,5 % 2的结果为 1。
- 逻辑运算符(Logical Operators):
- &&(逻辑与):当两个操作数都为逻辑真(1)时,结果为 1;否则为 0。例如,if (a && b)只有当a和b都为 1 时,条件才成立。
- ||(逻辑或):只要两个操作数中有一个为逻辑真(1),结果就为 1;只有当两个操作数都为逻辑假(0)时,结果才为 0。
- !(逻辑非):对操作数取反,若操作数为 1,则结果为 0;若操作数为 0,则结果为 1。
- 关系运算符(Relational Operators):
-
(大于):比较两个操作数,若左边操作数大于右边操作数,则结果为 1;否则为 0。例如,a > b。
- <(小于):比较两个操作数,若左边操作数小于右边操作数,则结果为 1;否则为 0。
-
=(大于等于):若左边操作数大于或等于右边操作数,则结果为 1;否则为 0。
- <=(小于等于):若左边操作数小于或等于右边操作数,则结果为 1;否则为 0。
- ==(等于):比较两个操作数是否相等,若相等则结果为 1;否则为 0。在比较时,会考虑x和z值。
- !=(不等于):比较两个操作数是否不相等,若不相等则结果为 1;否则为 0。
- 位运算符(Bit - wise Operators):对操作数的每一位进行运算。
- &(按位与):将两个操作数对应位进行与运算,每一位的结果只有当两个对应位都为 1 时才为 1,否则为 0。例如,4’b1010 & 4’b1100的结果为4’b1000。
- |(按位或):将两个操作数对应位进行或运算,每一位的结果只要有一个对应位为 1 就为 1,只有当两个对应位都为 0 时才为 0。
- ^(按位异或):将两个操作数对应位进行异或运算,每一位的结果当两个对应位不同时为 1,相同时为 0。
- ~(按位取反):对操作数的每一位取反,0 变为 1,1 变为 0。
- 缩减运算符(Reduction Operators):对单个操作数进行运算,结果为 1 位。
- &(缩减与):对操作数的所有位进行与运算,结果为 1 位。例如,& 4’b1010的结果为0,因为只要有一位为 0,与运算结果就为 0。
- |(缩减或):对操作数的所有位进行或运算,只要有一位为 1,结果就为 1。
- ^(缩减异或):对操作数的所有位进行异或运算。
- ~&(缩减与非):先进行缩减与运算,再对结果取反。
- ~|(缩减或非):先进行缩减或运算,再对结果取反。
- ~^(缩减同或):先进行缩减异或运算,再对结果取反,即当所有位相同时结果为 1,否则为 0。
- 移位运算符(Shift Operators):
- <<(左移):将操作数向左移动指定的位数,右边空出的位补 0。例如,4’b1010 << 1的结果为4’b0100。
-
(右移):将操作数向右移动指定的位数,左边空出的位补符号位(对于有符号数)或 0(对于无符号数)。例如,4’b1010 >> 1的结果为4’b0101。
- 条件运算符(Conditional Operator):也称为三元运算符,形式为condition? true_expression : false_expression。如果condition为真(1),则返回true_expression的值;否则返回false_expression的值。例如,result = (a > b)? a : b;表示如果a大于b,则result等于a;否则result等于b。
- 拼接运算符(Concatenation Operator):用大括号{}将多个信号或表达式拼接在一起。例如,{a, b}将信号a和b拼接成一个新的信号,拼接顺序为a在前,b在后。还可以重复拼接,如{4{a}}表示将信号a重复 4 次进行拼接。
阅读
《杀死一只知更鸟》
第三章 结束