FPGA的设计艺术(16)逻辑设计中无刻不在的判断之if/case语句

前言

Verilog中的if或者case语句十分简单,但确实十分重要,我们的逻辑设计可以说一定离不开它,我们时时刻刻使用它,我们使用它进行建模,通常对应的是多路选择器这样的硬件单元或者变种。

我们通常将if语句或者case语句与generate语句中的generate if与generate case语句相比较,因为都有if和case,实在太像了,但是它们之间其实有着本质的区别,本系列前面的generate有关的文章就讲到过,generate if的条件是常量,它综合出来的语句其实就是分支中的一条,满足if条件的那一条,而if语句综合出来的电路,则每个分支都包含在内,是一个选择的关系。

而且generate语句一般在always块外部,它用于判断哪个块有效,例如:

// Use a parameter to control our build parameter debug_build = 0; // Conditionally generate a counter generate if (debug_build) begin // Code for the counter always @(posedge clock, posedge reset) begin if (reset) begin count <= 4h0; end else begin count <= count + 1; end end end else begin initial begin count <= 4h0; end end endgenerate
<

可见,generate if之内包含的是always块或者initial块,也可以是某个module的例化。if语句则不行,它必须处于某个always块内。

当然,本文不是重点讨论这方面的,主要抛砖引玉,以供参考与思考。

下面讨论Verilog中两个最常用的构造-if语句和case语句。

case语句和if语句都是verilog中时序语句的示例。

下面们讨论如何在verilog中使用这两个语句。然后,我们考虑这两个构造的简短示例,以说明我们如何在实践中使用它们。

Verilog If语句

if语句是一个条件语句,它使用布尔条件来确定要执行哪些Verilog代码块。

每当条件评估为true时,就会执行与该条件关联的代码分支。

此语句类似于在其他编程语言(例如C)中使用的if语句。

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

if (<expression1>) begin // Code to execute end else if (<expression2>) begin // Code to execute end else begin // Code to execute end

如果不需要,我们可以从语句中排除else和else if分支。

实际上,我们已经在所有块中使用posege宏检测时钟信号的上升沿的文章中已经看到了这一点。

我们可以根据需要添加尽可能多的分支,以正确地对基础电路进行建模。

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

在上面的代码段中,这些表达式由和给出。

这些表达式将按顺序求值,并且如果表达式为true,则将执行与该表达式关联的代码。

if语句的仅一个分支将永远执行。通常,这是第一个计算结果为true的表达式。

当所有表达式都不为真时,唯一的例外情况发生。在这种情况下,else分支中的代码将执行。

当我们在if语句代码中省略else分支时,在这种情况下将不会执行任何分支。

与每个分支关联的代码可以包括任何有效的Verilog代码,包括更多的if语句。这种方法称为嵌套if语句。

在verilog中使用此类代码时,我们应注意限制嵌套语句的数量,因为它可能导致难以满足计时要求。

If语句示例

让我们考虑一个时钟多路复用器的示例。

在这种情况下,我们将使用一个可异步复位的D型触发器来寄存一个多路复用器的输出。

下面的电路图显示了我们将在本示例中使用的电路。

FPGA的设计艺术(16)逻辑设计中无刻不在的判断之if/case语句

电路图显示了两个输入多路复用器和ad型触发器。 多路复用器的输出是触发器的输入。

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

always @(posedge clock, posedge reset) begin if (reset) begin Q <= 1b0; end else begin if (addr) begin Q <= b; end else begin Q <= a; end end end
<

在此示例中,只要复位有效,我们将使用第一个if语句将触发器的输出设置为0b。

当复位未激活时,always块由时钟的上升沿触发。我们使用第一个if语句的else分支来捕获此条件。

我们使用第二条if语句对多路复用器电路的行为进行建模。这是Verilog中嵌套if语句的示例。

当addr信号为0b时,我们将触发器的输出分配给输入a。我们使用嵌套的if语句的第一个分支来捕获此条件。

然后,我们使用嵌套的if语句的else分支捕获addr信号为1b时的情况。

我们也可以在此处使用else-if类型语句,但是else语句更加简洁。两种情况下的行为都相同,因为在实际电路中信号只能为0b或1b。

Verilog case语句

我们使用verilog case语句根据设计中给定信号的值来选择要执行的代码块。

当我们在verilog中编写case语句时,我们指定了一个监视和评估输入信号。

然后将该信号的值与case语句的每个分支中指定的值进行比较。

找到输入信号值的匹配项后,将执行与该值关联的分支。

verilog case语句执行与C编程语言中的switch语句相同的功能。

下面的代码段显示了verilog中case语句的常规语法。

case (<variable>) <value1> : begin // This branch executes when <variable> = <value1> end <value2> : begin // This branch executes when <variable> = <value2> end default : begin // This branch executes in all other cases end endcase

尽管不建议这样做,但可以排除该语句的默认分支。如果排除了默认分支,则的所有有效值都必须具有其自己的分支。

与if语句一样,与每个分支关联的代码可以包括任何有效的Verilog代码。

这包括其他顺序语句,例如if或case语句。同样,我们应该尝试限制嵌套语句的数量,因为它可以更轻松地满足我们的时序要求。

case语句示例

为了更好地说明我们在verilog中使用case语句的方式,让我们考虑一个基本示例。

在本例中,我们将看一个简单的四对一多路复用器电路。

我们经常使用case语句在verilog中对大型多路复用器建模,因为它比基于连续分配的实现产生的可读性更高。

下面的电路图显示了我们将在本示例中使用的电路。 FPGA的设计艺术(16)逻辑设计中无刻不在的判断之if/case语句

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

always @(*) begin case (addr) 2b00 : begin q = a; end 2b01 : begin q = b; end 3b10 : begin q = c; end default : begin q = d; end endcase end
<

此示例说明了使用verilog中的case语句对多路复用器建模的简单性。实际上,case语句提供了在Verilog中建模多路复用器的最直观的方法。

尽管此示例非常简单,但仍有一些重要点需要我们更详细地考虑。

在此示例中要注意的第一件事是,我们使用阻塞赋值。这样做的原因是我们正在对组合逻辑进行建模,并且非阻塞分配通常会导致在设计中放置触发器。

这里要注意的另一件事是,我们可以从该示例中删除默认关键字。然后,我们将显式列出输出d所需的addr的值。

但是,我们在此示例中包括了default关键字,以演示应如何使用它。

免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:FPGA的设计艺术(16)逻辑设计中无刻不在的判断之if/case语句 https://www.yhzz.com.cn/a/12834.html

上一篇 2023-05-11
下一篇 2023-05-11

相关推荐

联系云恒

在线留言: 我要留言
客服热线:400-600-0310
工作时间:周一至周六,08:30-17:30,节假日休息。