FPGA的设计艺术(21)Verilog中如何对组合逻辑进行建模?

李锐博恩 2021-03-22 00:49:53 6307

前言

可以在Verilog中建模的数字电路主要分为两类:组合电路和时序电路。

事实上,电路也可以只分为组合电路和时序电路,至于混合电路,那是组合电路和时序电路相互交融的结果,因为我们现实世界中,往往都是组合电路与时序电路并存的。

本文我们将讨论使用assign关键字在verilog中进行连续赋值。然后,我们研究如何使用连续赋值在verilog中对基本逻辑门和多路复用器建模。

组合逻辑是两者中最简单的一种,仅由基本逻辑门组成,例如AND,OR和NOT。当电路输入发生变化时,输出几乎立即发生变化(信号传播通过电路时会有很小的延迟)。

相反,时序电路使用时钟并需要诸如触发器之类的存储元件。结果,输出变化与电路时钟同步并且不是立即发生的。

本文中,我们讨论了可用于在Verilog中设计组合逻辑电路的技术。

Verilog中的连续赋值

我们在设计中使用连续赋值将数据驱动到verilog网络类型上。结果,我们经常使用连续赋值对组合逻辑电路进行建模。

实际上,我们可以使用两种不同的方法在verilog中实现连续赋值。

其中第一个称为显式连续赋值。这是Verilog中连续赋值最常用的方法。

另外,我们也可以使用隐式连续赋值或众所周知的声明线网连续赋值(定义变量的时候赋值)。这种方法不太常见,但可以使我们编写更少的代码。

让我们更详细地介绍这两种技术。

显式连续分配

当我们想在Verilog中使用连续赋值时,通常会使用assign关键字。这种方法称为显式连续赋值。

下面的Verilog代码显示了使用assign关键字进行连续分配的一般语法。

assign <variable> = <value>;

上面代码中的variable字段是我们要为其赋值数据的信号的名称。我们只能使用连续赋值将数据赋值给线网类型变量。

value字段可以是一个固定值,也可以使用verilog运算符来创建一个表达式。我们可以在此表达式中使用变量或网络类型。

当我们使用连续赋值时,只要value字段中的信号之一更改状态,variable值就会更改。

下面的代码段显示了Verilog中连续赋值的最基本示例。在这种情况下,无论何时b信号改变状态,a的值都会更新,使其等于b。

assign a = b;

线网声明赋值

我们还可以在Verilog设计中使用隐式连续赋值。此方法在verilog中通常也称为线网声明赋值。

当使用线网声明赋值时,我们在声明我们信号的语句中放置一个连续赋值。这可以使我们减少必须编写的代码量。

要在verilog中使用线网声明赋值,我们在声明信号时使用=符号为信号分配值。

下面的代码段显示了用于线网声明赋值的常规语法。

<type> <variable> = <value>;

对于显式连续赋值和线网声明赋值,变量和值字段具有相同的功能。

例如,下面的verilog代码显示了我们如何使用线网声明赋值来分配b的值来表示a。

wire a = b;

在Verilog中建模组合逻辑电路

我们使用连续分配和Verilog运算符在Verilog中对基本组合逻辑电路进行建模。

为了说明我们将执行此操作,让我们看一下三个输入和门的最基本示例,如下所示。

电路图显示了三个输入和门

为了在Verilog中对该电路建模,我们使用assign关键字将数据驱动到and_out输出上。这意味着必须将and_out信号声明为线网类型变量,例如wire。

然后,我们可以使用按位和运算符(&)来对and门的行为进行建模。

下面的代码片段显示了我们如何在Verilog中对这三个输入与门进行建模。

assign and_out =a & b & c;

该示例说明了在Verilog中设计基本组​​合逻辑电路有多么简单。如果我们需要更改逻辑门的功能,则可以简单地使用其他Verilog逐位运算符。

如果我们需要构建更复杂的组合逻辑电路,那么我们也可以混合使用不同的按位运算符。

为了说明这一点,让我们以下面所示的基本电路为例。
具有功能(a和b)或c的逻辑电路

为了在Verilog中对该电路建模,我们需要使用按位运算符和(&)和或(|)运算符的混合体。下面的代码片段显示了我们如何在Verilog中实现该电路。

assign logic_out = (a & b) | c;

同样,此代码相对容易理解,它用到了verilog中的按位运算符。

