FPGA第 10 篇,Verilog 中的运算符和分支语句

2024-09-05 22:12

本文主要是介绍FPGA第 10 篇,Verilog 中的运算符和分支语句,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

我们都知道 Verilog 作为一种硬件描述语言,不仅用于设计和仿真数字电路,还为开发者提供了强大的工具,用于控制和优化硬件的行为。其中运算符分支语句是 Verilog 中的两大核心组成部分,它们负责执行逻辑操作、数学运算以及决定逻辑流的控制。

  • 运算符 在 Verilog 中用于进行各种计算和逻辑操作,它们类似于软件编程中的运算符,但特定于硬件操作,涵盖了算术、逻辑、按位操作、移位操作和条件表达式等。通过运算符,我们可以高效地描述复杂的数字逻辑和信号处理过程。

  • 分支语句 则用于控制电路的行为,决定在不同的条件下执行哪些逻辑。在设计状态机、控制器或条件逻辑时,分支语句如 if-elsecase 系列的语句起着至关重要的作用,它们为我们提供了灵活的方式,去实现条件判断、选择执行路径和优化硬件逻辑。

通过合理使用 Verilog 中的运算符和分支语句,我们可以构建功能强大且高效的硬件电路设计,满足各种复杂的数字系统需求。上期介绍了 Verilog 中的关键字和基数,请看,

Verilog 中的关键字和基数icon-default.png?t=O83Ahttps://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中的运算符可以分为以下几个主要类别:

  1. 算术运算符(上期讲过)
  2. 逻辑运算符
  3. 关系运算符
  4. 移位运算符
  5. 按位运算符
  6. 归约运算符

之前我们分析了 Verilog 中的算术运算符,FPGA第 8 篇,详细请看,

Verilog 数据类型、逻辑值和算术运算符icon-default.png?t=O83Ahttps://blog.csdn.net/weixin_65793170/article/details/141629702?spm=1001.2014.3001.5501这里我们来分享一下,其它运算符的应用。


3. 运算符优先级

(1)分析介绍

        在 Verilog 中,运算符的优先级对于表达式的计算顺序非常重要。以下是常见运算符按优先级从高到低的排序:

  1. 括号(Parentheses):() 优先级最高,用于强制指定计算顺序。

  2. 一元运算符(Unary Operators):按位非(~)、逻辑非(!)、按位与(&,单操作数)、按位或(|,单操作数)、按位异或(^,单操作数)、按位同或(~^^~,单操作数) 包括按位非、逻辑非及单操作数的按位操作符。

  3. 乘法运算符(Multiplicative Operators):*/用于乘法、除法和取模运算。

  4. 加法运算符(Additive Operators):+用于加法和减法运算。

  5. 移位运算符(Shift Operators):<<>><<<>>> 用于位的左移、右移以及算术移位操作。

  6. 关系运算符(Relational Operators):<><=>= 用于比较操作,如小于、大于等。

  7. 相等性运算符(Equality Operators):==!====!== 用于比较两个值是否相等或不等。

  8. 按位运算符(Bitwise Operators):按位与(&)、按位异或(^)、按位异或非(~^^~)、按位或(|) 用于按位与、或、异或等操作。

  9. 逻辑运算符(Logical Operators):逻辑与(&&)、逻辑或(||) 用于逻辑与和逻辑或操作。

  10. 条件运算符(Conditional Operator):?: 用于三元条件运算。

  11. 赋值运算符(Assignment Operators):=、非阻塞赋值 <= 用于赋值操作。

  12. 逗号运算符(Comma Operator):用于分隔多个表达式,按顺序计算。

(2)优先级关系

总的优先级关系为:

        一元运算符 > 二元运算符(算数运算符 > 移位运算符 > 关系运算符 > 相等性运算符 > 按位运算符 > 逻辑运算符) > 三元运算符(条件运算符 ?:) > 赋值运算符。

在编写代码时,可以使用 "()" 来增加优先级。

(3)注意事项

  1. 归约运算符在 Verilog 中被归为一元运算符,因此其优先级与其他一元运算符相同。
  2. 赋值运算符中的非阻塞赋值运算符 <= 和 关系运算符中的 小于等于 <= 在符号上是相同的,但它们的功能、语法环境以及优先级完全不同。

