本文主要是介绍FPGA第 10 篇,Verilog 中的运算符和分支语句,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
我们都知道 Verilog 作为一种硬件描述语言,不仅用于设计和仿真数字电路,还为开发者提供了强大的工具,用于控制和优化硬件的行为。其中运算符和分支语句是 Verilog 中的两大核心组成部分,它们负责执行逻辑操作、数学运算以及决定逻辑流的控制。
-
运算符 在 Verilog 中用于进行各种计算和逻辑操作,它们类似于软件编程中的运算符,但特定于硬件操作,涵盖了算术、逻辑、按位操作、移位操作和条件表达式等。通过运算符,我们可以高效地描述复杂的数字逻辑和信号处理过程。
-
分支语句 则用于控制电路的行为,决定在不同的条件下执行哪些逻辑。在设计状态机、控制器或条件逻辑时,分支语句如
if-else
和case
系列的语句起着至关重要的作用,它们为我们提供了灵活的方式,去实现条件判断、选择执行路径和优化硬件逻辑。
通过合理使用 Verilog 中的运算符和分支语句,我们可以构建功能强大且高效的硬件电路设计,满足各种复杂的数字系统需求。上期介绍了 Verilog 中的关键字和基数,请看,
Verilog 中的关键字和基数https://blog.csdn.net/weixin_65793170/article/details/141625021?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22141625021%22%2C%22source%22%3A%22weixin_65793170%22%7D
掌握这些技能基础,我们可以高效地设计和验证 FPGA 电路,从而实现所需的数字系统功能。这里我们继续分享一下 Verilog 中常用的运算符,记录一下
一. 运算符
1. 运算符介绍
运算符:在Verilog HDL中,运算符是构建硬件描述的基础元素之一,用于定义和操作信号、变量以及模块内部的数据流动。正确理解和使用这些运算符,对于编写高效、可读性强的 Verilog代码至关重要,Verilog提供了多种类型的运算符,每种运算符都有其特定的功能和应用场景。
2. 运算符分类
Verilog HDL中的运算符可以分为以下几个主要类别:
- 算术运算符(上期讲过)
- 逻辑运算符
- 关系运算符
- 移位运算符
- 按位运算符
- 归约运算符
之前我们分析了 Verilog 中的算术运算符,FPGA第 8 篇,详细请看,
Verilog 数据类型、逻辑值和算术运算符https://blog.csdn.net/weixin_65793170/article/details/141629702?spm=1001.2014.3001.5501这里我们来分享一下,其它运算符的应用。
3. 运算符优先级
(1)分析介绍
在 Verilog 中,运算符的优先级对于表达式的计算顺序非常重要。以下是常见运算符按优先级从高到低的排序:
括号(Parentheses):
()
优先级最高,用于强制指定计算顺序。一元运算符(Unary Operators):按位非(
~
)、逻辑非(!
)、按位与(&
,单操作数)、按位或(|
,单操作数)、按位异或(^
,单操作数)、按位同或(~^
或^~
,单操作数) 包括按位非、逻辑非及单操作数的按位操作符。乘法运算符(Multiplicative Operators):
*
、/
、%
用于乘法、除法和取模运算。加法运算符(Additive Operators):
+
、-
用于加法和减法运算。移位运算符(Shift Operators):
<<
、>>
、<<<
、>>>
用于位的左移、右移以及算术移位操作。关系运算符(Relational Operators):
<
、>
、<=
、>=
用于比较操作,如小于、大于等。相等性运算符(Equality Operators):
==
、!=
、===
、!==
用于比较两个值是否相等或不等。按位运算符(Bitwise Operators):按位与(
&
)、按位异或(^
)、按位异或非(~^
或^~
)、按位或(|
) 用于按位与、或、异或等操作。逻辑运算符(Logical Operators):逻辑与(
&&
)、逻辑或(||
) 用于逻辑与和逻辑或操作。条件运算符(Conditional Operator):
?:
用于三元条件运算。赋值运算符(Assignment Operators):
=
、非阻塞赋值<=
用于赋值操作。逗号运算符(Comma Operator):
,
用于分隔多个表达式,按顺序计算。
(2)优先级关系
总的优先级关系为:
一元运算符 > 二元运算符(算数运算符 > 移位运算符 > 关系运算符 > 相等性运算符 > 按位运算符 > 逻辑运算符) > 三元运算符(条件运算符
?:
) > 赋值运算符。在编写代码时,可以使用 "()" 来增加优先级。
(3)注意事项
- 归约运算符在 Verilog 中被归为一元运算符,因此其优先级与其他一元运算符相同。
- 赋值运算符中的非阻塞赋值运算符
<=
和 关系运算符中的 小于等于<=
在符号上是相同的,但它们的功能、语法环境以及优先级完全不同。
4. 按位运算符
(1)介绍
按位运算符:在 Verilog 中,按位运算符用于对两个相同长度的向量进行位级操作。这类运算符在组合逻辑设计中非常常见,可以用于实现各种逻辑功能,如数据选择、数据修改等。按位运算符能够帮助我们高效地处理多位数据。
(2)分类
按位运算符用于对两个相同长度的向量进行位级操作,并返回一个与输入向量相同长度的结果。常见的按位运算符包括:
- 按位与(Bitwise AND):
&
- 按位或(Bitwise OR):
|
- 按位异或(Bitwise XOR):
^
- 按位异或非(Bitwise XNOR):
~^
或^^
- 按位非(Bitwise NOT):
~
(一元运算符)
(3)含义
-
按位与
- 运算符:
&
(二元形式) - 功能:对两个向量的每一位执行逻辑与操作。如果两个向量的对应位都是1,则结果位为1;否则结果位为0。
- 代码示例:m & n
如果wire [3:0] m, n; wire [3:0] result;assign result = m & n; // 按位与
m
为4'b1100
,n
为4'b1010
,则result
为4'b1000
。
- 运算符:
-
按位或
- 运算符:
|
(二元形式) - 功能:对两个向量的每一位执行逻辑或操作。如果两个向量的对应位中至少有一位是1,则结果位为1;否则结果位为0。
- 代码示例:
如果wire [3:0] m, n; wire [3:0] result;assign result = m | n; // 按位或
m
为4'b1100
,n
为4'b1010
,则result
为4'b1110
。
- 运算符:
-
按位异或
- 运算符:
^
(二元形式) - 功能:对两个向量的每一位执行逻辑异或操作。如果两个向量的对应位不相同,则结果位为1;否则结果位为0。
- 代码示例:
如果wire [3:0] m, n; wire [3:0] result;assign result = m ^ n; // 按位异或
m
为4'b1100
,n
为4'b1010
,则result
为4'b0110
。
- 运算符:
-
按位异或非
- 运算符:
~^
或^^
(二元形式) - 功能:对两个向量的每一位执行逻辑异或非操作。如果两个向量的对应位相同,则结果位为1;否则结果位为0。
- 代码示例:
如果wire [3:0] m, n; wire [3:0] result;assign result = ~(m ^ n); // 按位异或非
m
为4'b1100
,n
为4'b1010
,则result
为4'b1001
。
- 运算符:
-
按位非
- 运算符:
~
(一元形式) - 功能:对一个向量的每一位执行逻辑非操作。如果位为1,则结果位为0;如果位为0,则结果位为1。
- 代码示例:
如果wire [3:0] m; wire [3:0] result;assign result = ~m; // 按位非
m
为4'b1100
,则result
为4'b0011
。
- 运算符:
5. 归约运算符
(1)介绍
归约运算符:在 Verilog 中,归约运算符是一类特殊的运算符,用于将一个向量简化成一个标量值。这类运算符通常用于逻辑判断、状态机控制以及其他需要对多个位进行综合分析的场合。归约运算符能够帮助设计者简化代码并提高逻辑表达的清晰度。
(2)分类
归约运算符是一类一元运算符,接受一个向量作为输入,并返回一个标量(通常是单比特)的结果。常见的归约运算符包括:
- 归约与(Reduction AND):
&
(一元形式)- 归约或(Reduction OR):
|
(一元形式)- 归约异或(Reduction XOR):
^
(一元形式)- 归约异或非(Reduction XNOR):
~^
或^^
(一元形式)
(3)含义
-
归约与
- 运算符:
&
(一元形式) - 功能:对一个向量中的所有位执行逻辑与操作。如果所有位都是1,则结果为1;否则结果为0。
- 代码示例:&m
如果wire [3:0] m; wire m_and;assign m_and = &m; // 归约与
m
为4'b1100
,则m_and
为1
。
- 运算符:
-
归约或
- 运算符:
|
(一元形式) - 功能:对一个向量中的所有位执行逻辑或操作。如果至少有一位是1,则结果为1;否则结果为0。
- 代码示例:
如果wire [3:0] m; wire m_or;assign m_or = |m; // 归约或
m
为4'b1100
,则m_or
为1
。
- 运算符:
-
归约异或
- 运算符:
^
(一元形式) - 功能:对一个向量中的所有位执行逻辑异或操作。如果1的位数为奇数,则结果为1;否则结果为0。
- 代码示例:
如果wire [3:0] m; wire m_xor;assign m_xor = ^m; // 归约异或
m
为4'b1100
,则m_xor
为0
。
- 运算符:
-
归约异或非
- 运算符:
~^
或^^
(一元形式) - 功能:对一个向量中的所有位执行逻辑异或非操作。如果1的位数为偶数,则结果为1;否则结果为0。
- 代码示例:
如果wire [3:0] m; wire m_xnor;assign m_xnor = ~^m; // 归约异或非
m
为4'b1100
,则m_xnor
为1
。
- 运算符:
(4)按位与归约
按位运算符 和 归约运算符的区别:
- 虽然 按位运算符 和 归约运算符,符号相同,但它们的应用场景不同,具体运算,取决于上下文。
- 按位运算符:指的是一类运算符,用于对两个相同长度的向量进行位级操作,返回一个与输入向量相同长度的结果。
- 归约运算符:指的是一类运算符,用于将一个向量简化成一个标量值。
6. 逻辑运算符
(1)介绍
逻辑运算符:在 Verilog 中,逻辑运算符是构建复杂逻辑表达式的基础,它们使得设计者能够清晰、准确地表达电路的行为特征。通过使用逻辑运算符,设计者可以轻松实现条件判断、状态转移以及其他高级逻辑功能。
(2)分类
在Verilog中,逻辑运算符用于对布尔表达式或条件进行逻辑运算。主要的逻辑运算符包括:
逻辑与:&& 表示:逻辑与(AND)操作
逻辑或:|| 表示:逻辑或(OR)操作
逻辑非:! 表示:逻辑非(NOT)操作
(3)含义
① 逻辑与
- 运算符:
&&
(二元形式) - 功能:对两个布尔表达式执行逻辑与操作。如果两个表达式的结果都为真 1,则结果为真 1;否则结果为假(0)。
- 代码示例:
wire a, b;
wire result;
assign result = a && b; // 逻辑与
- 示例解释:
- 如果
a
为 1,b
为 1,则result
为 1。 - 如果
a
为 1,b
为 0,则result
为 0。
- 如果
② 逻辑或
- 运算符:
||
(二元形式) - 功能:对两个布尔表达式执行逻辑或操作。如果两个表达式中至少有一个为真(1),则结果为真(1);否则结果为假(0)。
- 代码示例:
wire a, b;
wire result;
assign result = a || b; // 逻辑或
- 示例解释:
- 如果
a
为 0,b
为 1,则result
为 1。 - 如果
a
为 0,b
为 0,则result
为 0。
- 如果
③ 逻辑非
- 运算符:
!
(一元形式) - 功能:对布尔表达式执行逻辑非操作,将表达式的布尔值取反。如果表达式为真(1),结果为假(0);如果表达式为假(0),结果为真(1)。
- 代码示例:
wire a;
wire result;
assign result = !a; // 逻辑非
- 示例解释:
- 如果
a
为 1,则result
为 0。 - 如果
a
为 0,则result
为 1。
- 如果
(4)逻辑值取反
逻辑值 使用 逻辑运算符,逻辑非,取反
!x
=x
!z
=z
!1
=0
!0
=1
7. 关系运算符
(1)介绍
关系运算符:在 Verilog 中,关系运算符允许我们基于数值之间的比较来作出决策,这对于编写高效、可靠的硬件描述代码至关重要。无论是在时序控制、数据流管理还是在状态转换中,关系运算符都能帮助我们精确地定义硬件的行为模式。
(2)分类
在 Verilog 中,关系运算符用于比较两个数值或表达式,以确定它们之间的关系。主要的关系运算符包括:
- 等于:== 用于检查两个操作数是否相等
- 不等:!= 或 !== 用于检查两个操作数是否不相等
- 大于:> 用于检查左边的操作数是否大于右边的操作数
- 小于:< 用于检查左边的操作数是否小于右边的操作数
- 大于等于:>= 用于检查左边的操作数是否大于或等于右边的操作数
- 小于等于:<= 用于检查左边的操作数是否小于或等于右边的操作数
(3)含义
① 等于
- 运算符:
==
(二元形式) - 功能:检查两个表达式是否相等。如果两个表达式的值相同,则结果为真(1),否则结果为假(0)。
- 代码示例:
wire [3:0] a, b; wire result; assign result = (a == b); // 逻辑相等
- 示例解释:
- 如果
a
和b
的值相同,则result
为 1。 - 如果
a
和b
的值不同,则result
为 0。
- 如果
② 不等
- 运算符:
!=
(二元形式) - 功能:检查两个表达式是否不相等。如果两个表达式的值不同,则结果为真(1),否则结果为假(0)。
- 代码示例:
wire [3:0] a, b; wire result; assign result = (a != b); // 逻辑不等
- 示例解释:
- 如果
a
和b
的值不同,则result
为 1。 - 如果
a
和b
的值相同,则result
为 0。
- 如果
③ 大于
- 运算符:
>
(二元形式) - 功能:检查第一个表达式是否大于第二个表达式。如果第一个表达式的值大于第二个表达式的值,则结果为真(1),否则结果为假(0)。
- 代码示例:
wire [3:0] a, b; wire result; assign result = (a > b); // 大于
- 示例解释:
- 如果
a
的值大于b
的值,则result
为 1。 - 如果
a
的值小于或等于b
的值,则result
为 0。
- 如果
④ 小于
- 运算符:
<
(二元形式) - 功能:检查第一个表达式是否小于第二个表达式。如果第一个表达式的值小于第二个表达式的值,则结果为真(1),否则结果为假(0)。
- 代码示例:
wire [3:0] a, b; wire result; assign result = (a < b); // 小于
- 示例解释:
- 如果
a
的值小于b
的值,则result
为 1。 - 如果
a
的值大于或等于b
的值,则result
为 0。
- 如果
⑤ 大于等于
- 运算符:
>=
(二元形式) - 功能:检查第一个表达式是否大于或等于第二个表达式。如果第一个表达式的值大于或等于第二个表达式的值,则结果为真(1),否则结果为假(0)。
- 代码示例:
wire [3:0] a, b; wire result; assign result = (a >= b); // 大于等于
- 示例解释:
- 如果
a
的值大于或等于b
的值,则result
为 1。 - 如果
a
的值小于b
的值,则result
为 0。
- 如果
⑥ 小于等于
- 运算符:
<=
(二元形式) - 功能:检查第一个表达式是否小于或等于第二个表达式。如果第一个表达式的值小于或等于第二个表达式的值,则结果为真(1),否则结果为假(0)。
- 代码示例:
wire [3:0] a, b; wire result; assign result = (a <= b); // 小于等于
- 示例解释:
- 如果
a
的值小于或等于b
的值,则result
为 1。 - 如果
a
的值大于b
的值,则result
为 0。
- 如果
(4)逻辑与关系
逻辑运算符和关系运算符的区别:
- 逻辑运算符:主要处理布尔值(逻辑值)。用于对布尔表达式进行逻辑运算。
- 关系运算符:主要处理数值比较。用于比较数值或表达式之间的关系。
8. 移位运算符
(1)介绍
移位运算符:在 Verilog 中,移位运算符可以对二进制数据进行左移或右移操作,移动时会在空位中填充指定的值,这对于实现数据对齐、位域提取、乘除运算等操作非常有用,可以显著提高硬件性能和效率。
(2)分类
移位运算符用于将二进制数的位向左或向右移动。主要的移位运算符包括:
- 逻辑左移:
<< 表示
操作数向左移动指定的位数,并用0填充高位。- 逻辑右移:
>> 表示
操作数向右移动指定的位数,并用0填充高位。- 算术右移:
>>> 表示
操作数向右移动指定的位数,并用原来的符号位(最高有效位)填充高位。
(3)含义
① 逻辑左移(<<
)
- 运算符:
<<
(二元形式) - 功能:将二进制数的位向左移动指定的位数,右侧空位用
0
填充。每次左移一位,相当于将数值乘以2
。 - 代码示例:
wire [7:0] a; wire [7:0] result; assign result = a << 2; // 逻辑左移
- 示例解释:
- 如果
a
为8'b00001111
,则result
在左移两位后为8'b00111100
。
- 如果
② 逻辑右移(>>
)
- 运算符:
>>
(二元形式) - 功能:将二进制数的位向右移动指定的位数,左侧空位用
0
填充。每次右移一位,相当于将数值除以2
(向下取整)。 - 代码示例:
wire [7:0] a; wire [7:0] result; assign result = a >> 2; // 逻辑右移
- 示例解释:
- 如果
a
为8'b00001111
,则result
在右移两位后为8'b00000011
。
- 如果
③ 算术右移(>>>
)
- 运算符:
>>>
(二元形式) - 功能:将二进制数的位向右移动指定的位数,左侧的空位根据最高位(符号位)填充(即保持符号)。适用于有符号数的移位操作。
- 代码示例:
wire signed [7:0] a; wire signed [7:0] result; assign result = a >>> 2; // 算术右移
- 示例解释:
- 如果
a
为8'sb11111100
(即 -4),在算术右移两位后,result
为8'sb11111111
(即 -1)。
- 如果
9. 位拼接运算符
(1)介绍
位拼接运算符:在 Verilog 中,位拼接运算符允许我们将多个二进制数连接起来形成一个新的二进制数,这对于创建复杂的数据结构、实现特定的数据处理算法以及优化硬件资源的使用都非常有用。
(2)分类
位拼接运算符用于处理和组合数据,能够有效地将不同宽度的信号或常量合并为一个新的数据位宽。位拼接运算符的主要使用方式:
拼接运算符:
{}
用于将多个数据位拼接成一个新的数据位重复运算符:
{N{exp}}
用于生成特定模式的重复位数据。
(3)含义
① 位拼接运算符({}
)
- 运算符:
{}
(大括号) - 功能:将多个数据位拼接在一起,形成一个新的数据位宽。
- 用法:可以用于信号、常量或它们的组合,来形成一个更宽的数据位。
- 代码示例:
wire [3:0] a, b;
wire [7:0] result;
assign result = {a, b}; // 拼接两个信号
assign result = {4'b1010, a}; // 拼接常量和信号
assign result = {a[1:0], b[3:2]}; // 部分拼接
② 重复运算符({N{exp}}
)
- 运算符:
{N{exp}}
(大括号和重复符号) - 功能:将表达式
exp
重复N
次,形成一个新的数据位宽。 - 用法:用于生成特定模式的重复位数据。
- 代码示例:
wire [7:0] result; assign result = {4{4'b1010}}; // 重复 4 次 4'b1010,结果为 8'b10101010
10. 条件运算符
(1)介绍
条件运算符:在 Verilog 中,条件运算符是一种简洁而强大的工具,用于基于特定条件来选择不同的值或执行不同的操作,应用非常广泛,它能够将复杂的条件判断压缩为一行代码,使代码更加紧凑和易读。
(2)分类
条件运算符通常指的就是三元运算符,通常只有三元运算符被用作条件运算符。请看:
- 条件运算符(三元运算符):? :
常用于需要根据一个布尔条件选择不同的值的场景。
(3)含义
① 条件运算符(三元运算符 ? :
)
- 运算符:
? :
(三元运算符) - 功能:根据条件表达式的结果选择并返回两个表达式之一。如果条件为真,则返回第一个表达式的值;如果条件为假,则返回第二个表达式的值。
- 用法:常用于需要根据一个布尔条件选择不同的值的场景。
- 代码示例:
wire [3:0] a, b; wire [3:0] result; wire condition; assign result = condition ? a : b; // 如果 condition 为真,则 result 为 a,否则为 b
- 示例解释:
- 如果
condition
为1
(真),则result
的值为a
。 - 如果
condition
为0
(假),则result
的值为b
。 - 这种运算符常用于简洁表达需要根据条件选择不同信号的逻辑。
- 这里由于
condition
的值是未定义的,因此result
的值也将是不确定的。它既不是a
的值,也不是b
的值,而是与condition
一样,处于未定义状态。
- 如果
11. wire [n:0] a, b; 语句解析
这样的声明用于定义一个向量类型的信号线(wire),其中 [3:0]
表示该信号线的位宽,具体含义如下(其中 向量类型的信号线 也可以被称为 线网型变量):
位宽(Width):
[3:0]
表示该信号线的位宽为 4 位(从 0 到 3 共计 4 位)。这里的数字表示索引位置,索引是从高到低排列的,即[最高有效位:最低有效位]
。- 例如,在
[3:0]
中,3 是最高有效位(MSB),0 是最低有效位(LSB)。信号类型:
wire
是信号线类型的一种,用于表示组合逻辑中的连线。它可以连接逻辑门或其他组件的输入和输出。- 除了
wire
,Verilog 还有其他类型的信号,如reg
用于存储状态信息,integer
用于整型变量等。声明多个变量:
- 在
wire [3:0] a, b;
这一行中,声明了两个 4 位宽的信号线a
和b
。
二. 分支语句
分支语句:Verilog 提供了多种分支语句来实现条件判断和选择执行不同的代码块。这些语句广泛应用于硬件设计中,用于控制逻辑流。
1. if-else 语句
if-else 语句:在 Verilog 中,if-else语句是按顺序排列的,但在硬件实现中,这些条件判断的执行顺序并不是严格线性的。硬件电路通过逻辑门的组合几乎同时评估所有条件(受限于信号传播速度),但根据条件判断的结果,只有一个分支会被选中并执行。这意味着,从执行顺序的角度看,if-else语句在硬件中表现为几乎并行的条件评估,随后是串行地选择并执行满足条件的分支。不过,需要注意的是,由于硬件电路的并行性,这种“并行评估”并不会导致显著的时间延迟差异,而是表现为一种高效的逻辑处理方式。
- 关键词:
if
、else
- 功能:根据条件表达式的结果选择性地执行不同的代码块。如果条件为真,则执行
if
代码块;如果为假,则执行else
代码块(可选)。 - 用法:通常用于条件判断,选择不同的硬件行为。
- 代码示例:
wire [3:0] a, b; wire [3:0] result; wire condition;always @(*) beginif (condition)result = a;elseresult = b; end
- 示例解释:
- 如果
condition
为真,则result
赋值为a
。 - 如果
condition
为假,则result
赋值为b
。
- 如果
if-else 注意事项:
- 确保所有条件都被完整处理,避免生成锁存器。
- 避免多层嵌套,以减少逻辑复杂性和维护难度。
- 确保每个
if
语句都有对应的else
,否则可能导致综合问题。
2. case 语句
case 语句:在 Verilog 中,case语句的执行顺序在硬件实现时并非严格按照代码中的分支顺序进行。实际上,硬件电路会根据输入信号的值,在逻辑上几乎同时考虑所有case项,但物理上只会选择性地激活与输入值相匹配的分支。这种激活是即时的,一旦输入信号稳定,相应的分支逻辑就会被触发。因此,从执行顺序的角度来看,case语句在硬件中的行为更像是并行识别(所有case项都被考虑)后的串行执行(只有一个分支被激活)。
其中要注意,标准的
case
语句在 Verilog 中是不允许出现多个条件同时被触发的情况的,因为每个case
项都应该是互斥的,即每个输入值只能匹配到一个case
项。如果确实存在多个条件看似可以被触发(例如,由于输入信号的位宽大于比较位宽,导致未使用的位被忽略),那么这通常是一个设计错误,需要在代码编写阶段就加以避免。而且在 Verilog 中,
case
语句有三种主要的形式:case
、casez
和casex
。每种形式都有其特定的用途和行为特点。
(1)case 语句
- 关键词:
case
、default
- 功能:根据表达式的值,选择并执行匹配的分支代码块。如果没有匹配的分支,执行
default
分支(可选)。 - 用法:通常用于多选一的条件判断,尤其适用于状态机或控制信号选择。
- 代码示例:
wire [1:0] sel; reg [3:0] result;always @(*) begincase (sel)2'b00: result = 4'b0001;2'b01: result = 4'b0010;2'b10: result = 4'b0100;2'b11: result = 4'b1000;default: result = 4'b0000;endcase end
- 示例解释:
- 根据
sel
的值,选择不同的分支并给result
赋值。 - 如果
sel
为2'b01
,则result
为4'b0010
。 default
分支处理没有匹配到任何分支的情况。
- 根据
case 注意事项:
- 始终包含
default
子句,处理所有未匹配的情况,避免生成锁存器。- 确保所有可能的值都被处理,特别是在有限状态机(FSM)设计中。
(2)casez 语句
- 关键词:
casez
、default
- 功能:与
case
类似,但允许在选择器表达式中使用z
(高阻态)作为通配符。 - 用法:用于处理带有
z
或x
(未知状态)的位模式匹配。 - 代码示例:
wire [3:0] opcode; reg [7:0] result;always @(*) begincasez (opcode)4'b1zzz: result = 8'hFF; // 匹配高位为 1,其他位为 z 或任意值4'b01zz: result = 8'hAA; // 匹配前两位为 01,其他位为 z 或任意值default: result = 8'h00;endcase end
- 示例解释:
casez
允许在选择表达式中使用z
,作为匹配条件。- 当
opcode
为4'b1001
或4'b111z
时,result
将匹配4'b1zzz
,并赋值为8'hFF
。
casez 注意事项:
- 小心使用
z
作为通配符,确保它不会意外匹配到错误的条件。- 确认使用
z
时电路中的高阻态信号被正确处理。
(3)casex 语句
- 关键词:
casex
、default
- 功能:与
casez
类似,但casex
允许x
和z
作为通配符进行匹配。 - 用法:用于处理带有
x
(未知状态)和z
的位模式匹配。 - 代码示例:
wire [3:0] opcode; reg [7:0] result;always @(*) begincasex (opcode)4'b1xxx: result = 8'hFF; // 匹配高位为 1,其他位为 x 或 z4'b01xx: result = 8'hAA; // 匹配前两位为 01,其他位为 x 或 zdefault: result = 8'h00;endcase end
- 示例解释:
casex
允许x
和z
作为通配符。- 当
opcode
为4'b1011
或4'b10zx
时,匹配4'b1xxx
,并将result
赋值为8'hFF
。
casez 注意事项:
- 尽量避免在综合过程中使用
x
作为通配符,因为x
可能引发不可预知的硬件行为。- 适合用于仿真,但在综合硬件时要特别谨慎。
(4)通用注意事项
- 确保所有条件都被覆盖,以避免未定义行为。
- 避免过多分支,保持代码简洁,增强可读性和可维护性。
创作不易,感觉有用,就一键三连,感谢(●'◡'●)
这篇关于FPGA第 10 篇,Verilog 中的运算符和分支语句的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!