如何在verilog中使用If语句和case语句?

描述

在这篇文章中,我们讨论了verilog中最常用的两个结构-if语句和case语句。

我们在上一篇文章中已经看到了如何使用程序块(例如 always 块来编写按顺序执行的 verilog 代码。 我们还可以在程序块中使用许多语句来控制在我们的verilog设计中信号赋值的方式。

这些语句统称为顺序语句。case 语句和 if 语句都是 verilog 中顺序语句的示例。在这篇文章的其余部分,我们将讨论如何在verilog中使用这两个语句。

然后,我们考虑这两个结构的简短示例,以说明我们如何在实践中使用它们。

Verilog If 语句

if 语句是一个条件语句,它使用布尔条件来确定要执行哪些verilog代码块。只要条件的计算结果为 true,就会执行与该条件关联的代码分支。此语句类似于其他编程语言(如 C)中使用的 if 语句。

下面的 verilog 代码片段显示了 if 语句的基本语法。

1 if () begin
2   // Code to execute
3 end
4 else if () begin
5   // Code to execute
6 end
7 else begin
8   // Code to execute
9 end

如果我们不需要 else 和 else 分支,我们可以从语句中删除它们。事实上,我们已经在关于always块的帖子中看到了这一点,我们在其中使用 posedge 宏来检测时钟信号的上升沿。如果需要,我们可以包含尽可能多的其他分支,以正确建模底层电路。

if 语句使用布尔条件来确定要执行的代码行

在上面的代码段中,这些表达式由 给出。这些表达式按顺序计算,如果表达式的计算结果为 true,则执行与表达式关联的代码。 if 语句只有一个分支将执行。这通常是计算结果为 true 的第一个表达式。唯一的例外情况是,当所有表达式都不为 true 时。在这种情况下,将执行 else 分支中的代码。当我们在 if 语句代码中省略 else 分支时,在这种情况下不会执行任何分支。

与每个分支关联的代码可以包含任何有效的 verilog 代码,包括进一步的 if 语句。此方法称为嵌套 if 语句。 在 verilog 中使用这种类型的代码时,我们应该注意限制嵌套语句的数量,因为它可能会导致满足时间的困难。

If 语句示例

我们已经看到了 if 语句的实际示例,当在 verilog always块的帖子中对触发器进行建模时。为了更彻底地演示此结构,让我们考虑一个时钟多路复用器的示例。

在本例中,我们将使用异步复位的 D 类型触发器来保存多路复用器的输出。下面的电路图显示了我们将在本例中使用的电路。

时钟信号

下面的代码片段显示了我们如何使用单个 always 块和 if 语句来实现这一点。

1 always @(posedge clock, posedge reset) begin
2   if (reset) begin
3     Q <= 1'b0;
4   end
5   else begin
6     if (addr) begin
7       Q <= b;
8     end
9     else begin
10       Q <= a;
11     end
12   end
13 end

在此示例中,我们使用第一个if语句在复位时触发,输出0。当复位无效时,always块已由时钟的上升沿触发。我们使用第一个 if 语句的 else 分支来被触发,我们使用第二个if语句来模拟多路复用电路的行为。这是 verilog 中嵌套 if 语句的示例。

当 addr 信号为 0b时,我们使用嵌套 if 语句的第一个分支被触发,将输入a赋值给输出。然后,我们使用嵌套 if 语句的 else 分支来捕获 addr信号为1b 时的情况。 我们也可以在这里使用 else-if 类型语句,但 else 语句更简洁。这两种情况下的行为是相同的,因为信号在实际电路中只能是0b或1b。

Verilog case语句

我们使用 verilog case 语句根据设计中给定信号的值选择要执行的代码块。当我们在verilog中编写语句时,我们指定了一个要监视和评估的输入信号。然后将该信号的值与case语句的每个分支中指定的值进行比较。找到输入信号值的匹配项后,将执行与该值关联的分支。 verilog case语句执行的功能 C语言中的switch语句相同。下面的代码片段显示了 verilog 中case语句的一般语法。

1 case ()
2    : begin
3     // This branch executes when =
4   end
5    : begin
6     // This branch executes when =
7   end
8   default : begin
9     // This branch executes in all other cases
10   end
11 endcase

可以删除语句的默认分支,尽管这是不可取的。如果删除默认分支,则<变量>的所有有效值都必须具有自己的分支。与 if 语句一样,与每个分支关联的代码可以包含任何有效的 verilog 代码。这包括进一步嵌套顺序语句,例如if或case语句。同样,我们应该尝试限制嵌套语句的数量,因为它可以更轻松地满足我们的计时要求。

case语句示例 为了更好地演示erilog中使用case语句的使用方式,让我们考虑一个基本示例。在本例中,我们将介绍一个简单的四比一多路复用电路。 我们经常使用 case 语句在 verilog 中对大型多路复用器进行建模,因为它生成的代码比基于连续赋值的实现更具可读性。下面的电路图显示了我们将在本例中使用的电路。

下面的代码片段显示了我们将如何使用 case 语句实现此电路。

时钟信号

1 always @(*) begin
2   case (addr)
3     2'b00 : begin
4       q = a;
5     end
6     2'b01 : begin
7       q = b;
8     end
9     2'b10 : begin
10       q = c;
11     end
12     default : begin
13       q = d;
14     end
15   endcase
16 end

此示例显示了使用 verilog中的case语句对多路复用器进行建模是多么简单。事实上,case语句提供了在 verilog 中对多路复用器进行建模的最直观方法。 虽然这个例子很简单,但有几个要点我们应该更详细地考虑。在这个例子中首先要注意的是,我们使用阻塞赋值。这样做的原因是我们正在对组合逻辑进行建模,而非阻塞分配通常会导致在我们的设计中放置触发器。

这里要注意的另一件事是,我们可以从此示例中删除默认关键字。然后,我们将显式列出输出d 值所需的 addr 值。但是,我们在此示例中包含了默认关键字,以演示应如何使用它。  





审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分