4.  按位运算符

(1)介绍

        按位运算符:在 Verilog 中,按位运算符用于对两个相同长度的向量进行位级操作。这类运算符在组合逻辑设计中非常常见,可以用于实现各种逻辑功能,如数据选择、数据修改等。按位运算符能够帮助我们高效地处理多位数据。

(2)分类

        按位运算符用于对两个相同长度的向量进行位级操作,并返回一个与输入向量相同长度的结果。常见的按位运算符包括:

  1. 按位与(Bitwise AND):&
  2. 按位或(Bitwise OR):|
  3. 按位异或(Bitwise XOR):^
  4. 按位异或非(Bitwise XNOR):~^ 或 ^^
  5. 按位非(Bitwise NOT):~ (一元运算符)

(3)含义

  • 按位与
    • 运算符&(二元形式)
    • 功能:对两个向量的每一位执行逻辑与操作。如果两个向量的对应位都是1,则结果位为1;否则结果位为0。
    • 代码示例m & n
      wire [3:0] m, n;
      wire [3:0] result;assign result = m & n;  // 按位与
      如果 m 为 4'b1100n 为 4'b1010,则 result 为 4'b1000
  • 按位或
    • 运算符|(二元形式)
    • 功能:对两个向量的每一位执行逻辑或操作。如果两个向量的对应位中至少有一位是1,则结果位为1;否则结果位为0。
    • 代码示例
      wire [3:0] m, n;
      wire [3:0] result;assign result = m | n;  // 按位或
      如果 m 为 4'b1100n 为 4'b1010,则 result 为 4'b1110
  • 按位异或
    • 运算符^(二元形式)
    • 功能:对两个向量的每一位执行逻辑异或操作。如果两个向量的对应位不相同,则结果位为1;否则结果位为0。
    • 代码示例
      wire [3:0] m, n;
      wire [3:0] result;assign result = m ^ n;  // 按位异或
      如果 m 为 4'b1100n 为 4'b1010,则 result 为 4'b0110
  • 按位异或非
    • 运算符~^ 或 ^^(二元形式)
    • 功能:对两个向量的每一位执行逻辑异或非操作。如果两个向量的对应位相同,则结果位为1;否则结果位为0。
    • 代码示例
      wire [3:0] m, n;
      wire [3:0] result;assign result = ~(m ^ n);  // 按位异或非
      如果 m 为 4'b1100n 为 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)按位与归约

按位运算符 和 归约运算符的区别:

  1. 虽然 按位运算符 和 归约运算符,符号相同,但它们的应用场景不同,具体运算,取决于上下文。
  2. 按位运算符:指的是一类运算符,用于对两个相同长度的向量进行位级操作,返回一个与输入向量相同长度的结果。
  3. 归约运算符:指的是一类运算符,用于将一个向量简化成一个标量值。

6. 逻辑运算符

(1)介绍

        逻辑运算符:在 Verilog 中,逻辑运算符是构建复杂逻辑表达式的基础,它们使得设计者能够清晰、准确地表达电路的行为特征。通过使用逻辑运算符,设计者可以轻松实现条件判断、状态转移以及其他高级逻辑功能。

(2)分类

在Verilog中,逻辑运算符用于对布尔表达式或条件进行逻辑运算。主要的逻辑运算符包括:

  1. 逻辑与:&&        表示:逻辑与(AND)操作        

  2. 逻辑或:||           表示:逻辑或(OR)操作

  3. 逻辑非:!            表示:逻辑非(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 中,关系运算符用于比较两个数值或表达式,以确定它们之间的关系。主要的关系运算符包括:

  1. 等于:== 用于检查两个操作数是否相等
  2. 不等:!= 或 !== 用于检查两个操作数是否不相等
  3. 大于:> 用于检查左边的操作数是否大于右边的操作数
  4. 小于:< 用于检查左边的操作数是否小于右边的操作数
  5. 大于等于:>= 用于检查左边的操作数是否大于或等于右边的操作数
  6. 小于等于:<= 用于检查左边的操作数是否小于或等于右边的操作数

(3)含义

① 等于
  • 运算符==(二元形式)
  • 功能:检查两个表达式是否相等。如果两个表达式的值相同,则结果为真(1),否则结果为假(0)。
  • 代码示例
    wire [3:0] a, b; 
    wire result; 
    assign result = (a == b); // 逻辑相等
  • 示例解释
    • 如果 ab 的值相同,则 result 为 1。
    • 如果 ab 的值不同,则 result 为 0。
② 不等
  • 运算符!=(二元形式)
  • 功能:检查两个表达式是否不相等。如果两个表达式的值不同,则结果为真(1),否则结果为假(0)。
  • 代码示例
    wire [3:0] a, b; 
    wire result; 
    assign result = (a != b); // 逻辑不等
  • 示例解释
    • 如果 ab 的值不同,则 result 为 1。
    • 如果 ab 的值相同,则 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)分类

