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

李锐博恩 2021-03-18 22:57:24 4303

前言

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 <= 4'h0;

      end

      else begin

        count <= count + 1;

      end

    end

  end

  else begin

    initial begin

      count <= 4'h0;

    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型触发器来寄存一个多路复用器的输出。

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

寄存电路

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

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

always @(posedge clock, posedge reset) begin

  if (reset) begin

    Q <= 1'b0;

  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中对大型多路复用器建模,因为它比基于连续分配的实现产生的可读性更高。

下面的电路图显示了我们将在本示例中使用的电路。
四输入多路复用器

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

always @(*) begin

  case (addr)

    2'b00 : begin

      q = a;

    end

    2'b01 : begin

      q = b;

    end

    3'b10 : begin

      q = c;

    end

    default : begin

      q = d;

    end

  endcase

end

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

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

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

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

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

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 93 8 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
李锐博恩
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区