但是,我们需要确保使用括号对更复杂的逻辑电路建模。这不仅可以确保电路正常运行,还可以使我们的代码更易于阅读和维护。

在Verilog中建模多路复用器

多路复用器是组合逻辑电路中常用的另一个组件。

在verilog中,我们可以通过多种方式对这些组件进行建模。

这些方法之一使用一种称为always Block的构造。我们通常使用此构造来对时序逻辑电路建模。这种方式我们后面会单独讲解。

在本文的其余部分,我们将介绍可用于建模多路复用器的其他方法。

Verilog条件运算符

verilog中有一个条件运算符。它的功能与C编程语言中的条件运算符相同。

要使用条件运算符,我们在?之前写一个逻辑表达式。然后对运算符进行评估,以查看它是对还是错。

根据表达式是true还是false,将输出分配给两个值之一。

下面的Verilog代码显示条件运算符使用的常规语法。

output = <expression> ? <value if true> : <value if false>;

从此示例中可以清楚地看出,我们如何使用此运算符创建基本的二对一多路复用器。

但是,让我们来看一个简单的2比1多路复用器的示例,如下电路图所示。

2路输入多路复用器电路

下面的代码片段显示了我们如何使用条件运算符在verilog中对该多路复用器建模。

assign q = addr ? b : a;
嵌套条件运算符

尽管这种情况并不常见,但我们也可以通过嵌套条件运算符来编写代码以构建更大的多路复用器。

为了说明如何做到这一点,让我们考虑一个基本的4比1多路复用器,如下电路所示。
四输入多路复用器

为了使用条件运算符在verilog中对此建模,我们将多路复用器电路视为一对两个输入多路复用器。

这意味着一个多路复用器将在输入A和B之间进行选择,而另一个在C和D之间进行选择。这两个多路复用器均使用地址信号的LSB作为地址引脚。

assign mux1 = addr[0] ? b : a;

assign mux2 = addr[0] ? d : c;

为了创建完整的四路输入多路复用器,我们将需要另一个多路复用器。

这将获取前两个多路复用器的输出,并使用地址信号的MSB在它们之间进行选择。

下面的代码段显示了执行此操作的最简单方法。该代码使用我们在上一个示例中定义的信号mux1和mux2。

assign q = addr[1] ? mux2 : mux1;

但是,我们可以轻松地从此代码中删除mux1和mux2信号,而使用嵌套的条件运算符。

这减少了我们在不影响功能的情况下必须编写的代码量。

下面的代码段显示了我们将如何执行此操作。

assign q = addr[1] ? (addr[0] ? d : c) : (addr[0] ? b : a);

从该示例可以看出,当我们使用条件运算符在verilog中对多路复用器进行建模时,代码很快就会变得难以理解。因此,我们仅应使用此方法对小型多路复用器建模。

数组作为多路复用器

我们也可以使用Verilog数组来构建简单的多路复用器。

为此,我们将所有多路复用器输入组合为一个数组类型,并使用该地址指向数组中的元素。

为了更好地了解其工作原理,我们以一个基本的四对一多路复用器为例。

我们要做的第一件事是将输入信号组合成一个数组。我们有两种方法可以做到这一点。

首先,我们可以声明一个数组,然后分配所有各个位,如下面的Verilog代码所示。

// Assigning individual bits in the vector

assign in_vec[0] = a;

assign in_vec[1] = b;

assign in_vec[2] = c;

assign in_vec[3] = d;

另外,我们可以使用verilog拼接运算符,它允许我们在一行代码中分配整个数组。

为此,我们使用一对花括号-{}-并列出要包含在其中的数组中的元素。

当我们使用拼接运算符时,只要我们使用net类型,我们还可以在一个语句中声明并分配变量。

下面的Verilog代码显示了如何使用串联运算符填充数组。

// Using vector assignment

assign in_vec = {d, c, b, a};

// Declare and assign the vector in one line

wire [3:0] in_vec = {d, c, b, a};

由于verilog是一种松散类型的语言,因此我们可以使用两位加法器信号,就好像它是整数类型一样。然后,该信号用作确定四个元素中的哪一个的指针。

下面的代码片段在实践中演示了此方法。由于多路复用器输出是wire,因此在这种情况下,我们必须使用连续赋值。

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

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

举报反馈

举报类型

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

详细说明

审核成功

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

审核失败

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

小包子的红包

恭喜发财,大吉大利

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

    易百纳技术社区