移位运算符用于将二进制数的位向左或向右移动。主要的移位运算符包括:

  1. 逻辑左移:<< 表示操作数向左移动指定的位数,并用0填充高位。
  2. 逻辑右移:>> 表示操作数向右移动指定的位数,并用0填充高位。
  3. 算术右移:>>> 表示操作数向右移动指定的位数,并用原来的符号位(最高有效位)填充高位。

(3)含义

① 逻辑左移(<<
  • 运算符<<(二元形式)
  • 功能:将二进制数的位向左移动指定的位数,右侧空位用 0 填充。每次左移一位,相当于将数值乘以 2
  • 代码示例
    wire [7:0] a; 
    wire [7:0] result; 
    assign result = a << 2; // 逻辑左移
  • 示例解释
    • 如果 a8'b00001111,则 result 在左移两位后为 8'b00111100
② 逻辑右移(>>
  • 运算符>>(二元形式)
  • 功能:将二进制数的位向右移动指定的位数,左侧空位用 0 填充。每次右移一位,相当于将数值除以 2(向下取整)。
  • 代码示例
    wire [7:0] a; 
    wire [7:0] result; 
    assign result = a >> 2; // 逻辑右移
  • 示例解释
    • 如果 a8'b00001111,则 result 在右移两位后为 8'b00000011
③ 算术右移(>>>
  • 运算符>>>(二元形式)
  • 功能:将二进制数的位向右移动指定的位数,左侧的空位根据最高位(符号位)填充(即保持符号)。适用于有符号数的移位操作。
  • 代码示例
    wire signed [7:0] a; 
    wire signed [7:0] result; 
    assign result = a >>> 2; // 算术右移
  • 示例解释
    • 如果 a8'sb11111100(即 -4),在算术右移两位后,result8'sb11111111(即 -1)。

9. 位拼接运算符

(1)介绍

        位拼接运算符:在 Verilog 中,位拼接运算符允许我们将多个二进制数连接起来形成一个新的二进制数,这对于创建复杂的数据结构、实现特定的数据处理算法以及优化硬件资源的使用都非常有用。

(2)分类

位拼接运算符用于处理和组合数据,能够有效地将不同宽度的信号或常量合并为一个新的数据位宽。位拼接运算符的主要使用方式:

  1. 拼接运算符:{} 用于将多个数据位拼接成一个新的数据位

  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
  • 示例解释
    • 如果 condition1(真),则 result 的值为 a
    • 如果 condition0(假),则 result 的值为 b
    • 这种运算符常用于简洁表达需要根据条件选择不同信号的逻辑。
    • 这里由于 condition 的值是未定义的,因此 result 的值也将是不确定的。它既不是 a 的值,也不是 b 的值,而是与 condition 一样,处于未定义状态。

11. wire [n:0] a, b; 语句解析

        这样的声明用于定义一个向量类型的信号线(wire),其中 [3:0] 表示该信号线的位宽,具体含义如下(其中 向量类型的信号线 也可以被称为 线网型变量):

  1. 位宽(Width)

    • [3:0] 表示该信号线的位宽为 4 位(从 0 到 3 共计 4 位)。这里的数字表示索引位置,索引是从高到低排列的,即 [最高有效位:最低有效位]
    • 例如,在 [3:0] 中,3 是最高有效位(MSB),0 是最低有效位(LSB)。
  2. 信号类型

    • wire 是信号线类型的一种,用于表示组合逻辑中的连线。它可以连接逻辑门或其他组件的输入和输出。
    • 除了 wire,Verilog 还有其他类型的信号,如 reg 用于存储状态信息,integer 用于整型变量等。
  3. 声明多个变量

    • 在 wire [3:0] a, b; 这一行中,声明了两个 4 位宽的信号线 a 和 b


二. 分支语句

        分支语句:Verilog 提供了多种分支语句来实现条件判断和选择执行不同的代码块。这些语句广泛应用于硬件设计中,用于控制逻辑流。

1. if-else 语句

        if-else 语句:在 Verilog 中,if-else语句是按顺序排列的,但在硬件实现中,这些条件判断的执行顺序并不是严格线性的。硬件电路通过逻辑门的组合几乎同时评估所有条件(受限于信号传播速度),但根据条件判断的结果,只有一个分支会被选中并执行。这意味着,从执行顺序的角度看,if-else语句在硬件中表现为几乎并行的条件评估,随后是串行地选择并执行满足条件的分支。不过,需要注意的是,由于硬件电路的并行性,这种“并行评估”并不会导致显著的时间延迟差异,而是表现为一种高效的逻辑处理方式。

  • 关键词ifelse
  • 功能:根据条件表达式的结果选择性地执行不同的代码块。如果条件为真,则执行 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 注意事项:

  1. 确保所有条件都被完整处理,避免生成锁存器。
  2. 避免多层嵌套,以减少逻辑复杂性和维护难度。
  3. 确保每个 if 语句都有对应的 else,否则可能导致综合问题。

2. case 语句

        case 语句在 Verilog 中,case语句的执行顺序在硬件实现时并非严格按照代码中的分支顺序进行。实际上,硬件电路会根据输入信号的值,在逻辑上几乎同时考虑所有case项,但物理上只会选择性地激活与输入值相匹配的分支。这种激活是即时的,一旦输入信号稳定,相应的分支逻辑就会被触发。因此,从执行顺序的角度来看,case语句在硬件中的行为更像是并行识别(所有case项都被考虑)后的串行执行(只有一个分支被激活)。

        其中要注意,标准的case语句在 Verilog 中是不允许出现多个条件同时被触发的情况的,因为每个case项都应该是互斥的,即每个输入值只能匹配到一个case项。如果确实存在多个条件看似可以被触发(例如,由于输入信号的位宽大于比较位宽,导致未使用的位被忽略),那么这通常是一个设计错误,需要在代码编写阶段就加以避免。

        而且在 Verilog 中,case 语句有三种主要的形式:casecasezcasex。每种形式都有其特定的用途和行为特点。

(1)case 语句

  • 关键词casedefault
  • 功能:根据表达式的值,选择并执行匹配的分支代码块。如果没有匹配的分支,执行 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 赋值。
    • 如果 sel2'b01,则 result4'b0010
    • default 分支处理没有匹配到任何分支的情况。

case 注意事项:

  1. 始终包含 default 子句,处理所有未匹配的情况,避免生成锁存器。
  2. 确保所有可能的值都被处理,特别是在有限状态机(FSM)设计中。

(2)casez 语句

  • 关键词casezdefault
  • 功能:与 case 类似,但允许在选择器表达式中使用 z(高阻态)作为通配符。
  • 用法:用于处理带有 zx(未知状态)的位模式匹配。
  • 代码示例
    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,作为匹配条件。
    • opcode4'b10014'b111z 时,result 将匹配 4'b1zzz,并赋值为 8'hFF

casez 注意事项:

  1. 小心使用 z 作为通配符,确保它不会意外匹配到错误的条件。
  2. 确认使用 z 时电路中的高阻态信号被正确处理。

(3)casex 语句

  • 关键词casexdefault
  • 功能:与 casez 类似,但 casex 允许 xz 作为通配符进行匹配。
  • 用法:用于处理带有 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 允许 xz 作为通配符。
    • opcode4'b10114'b10zx 时,匹配 4'b1xxx,并将 result 赋值为 8'hFF

casez 注意事项:

  1. 尽量避免在综合过程中使用 x 作为通配符,因为 x 可能引发不可预知的硬件行为。
  2. 适合用于仿真,但在综合硬件时要特别谨慎。

(4)通用注意事项

  1. 确保所有条件都被覆盖,以避免未定义行为。
  2. 避免过多分支,保持代码简洁,增强可读性和可维护性。

创作不易,感觉有用,就一键三连,感谢(●'◡'●)

这篇关于FPGA第 10 篇,Verilog 中的运算符和分支语句的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1140213

相关文章

【重学 MySQL】十九、位运算符的使用

【重学 MySQL】十九、位运算符的使用 示例检查权限添加权限移除权限 在 MySQL 中,位运算符允许你直接在整数类型的列或表达式上进行位级操作。这些操作对于处理那些需要在二进制表示上进行直接修改或比较的场景特别有用,比如权限管理、状态标记等。 &(位与) 对两个数的二进制表示进行位与操作。只有两个相应的二进制位都为 1 时,结果的该位才为 1,否则为 0。 |(位

C语言程序设计(数据类型、运算符与表达式)

一、C的数据类型 C语言提供的数据类型: 二、常量和变量 2.1常量和符号常量 在程序运行过程中,其值不能被改变的量称为常量。 常量区分为不同的类型: 程序中用#define(预处理器指令)命令行定义变量将代表常量,用一个标识符代表一个常量,称为符合常量。 2.2变量 变量代表内存中具有特定属性的一个存储单元,用来存放数据,在程序运行期间,这些值是可以 改变的。 变

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

第二十四章 rust中的运算符重载

注意 本系列文章已升级、转移至我的自建站点中,本章原文为:rust中的运算符重载 目录 注意一、前言二、基本使用三、常用运算符四、通用约束 一、前言 C/C++中有运算符重载这一概念,它的目的是让即使含不相干的内容也能通过我们自定义的方法进行运算符操作运算。 比如字符串本身是不能相加的,但由于C++中的String重载了运算符+,所以我们就可以将两个字符串进行相加、但实际

【Python知识宝库】上下文管理器与with语句:资源管理的优雅方式

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、什么是上下文管理器?二、上下文管理器的实现三、使用内置上下文管理器四、使用`contextlib`模块五、总结 前言 在Python编程中,资源管理是一个重要的主题,尤其是在处理文件、网络连接和数据库

《C++中的移动构造函数与移动赋值运算符:解锁高效编程的最佳实践》

在 C++的编程世界中,移动构造函数和移动赋值运算符是提升程序性能和效率的重要工具。理解并正确运用它们,可以让我们的代码更加高效、简洁和优雅。 一、引言 随着现代软件系统的日益复杂和对性能要求的不断提高,C++程序员需要不断探索新的技术和方法来优化代码。移动构造函数和移动赋值运算符的出现,为解决资源管理和性能优化问题提供了有力的手段。它们允许我们在不进行不必要的复制操作的情况下,高效地转移资源

FPGA编译与部署方法全方位介绍

FPGA编译与部署是FPGA开发中的核心环节,涉及从代码编写、调试到将设计部署到FPGA硬件的全过程。这个流程需要经过创建项目、编写FPGA VI、模拟调试、编译生成比特流文件,最后将设计部署到硬件上运行。编译的特点在于并行执行能力、定制化硬件实现以及复杂的时钟管理。通过LabVIEW的FPGA模块和NI硬件,可以快速完成开发和部署,尤其适用于复杂控制与高性能数据处理系统。 1. FPG

Java基础--基本运算符介绍

Java运算符 用于指明对于操作数的运算方式。 分类: 按照操作数的数目来进行分类: 单目a++ 双目a+b 三目(a>b)?x:y; 按照运算符的功能来进行分类: 算术运算:+ - * / %(取余)++ – 如: int x=1; x=x+1;//x空间内的值,自己增加了一个 x++;//x空间内的值,自增一个 ++x;//对于x空间内的值来讲都是一致,最终的结果都自

FPGA开发:条件语句 × 循环语句

条件语句 if_else语句 if_else语句,用来判断是否满足所给定的条件,根据判断的结果(真或假)决定执行给出的两种操作之一。 if(表达式)语句; 例如: if(a>b) out1=int1; if(表达式)         语句1; else         语句2; 例如: if(a>b)out1=int1;elseout1=int2; if(表达式1) 语句1; els

mysql 修改表结构语句

主要还是要参考mysql的官方网站 http://dev.mysql.com/doc/refman/5.7/en/alter-table.html 简单例子: alter table_name alter column old_column_name new_column_name int unsigned;