赞
踩
关注、星标公众号,精彩内容每日送达
来源:网络素材
在这篇文章中,我们讨论了verilog中最常用的两个结构-if语句和case语句。
我们在上一篇文章中已经看到了如何使用程序块(例如 always 块来编写按顺序执行的 verilog 代码。
我们还可以在程序块中使用许多语句来控制在我们的verilog设计中信号赋值的方式。这些语句统称为顺序语句。case 语句和 if 语句都是 verilog 中顺序语句的示例。在这篇文章的其余部分,我们将讨论如何在verilog中使用这两个语句。然后,我们考虑这两个结构的简短示例,以说明我们如何在实践中使用它们。
if 语句是一个条件语句,它使用布尔条件来确定要执行哪些verilog代码块。只要条件的计算结果为 true,就会执行与该条件关联的代码分支。此语句类似于其他编程语言(如 C)中使用的 if 语句。
下面的 verilog 代码片段显示了 if 语句的基本语法。
1 | if (<expression1>) begin |
2 | // Code to execute |
3 | end |
4 | else if (<expression2>) begin |
5 | // Code to execute |
6 | end |
7 | else begin |
8 | // Code to execute |
9 | end |
如果我们不需要 else 和 else 分支,我们可以从语句中删除它们。事实上,我们已经在关于always块的帖子中看到了这一点,我们在其中使用 posedge 宏来检测时钟信号的上升沿。如果需要,我们可以包含尽可能多的其他分支,以正确建模底层电路。
if 语句使用布尔条件来确定要执行的代码行。在上面的代码段中,这些表达式由 <expression1> 和 <expression2> 给出。这些表达式按顺序计算,如果表达式的计算结果为 true,则执行与表达式关联的代码。
if 语句只有一个分支将执行。这通常是计算结果为 true 的第一个表达式。唯一的例外情况是,当所有表达式都不为 true 时。在这种情况下,将执行 else 分支中的代码。当我们在 if 语句代码中省略 else 分支时,在这种情况下不会执行任何分支。
与每个分支关联的代码可以包含任何有效的 verilog 代码,包括进一步的 if 语句。此方法称为嵌套 if 语句。
在 verilog 中使用这种类型的代码时,我们应该注意限制嵌套语句的数量,因为它可能会导致满足时间的困难。
我们已经看到了 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语句执行的功能 C语言中的switch语句相同。下面的代码片段显示了 verilog 中case语句的一般语法。
1 | case (<variable>) |
2 | <value1> : begin |
3 | // This branch executes when <variable> = <value1> |
4 | end |
5 | <value2> : begin |
6 | // This branch executes when <variable> = <value2> |
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 值。但是,我们在此示例中包含了默认关键字,以演示应如何使用它。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。